|  | // RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify -DVMB %s | 
|  | // RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMB %s | 
|  | // RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMV -fms-memptr-rep=virtual %s | 
|  | // | 
|  | // This file should also give no diagnostics when run through cl.exe from MSVS | 
|  | // 2012, which supports C++11 and static_assert.  It should pass for both 64-bit | 
|  | // and 32-bit x86. | 
|  | // | 
|  | // Test the size of various member pointer combinations: | 
|  | // - complete and incomplete | 
|  | // - single, multiple, and virtual inheritance (and unspecified for incomplete) | 
|  | // - data and function pointers | 
|  | // - templated with declared specializations with annotations | 
|  | // - template that can be instantiated | 
|  |  | 
|  | // http://llvm.org/PR12070 | 
|  | struct Foo { | 
|  | typedef int Foo::*FooInt; | 
|  | int f; | 
|  | }; | 
|  |  | 
|  | #ifdef VMB | 
|  | enum { | 
|  | kSingleDataAlign             = 1 * sizeof(int), | 
|  | kSingleFunctionAlign         = 1 * sizeof(void *), | 
|  | kMultipleDataAlign           = 1 * sizeof(int), | 
|  | // Everything with more than 1 field is 8 byte aligned, except virtual data | 
|  | // member pointers on x64 (ugh). | 
|  | kMultipleFunctionAlign       = 8, | 
|  | #ifdef _M_X64 | 
|  | kVirtualDataAlign            = 4, | 
|  | #else | 
|  | kVirtualDataAlign            = 8, | 
|  | #endif | 
|  | kVirtualFunctionAlign        = 8, | 
|  | kUnspecifiedDataAlign        = 8, | 
|  | kUnspecifiedFunctionAlign    = 8, | 
|  |  | 
|  | kSingleDataSize             = 1 * sizeof(int), | 
|  | kSingleFunctionSize         = 1 * sizeof(void *), | 
|  | kMultipleDataSize           = 1 * sizeof(int), | 
|  | kMultipleFunctionSize       = 2 * sizeof(void *), | 
|  | kVirtualDataSize            = 2 * sizeof(int), | 
|  | kVirtualFunctionSize        = 2 * sizeof(int) + 1 * sizeof(void *), | 
|  | kUnspecifiedDataSize        = 3 * sizeof(int), | 
|  | kUnspecifiedFunctionSize    = 2 * sizeof(int) + 2 * sizeof(void *), | 
|  | }; | 
|  | #elif VMV | 
|  | enum { | 
|  | // Everything with more than 1 field is 8 byte aligned, except virtual data | 
|  | // member pointers on x64 (ugh). | 
|  | #ifdef _M_X64 | 
|  | kVirtualDataAlign = 4, | 
|  | #else | 
|  | kVirtualDataAlign = 8, | 
|  | #endif | 
|  | kMultipleDataAlign = kVirtualDataAlign, | 
|  | kSingleDataAlign = kVirtualDataAlign, | 
|  |  | 
|  | kUnspecifiedFunctionAlign = 8, | 
|  | kVirtualFunctionAlign = kUnspecifiedFunctionAlign, | 
|  | kMultipleFunctionAlign = kUnspecifiedFunctionAlign, | 
|  | kSingleFunctionAlign = kUnspecifiedFunctionAlign, | 
|  |  | 
|  | kUnspecifiedDataSize = 3 * sizeof(int), | 
|  | kVirtualDataSize = kUnspecifiedDataSize, | 
|  | kMultipleDataSize = kUnspecifiedDataSize, | 
|  | kSingleDataSize = kUnspecifiedDataSize, | 
|  |  | 
|  | kUnspecifiedFunctionSize = 2 * sizeof(int) + 2 * sizeof(void *), | 
|  | kVirtualFunctionSize = kUnspecifiedFunctionSize, | 
|  | kMultipleFunctionSize = kUnspecifiedFunctionSize, | 
|  | kSingleFunctionSize = kUnspecifiedFunctionSize, | 
|  | }; | 
|  | #else | 
|  | #error "test doesn't yet support this mode!" | 
|  | #endif | 
|  |  | 
|  | // incomplete types | 
|  | #ifdef VMB | 
|  | class __single_inheritance IncSingle; | 
|  | class __multiple_inheritance IncMultiple; | 
|  | class __virtual_inheritance IncVirtual; | 
|  | #else | 
|  | class IncSingle; | 
|  | class IncMultiple; | 
|  | class IncVirtual; | 
|  | #endif | 
|  | static_assert(sizeof(int IncSingle::*)        == kSingleDataSize, ""); | 
|  | static_assert(sizeof(int IncMultiple::*)      == kMultipleDataSize, ""); | 
|  | static_assert(sizeof(int IncVirtual::*)       == kVirtualDataSize, ""); | 
|  | static_assert(sizeof(void (IncSingle::*)())   == kSingleFunctionSize, ""); | 
|  | static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, ""); | 
|  | static_assert(sizeof(void (IncVirtual::*)())  == kVirtualFunctionSize, ""); | 
|  |  | 
|  | static_assert(__alignof(int IncSingle::*)        == __alignof(void *), ""); | 
|  | static_assert(__alignof(int IncMultiple::*)      == __alignof(void *), ""); | 
|  | static_assert(__alignof(int IncVirtual::*)       == __alignof(void *), ""); | 
|  | static_assert(__alignof(void (IncSingle::*)())   == __alignof(void *), ""); | 
|  | static_assert(__alignof(void (IncMultiple::*)()) == __alignof(void *), ""); | 
|  | static_assert(__alignof(void (IncVirtual::*)())  == __alignof(void *), ""); | 
|  |  | 
|  | // An incomplete type with an unspecified inheritance model seems to take one | 
|  | // more slot than virtual. | 
|  | class IncUnspecified; | 
|  | static_assert(sizeof(int IncUnspecified::*) == kUnspecifiedDataSize, ""); | 
|  | static_assert(sizeof(void (IncUnspecified::*)()) == kUnspecifiedFunctionSize, ""); | 
|  |  | 
|  | // complete types | 
|  | struct B1 { }; | 
|  | struct B2 { }; | 
|  | struct Single { }; | 
|  | struct Multiple : B1, B2 { }; | 
|  | struct Virtual : virtual B1 { }; | 
|  | static_assert(sizeof(int Single::*)        == kSingleDataSize, ""); | 
|  | static_assert(sizeof(int Multiple::*)      == kMultipleDataSize, ""); | 
|  | static_assert(sizeof(int Virtual::*)       == kVirtualDataSize, ""); | 
|  | static_assert(sizeof(void (Single::*)())   == kSingleFunctionSize, ""); | 
|  | static_assert(sizeof(void (Multiple::*)()) == kMultipleFunctionSize, ""); | 
|  | static_assert(sizeof(void (Virtual::*)())  == kVirtualFunctionSize, ""); | 
|  |  | 
|  | // Test both declared and defined templates. | 
|  | template <typename T> class X; | 
|  | #ifdef VMB | 
|  | template <> class __single_inheritance   X<IncSingle>; | 
|  | template <> class __multiple_inheritance X<IncMultiple>; | 
|  | template <> class __virtual_inheritance  X<IncVirtual>; | 
|  | #else | 
|  | template <> class X<IncSingle>; | 
|  | template <> class X<IncMultiple>; | 
|  | template <> class X<IncVirtual>; | 
|  | #endif | 
|  | // Don't declare X<IncUnspecified>. | 
|  | static_assert(sizeof(int X<IncSingle>::*)           == kSingleDataSize, ""); | 
|  | static_assert(sizeof(int X<IncMultiple>::*)         == kMultipleDataSize, ""); | 
|  | static_assert(sizeof(int X<IncVirtual>::*)          == kVirtualDataSize, ""); | 
|  | static_assert(sizeof(int X<IncUnspecified>::*)      == kUnspecifiedDataSize, ""); | 
|  | static_assert(sizeof(void (X<IncSingle>::*)())      == kSingleFunctionSize, ""); | 
|  | static_assert(sizeof(void (X<IncMultiple>::*)())    == kMultipleFunctionSize, ""); | 
|  | static_assert(sizeof(void (X<IncVirtual>::*)())     == kVirtualFunctionSize, ""); | 
|  | static_assert(sizeof(void (X<IncUnspecified>::*)()) == kUnspecifiedFunctionSize, ""); | 
|  |  | 
|  | template <typename T> | 
|  | struct Y : T { }; | 
|  | static_assert(sizeof(int Y<Single>::*)        == kSingleDataSize, ""); | 
|  | static_assert(sizeof(int Y<Multiple>::*)      == kMultipleDataSize, ""); | 
|  | static_assert(sizeof(int Y<Virtual>::*)       == kVirtualDataSize, ""); | 
|  | static_assert(sizeof(void (Y<Single>::*)())   == kSingleFunctionSize, ""); | 
|  | static_assert(sizeof(void (Y<Multiple>::*)()) == kMultipleFunctionSize, ""); | 
|  | static_assert(sizeof(void (Y<Virtual>::*)())  == kVirtualFunctionSize, ""); | 
|  |  | 
|  | struct A { int x; void bar(); }; | 
|  | struct B : A { virtual void foo(); }; | 
|  | static_assert(sizeof(int B::*) == kSingleDataSize, ""); | 
|  | // A non-primary base class uses the multiple inheritance model for member | 
|  | // pointers. | 
|  | static_assert(sizeof(void (B::*)()) == kMultipleFunctionSize, ""); | 
|  |  | 
|  | struct AA { int x; virtual void foo(); }; | 
|  | struct BB : AA { void bar(); }; | 
|  | struct CC : BB { virtual void baz(); }; | 
|  | static_assert(sizeof(void (CC::*)()) == kSingleFunctionSize, ""); | 
|  |  | 
|  | // We start out unspecified. | 
|  | struct ForwardDecl1; | 
|  | struct ForwardDecl2; | 
|  |  | 
|  | // Re-declare to force us to iterate decls when adding attributes. | 
|  | struct ForwardDecl1; | 
|  | struct ForwardDecl2; | 
|  |  | 
|  | typedef int ForwardDecl1::*MemPtr1; | 
|  | typedef int ForwardDecl2::*MemPtr2; | 
|  | MemPtr1 variable_forces_sizing; | 
|  |  | 
|  | struct ForwardDecl1 : B { | 
|  | virtual void foo(); | 
|  | }; | 
|  | struct ForwardDecl2 : B { | 
|  | virtual void foo(); | 
|  | }; | 
|  |  | 
|  | static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, ""); | 
|  | static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, ""); | 
|  | static_assert(sizeof(MemPtr2) == kSingleDataSize, ""); | 
|  |  | 
|  | struct MemPtrInBody { | 
|  | typedef int MemPtrInBody::*MemPtr; | 
|  | int a; | 
|  | operator MemPtr() const { | 
|  | return a ? &MemPtrInBody::a : 0; | 
|  | } | 
|  | }; | 
|  |  | 
|  | static_assert(sizeof(MemPtrInBody::MemPtr) == kSingleDataSize, ""); | 
|  |  | 
|  | // Passing a member pointer through a template should get the right size. | 
|  | template<typename T> | 
|  | struct SingleTemplate; | 
|  | template<typename T> | 
|  | struct SingleTemplate<void (T::*)(void)> { | 
|  | static_assert(sizeof(int T::*) == kSingleDataSize, ""); | 
|  | static_assert(sizeof(void (T::*)()) == kSingleFunctionSize, ""); | 
|  | }; | 
|  |  | 
|  | template<typename T> | 
|  | struct UnspecTemplate; | 
|  | template<typename T> | 
|  | struct UnspecTemplate<void (T::*)(void)> { | 
|  | static_assert(sizeof(int T::*) == kUnspecifiedDataSize, ""); | 
|  | static_assert(sizeof(void (T::*)()) == kUnspecifiedFunctionSize, ""); | 
|  | }; | 
|  |  | 
|  | struct NewUnspecified; | 
|  | SingleTemplate<void (IncSingle::*)()> tmpl_single; | 
|  | UnspecTemplate<void (NewUnspecified::*)()> tmpl_unspec; | 
|  |  | 
|  | struct NewUnspecified { }; | 
|  |  | 
|  | static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, ""); | 
|  |  | 
|  | template <typename T> | 
|  | struct MemPtrInTemplate { | 
|  | // We can't require that the template arg be complete until we're | 
|  | // instantiated. | 
|  | int T::*data_ptr; | 
|  | void (T::*func_ptr)(); | 
|  | }; | 
|  |  | 
|  | #ifdef VMB | 
|  | int Virtual::*CastTest = reinterpret_cast<int Virtual::*>(&AA::x); | 
|  | // expected-error@-1 {{cannot reinterpret_cast from member pointer type}} | 
|  | #endif | 
|  |  | 
|  | namespace ErrorTest { | 
|  | template <typename T, typename U> struct __single_inheritance A; | 
|  | // expected-warning@-1 {{inheritance model ignored on primary template}} | 
|  | template <typename T> struct __multiple_inheritance A<T, T>; | 
|  | // expected-warning@-1 {{inheritance model ignored on partial specialization}} | 
|  | template <> struct __single_inheritance A<int, float>; | 
|  |  | 
|  | struct B {}; // expected-note {{'B' defined here}} | 
|  | struct __multiple_inheritance B; // expected-error{{inheritance model does not match definition}} | 
|  |  | 
|  | struct __multiple_inheritance C {}; // expected-error{{inheritance model does not match definition}} | 
|  | // expected-note@-1 {{'C' defined here}} | 
|  |  | 
|  | struct __virtual_inheritance D; | 
|  | struct D : virtual B {}; | 
|  | } | 
|  | #ifdef VMB | 
|  |  | 
|  | namespace PR20017 { | 
|  | template <typename T> | 
|  | struct A { | 
|  | int T::*f(); | 
|  | }; | 
|  |  | 
|  | struct B; | 
|  |  | 
|  | auto a = &A<B>::f; | 
|  |  | 
|  | struct B {}; | 
|  |  | 
|  | void q() { | 
|  | A<B> b; | 
|  | (b.*a)(); | 
|  | } | 
|  | } | 
|  |  | 
|  | #pragma pointers_to_members(full_generality, multiple_inheritance) | 
|  | struct TrulySingleInheritance; | 
|  | static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, ""); | 
|  | #pragma pointers_to_members(best_case) | 
|  | // This definition shouldn't conflict with the increased generality that the | 
|  | // multiple_inheritance model gave to TrulySingleInheritance. | 
|  | struct TrulySingleInheritance {}; | 
|  |  | 
|  | // Even if a definition proceeds the first mention of a pointer to member, we | 
|  | // still give the record the fully general representation. | 
|  | #pragma pointers_to_members(full_generality, virtual_inheritance) | 
|  | struct SingleInheritanceAsVirtualAfterPragma {}; | 
|  | static_assert(sizeof(int SingleInheritanceAsVirtualAfterPragma::*) == 12, ""); | 
|  |  | 
|  | #pragma pointers_to_members(best_case) | 
|  |  | 
|  | // The above holds even if the pragma comes after the definition. | 
|  | struct SingleInheritanceAsVirtualBeforePragma {}; | 
|  | #pragma pointers_to_members(virtual_inheritance) | 
|  | static_assert(sizeof(int SingleInheritanceAsVirtualBeforePragma::*) == 12, ""); | 
|  |  | 
|  | #pragma pointers_to_members(single) // expected-error{{unexpected 'single'}} | 
|  | #endif | 
|  |  | 
|  | namespace merging { | 
|  | struct __single_inheritance S; | 
|  | struct __single_inheritance S; | 
|  |  | 
|  | struct __single_inheritance M; // expected-note{{previous inheritance model specified here}} | 
|  | struct __multiple_inheritance M; // expected-error{{inheritance model does not match previous declaration}} | 
|  | } |