383 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding -Wundefined-reinterpret-cast -Wno-unused-volatile-lvalue %s2 3#include <stdint.h>4 5enum test { testval = 1 };6struct structure { int m; };7typedef void (*fnptr)();8 9// Test the conversion to self.10void self_conversion()11{12 // T->T is allowed per [expr.reinterpret.cast]p2 so long as it doesn't13 // 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 allowed22 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.39void 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 49void 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 59void 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 a77 // cv-unqualified non-class, non-array type, the type of the78 // 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 86void 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 95void refs()96{97 long l = 0;98 char &c = reinterpret_cast<char&>(l);99 // Bad: from rvalue100 (void)reinterpret_cast<int&>(&c); // expected-error {{reinterpret_cast from rvalue to reference type 'int &'}}101}102 103void 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 pointer116 // 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 121namespace PR5545 {122// PR5545123class A;124class B;125void (A::*a)();126void (B::*b)() = reinterpret_cast<void (B::*)()>(a);127}128 129void 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 138namespace 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 146void 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 // Look through parens171 (void)*(reinterpret_cast<double*>(&l)); // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}}172 (void)*((reinterpret_cast<double*>((&l)))); // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}}173 174 // TODO: add warning for tag types175 (void)reinterpret_cast<A&>(b);176 (void)*reinterpret_cast<A*>(&b);177 (void)reinterpret_cast<B&>(a);178 (void)*reinterpret_cast<B*>(&a);179 (void)reinterpret_cast<A2&>(b2);180 (void)*reinterpret_cast<A2*>(&b2);181 (void)reinterpret_cast<B2&>(a2);182 (void)*reinterpret_cast<B2*>(&a2);183 184 // Casting to itself is allowed185 (void)reinterpret_cast<A&>(a);186 (void)*reinterpret_cast<A*>(&a);187 (void)reinterpret_cast<B&>(b);188 (void)*reinterpret_cast<B*>(&b);189 (void)reinterpret_cast<long&>(l);190 (void)*reinterpret_cast<long*>(&l);191 (void)reinterpret_cast<double&>(d);192 (void)*reinterpret_cast<double*>(&d);193 (void)reinterpret_cast<char&>(c);194 (void)*reinterpret_cast<char*>(&c);195 196 // Casting to and from chars are allowable197 (void)reinterpret_cast<A&>(c);198 (void)*reinterpret_cast<A*>(&c);199 (void)reinterpret_cast<B&>(c);200 (void)*reinterpret_cast<B*>(&c);201 (void)reinterpret_cast<long&>(c);202 (void)*reinterpret_cast<long*>(&c);203 (void)reinterpret_cast<double&>(c);204 (void)*reinterpret_cast<double*>(&c);205 (void)reinterpret_cast<char&>(l);206 (void)*reinterpret_cast<char*>(&l);207 (void)reinterpret_cast<char&>(d);208 (void)*reinterpret_cast<char*>(&d);209 (void)reinterpret_cast<char&>(f);210 (void)*reinterpret_cast<char*>(&f);211 212 // Casting from void pointer.213 (void)*reinterpret_cast<A*>(v_ptr);214 (void)*reinterpret_cast<B*>(v_ptr);215 (void)*reinterpret_cast<long*>(v_ptr);216 (void)*reinterpret_cast<double*>(v_ptr);217 (void)*reinterpret_cast<float*>(v_ptr);218 219 // Casting to void pointer220 (void)*reinterpret_cast<void*>(&a); // expected-error {{indirection not permitted on operand of type 'void *'}}221 (void)*reinterpret_cast<void*>(&b); // expected-error {{indirection not permitted on operand of type 'void *'}}222 (void)*reinterpret_cast<void*>(&l); // expected-error {{indirection not permitted on operand of type 'void *'}}223 (void)*reinterpret_cast<void*>(&d); // expected-error {{indirection not permitted on operand of type 'void *'}}224 (void)*reinterpret_cast<void*>(&f); // expected-error {{indirection not permitted on operand of type 'void *'}}225}226 227void reinterpret_cast_allowlist () {228 // the dynamic type of the object229 int a;230 float b;231 (void)reinterpret_cast<int&>(a);232 (void)*reinterpret_cast<int*>(&a);233 (void)reinterpret_cast<float&>(b);234 (void)*reinterpret_cast<float*>(&b);235 236 // a cv-qualified version of the dynamic object237 (void)reinterpret_cast<const int&>(a);238 (void)*reinterpret_cast<const int*>(&a);239 (void)reinterpret_cast<volatile int&>(a);240 (void)*reinterpret_cast<volatile int*>(&a);241 (void)reinterpret_cast<const volatile int&>(a);242 (void)*reinterpret_cast<const volatile int*>(&a);243 (void)reinterpret_cast<const float&>(b);244 (void)*reinterpret_cast<const float*>(&b);245 (void)reinterpret_cast<volatile float&>(b);246 (void)*reinterpret_cast<volatile float*>(&b);247 (void)reinterpret_cast<const volatile float&>(b);248 (void)*reinterpret_cast<const volatile float*>(&b);249 250 // a type that is the signed or unsigned type corresponding to the dynamic251 // type of the object252 signed d;253 unsigned e;254 (void)reinterpret_cast<signed&>(d);255 (void)*reinterpret_cast<signed*>(&d);256 (void)reinterpret_cast<signed&>(e);257 (void)*reinterpret_cast<signed*>(&e);258 (void)reinterpret_cast<unsigned&>(d);259 (void)*reinterpret_cast<unsigned*>(&d);260 (void)reinterpret_cast<unsigned&>(e);261 (void)*reinterpret_cast<unsigned*>(&e);262 263 // a type that is the signed or unsigned type corresponding a cv-qualified264 // version of the dynamic type the object265 (void)reinterpret_cast<const signed&>(d);266 (void)*reinterpret_cast<const signed*>(&d);267 (void)reinterpret_cast<const signed&>(e);268 (void)*reinterpret_cast<const signed*>(&e);269 (void)reinterpret_cast<const unsigned&>(d);270 (void)*reinterpret_cast<const unsigned*>(&d);271 (void)reinterpret_cast<const unsigned&>(e);272 (void)*reinterpret_cast<const unsigned*>(&e);273 (void)reinterpret_cast<volatile signed&>(d);274 (void)*reinterpret_cast<volatile signed*>(&d);275 (void)reinterpret_cast<volatile signed&>(e);276 (void)*reinterpret_cast<volatile signed*>(&e);277 (void)reinterpret_cast<volatile unsigned&>(d);278 (void)*reinterpret_cast<volatile unsigned*>(&d);279 (void)reinterpret_cast<volatile unsigned&>(e);280 (void)*reinterpret_cast<volatile unsigned*>(&e);281 (void)reinterpret_cast<const volatile signed&>(d);282 (void)*reinterpret_cast<const volatile signed*>(&d);283 (void)reinterpret_cast<const volatile signed&>(e);284 (void)*reinterpret_cast<const volatile signed*>(&e);285 (void)reinterpret_cast<const volatile unsigned&>(d);286 (void)*reinterpret_cast<const volatile unsigned*>(&d);287 (void)reinterpret_cast<const volatile unsigned&>(e);288 (void)*reinterpret_cast<const volatile unsigned*>(&e);289 290 // an aggregate or union type that includes one of the aforementioned types291 // among its members (including, recursively, a member of a subaggregate or292 // contained union)293 // TODO: checking is not implemented for tag types294 295 // a type that is a (possible cv-qualified) base class type of the dynamic296 // type of the object297 // TODO: checking is not implemented for tag types298 299 // a char or unsigned char type300 (void)reinterpret_cast<char&>(a);301 (void)*reinterpret_cast<char*>(&a);302 (void)reinterpret_cast<unsigned char&>(a);303 (void)*reinterpret_cast<unsigned char*>(&a);304 (void)reinterpret_cast<char&>(b);305 (void)*reinterpret_cast<char*>(&b);306 (void)reinterpret_cast<unsigned char&>(b);307 (void)*reinterpret_cast<unsigned char*>(&b);308}309 310namespace templated {311template <typename TARGETTYPE, typename UATYPE>312void cast_uninstantiated() {313 const UATYPE* data;314 (void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning315}316 317 318template <typename TARGETTYPE, typename UATYPE>319void cast_instantiated_badly() {320 const UATYPE* data;321 (void)*reinterpret_cast<const TARGETTYPE*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}322}323 324template <typename TARGETTYPE, typename UATYPE>325void cast_instantiated_well() {326 const UATYPE* data;327 (void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning328}329 330template <typename TARGETTYPE>331void cast_one_tmpl_arg_uninstantiated() {332 const int* data;333 (void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning334}335 336template <typename TARGETTYPE>337void cast_one_tmpl_arg_instantiated_badly() {338 const float* data;339 (void)*reinterpret_cast<const TARGETTYPE*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}340}341 342template <typename TARGETTYPE>343void cast_one_tmpl_arg_instantiated_well() {344 const float* data;345 (void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning346}347 348template <int size>349void cast_nontype_template_true_positive_noninstantiated() {350 const float *data;351 const int arr[size];352 (void)*reinterpret_cast<const int*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}353}354 355template <int size>356void cast_nontype_template_true_negative_noninstantiated() {357 const int data[size];358 (void)*reinterpret_cast<const int*>(data); // no warning359}360 361void top() {362 cast_instantiated_badly<int, float>();363 // expected-note@-1 {{in instantiation of function template specialization 'templated::cast_instantiated_badly<int, float>' requested here}}364 cast_instantiated_well<int, int>();365 cast_one_tmpl_arg_instantiated_badly<int>();366 // expected-note@-1 {{in instantiation of function template specialization 'templated::cast_one_tmpl_arg_instantiated_badly<int>' requested here}}367 cast_one_tmpl_arg_instantiated_well<float>();368}369 370template<typename T, typename U>371void cast_template_dependent_type_noninstantiated(T** x)372{373 (void)*reinterpret_cast<U**>(x);374}375 376template<typename T, typename U>377void cast_template_dependent_member_type_noninstantiated(typename T::X x)378{379 (void)*reinterpret_cast<typename U::Y>(x);380}381 382} // namespace templated383