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 17struct S { 18 S() : a(0) {} 19 ~S() {} 20 int a; 21 int f() { return 0; } 22 virtual int v() { return 0; } 23}; 24 25struct T : S { 26 T() : b(0) {} 27 int b; 28 int g() { return 0; } 29 virtual int v() { return 1; } 30}; 31 32struct U : S, T { virtual int v() { return 2; } }; 33 34T *p = 0; // Make p global so that lsan does not complain. 35 36int 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