brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.6 KiB · 10b2ed1 Raw
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