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