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