Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s
      2 // RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify %s
      3 //
      4 // This file should also give no diagnostics when run through cl.exe from MSVS
      5 // 2012, which supports C++11 and static_assert.  It should pass for both 64-bit
      6 // and 32-bit x86.
      7 //
      8 // Test the size of various member pointer combinations:
      9 // - complete and incomplete
     10 // - single, multiple, and virtual inheritance (and unspecified for incomplete)
     11 // - data and function pointers
     12 // - templated with declared specializations with annotations
     13 // - template that can be instantiated
     14 
     15 // http://llvm.org/PR12070
     16 struct Foo {
     17   typedef int Foo::*FooInt;
     18   int f;
     19 };
     20 
     21 enum {
     22   kSingleDataSize             = 1 * sizeof(int),
     23   kSingleFunctionSize         = 1 * sizeof(void *),
     24   kMultipleDataSize           = 1 * sizeof(int),
     25   kMultipleFunctionSize       = 2 * sizeof(void *),
     26   kVirtualDataSize            = 2 * sizeof(int),
     27   kVirtualFunctionSize        = 2 * sizeof(int) + 1 * sizeof(void *),
     28   // Unspecified is weird, it's 1 more slot than virtual.
     29   kUnspecifiedDataSize        = kVirtualDataSize + 1 * sizeof(int),
     30   kUnspecifiedFunctionSize    = kVirtualFunctionSize + 1 * sizeof(void *),
     31 };
     32 
     33 // incomplete types
     34 class __single_inheritance IncSingle;
     35 class __multiple_inheritance IncMultiple;
     36 class __virtual_inheritance IncVirtual;
     37 static_assert(sizeof(int IncSingle::*)        == kSingleDataSize, "");
     38 static_assert(sizeof(int IncMultiple::*)      == kMultipleDataSize, "");
     39 static_assert(sizeof(int IncVirtual::*)       == kVirtualDataSize, "");
     40 static_assert(sizeof(void (IncSingle::*)())   == kSingleFunctionSize, "");
     41 static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, "");
     42 static_assert(sizeof(void (IncVirtual::*)())  == kVirtualFunctionSize, "");
     43 
     44 // An incomplete type with an unspecified inheritance model seems to take one
     45 // more slot than virtual.  It's not clear what it's used for yet.
     46 class IncUnspecified;
     47 static_assert(sizeof(int IncUnspecified::*) == kUnspecifiedDataSize, "");
     48 static_assert(sizeof(void (IncUnspecified::*)()) == kUnspecifiedFunctionSize, "");
     49 
     50 // complete types
     51 struct B1 { };
     52 struct B2 { };
     53 struct Single { };
     54 struct Multiple : B1, B2 { };
     55 struct Virtual : virtual B1 { };
     56 static_assert(sizeof(int Single::*)        == kSingleDataSize, "");
     57 static_assert(sizeof(int Multiple::*)      == kMultipleDataSize, "");
     58 static_assert(sizeof(int Virtual::*)       == kVirtualDataSize, "");
     59 static_assert(sizeof(void (Single::*)())   == kSingleFunctionSize, "");
     60 static_assert(sizeof(void (Multiple::*)()) == kMultipleFunctionSize, "");
     61 static_assert(sizeof(void (Virtual::*)())  == kVirtualFunctionSize, "");
     62 
     63 // Test both declared and defined templates.
     64 template <typename T> class X;
     65 template <> class __single_inheritance   X<IncSingle>;
     66 template <> class __multiple_inheritance X<IncMultiple>;
     67 template <> class __virtual_inheritance  X<IncVirtual>;
     68 // Don't declare X<IncUnspecified>.
     69 static_assert(sizeof(int X<IncSingle>::*)           == kSingleDataSize, "");
     70 static_assert(sizeof(int X<IncMultiple>::*)         == kMultipleDataSize, "");
     71 static_assert(sizeof(int X<IncVirtual>::*)          == kVirtualDataSize, "");
     72 static_assert(sizeof(int X<IncUnspecified>::*)      == kUnspecifiedDataSize, "");
     73 static_assert(sizeof(void (X<IncSingle>::*)())      == kSingleFunctionSize, "");
     74 static_assert(sizeof(void (X<IncMultiple>::*)())    == kMultipleFunctionSize, "");
     75 static_assert(sizeof(void (X<IncVirtual>::*)())     == kVirtualFunctionSize, "");
     76 static_assert(sizeof(void (X<IncUnspecified>::*)()) == kUnspecifiedFunctionSize, "");
     77 
     78 template <typename T>
     79 struct Y : T { };
     80 static_assert(sizeof(int Y<Single>::*)        == kSingleDataSize, "");
     81 static_assert(sizeof(int Y<Multiple>::*)      == kMultipleDataSize, "");
     82 static_assert(sizeof(int Y<Virtual>::*)       == kVirtualDataSize, "");
     83 static_assert(sizeof(void (Y<Single>::*)())   == kSingleFunctionSize, "");
     84 static_assert(sizeof(void (Y<Multiple>::*)()) == kMultipleFunctionSize, "");
     85 static_assert(sizeof(void (Y<Virtual>::*)())  == kVirtualFunctionSize, "");
     86 
     87 struct A { int x; void bar(); };
     88 struct B : A { virtual void foo(); };
     89 static_assert(sizeof(int B::*) == kSingleDataSize, "");
     90 // A non-primary base class uses the multiple inheritance model for member
     91 // pointers.
     92 static_assert(sizeof(void (B::*)()) == kMultipleFunctionSize, "");
     93 
     94 struct AA { int x; virtual void foo(); };
     95 struct BB : AA { void bar(); };
     96 struct CC : BB { virtual void baz(); };
     97 static_assert(sizeof(void (CC::*)()) == kSingleFunctionSize, "");
     98 
     99 // We start out unspecified.
    100 struct ForwardDecl1;
    101 struct ForwardDecl2;
    102 
    103 // Re-declare to force us to iterate decls when adding attributes.
    104 struct ForwardDecl1;
    105 struct ForwardDecl2;
    106 
    107 typedef int ForwardDecl1::*MemPtr1;
    108 typedef int ForwardDecl2::*MemPtr2;
    109 MemPtr1 variable_forces_sizing;
    110 
    111 struct ForwardDecl1 : B {
    112   virtual void foo();
    113 };
    114 struct ForwardDecl2 : B {
    115   virtual void foo();
    116 };
    117 
    118 static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, "");
    119 static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, "");
    120 // FIXME: Clang fails this assert because it locks in the inheritance model at
    121 // the point of the typedef instead of the first usage, while MSVC does not.
    122 //static_assert(sizeof(MemPtr2) == kSingleDataSize, "");
    123 
    124 struct MemPtrInBody {
    125   typedef int MemPtrInBody::*MemPtr;
    126   int a;
    127   operator MemPtr() const {
    128     return a ? &MemPtrInBody::a : 0;
    129   }
    130 };
    131 
    132 static_assert(sizeof(MemPtrInBody::MemPtr) == kSingleDataSize, "");
    133 
    134 // Passing a member pointer through a template should get the right size.
    135 template<typename T>
    136 struct SingleTemplate;
    137 template<typename T>
    138 struct SingleTemplate<void (T::*)(void)> {
    139   static_assert(sizeof(int T::*) == kSingleDataSize, "");
    140   static_assert(sizeof(void (T::*)()) == kSingleFunctionSize, "");
    141 };
    142 
    143 template<typename T>
    144 struct UnspecTemplate;
    145 template<typename T>
    146 struct UnspecTemplate<void (T::*)(void)> {
    147   static_assert(sizeof(int T::*) == kUnspecifiedDataSize, "");
    148   static_assert(sizeof(void (T::*)()) == kUnspecifiedFunctionSize, "");
    149 };
    150 
    151 struct NewUnspecified;
    152 SingleTemplate<void (IncSingle::*)()> tmpl_single;
    153 UnspecTemplate<void (NewUnspecified::*)()> tmpl_unspec;
    154 
    155 struct NewUnspecified { };
    156 
    157 static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, "");
    158 
    159 template <typename T>
    160 struct MemPtrInTemplate {
    161   // We can't require that the template arg be complete until we're
    162   // instantiated.
    163   int T::*data_ptr;
    164   void (T::*func_ptr)();
    165 };
    166 
    167 int Virtual::*CastTest = reinterpret_cast<int Virtual::*>(&AA::x);
    168   // expected-error@-1 {{cannot reinterpret_cast from member pointer type}}
    169