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