blob: e9fffd5aefca2dfe74b1fa7fae7d64df426aa4c9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
// RUN: %clang -ccc-cxx -fsanitize=vptr %s -O3 -o %t
// RUN: %t rT && %t mT && %t fT
// RUN: %t rU && %t mU && %t fU
// RUN: %t rS 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
// RUN: %t mS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
// RUN: %t fS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
// RUN: %t rV 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
// RUN: %t mV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
// RUN: %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
struct S {
S() : a(0) {}
~S() {}
int a;
int f() { return 0; }
virtual int v() { return 0; }
};
struct T : S {
T() : b(0) {}
int b;
int g() { return 0; }
virtual int v() { return 1; }
};
struct U : S, T { virtual int v() { return 2; } };
int main(int, char **argv) {
T t;
(void)t.a;
(void)t.b;
(void)t.f();
(void)t.g();
(void)t.v();
(void)t.S::v();
U u;
(void)u.T::a;
(void)u.b;
(void)u.T::f();
(void)u.g();
(void)u.v();
(void)u.T::v();
(void)((T&)u).S::v();
T *p = 0;
switch (argv[1][1]) {
case 'S':
p = reinterpret_cast<T*>(new S);
break;
case 'T':
p = new T;
break;
case 'U':
p = new U;
break;
case 'V':
p = reinterpret_cast<T*>(new U);
break;
}
switch (argv[1][0]) {
case 'r':
// CHECK-REFERENCE: vptr.cpp:65:13: fatal error: reference binding to address 0x{{[0-9a-f]*}} which does not point to an object of type 'T'
{T &r = *p;}
break;
case 'm':
// CHECK-MEMBER: vptr.cpp:69:15: fatal error: member access within address 0x{{[0-9a-f]*}} which does not point to an object of type 'T'
return p->b;
case 'f':
// CHECK-MEMFUN: vptr.cpp:72:12: fatal error: member call on address 0x{{[0-9a-f]*}} which does not point to an object of type 'T'
return p->g();
}
}
|