1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -triple %itanium_abi_triple -verify -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s |
2 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s |
3 | |
4 | // RUN: not %clang_cc1 -std=c++11 -fsyntax-only -triple %itanium_abi_triple -fdiagnostics-parseable-fixits -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s 2>&1 | FileCheck %s |
5 | // RUN: not %clang_cc1 -std=c++11 -fsyntax-only -triple %ms_abi_triple -fdiagnostics-parseable-fixits -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s 2>&1 | FileCheck %s |
6 | |
7 | // PR 13824 |
8 | class A { |
9 | }; |
10 | class DA : public A { |
11 | }; |
12 | class DDA : public DA { |
13 | }; |
14 | class DAo : protected A { |
15 | }; |
16 | class DAi : private A { |
17 | }; |
18 | |
19 | class DVA : public virtual A { |
20 | }; |
21 | class DDVA : public virtual DA { |
22 | }; |
23 | class DMA : public virtual A, public virtual DA { //expected-warning{{direct base 'A' is inaccessible due to ambiguity:\n class DMA -> class A\n class DMA -> class DA -> class A}} |
24 | }; |
25 | |
26 | class B; |
27 | |
28 | struct C { |
29 | // Do not fail on incompletely-defined classes. |
30 | decltype(reinterpret_cast<C *>(0)) foo; |
31 | decltype(reinterpret_cast<A *>((C *) 0)) bar; |
32 | decltype(reinterpret_cast<C *>((A *) 0)) baz; |
33 | }; |
34 | |
35 | void reinterpret_not_defined_class(B *b, C *c) { |
36 | // Should not fail if class has no definition. |
37 | (void)*reinterpret_cast<C *>(b); |
38 | (void)*reinterpret_cast<B *>(c); |
39 | |
40 | (void)reinterpret_cast<C &>(*b); |
41 | (void)reinterpret_cast<B &>(*c); |
42 | } |
43 | |
44 | // Do not fail on erroneous classes with fields of incompletely-defined types. |
45 | // Base class is malformed. |
46 | namespace BaseMalformed { |
47 | struct A; // expected-note {{forward declaration of 'BaseMalformed::A'}} |
48 | struct B { |
49 | A a; // expected-error {{field has incomplete type 'BaseMalformed::A'}} |
50 | }; |
51 | struct C : public B {} c; |
52 | B *b = reinterpret_cast<B *>(&c); |
53 | } // end anonymous namespace |
54 | |
55 | // Child class is malformed. |
56 | namespace ChildMalformed { |
57 | struct A; // expected-note {{forward declaration of 'ChildMalformed::A'}} |
58 | struct B {}; |
59 | struct C : public B { |
60 | A a; // expected-error {{field has incomplete type 'ChildMalformed::A'}} |
61 | } c; |
62 | B *b = reinterpret_cast<B *>(&c); |
63 | } // end anonymous namespace |
64 | |
65 | // Base class outside upcast base-chain is malformed. |
66 | namespace BaseBaseMalformed { |
67 | struct A; // expected-note {{forward declaration of 'BaseBaseMalformed::A'}} |
68 | struct Y {}; |
69 | struct X { A a; }; // expected-error {{field has incomplete type 'BaseBaseMalformed::A'}} |
70 | struct B : Y, X {}; |
71 | struct C : B {} c; |
72 | B *p = reinterpret_cast<B*>(&c); |
73 | } |
74 | |
75 | namespace InheritanceMalformed { |
76 | struct A; // expected-note {{forward declaration of 'InheritanceMalformed::A'}} |
77 | struct B : A {}; // expected-error {{base class has incomplete type}} |
78 | struct C : B {} c; |
79 | B *p = reinterpret_cast<B*>(&c); |
80 | } |
81 | |
82 | // Virtual base class outside upcast base-chain is malformed. |
83 | namespace VBaseMalformed{ |
84 | struct A; // expected-note {{forward declaration of 'VBaseMalformed::A'}} |
85 | struct X { A a; }; // expected-error {{field has incomplete type 'VBaseMalformed::A'}} |
86 | struct B : public virtual X {}; |
87 | struct C : B {} c; |
88 | B *p = reinterpret_cast<B*>(&c); |
89 | } |
90 | |
91 | void reinterpret_not_updowncast(A *pa, const A *pca, A &a, const A &ca) { |
92 | (void)*reinterpret_cast<C *>(pa); |
93 | (void)*reinterpret_cast<const C *>(pa); |
94 | (void)*reinterpret_cast<volatile C *>(pa); |
95 | (void)*reinterpret_cast<const volatile C *>(pa); |
96 | |
97 | (void)*reinterpret_cast<const C *>(pca); |
98 | (void)*reinterpret_cast<const volatile C *>(pca); |
99 | |
100 | (void)reinterpret_cast<C &>(a); |
101 | (void)reinterpret_cast<const C &>(a); |
102 | (void)reinterpret_cast<volatile C &>(a); |
103 | (void)reinterpret_cast<const volatile C &>(a); |
104 | |
105 | (void)reinterpret_cast<const C &>(ca); |
106 | (void)reinterpret_cast<const volatile C &>(ca); |
107 | } |
108 | |
109 | void reinterpret_pointer_downcast(A *a, const A *ca) { |
110 | (void)*reinterpret_cast<DA *>(a); |
111 | (void)*reinterpret_cast<const DA *>(a); |
112 | (void)*reinterpret_cast<volatile DA *>(a); |
113 | (void)*reinterpret_cast<const volatile DA *>(a); |
114 | |
115 | (void)*reinterpret_cast<const DA *>(ca); |
116 | (void)*reinterpret_cast<const volatile DA *>(ca); |
117 | |
118 | (void)*reinterpret_cast<DDA *>(a); |
119 | (void)*reinterpret_cast<DAo *>(a); |
120 | (void)*reinterpret_cast<DAi *>(a); |
121 | // expected-warning@+2 {{'reinterpret_cast' to class 'DVA *' from its virtual base 'A *' behaves differently from 'static_cast'}} |
122 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
123 | (void)*reinterpret_cast<DVA *>(a); |
124 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:26}:"static_cast" |
125 | |
126 | // expected-warning@+2 {{'reinterpret_cast' to class 'DDVA *' from its virtual base 'A *' behaves differently from 'static_cast'}} |
127 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
128 | (void)*reinterpret_cast<DDVA *>(a); |
129 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:26}:"static_cast" |
130 | |
131 | // expected-warning@+2 {{'reinterpret_cast' to class 'DMA *' from its virtual base 'A *' behaves differently from 'static_cast'}} |
132 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
133 | (void)*reinterpret_cast<DMA *>(a); |
134 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:26}:"static_cast" |
135 | } |
136 | |
137 | void reinterpret_reference_downcast(A a, A &ra, const A &cra) { |
138 | (void)reinterpret_cast<DA &>(a); |
139 | (void)reinterpret_cast<const DA &>(a); |
140 | (void)reinterpret_cast<volatile DA &>(a); |
141 | (void)reinterpret_cast<const volatile DA &>(a); |
142 | |
143 | (void)reinterpret_cast<DA &>(ra); |
144 | (void)reinterpret_cast<const DA &>(ra); |
145 | (void)reinterpret_cast<volatile DA &>(ra); |
146 | (void)reinterpret_cast<const volatile DA &>(ra); |
147 | |
148 | (void)reinterpret_cast<const DA &>(cra); |
149 | (void)reinterpret_cast<const volatile DA &>(cra); |
150 | |
151 | (void)reinterpret_cast<DDA &>(a); |
152 | (void)reinterpret_cast<DAo &>(a); |
153 | (void)reinterpret_cast<DAi &>(a); |
154 | // expected-warning@+2 {{'reinterpret_cast' to class 'DVA &' from its virtual base 'A' behaves differently from 'static_cast'}} |
155 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
156 | (void)reinterpret_cast<DVA &>(a); |
157 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
158 | |
159 | // expected-warning@+2 {{'reinterpret_cast' to class 'DDVA &' from its virtual base 'A' behaves differently from 'static_cast'}} |
160 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
161 | (void)reinterpret_cast<DDVA &>(a); |
162 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
163 | |
164 | // expected-warning@+2 {{'reinterpret_cast' to class 'DMA &' from its virtual base 'A' behaves differently from 'static_cast'}} |
165 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
166 | (void)reinterpret_cast<DMA &>(a); |
167 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
168 | } |
169 | |
170 | void reinterpret_pointer_upcast(DA *da, const DA *cda, DDA *dda, DAo *dao, |
171 | DAi *dai, DVA *dva, DDVA *ddva, DMA *dma) { |
172 | (void)*reinterpret_cast<A *>(da); |
173 | (void)*reinterpret_cast<const A *>(da); |
174 | (void)*reinterpret_cast<volatile A *>(da); |
175 | (void)*reinterpret_cast<const volatile A *>(da); |
176 | |
177 | (void)*reinterpret_cast<const A *>(cda); |
178 | (void)*reinterpret_cast<const volatile A *>(cda); |
179 | |
180 | (void)*reinterpret_cast<A *>(dda); |
181 | (void)*reinterpret_cast<DA *>(dda); |
182 | (void)*reinterpret_cast<A *>(dao); |
183 | (void)*reinterpret_cast<A *>(dai); |
184 | // expected-warning@+2 {{'reinterpret_cast' from class 'DVA *' to its virtual base 'A *' behaves differently from 'static_cast'}} |
185 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
186 | (void)*reinterpret_cast<A *>(dva); |
187 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:26}:"static_cast" |
188 | |
189 | // expected-warning@+2 {{'reinterpret_cast' from class 'DDVA *' to its virtual base 'A *' behaves differently from 'static_cast'}} |
190 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
191 | (void)*reinterpret_cast<A *>(ddva); |
192 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:26}:"static_cast" |
193 | |
194 | // expected-warning@+2 {{'reinterpret_cast' from class 'DDVA *' to its virtual base 'DA *' behaves differently from 'static_cast'}} |
195 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
196 | (void)*reinterpret_cast<DA *>(ddva); |
197 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:26}:"static_cast" |
198 | |
199 | // expected-warning@+2 {{'reinterpret_cast' from class 'DMA *' to its virtual base 'A *' behaves differently from 'static_cast'}} |
200 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
201 | (void)*reinterpret_cast<A *>(dma); |
202 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:26}:"static_cast" |
203 | |
204 | // expected-warning@+2 {{'reinterpret_cast' from class 'DMA *' to its virtual base 'DA *' behaves differently from 'static_cast'}} |
205 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
206 | (void)*reinterpret_cast<DA *>(dma); |
207 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:26}:"static_cast" |
208 | } |
209 | |
210 | void reinterpret_reference_upcast(DA &da, const DA &cda, DDA &dda, DAo &dao, |
211 | DAi &dai, DVA &dva, DDVA &ddva, DMA &dma) { |
212 | (void)reinterpret_cast<A &>(da); |
213 | (void)reinterpret_cast<const A &>(da); |
214 | (void)reinterpret_cast<volatile A &>(da); |
215 | (void)reinterpret_cast<const volatile A &>(da); |
216 | |
217 | (void)reinterpret_cast<const A &>(cda); |
218 | (void)reinterpret_cast<const volatile A &>(cda); |
219 | |
220 | (void)reinterpret_cast<A &>(dda); |
221 | (void)reinterpret_cast<DA &>(dda); |
222 | (void)reinterpret_cast<A &>(dao); |
223 | (void)reinterpret_cast<A &>(dai); |
224 | // expected-warning@+2 {{'reinterpret_cast' from class 'DVA' to its virtual base 'A &' behaves differently from 'static_cast'}} |
225 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
226 | (void)reinterpret_cast<A &>(dva); |
227 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
228 | |
229 | // expected-warning@+2 {{'reinterpret_cast' from class 'DDVA' to its virtual base 'A &' behaves differently from 'static_cast'}} |
230 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
231 | (void)reinterpret_cast<A &>(ddva); |
232 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
233 | |
234 | // expected-warning@+2 {{'reinterpret_cast' from class 'DDVA' to its virtual base 'DA &' behaves differently from 'static_cast'}} |
235 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
236 | (void)reinterpret_cast<DA &>(ddva); |
237 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
238 | |
239 | // expected-warning@+2 {{'reinterpret_cast' from class 'DMA' to its virtual base 'A &' behaves differently from 'static_cast'}} |
240 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
241 | (void)reinterpret_cast<A &>(dma); |
242 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
243 | |
244 | // expected-warning@+2 {{'reinterpret_cast' from class 'DMA' to its virtual base 'DA &' behaves differently from 'static_cast'}} |
245 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
246 | (void)reinterpret_cast<DA &>(dma); |
247 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
248 | } |
249 | |
250 | struct E { |
251 | int x; |
252 | }; |
253 | |
254 | class F : public E { |
255 | virtual int foo() { return x; } |
256 | }; |
257 | |
258 | class G : public F { |
259 | }; |
260 | |
261 | class H : public E, public A { |
262 | }; |
263 | |
264 | class I : virtual public F { |
265 | }; |
266 | |
267 | typedef const F * K; |
268 | typedef volatile K L; |
269 | |
270 | void different_subobject_downcast(E *e, F *f, A *a) { |
271 | // expected-warning@+2 {{'reinterpret_cast' to class 'F *' from its base at non-zero offset 'E *' behaves differently from 'static_cast'}} |
272 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
273 | (void)reinterpret_cast<F *>(e); |
274 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
275 | |
276 | // expected-warning@+2 {{'reinterpret_cast' to class 'G *' from its base at non-zero offset 'E *' behaves differently from 'static_cast'}} |
277 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
278 | (void)reinterpret_cast<G *>(e); |
279 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
280 | |
281 | (void)reinterpret_cast<H *>(e); |
282 | // expected-warning@+2 {{'reinterpret_cast' to class 'I *' from its virtual base 'E *' behaves differently from 'static_cast'}} |
283 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
284 | (void)reinterpret_cast<I *>(e); |
285 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
286 | |
287 | |
288 | (void)reinterpret_cast<G *>(f); |
289 | // expected-warning@+2 {{'reinterpret_cast' to class 'I *' from its virtual base 'F *' behaves differently from 'static_cast'}} |
290 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
291 | (void)reinterpret_cast<I *>(f); |
292 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
293 | |
294 | #ifdef MSABI |
295 | // In MS ABI mode, A is at non-zero offset in H. |
296 | // expected-warning@+3 {{'reinterpret_cast' to class 'H *' from its base at non-zero offset 'A *' behaves differently from 'static_cast'}} |
297 | // expected-note@+2 {{use 'static_cast'}} |
298 | #endif |
299 | (void)reinterpret_cast<H *>(a); |
300 | |
301 | // expected-warning@+2 {{'reinterpret_cast' to class 'L' (aka 'const F *volatile') from its base at non-zero offset 'E *' behaves differently from 'static_cast'}} |
302 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}} |
303 | (void)reinterpret_cast<L>(e); |
304 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
305 | } |
306 | |
307 | void different_subobject_upcast(F *f, G *g, H *h, I *i) { |
308 | // expected-warning@+2 {{'reinterpret_cast' from class 'F *' to its base at non-zero offset 'E *' behaves differently from 'static_cast'}} |
309 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
310 | (void)reinterpret_cast<E *>(f); |
311 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
312 | |
313 | (void)reinterpret_cast<F *>(g); |
314 | // expected-warning@+2 {{'reinterpret_cast' from class 'G *' to its base at non-zero offset 'E *' behaves differently from 'static_cast'}} |
315 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
316 | (void)reinterpret_cast<E *>(g); |
317 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
318 | |
319 | (void)reinterpret_cast<E *>(h); |
320 | |
321 | #ifdef MSABI |
322 | // In MS ABI mode, A is at non-zero offset in H. |
323 | // expected-warning@+3 {{'reinterpret_cast' from class 'H *' to its base at non-zero offset 'A *' behaves differently from 'static_cast'}} |
324 | // expected-note@+2 {{use 'static_cast'}} |
325 | #endif |
326 | (void)reinterpret_cast<A *>(h); |
327 | |
328 | // expected-warning@+2 {{'reinterpret_cast' from class 'I *' to its virtual base 'F *' behaves differently from 'static_cast'}} |
329 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
330 | (void)reinterpret_cast<F *>(i); |
331 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
332 | |
333 | // expected-warning@+2 {{'reinterpret_cast' from class 'I *' to its virtual base 'E *' behaves differently from 'static_cast'}} |
334 | // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while upcasting}} |
335 | (void)reinterpret_cast<E *>(i); |
336 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" |
337 | } |
338 | |