1 // { dg-do run { target { ilp32 || lp64 } } }
2 // { dg-options "-fsanitize=vptr" }
3
4 struct S
5 {
SS6 S() : a(0) {}
~SS7 ~S() {}
8 int a;
fS9 int f() { return 0; }
vS10 virtual int v() { return 0; }
11 };
12
13 struct T : S
14 {
TT15 T() : b(0) {}
16 int b;
gT17 int g() { return 0; }
vT18 virtual int v() { return 1; }
19 };
20
vU21 struct U : S, T { virtual int v() { return 2; } }; // { dg-warning "direct base .S. inaccessible in .U. due to ambiguity" }
22 struct V : S {};
23
24 void
foo()25 foo ()
26 {
27 T t;
28 (void)t.a;
29 (void)t.b;
30 (void)t.f();
31 (void)t.g();
32 (void)t.v();
33 (void)t.S::v();
34
35 U u;
36 (void)u.T::a;
37 (void)u.b;
38 (void)u.T::f();
39 (void)u.g();
40 (void)u.v();
41 (void)u.T::v();
42 (void)((T&)u).S::v();
43 }
44
45 T *x;
46
47 __attribute__((noinline, noclone)) int
bar(T * p,int q)48 bar (T *p, int q)
49 {
50 switch (q)
51 {
52 // These shouldn't fail:
53 case 0x10:
54 case 0x20:
55 case 0x30:
56 case 0x40:
57 {
58 T &r = *p;
59 break;
60 }
61 case 0x21:
62 case 0x31:
63 return p->b;
64 case 0x22:
65 case 0x32:
66 return p->g ();
67 case 0x23:
68 case 0x33:
69 x = static_cast<T*>(reinterpret_cast<S*>(p));
70 break;
71 case 0x44:
72 return reinterpret_cast<U*>(p)->v() - 2;
73 // These should:
74 case 0x11:
75 return p->b;
76 // { dg-output "\[^\n\r]*vptr-1.C:75:\[0-9]*: runtime error: member access within address 0x\[0-9a-fA-F]* which does not point to an object of type 'T'(\n|\r\n|\r)" }
77 // { dg-output "0x\[0-9a-fA-F]*: note: object is of type 'S'(\n|\r\n|\r)" }
78 // { dg-output " .. .. .. .. .. .. .. .. .. .. .. .. \[^\n\r]*(\n|\r\n|\r)" }
79 // { dg-output " \\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
80 // { dg-output " vptr for 'S'\[^\n\r]*(\n|\r\n|\r)" }
81 case 0x12:
82 return p->g ();
83 // { dg-output "\[^\n\r]*vptr-1.C:82:\[0-9]*: runtime error: member call on address 0x\[0-9a-fA-F]* which does not point to an object of type 'T'(\n|\r\n|\r)" }
84 // { dg-output "0x\[0-9a-fA-F]*: note: object is of type 'S'(\n|\r\n|\r)" }
85 // { dg-output " .. .. .. .. .. .. .. .. .. .. .. .. \[^\n\r]*(\n|\r\n|\r)" }
86 // { dg-output " \\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
87 // { dg-output " vptr for 'S'\[^\n\r]*(\n|\r\n|\r)" }
88 case 0x13:
89 x = static_cast<T*>(reinterpret_cast<S*>(p));
90 break;
91 // { dg-output "\[^\n\r]*vptr-1.C:89:\[0-9]*: runtime error: downcast of address 0x\[0-9a-fA-F]* which does not point to an object of type 'T'(\n|\r\n|\r)" }
92 // { dg-output "0x\[0-9a-fA-F]*: note: object is of type 'S'(\n|\r\n|\r)" }
93 // { dg-output " .. .. .. .. .. .. .. .. .. .. .. .. \[^\n\r]*(\n|\r\n|\r)" }
94 // { dg-output " \\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
95 // { dg-output " vptr for 'S'\[^\n\r]*(\n|\r\n|\r)" }
96 case 0x34:
97 return reinterpret_cast<U*>(p)->v() - 2;
98 // { dg-output "\[^\n\r]*vptr-1.C:97:\[0-9]*: runtime error: member call on address 0x\[0-9a-fA-F]* which does not point to an object of type 'U'(\n|\r\n|\r)" }
99 // { dg-output "0x\[0-9a-fA-F]*: note: object is base class subobject at offset 16 within object of type 'U'(\n|\r\n|\r)" { target lp64 } }
100 // { dg-output "0x\[0-9a-fA-F]*: note: object is base class subobject at offset 8 within object of type 'U'(\n|\r\n|\r)" { target ilp32 } }
101 // { dg-output " .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. \[^\n\r]*(\n|\r\n|\r)" }
102 // { dg-output " \\^ ~~~~~~~~~~~~~~~~~~~~~~~(\n|\r\n|\r)" { target lp64 } }
103 // { dg-output " vptr for 'T' base class of 'U'\[^\n\r]*(\n|\r\n|\r)" { target lp64 } }
104 // { dg-output " \\^ ~~~~~~~~~~~(\n|\r\n|\r)" { target ilp32 } }
105 // { dg-output " vptr for 'T' base class of 'U'\[^\n\r]*(\n|\r\n|\r)" { target ilp32 } }
106 case 0x41:
107 return p->b;
108 // { dg-output "\[^\n\r]*vptr-1.C:107:\[0-9]*: runtime error: member access within address 0x\[0-9a-fA-F]* which does not point to an object of type 'T'(\n|\r\n|\r)" }
109 // { dg-output "0x\[0-9a-fA-F]*: note: object is of type 'U'(\n|\r\n|\r)" }
110 // { dg-output " .. .. .. .. .. .. .. .. .. .. .. .. \[^\n\r]*(\n|\r\n|\r)" }
111 // { dg-output " \\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
112 // { dg-output " vptr for 'U'\[^\n\r]*(\n|\r\n|\r)" }
113 case 0x42:
114 return p->g ();
115 // { dg-output "\[^\n\r]*vptr-1.C:114:\[0-9]*: runtime error: member call on address 0x\[0-9a-fA-F]* which does not point to an object of type 'T'(\n|\r\n|\r)" }
116 // { dg-output "0x\[0-9a-fA-F]*: note: object is of type 'U'(\n|\r\n|\r)" }
117 // { dg-output " .. .. .. .. .. .. .. .. .. .. .. .. \[^\n\r]*(\n|\r\n|\r)" }
118 // { dg-output " \\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
119 // { dg-output " vptr for 'U'\[^\n\r]*(\n|\r\n|\r)" }
120 case 0x43:
121 x = static_cast<T*>(reinterpret_cast<S*>(p));
122 break;
123 // { dg-output "\[^\n\r]*vptr-1.C:121:\[0-9]*: runtime error: downcast of address 0x\[0-9a-fA-F]* which does not point to an object of type 'T'(\n|\r\n|\r)" }
124 // { dg-output "0x\[0-9a-fA-F]*: note: object is of type 'U'(\n|\r\n|\r)" }
125 // { dg-output " .. .. .. .. .. .. .. .. .. .. .. .. \[^\n\r]*(\n|\r\n|\r)" }
126 // { dg-output " \\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
127 // { dg-output " vptr for 'U'\[^\n\r]*(\n|\r\n|\r)" }
128 case 0x51:
129 return p->b;
130 // { dg-output "\[^\n\r]*vptr-1.C:129:\[0-9]*: runtime error: member access within address 0x\[0-9a-fA-F]* which does not point to an object of type 'T'(\n|\r\n|\r)" }
131 // { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" }
132 // { dg-output " .. .. .. .. 00 00 00 00 00 00 00 00 \[^\n\r]*(\n|\r\n|\r)" { target lp64 } }
133 // { dg-output " \\^~~~~~~~~~~~~~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" { target lp64 } }
134 // { dg-output " ?.. .. .. .. ?00 00 00 00 ?.. .. .. .. ?\[^\n\r]*(\n|\r\n|\r)" { target ilp32 } }
135 // { dg-output " \\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" { target ilp32 } }
136 // { dg-output " invalid vptr" }
137 }
138 return 0;
139 }
140
141 char b[sizeof (U)] __attribute__((aligned (__alignof__ (U)))) = {};
142
143 __attribute__((noinline, noclone)) void
baz(int q)144 baz (int q)
145 {
146 T *p = 0;
147 S *s = 0;
148 U *u = 0;
149 switch (q)
150 {
151 case 0x10: case 0x11: case 0x12: case 0x13:
152 s = new S;
153 bar (reinterpret_cast<T *>(s), q);
154 delete s;
155 break;
156 case 0x20: case 0x21: case 0x22: case 0x23:
157 p = new T;
158 bar (p, q);
159 delete p;
160 break;
161 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
162 u = new U;
163 bar (u, q);
164 delete u;
165 break;
166 case 0x40: case 0x41: case 0x42: case 0x43: case 0x44:
167 u = new U;
168 bar (reinterpret_cast<T *>(u), q);
169 delete u;
170 break;
171 case 0x51:
172 p = reinterpret_cast<T*>(b);
173 bar (p, q);
174 break;
175 }
176 }
177
178 int
main()179 main ()
180 {
181 foo ();
182 for (int q = 0; q < 0x52; q++)
183 baz (q);
184 }
185