diff options
Diffstat (limited to 'test/SemaCXX/member-pointer-ms.cpp')
-rw-r--r-- | test/SemaCXX/member-pointer-ms.cpp | 122 |
1 files changed, 114 insertions, 8 deletions
diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp index aee8e2e..e7c4ae9 100644 --- a/test/SemaCXX/member-pointer-ms.cpp +++ b/test/SemaCXX/member-pointer-ms.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s -// RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify %s +// 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 @@ -18,22 +19,73 @@ struct Foo { 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 *), - // Unspecified is weird, it's 1 more slot than virtual. - kUnspecifiedDataSize = kVirtualDataSize + 1 * sizeof(int), - kUnspecifiedFunctionSize = kVirtualFunctionSize + 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, ""); @@ -41,6 +93,13 @@ static_assert(sizeof(void (IncSingle::*)()) == kSingleFunctionSize, ""); static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, ""); static_assert(sizeof(void (IncVirtual::*)()) == kVirtualFunctionSize, ""); +static_assert(__alignof(int IncSingle::*) == kSingleDataAlign, ""); +static_assert(__alignof(int IncMultiple::*) == kMultipleDataAlign, ""); +static_assert(__alignof(int IncVirtual::*) == kVirtualDataAlign, ""); +static_assert(__alignof(void (IncSingle::*)()) == kSingleFunctionAlign, ""); +static_assert(__alignof(void (IncMultiple::*)()) == kMultipleFunctionAlign, ""); +static_assert(__alignof(void (IncVirtual::*)()) == kVirtualFunctionAlign, ""); + // An incomplete type with an unspecified inheritance model seems to take one // more slot than virtual. It's not clear what it's used for yet. class IncUnspecified; @@ -62,9 +121,15 @@ 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, ""); @@ -117,9 +182,7 @@ struct ForwardDecl2 : B { static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, ""); static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, ""); -// FIXME: Clang fails this assert because it locks in the inheritance model at -// the point of the typedef instead of the first usage, while MSVC does not. -//static_assert(sizeof(MemPtr2) == kSingleDataSize, ""); +static_assert(sizeof(MemPtr2) == kSingleDataSize, ""); struct MemPtrInBody { typedef int MemPtrInBody::*MemPtr; @@ -164,5 +227,48 @@ struct MemPtrInTemplate { 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 +#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 |