Home | History | Annotate | Download | only in SemaCXX
      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 {{not allowed}}
    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