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