Clang Project

clang_source_code/test/SemaCXX/warn-reinterpret-base-class.cpp
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
8class A {
9};
10class DA : public A {
11};
12class DDA : public DA {
13};
14class DAo : protected A {
15};
16class DAi : private A {
17};
18
19class DVA : public virtual A {
20};
21class DDVA : public virtual DA {
22};
23class 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
26class B;
27
28struct 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
35void 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.
46namespace 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.
56namespace 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.
66namespace 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
75namespace 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.
83namespace 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
91void 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
109void 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
137void 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
170void 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
210void 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
250struct E {
251  int x;
252};
253
254class F : public E {
255  virtual int foo() { return x; }
256};
257
258class G : public F {
259};
260
261class H : public E, public A {
262};
263
264class I : virtual public F {
265};
266
267typedef const F * K;
268typedef volatile K L;
269
270void 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
307void 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