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