xref: /llvm-project/clang/test/SemaCXX/reinterpret-cast.cpp (revision d049db83627d164e4353f59a5f0b4f87dd74b138)
1 // RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding -Wundefined-reinterpret-cast -Wno-unused-volatile-lvalue %s
2 
3 #include <stdint.h>
4 
5 enum test { testval = 1 };
6 struct structure { int m; };
7 typedef void (*fnptr)();
8 
9 // Test the conversion to self.
10 void self_conversion()
11 {
12   // T->T is allowed per [expr.reinterpret.cast]p2 so long as it doesn't
13   // cast away constness, and is integral, enumeration, pointer or
14   // pointer-to-member.
15   int i = 0;
16   (void)reinterpret_cast<int>(i);
17 
18   test e = testval;
19   (void)reinterpret_cast<test>(e);
20 
21   // T*->T* is allowed
22   int *pi = 0;
23   (void)reinterpret_cast<int*>(pi);
24 
25   const int structure::*psi = 0;
26   (void)reinterpret_cast<const int structure::*>(psi);
27 
28   const int ci = 0;
29   (void)reinterpret_cast<const int>(i);
30 
31   structure s;
32   (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}}
33 
34   float f = 0.0f;
35   (void)reinterpret_cast<float>(f); // expected-error {{reinterpret_cast from 'float' to 'float' is not allowed}}
36 }
37 
38 // Test conversion between pointer and integral types, as in /3 and /4.
39 void integral_conversion()
40 {
41   void *vp = reinterpret_cast<void*>(testval);
42   intptr_t i = reinterpret_cast<intptr_t>(vp);
43   (void)reinterpret_cast<float*>(i);
44   fnptr fnp = reinterpret_cast<fnptr>(i);
45   (void)reinterpret_cast<char>(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}}
46   (void)reinterpret_cast<intptr_t>(fnp);
47 }
48 
49 void pointer_conversion()
50 {
51   int *p1 = 0;
52   float *p2 = reinterpret_cast<float*>(p1);
53   structure *p3 = reinterpret_cast<structure*>(p2);
54   typedef int **ppint;
55   ppint *deep = reinterpret_cast<ppint*>(p3);
56   (void)reinterpret_cast<fnptr*>(deep);
57 }
58 
59 void constness()
60 {
61   int ***const ipppc = 0;
62   // Valid: T1* -> T2 const*
63   int const *icp = reinterpret_cast<int const*>(ipppc);
64   // Invalid: T1 const* -> T2*
65   (void)reinterpret_cast<int*>(icp); // expected-error {{reinterpret_cast from 'const int *' to 'int *' casts away qualifiers}}
66   // Invalid: T1*** -> T2 const* const**
67   int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***' to 'const int *const **' casts away qualifiers}}
68   // Valid: T1* -> T2*
69   int *ip = reinterpret_cast<int*>(icpcpp);
70   // Valid: T* -> T const*
71   (void)reinterpret_cast<int const*>(ip);
72   // Valid: T*** -> T2 const* const* const*
73   (void)reinterpret_cast<int const* const* const*>(ipppc);
74 
75   // C++ [expr.type]/8.2.2:
76   //   If a pr-value initially has the type cv-T, where T is a
77   //   cv-unqualified non-class, non-array type, the type of the
78   //   expression is adjusted to T prior to any further analysis.
79   int i = 0;
80   // Valid: T -> T (top level const is ignored)
81   (void)reinterpret_cast<const int>(i);
82   // Valid: T* -> T* (top level const is ignored)
83   (void)reinterpret_cast<int *const>(ip);
84 }
85 
86 void fnptrs()
87 {
88   typedef int (*fnptr2)(int);
89   fnptr fp = 0;
90   (void)reinterpret_cast<fnptr2>(fp);
91   void *vp = reinterpret_cast<void*>(fp);
92   (void)reinterpret_cast<fnptr>(vp);
93 }
94 
95 void refs()
96 {
97   long l = 0;
98   char &c = reinterpret_cast<char&>(l);
99   // Bad: from rvalue
100   (void)reinterpret_cast<int&>(&c); // expected-error {{reinterpret_cast from rvalue to reference type 'int &'}}
101 }
102 
103 void memptrs()
104 {
105   const int structure::*psi = 0;
106   (void)reinterpret_cast<const float structure::*>(psi);
107   (void)reinterpret_cast<int structure::*>(psi); // expected-error {{reinterpret_cast from 'const int structure::*' to 'int structure::*' casts away qualifiers}}
108 
109   void (structure::*psf)() = 0;
110   (void)reinterpret_cast<int (structure::*)()>(psf);
111 
112   (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error-re {{reinterpret_cast from 'const int structure::*' to 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' is not allowed}}
113   (void)reinterpret_cast<int structure::*>(psf); // expected-error-re {{reinterpret_cast from 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' to 'int structure::*' is not allowed}}
114 
115   // Cannot cast from integers to member pointers, not even the null pointer
116   // literal.
117   (void)reinterpret_cast<void (structure::*)()>(0); // expected-error-re {{reinterpret_cast from 'int' to 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' is not allowed}}
118   (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int structure::*' is not allowed}}
119 }
120 
121 namespace PR5545 {
122 // PR5545
123 class A;
124 class B;
125 void (A::*a)();
126 void (B::*b)() = reinterpret_cast<void (B::*)()>(a);
127 }
128 
129 void const_arrays() {
130   typedef char STRING[10];
131   const STRING *s;
132   const char *c;
133 
134   (void)reinterpret_cast<char *>(s); // expected-error {{reinterpret_cast from 'const STRING *' (aka 'const char (*)[10]') to 'char *' casts away qualifiers}}
135   (void)reinterpret_cast<const STRING *>(c);
136 }
137 
138 namespace PR9564 {
139   struct a { int a : 10; }; a x;
140   int *y = &reinterpret_cast<int&>(x.a); // expected-error {{reinterpret_cast from bit-field lvalue to reference type 'int &'}}
141 
142   __attribute((ext_vector_type(4))) typedef float v4;
143   float& w(v4 &a) { return reinterpret_cast<float&>(a[1]); } // expected-error {{not allowed}}
144 }
145 
146 void dereference_reinterpret_cast() {
147   struct A {};
148   typedef A A2;
149   class B {};
150   typedef B B2;
151   A a;
152   B b;
153   A2 a2;
154   B2 b2;
155   long l;
156   double d;
157   float f;
158   char c;
159   unsigned char uc;
160   void* v_ptr;
161   (void)reinterpret_cast<double&>(l);  // expected-warning {{reinterpret_cast from 'long' to 'double &' has undefined behavior}}
162   (void)*reinterpret_cast<double*>(&l);  // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}}
163   (void)reinterpret_cast<double&>(f);  // expected-warning {{reinterpret_cast from 'float' to 'double &' has undefined behavior}}
164   (void)*reinterpret_cast<double*>(&f);  // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'float *' has undefined behavior}}
165   (void)reinterpret_cast<float&>(l);  // expected-warning {{reinterpret_cast from 'long' to 'float &' has undefined behavior}}
166   (void)*reinterpret_cast<float*>(&l);  // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'long *' has undefined behavior}}
167   (void)reinterpret_cast<float&>(d);  // expected-warning {{reinterpret_cast from 'double' to 'float &' has undefined behavior}}
168   (void)*reinterpret_cast<float*>(&d);  // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'double *' has undefined behavior}}
169 
170   // TODO: add warning for tag types
171   (void)reinterpret_cast<A&>(b);
172   (void)*reinterpret_cast<A*>(&b);
173   (void)reinterpret_cast<B&>(a);
174   (void)*reinterpret_cast<B*>(&a);
175   (void)reinterpret_cast<A2&>(b2);
176   (void)*reinterpret_cast<A2*>(&b2);
177   (void)reinterpret_cast<B2&>(a2);
178   (void)*reinterpret_cast<B2*>(&a2);
179 
180   // Casting to itself is allowed
181   (void)reinterpret_cast<A&>(a);
182   (void)*reinterpret_cast<A*>(&a);
183   (void)reinterpret_cast<B&>(b);
184   (void)*reinterpret_cast<B*>(&b);
185   (void)reinterpret_cast<long&>(l);
186   (void)*reinterpret_cast<long*>(&l);
187   (void)reinterpret_cast<double&>(d);
188   (void)*reinterpret_cast<double*>(&d);
189   (void)reinterpret_cast<char&>(c);
190   (void)*reinterpret_cast<char*>(&c);
191 
192   // Casting to and from chars are allowable
193   (void)reinterpret_cast<A&>(c);
194   (void)*reinterpret_cast<A*>(&c);
195   (void)reinterpret_cast<B&>(c);
196   (void)*reinterpret_cast<B*>(&c);
197   (void)reinterpret_cast<long&>(c);
198   (void)*reinterpret_cast<long*>(&c);
199   (void)reinterpret_cast<double&>(c);
200   (void)*reinterpret_cast<double*>(&c);
201   (void)reinterpret_cast<char&>(l);
202   (void)*reinterpret_cast<char*>(&l);
203   (void)reinterpret_cast<char&>(d);
204   (void)*reinterpret_cast<char*>(&d);
205   (void)reinterpret_cast<char&>(f);
206   (void)*reinterpret_cast<char*>(&f);
207 
208   // Casting from void pointer.
209   (void)*reinterpret_cast<A*>(v_ptr);
210   (void)*reinterpret_cast<B*>(v_ptr);
211   (void)*reinterpret_cast<long*>(v_ptr);
212   (void)*reinterpret_cast<double*>(v_ptr);
213   (void)*reinterpret_cast<float*>(v_ptr);
214 
215   // Casting to void pointer
216   (void)*reinterpret_cast<void*>(&a); // expected-error {{indirection not permitted on operand of type 'void *'}}
217   (void)*reinterpret_cast<void*>(&b); // expected-error {{indirection not permitted on operand of type 'void *'}}
218   (void)*reinterpret_cast<void*>(&l); // expected-error {{indirection not permitted on operand of type 'void *'}}
219   (void)*reinterpret_cast<void*>(&d); // expected-error {{indirection not permitted on operand of type 'void *'}}
220   (void)*reinterpret_cast<void*>(&f); // expected-error {{indirection not permitted on operand of type 'void *'}}
221 }
222 
223 void reinterpret_cast_allowlist () {
224   // the dynamic type of the object
225   int a;
226   float b;
227   (void)reinterpret_cast<int&>(a);
228   (void)*reinterpret_cast<int*>(&a);
229   (void)reinterpret_cast<float&>(b);
230   (void)*reinterpret_cast<float*>(&b);
231 
232   // a cv-qualified version of the dynamic object
233   (void)reinterpret_cast<const int&>(a);
234   (void)*reinterpret_cast<const int*>(&a);
235   (void)reinterpret_cast<volatile int&>(a);
236   (void)*reinterpret_cast<volatile int*>(&a);
237   (void)reinterpret_cast<const volatile int&>(a);
238   (void)*reinterpret_cast<const volatile int*>(&a);
239   (void)reinterpret_cast<const float&>(b);
240   (void)*reinterpret_cast<const float*>(&b);
241   (void)reinterpret_cast<volatile float&>(b);
242   (void)*reinterpret_cast<volatile float*>(&b);
243   (void)reinterpret_cast<const volatile float&>(b);
244   (void)*reinterpret_cast<const volatile float*>(&b);
245 
246   // a type that is the signed or unsigned type corresponding to the dynamic
247   // type of the object
248   signed d;
249   unsigned e;
250   (void)reinterpret_cast<signed&>(d);
251   (void)*reinterpret_cast<signed*>(&d);
252   (void)reinterpret_cast<signed&>(e);
253   (void)*reinterpret_cast<signed*>(&e);
254   (void)reinterpret_cast<unsigned&>(d);
255   (void)*reinterpret_cast<unsigned*>(&d);
256   (void)reinterpret_cast<unsigned&>(e);
257   (void)*reinterpret_cast<unsigned*>(&e);
258 
259   // a type that is the signed or unsigned type corresponding a cv-qualified
260   // version of the dynamic type the object
261   (void)reinterpret_cast<const signed&>(d);
262   (void)*reinterpret_cast<const signed*>(&d);
263   (void)reinterpret_cast<const signed&>(e);
264   (void)*reinterpret_cast<const signed*>(&e);
265   (void)reinterpret_cast<const unsigned&>(d);
266   (void)*reinterpret_cast<const unsigned*>(&d);
267   (void)reinterpret_cast<const unsigned&>(e);
268   (void)*reinterpret_cast<const unsigned*>(&e);
269   (void)reinterpret_cast<volatile signed&>(d);
270   (void)*reinterpret_cast<volatile signed*>(&d);
271   (void)reinterpret_cast<volatile signed&>(e);
272   (void)*reinterpret_cast<volatile signed*>(&e);
273   (void)reinterpret_cast<volatile unsigned&>(d);
274   (void)*reinterpret_cast<volatile unsigned*>(&d);
275   (void)reinterpret_cast<volatile unsigned&>(e);
276   (void)*reinterpret_cast<volatile unsigned*>(&e);
277   (void)reinterpret_cast<const volatile signed&>(d);
278   (void)*reinterpret_cast<const volatile signed*>(&d);
279   (void)reinterpret_cast<const volatile signed&>(e);
280   (void)*reinterpret_cast<const volatile signed*>(&e);
281   (void)reinterpret_cast<const volatile unsigned&>(d);
282   (void)*reinterpret_cast<const volatile unsigned*>(&d);
283   (void)reinterpret_cast<const volatile unsigned&>(e);
284   (void)*reinterpret_cast<const volatile unsigned*>(&e);
285 
286   // an aggregate or union type that includes one of the aforementioned types
287   // among its members (including, recursively, a member of a subaggregate or
288   // contained union)
289   // TODO: checking is not implemented for tag types
290 
291   // a type that is a (possible cv-qualified) base class type of the dynamic
292   // type of the object
293   // TODO: checking is not implemented for tag types
294 
295   // a char or unsigned char type
296   (void)reinterpret_cast<char&>(a);
297   (void)*reinterpret_cast<char*>(&a);
298   (void)reinterpret_cast<unsigned char&>(a);
299   (void)*reinterpret_cast<unsigned char*>(&a);
300   (void)reinterpret_cast<char&>(b);
301   (void)*reinterpret_cast<char*>(&b);
302   (void)reinterpret_cast<unsigned char&>(b);
303   (void)*reinterpret_cast<unsigned char*>(&b);
304 }
305 
306 namespace templated {
307 template <typename TARGETTYPE, typename UATYPE>
308 void cast_uninstantiated() {
309   const UATYPE* data;
310   (void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
311 }
312 
313 
314 template <typename TARGETTYPE, typename UATYPE>
315 void cast_instantiated_badly() {
316   const UATYPE* data;
317   (void)*reinterpret_cast<const TARGETTYPE*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
318 }
319 
320 template <typename TARGETTYPE, typename UATYPE>
321 void cast_instantiated_well() {
322   const UATYPE* data;
323   (void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
324 }
325 
326 template <typename TARGETTYPE>
327 void cast_one_tmpl_arg_uninstantiated() {
328   const int* data;
329   (void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
330 }
331 
332 template <typename TARGETTYPE>
333 void cast_one_tmpl_arg_instantiated_badly() {
334   const float* data;
335   (void)*reinterpret_cast<const TARGETTYPE*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
336 }
337 
338 template <typename TARGETTYPE>
339 void cast_one_tmpl_arg_instantiated_well() {
340   const float* data;
341   (void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
342 }
343 
344 template <int size>
345 void cast_nontype_template_true_positive_noninstantiated() {
346   const float *data;
347   const int arr[size];
348   (void)*reinterpret_cast<const int*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
349 }
350 
351 template <int size>
352 void cast_nontype_template_true_negative_noninstantiated() {
353   const int data[size];
354   (void)*reinterpret_cast<const int*>(data); // no warning
355 }
356 
357 void top() {
358   cast_instantiated_badly<int, float>();
359   // expected-note@-1 {{in instantiation of function template specialization 'templated::cast_instantiated_badly<int, float>' requested here}}
360   cast_instantiated_well<int, int>();
361   cast_one_tmpl_arg_instantiated_badly<int>();
362   // expected-note@-1 {{in instantiation of function template specialization 'templated::cast_one_tmpl_arg_instantiated_badly<int>' requested here}}
363   cast_one_tmpl_arg_instantiated_well<float>();
364 }
365 
366 template<typename T, typename U>
367 void cast_template_dependent_type_noninstantiated(T** x)
368 {
369     (void)*reinterpret_cast<U**>(x);
370 }
371 
372 template<typename T, typename U>
373 void cast_template_dependent_member_type_noninstantiated(typename T::X x)
374 {
375     (void)*reinterpret_cast<typename U::Y>(x);
376 }
377 
378 } // namespace templated
379