xref: /aosp_15_r20/external/clang/test/SemaCXX/reinterpret-cast.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding -Wundefined-reinterpret-cast -Wno-unused-volatile-lvalue %s
2*67e74705SXin Li 
3*67e74705SXin Li #include <stdint.h>
4*67e74705SXin Li 
5*67e74705SXin Li enum test { testval = 1 };
6*67e74705SXin Li struct structure { int m; };
7*67e74705SXin Li typedef void (*fnptr)();
8*67e74705SXin Li 
9*67e74705SXin Li // Test the conversion to self.
self_conversion()10*67e74705SXin Li void self_conversion()
11*67e74705SXin Li {
12*67e74705SXin Li   // T->T is allowed per [expr.reinterpret.cast]p2 so long as it doesn't
13*67e74705SXin Li   // cast away constness, and is integral, enumeration, pointer or
14*67e74705SXin Li   // pointer-to-member.
15*67e74705SXin Li   int i = 0;
16*67e74705SXin Li   (void)reinterpret_cast<int>(i);
17*67e74705SXin Li 
18*67e74705SXin Li   test e = testval;
19*67e74705SXin Li   (void)reinterpret_cast<test>(e);
20*67e74705SXin Li 
21*67e74705SXin Li   // T*->T* is allowed
22*67e74705SXin Li   int *pi = 0;
23*67e74705SXin Li   (void)reinterpret_cast<int*>(pi);
24*67e74705SXin Li 
25*67e74705SXin Li   const int structure::*psi = 0;
26*67e74705SXin Li   (void)reinterpret_cast<const int structure::*>(psi);
27*67e74705SXin Li 
28*67e74705SXin Li   structure s;
29*67e74705SXin Li   (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}}
30*67e74705SXin Li 
31*67e74705SXin Li   float f = 0.0f;
32*67e74705SXin Li   (void)reinterpret_cast<float>(f); // expected-error {{reinterpret_cast from 'float' to 'float' is not allowed}}
33*67e74705SXin Li }
34*67e74705SXin Li 
35*67e74705SXin Li // Test conversion between pointer and integral types, as in /3 and /4.
integral_conversion()36*67e74705SXin Li void integral_conversion()
37*67e74705SXin Li {
38*67e74705SXin Li   void *vp = reinterpret_cast<void*>(testval);
39*67e74705SXin Li   intptr_t i = reinterpret_cast<intptr_t>(vp);
40*67e74705SXin Li   (void)reinterpret_cast<float*>(i);
41*67e74705SXin Li   fnptr fnp = reinterpret_cast<fnptr>(i);
42*67e74705SXin Li   (void)reinterpret_cast<char>(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}}
43*67e74705SXin Li   (void)reinterpret_cast<intptr_t>(fnp);
44*67e74705SXin Li }
45*67e74705SXin Li 
pointer_conversion()46*67e74705SXin Li void pointer_conversion()
47*67e74705SXin Li {
48*67e74705SXin Li   int *p1 = 0;
49*67e74705SXin Li   float *p2 = reinterpret_cast<float*>(p1);
50*67e74705SXin Li   structure *p3 = reinterpret_cast<structure*>(p2);
51*67e74705SXin Li   typedef int **ppint;
52*67e74705SXin Li   ppint *deep = reinterpret_cast<ppint*>(p3);
53*67e74705SXin Li   (void)reinterpret_cast<fnptr*>(deep);
54*67e74705SXin Li }
55*67e74705SXin Li 
constness()56*67e74705SXin Li void constness()
57*67e74705SXin Li {
58*67e74705SXin Li   int ***const ipppc = 0;
59*67e74705SXin Li   // Valid: T1* -> T2 const*
60*67e74705SXin Li   int const *icp = reinterpret_cast<int const*>(ipppc);
61*67e74705SXin Li   // Invalid: T1 const* -> T2*
62*67e74705SXin Li   (void)reinterpret_cast<int*>(icp); // expected-error {{reinterpret_cast from 'const int *' to 'int *' casts away qualifiers}}
63*67e74705SXin Li   // Invalid: T1*** -> T2 const* const**
64*67e74705SXin Li   int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***' to 'const int *const **' casts away qualifiers}}
65*67e74705SXin Li   // Valid: T1* -> T2*
66*67e74705SXin Li   int *ip = reinterpret_cast<int*>(icpcpp);
67*67e74705SXin Li   // Valid: T* -> T const*
68*67e74705SXin Li   (void)reinterpret_cast<int const*>(ip);
69*67e74705SXin Li   // Valid: T*** -> T2 const* const* const*
70*67e74705SXin Li   (void)reinterpret_cast<int const* const* const*>(ipppc);
71*67e74705SXin Li }
72*67e74705SXin Li 
fnptrs()73*67e74705SXin Li void fnptrs()
74*67e74705SXin Li {
75*67e74705SXin Li   typedef int (*fnptr2)(int);
76*67e74705SXin Li   fnptr fp = 0;
77*67e74705SXin Li   (void)reinterpret_cast<fnptr2>(fp);
78*67e74705SXin Li   void *vp = reinterpret_cast<void*>(fp);
79*67e74705SXin Li   (void)reinterpret_cast<fnptr>(vp);
80*67e74705SXin Li }
81*67e74705SXin Li 
refs()82*67e74705SXin Li void refs()
83*67e74705SXin Li {
84*67e74705SXin Li   long l = 0;
85*67e74705SXin Li   char &c = reinterpret_cast<char&>(l);
86*67e74705SXin Li   // Bad: from rvalue
87*67e74705SXin Li   (void)reinterpret_cast<int&>(&c); // expected-error {{reinterpret_cast from rvalue to reference type 'int &'}}
88*67e74705SXin Li }
89*67e74705SXin Li 
memptrs()90*67e74705SXin Li void memptrs()
91*67e74705SXin Li {
92*67e74705SXin Li   const int structure::*psi = 0;
93*67e74705SXin Li   (void)reinterpret_cast<const float structure::*>(psi);
94*67e74705SXin Li   (void)reinterpret_cast<int structure::*>(psi); // expected-error {{reinterpret_cast from 'const int structure::*' to 'int structure::*' casts away qualifiers}}
95*67e74705SXin Li 
96*67e74705SXin Li   void (structure::*psf)() = 0;
97*67e74705SXin Li   (void)reinterpret_cast<int (structure::*)()>(psf);
98*67e74705SXin Li 
99*67e74705SXin Li   (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error-re {{reinterpret_cast from 'const int structure::*' to 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' is not allowed}}
100*67e74705SXin Li   (void)reinterpret_cast<int structure::*>(psf); // expected-error-re {{reinterpret_cast from 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' to 'int structure::*' is not allowed}}
101*67e74705SXin Li 
102*67e74705SXin Li   // Cannot cast from integers to member pointers, not even the null pointer
103*67e74705SXin Li   // literal.
104*67e74705SXin Li   (void)reinterpret_cast<void (structure::*)()>(0); // expected-error-re {{reinterpret_cast from 'int' to 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' is not allowed}}
105*67e74705SXin Li   (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int structure::*' is not allowed}}
106*67e74705SXin Li }
107*67e74705SXin Li 
108*67e74705SXin Li namespace PR5545 {
109*67e74705SXin Li // PR5545
110*67e74705SXin Li class A;
111*67e74705SXin Li class B;
112*67e74705SXin Li void (A::*a)();
113*67e74705SXin Li void (B::*b)() = reinterpret_cast<void (B::*)()>(a);
114*67e74705SXin Li }
115*67e74705SXin Li 
116*67e74705SXin Li // <rdar://problem/8018292>
const_arrays()117*67e74705SXin Li void const_arrays() {
118*67e74705SXin Li   typedef char STRING[10];
119*67e74705SXin Li   const STRING *s;
120*67e74705SXin Li   const char *c;
121*67e74705SXin Li 
122*67e74705SXin Li   (void)reinterpret_cast<char *>(s); // expected-error {{reinterpret_cast from 'const STRING *' (aka 'char const (*)[10]') to 'char *' casts away qualifiers}}
123*67e74705SXin Li   (void)reinterpret_cast<const STRING *>(c);
124*67e74705SXin Li }
125*67e74705SXin Li 
126*67e74705SXin Li namespace PR9564 {
127*67e74705SXin Li   struct a { int a : 10; }; a x;
128*67e74705SXin Li   int *y = &reinterpret_cast<int&>(x.a); // expected-error {{not allowed}}
129*67e74705SXin Li 
130*67e74705SXin Li   __attribute((ext_vector_type(4))) typedef float v4;
w(v4 & a)131*67e74705SXin Li   float& w(v4 &a) { return reinterpret_cast<float&>(a[1]); } // expected-error {{not allowed}}
132*67e74705SXin Li }
133*67e74705SXin Li 
dereference_reinterpret_cast()134*67e74705SXin Li void dereference_reinterpret_cast() {
135*67e74705SXin Li   struct A {};
136*67e74705SXin Li   typedef A A2;
137*67e74705SXin Li   class B {};
138*67e74705SXin Li   typedef B B2;
139*67e74705SXin Li   A a;
140*67e74705SXin Li   B b;
141*67e74705SXin Li   A2 a2;
142*67e74705SXin Li   B2 b2;
143*67e74705SXin Li   long l;
144*67e74705SXin Li   double d;
145*67e74705SXin Li   float f;
146*67e74705SXin Li   char c;
147*67e74705SXin Li   unsigned char uc;
148*67e74705SXin Li   void* v_ptr;
149*67e74705SXin Li   (void)reinterpret_cast<double&>(l);  // expected-warning {{reinterpret_cast from 'long' to 'double &' has undefined behavior}}
150*67e74705SXin Li   (void)*reinterpret_cast<double*>(&l);  // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}}
151*67e74705SXin Li   (void)reinterpret_cast<double&>(f);  // expected-warning {{reinterpret_cast from 'float' to 'double &' has undefined behavior}}
152*67e74705SXin Li   (void)*reinterpret_cast<double*>(&f);  // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'float *' has undefined behavior}}
153*67e74705SXin Li   (void)reinterpret_cast<float&>(l);  // expected-warning {{reinterpret_cast from 'long' to 'float &' has undefined behavior}}
154*67e74705SXin Li   (void)*reinterpret_cast<float*>(&l);  // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'long *' has undefined behavior}}
155*67e74705SXin Li   (void)reinterpret_cast<float&>(d);  // expected-warning {{reinterpret_cast from 'double' to 'float &' has undefined behavior}}
156*67e74705SXin Li   (void)*reinterpret_cast<float*>(&d);  // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'double *' has undefined behavior}}
157*67e74705SXin Li 
158*67e74705SXin Li   // TODO: add warning for tag types
159*67e74705SXin Li   (void)reinterpret_cast<A&>(b);
160*67e74705SXin Li   (void)*reinterpret_cast<A*>(&b);
161*67e74705SXin Li   (void)reinterpret_cast<B&>(a);
162*67e74705SXin Li   (void)*reinterpret_cast<B*>(&a);
163*67e74705SXin Li   (void)reinterpret_cast<A2&>(b2);
164*67e74705SXin Li   (void)*reinterpret_cast<A2*>(&b2);
165*67e74705SXin Li   (void)reinterpret_cast<B2&>(a2);
166*67e74705SXin Li   (void)*reinterpret_cast<B2*>(&a2);
167*67e74705SXin Li 
168*67e74705SXin Li   // Casting to itself is allowed
169*67e74705SXin Li   (void)reinterpret_cast<A&>(a);
170*67e74705SXin Li   (void)*reinterpret_cast<A*>(&a);
171*67e74705SXin Li   (void)reinterpret_cast<B&>(b);
172*67e74705SXin Li   (void)*reinterpret_cast<B*>(&b);
173*67e74705SXin Li   (void)reinterpret_cast<long&>(l);
174*67e74705SXin Li   (void)*reinterpret_cast<long*>(&l);
175*67e74705SXin Li   (void)reinterpret_cast<double&>(d);
176*67e74705SXin Li   (void)*reinterpret_cast<double*>(&d);
177*67e74705SXin Li   (void)reinterpret_cast<char&>(c);
178*67e74705SXin Li   (void)*reinterpret_cast<char*>(&c);
179*67e74705SXin Li 
180*67e74705SXin Li   // Casting to and from chars are allowable
181*67e74705SXin Li   (void)reinterpret_cast<A&>(c);
182*67e74705SXin Li   (void)*reinterpret_cast<A*>(&c);
183*67e74705SXin Li   (void)reinterpret_cast<B&>(c);
184*67e74705SXin Li   (void)*reinterpret_cast<B*>(&c);
185*67e74705SXin Li   (void)reinterpret_cast<long&>(c);
186*67e74705SXin Li   (void)*reinterpret_cast<long*>(&c);
187*67e74705SXin Li   (void)reinterpret_cast<double&>(c);
188*67e74705SXin Li   (void)*reinterpret_cast<double*>(&c);
189*67e74705SXin Li   (void)reinterpret_cast<char&>(l);
190*67e74705SXin Li   (void)*reinterpret_cast<char*>(&l);
191*67e74705SXin Li   (void)reinterpret_cast<char&>(d);
192*67e74705SXin Li   (void)*reinterpret_cast<char*>(&d);
193*67e74705SXin Li   (void)reinterpret_cast<char&>(f);
194*67e74705SXin Li   (void)*reinterpret_cast<char*>(&f);
195*67e74705SXin Li 
196*67e74705SXin Li   // Casting from void pointer.
197*67e74705SXin Li   (void)*reinterpret_cast<A*>(v_ptr);
198*67e74705SXin Li   (void)*reinterpret_cast<B*>(v_ptr);
199*67e74705SXin Li   (void)*reinterpret_cast<long*>(v_ptr);
200*67e74705SXin Li   (void)*reinterpret_cast<double*>(v_ptr);
201*67e74705SXin Li   (void)*reinterpret_cast<float*>(v_ptr);
202*67e74705SXin Li 
203*67e74705SXin Li   // Casting to void pointer
204*67e74705SXin Li   (void)*reinterpret_cast<void*>(&a); // expected-warning {{ISO C++ does not allow}}
205*67e74705SXin Li   (void)*reinterpret_cast<void*>(&b); // expected-warning {{ISO C++ does not allow}}
206*67e74705SXin Li   (void)*reinterpret_cast<void*>(&l); // expected-warning {{ISO C++ does not allow}}
207*67e74705SXin Li   (void)*reinterpret_cast<void*>(&d); // expected-warning {{ISO C++ does not allow}}
208*67e74705SXin Li   (void)*reinterpret_cast<void*>(&f); // expected-warning {{ISO C++ does not allow}}
209*67e74705SXin Li }
210*67e74705SXin Li 
reinterpret_cast_whitelist()211*67e74705SXin Li void reinterpret_cast_whitelist () {
212*67e74705SXin Li   // the dynamic type of the object
213*67e74705SXin Li   int a;
214*67e74705SXin Li   float b;
215*67e74705SXin Li   (void)reinterpret_cast<int&>(a);
216*67e74705SXin Li   (void)*reinterpret_cast<int*>(&a);
217*67e74705SXin Li   (void)reinterpret_cast<float&>(b);
218*67e74705SXin Li   (void)*reinterpret_cast<float*>(&b);
219*67e74705SXin Li 
220*67e74705SXin Li   // a cv-qualified version of the dynamic object
221*67e74705SXin Li   (void)reinterpret_cast<const int&>(a);
222*67e74705SXin Li   (void)*reinterpret_cast<const int*>(&a);
223*67e74705SXin Li   (void)reinterpret_cast<volatile int&>(a);
224*67e74705SXin Li   (void)*reinterpret_cast<volatile int*>(&a);
225*67e74705SXin Li   (void)reinterpret_cast<const volatile int&>(a);
226*67e74705SXin Li   (void)*reinterpret_cast<const volatile int*>(&a);
227*67e74705SXin Li   (void)reinterpret_cast<const float&>(b);
228*67e74705SXin Li   (void)*reinterpret_cast<const float*>(&b);
229*67e74705SXin Li   (void)reinterpret_cast<volatile float&>(b);
230*67e74705SXin Li   (void)*reinterpret_cast<volatile float*>(&b);
231*67e74705SXin Li   (void)reinterpret_cast<const volatile float&>(b);
232*67e74705SXin Li   (void)*reinterpret_cast<const volatile float*>(&b);
233*67e74705SXin Li 
234*67e74705SXin Li   // a type that is the signed or unsigned type corresponding to the dynamic
235*67e74705SXin Li   // type of the object
236*67e74705SXin Li   signed d;
237*67e74705SXin Li   unsigned e;
238*67e74705SXin Li   (void)reinterpret_cast<signed&>(d);
239*67e74705SXin Li   (void)*reinterpret_cast<signed*>(&d);
240*67e74705SXin Li   (void)reinterpret_cast<signed&>(e);
241*67e74705SXin Li   (void)*reinterpret_cast<signed*>(&e);
242*67e74705SXin Li   (void)reinterpret_cast<unsigned&>(d);
243*67e74705SXin Li   (void)*reinterpret_cast<unsigned*>(&d);
244*67e74705SXin Li   (void)reinterpret_cast<unsigned&>(e);
245*67e74705SXin Li   (void)*reinterpret_cast<unsigned*>(&e);
246*67e74705SXin Li 
247*67e74705SXin Li   // a type that is the signed or unsigned type corresponding a cv-qualified
248*67e74705SXin Li   // version of the dynamic type the object
249*67e74705SXin Li   (void)reinterpret_cast<const signed&>(d);
250*67e74705SXin Li   (void)*reinterpret_cast<const signed*>(&d);
251*67e74705SXin Li   (void)reinterpret_cast<const signed&>(e);
252*67e74705SXin Li   (void)*reinterpret_cast<const signed*>(&e);
253*67e74705SXin Li   (void)reinterpret_cast<const unsigned&>(d);
254*67e74705SXin Li   (void)*reinterpret_cast<const unsigned*>(&d);
255*67e74705SXin Li   (void)reinterpret_cast<const unsigned&>(e);
256*67e74705SXin Li   (void)*reinterpret_cast<const unsigned*>(&e);
257*67e74705SXin Li   (void)reinterpret_cast<volatile signed&>(d);
258*67e74705SXin Li   (void)*reinterpret_cast<volatile signed*>(&d);
259*67e74705SXin Li   (void)reinterpret_cast<volatile signed&>(e);
260*67e74705SXin Li   (void)*reinterpret_cast<volatile signed*>(&e);
261*67e74705SXin Li   (void)reinterpret_cast<volatile unsigned&>(d);
262*67e74705SXin Li   (void)*reinterpret_cast<volatile unsigned*>(&d);
263*67e74705SXin Li   (void)reinterpret_cast<volatile unsigned&>(e);
264*67e74705SXin Li   (void)*reinterpret_cast<volatile unsigned*>(&e);
265*67e74705SXin Li   (void)reinterpret_cast<const volatile signed&>(d);
266*67e74705SXin Li   (void)*reinterpret_cast<const volatile signed*>(&d);
267*67e74705SXin Li   (void)reinterpret_cast<const volatile signed&>(e);
268*67e74705SXin Li   (void)*reinterpret_cast<const volatile signed*>(&e);
269*67e74705SXin Li   (void)reinterpret_cast<const volatile unsigned&>(d);
270*67e74705SXin Li   (void)*reinterpret_cast<const volatile unsigned*>(&d);
271*67e74705SXin Li   (void)reinterpret_cast<const volatile unsigned&>(e);
272*67e74705SXin Li   (void)*reinterpret_cast<const volatile unsigned*>(&e);
273*67e74705SXin Li 
274*67e74705SXin Li   // an aggregate or union type that includes one of the aforementioned types
275*67e74705SXin Li   // among its members (including, recursively, a member of a subaggregate or
276*67e74705SXin Li   // contained union)
277*67e74705SXin Li   // TODO: checking is not implemented for tag types
278*67e74705SXin Li 
279*67e74705SXin Li   // a type that is a (possible cv-qualified) base class type of the dynamic
280*67e74705SXin Li   // type of the object
281*67e74705SXin Li   // TODO: checking is not implemented for tag types
282*67e74705SXin Li 
283*67e74705SXin Li   // a char or unsigned char type
284*67e74705SXin Li   (void)reinterpret_cast<char&>(a);
285*67e74705SXin Li   (void)*reinterpret_cast<char*>(&a);
286*67e74705SXin Li   (void)reinterpret_cast<unsigned char&>(a);
287*67e74705SXin Li   (void)*reinterpret_cast<unsigned char*>(&a);
288*67e74705SXin Li   (void)reinterpret_cast<char&>(b);
289*67e74705SXin Li   (void)*reinterpret_cast<char*>(&b);
290*67e74705SXin Li   (void)reinterpret_cast<unsigned char&>(b);
291*67e74705SXin Li   (void)*reinterpret_cast<unsigned char*>(&b);
292*67e74705SXin Li }
293