Home | History | Annotate | Download | only in TypeCheck
      1 // RUN: %clangxx -fsanitize=vptr %s -O3 -o %t
      2 // RUN: %run %t rT && %run %t mT && %run %t fT && %run %t cT
      3 // RUN: %run %t rU && %run %t mU && %run %t fU && %run %t cU
      4 // RUN: %run %t rS && %run %t rV && %run %t oV
      5 // RUN: %run %t mS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace
      6 // RUN: %run %t fS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
      7 // RUN: %run %t cS 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace
      8 // RUN: %run %t mV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace
      9 // RUN: %run %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
     10 // RUN: %run %t cV 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace
     11 // RUN: %run %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --strict-whitespace
     12 // RUN: %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace
     13 
     14 // FIXME: This test produces linker errors on Darwin.
     15 // XFAIL: darwin
     16 
     17 struct S {
     18   S() : a(0) {}
     19   ~S() {}
     20   int a;
     21   int f() { return 0; }
     22   virtual int v() { return 0; }
     23 };
     24 
     25 struct T : S {
     26   T() : b(0) {}
     27   int b;
     28   int g() { return 0; }
     29   virtual int v() { return 1; }
     30 };
     31 
     32 struct U : S, T { virtual int v() { return 2; } };
     33 
     34 T *p = 0;  // Make p global so that lsan does not complain.
     35 
     36 int main(int, char **argv) {
     37   T t;
     38   (void)t.a;
     39   (void)t.b;
     40   (void)t.f();
     41   (void)t.g();
     42   (void)t.v();
     43   (void)t.S::v();
     44 
     45   U u;
     46   (void)u.T::a;
     47   (void)u.b;
     48   (void)u.T::f();
     49   (void)u.g();
     50   (void)u.v();
     51   (void)u.T::v();
     52   (void)((T&)u).S::v();
     53 
     54   char Buffer[sizeof(U)] = {};
     55   switch (argv[1][1]) {
     56   case '0':
     57     p = reinterpret_cast<T*>(Buffer);
     58     break;
     59   case 'S':
     60     p = reinterpret_cast<T*>(new S);
     61     break;
     62   case 'T':
     63     p = new T;
     64     break;
     65   case 'U':
     66     p = new U;
     67     break;
     68   case 'V':
     69     p = reinterpret_cast<T*>(new U);
     70     break;
     71   }
     72 
     73   switch (argv[1][0]) {
     74   case 'r':
     75     // Binding a reference to storage of appropriate size and alignment is OK.
     76     {T &r = *p;}
     77     break;
     78 
     79   case 'm':
     80     // CHECK-MEMBER: vptr.cpp:[[@LINE+5]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
     81     // CHECK-MEMBER-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']]
     82     // CHECK-MEMBER-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }}
     83     // CHECK-MEMBER-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
     84     // CHECK-MEMBER-NEXT: {{^              vptr for}} [[DYN_TYPE]]
     85     return p->b;
     86 
     87     // CHECK-NULL-MEMBER: vptr.cpp:[[@LINE-2]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
     88     // CHECK-NULL-MEMBER-NEXT: [[PTR]]: note: object has invalid vptr
     89     // CHECK-NULL-MEMBER-NEXT: {{^  ?.. .. .. ..  ?00 00 00 00  ?00 00 00 00  ?}}
     90     // CHECK-NULL-MEMBER-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
     91     // CHECK-NULL-MEMBER-NEXT: {{^              invalid vptr}}
     92 
     93   case 'f':
     94     // CHECK-MEMFUN: vptr.cpp:[[@LINE+5]]:12: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
     95     // CHECK-MEMFUN-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']]
     96     // CHECK-MEMFUN-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }}
     97     // CHECK-MEMFUN-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
     98     // CHECK-MEMFUN-NEXT: {{^              vptr for}} [[DYN_TYPE]]
     99     return p->g();
    100 
    101   case 'o':
    102     // CHECK-OFFSET: vptr.cpp:[[@LINE+5]]:12: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'U'
    103     // CHECK-OFFSET-NEXT: 0x{{[0-9a-f]*}}: note: object is base class subobject at offset {{8|16}} within object of type [[DYN_TYPE:'U']]
    104     // CHECK-OFFSET-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  .. .. .. .. .. .. .. ..  .. .. .. .. .. .. .. ..  }}
    105     // CHECK-OFFSET-NEXT: {{^              \^                        (                         ~~~~~~~~~~~~)?~~~~~~~~~~~ *$}}
    106     // CHECK-OFFSET-NEXT: {{^                                       (                         )?vptr for}} 'T' base class of [[DYN_TYPE]]
    107     return reinterpret_cast<U*>(p)->v() - 2;
    108 
    109   case 'c':
    110     // CHECK-DOWNCAST: vptr.cpp:[[@LINE+5]]:5: runtime error: downcast of address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
    111     // CHECK-DOWNCAST-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']]
    112     // CHECK-DOWNCAST-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }}
    113     // CHECK-DOWNCAST-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
    114     // CHECK-DOWNCAST-NEXT: {{^              vptr for}} [[DYN_TYPE]]
    115     static_cast<T*>(reinterpret_cast<S*>(p));
    116     return 0;
    117   }
    118 }
    119