302 lines · cpp
1// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify -DVMB %s2// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMB %s3// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMV -fms-memptr-rep=virtual %s4//5// This file should also give no diagnostics when run through cl.exe from MSVS6// 2012, which supports C++11 and static_assert. It should pass for both 64-bit7// and 32-bit x86.8//9// Test the size of various member pointer combinations:10// - complete and incomplete11// - single, multiple, and virtual inheritance (and unspecified for incomplete)12// - data and function pointers13// - templated with declared specializations with annotations14// - template that can be instantiated15 16// http://llvm.org/PR1207017struct Foo {18 typedef int Foo::*FooInt;19 int f;20};21 22#ifdef VMB23enum {24 kSingleDataAlign = 1 * sizeof(int),25 kSingleFunctionAlign = 1 * sizeof(void *),26 kMultipleDataAlign = 1 * sizeof(int),27 // Everything with more than 1 field is 8 byte aligned, except virtual data28 // member pointers on x64 (ugh).29 kMultipleFunctionAlign = 8,30#ifdef _M_X6431 kVirtualDataAlign = 4,32#else33 kVirtualDataAlign = 8,34#endif35 kVirtualFunctionAlign = 8,36 kUnspecifiedDataAlign = 8,37 kUnspecifiedFunctionAlign = 8,38 39 kSingleDataSize = 1 * sizeof(int),40 kSingleFunctionSize = 1 * sizeof(void *),41 kMultipleDataSize = 1 * sizeof(int),42 kMultipleFunctionSize = 2 * sizeof(void *),43 kVirtualDataSize = 2 * sizeof(int),44 kVirtualFunctionSize = 2 * sizeof(int) + 1 * sizeof(void *),45 kUnspecifiedDataSize = 3 * sizeof(int),46 kUnspecifiedFunctionSize = 2 * sizeof(int) + 2 * sizeof(void *),47};48#elif VMV49enum {50 // Everything with more than 1 field is 8 byte aligned, except virtual data51 // member pointers on x64 (ugh).52#ifdef _M_X6453 kVirtualDataAlign = 4,54#else55 kVirtualDataAlign = 8,56#endif57 kMultipleDataAlign = kVirtualDataAlign,58 kSingleDataAlign = kVirtualDataAlign,59 60 kUnspecifiedFunctionAlign = 8,61 kVirtualFunctionAlign = kUnspecifiedFunctionAlign,62 kMultipleFunctionAlign = kUnspecifiedFunctionAlign,63 kSingleFunctionAlign = kUnspecifiedFunctionAlign,64 65 kUnspecifiedDataSize = 3 * sizeof(int),66 kVirtualDataSize = kUnspecifiedDataSize,67 kMultipleDataSize = kUnspecifiedDataSize,68 kSingleDataSize = kUnspecifiedDataSize,69 70 kUnspecifiedFunctionSize = 2 * sizeof(int) + 2 * sizeof(void *),71 kVirtualFunctionSize = kUnspecifiedFunctionSize,72 kMultipleFunctionSize = kUnspecifiedFunctionSize,73 kSingleFunctionSize = kUnspecifiedFunctionSize,74};75#else76#error "test doesn't yet support this mode!"77#endif78 79// incomplete types80#ifdef VMB81class __single_inheritance IncSingle;82class __multiple_inheritance IncMultiple;83class __virtual_inheritance IncVirtual;84#else85class IncSingle;86class IncMultiple;87class IncVirtual;88#endif89static_assert(sizeof(int IncSingle::*) == kSingleDataSize, "");90static_assert(sizeof(int IncMultiple::*) == kMultipleDataSize, "");91static_assert(sizeof(int IncVirtual::*) == kVirtualDataSize, "");92static_assert(sizeof(void (IncSingle::*)()) == kSingleFunctionSize, "");93static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, "");94static_assert(sizeof(void (IncVirtual::*)()) == kVirtualFunctionSize, "");95 96static_assert(__alignof(int IncSingle::*) == __alignof(void *), "");97static_assert(__alignof(int IncMultiple::*) == __alignof(void *), "");98static_assert(__alignof(int IncVirtual::*) == __alignof(void *), "");99static_assert(__alignof(void (IncSingle::*)()) == __alignof(void *), "");100static_assert(__alignof(void (IncMultiple::*)()) == __alignof(void *), "");101static_assert(__alignof(void (IncVirtual::*)()) == __alignof(void *), "");102 103// An incomplete type with an unspecified inheritance model seems to take one104// more slot than virtual.105class IncUnspecified;106static_assert(sizeof(int IncUnspecified::*) == kUnspecifiedDataSize, "");107static_assert(sizeof(void (IncUnspecified::*)()) == kUnspecifiedFunctionSize, "");108 109// complete types110struct B1 { };111struct B2 { };112struct Single { };113struct Multiple : B1, B2 { };114struct Virtual : virtual B1 { };115static_assert(sizeof(int Single::*) == kSingleDataSize, "");116static_assert(sizeof(int Multiple::*) == kMultipleDataSize, "");117static_assert(sizeof(int Virtual::*) == kVirtualDataSize, "");118static_assert(sizeof(void (Single::*)()) == kSingleFunctionSize, "");119static_assert(sizeof(void (Multiple::*)()) == kMultipleFunctionSize, "");120static_assert(sizeof(void (Virtual::*)()) == kVirtualFunctionSize, "");121 122// Test both declared and defined templates.123template <typename T> class X;124#ifdef VMB125template <> class __single_inheritance X<IncSingle>;126template <> class __multiple_inheritance X<IncMultiple>;127template <> class __virtual_inheritance X<IncVirtual>;128#else129template <> class X<IncSingle>;130template <> class X<IncMultiple>;131template <> class X<IncVirtual>;132#endif133// Don't declare X<IncUnspecified>.134static_assert(sizeof(int X<IncSingle>::*) == kSingleDataSize, "");135static_assert(sizeof(int X<IncMultiple>::*) == kMultipleDataSize, "");136static_assert(sizeof(int X<IncVirtual>::*) == kVirtualDataSize, "");137static_assert(sizeof(int X<IncUnspecified>::*) == kUnspecifiedDataSize, "");138static_assert(sizeof(void (X<IncSingle>::*)()) == kSingleFunctionSize, "");139static_assert(sizeof(void (X<IncMultiple>::*)()) == kMultipleFunctionSize, "");140static_assert(sizeof(void (X<IncVirtual>::*)()) == kVirtualFunctionSize, "");141static_assert(sizeof(void (X<IncUnspecified>::*)()) == kUnspecifiedFunctionSize, "");142 143template <typename T>144struct Y : T { };145static_assert(sizeof(int Y<Single>::*) == kSingleDataSize, "");146static_assert(sizeof(int Y<Multiple>::*) == kMultipleDataSize, "");147static_assert(sizeof(int Y<Virtual>::*) == kVirtualDataSize, "");148static_assert(sizeof(void (Y<Single>::*)()) == kSingleFunctionSize, "");149static_assert(sizeof(void (Y<Multiple>::*)()) == kMultipleFunctionSize, "");150static_assert(sizeof(void (Y<Virtual>::*)()) == kVirtualFunctionSize, "");151 152struct A { int x; void bar(); };153struct B : A { virtual void foo(); };154static_assert(sizeof(int B::*) == kSingleDataSize, "");155// A non-primary base class uses the multiple inheritance model for member156// pointers.157static_assert(sizeof(void (B::*)()) == kMultipleFunctionSize, "");158 159struct AA { int x; virtual void foo(); };160struct BB : AA { void bar(); };161struct CC : BB { virtual void baz(); };162static_assert(sizeof(void (CC::*)()) == kSingleFunctionSize, "");163 164// We start out unspecified.165struct ForwardDecl1;166struct ForwardDecl2;167 168// Re-declare to force us to iterate decls when adding attributes.169struct ForwardDecl1;170struct ForwardDecl2;171 172typedef int ForwardDecl1::*MemPtr1;173typedef int ForwardDecl2::*MemPtr2;174MemPtr1 variable_forces_sizing;175 176struct ForwardDecl1 : B {177 virtual void foo();178};179struct ForwardDecl2 : B {180 virtual void foo();181};182 183static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, "");184static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, "");185static_assert(sizeof(MemPtr2) == kSingleDataSize, "");186 187struct MemPtrInBody {188 typedef int MemPtrInBody::*MemPtr;189 int a;190 operator MemPtr() const {191 return a ? &MemPtrInBody::a : 0;192 }193};194 195static_assert(sizeof(MemPtrInBody::MemPtr) == kSingleDataSize, "");196 197// Passing a member pointer through a template should get the right size.198template<typename T>199struct SingleTemplate;200template<typename T>201struct SingleTemplate<void (T::*)(void)> {202 static_assert(sizeof(int T::*) == kSingleDataSize, "");203 static_assert(sizeof(void (T::*)()) == kSingleFunctionSize, "");204};205 206template<typename T>207struct UnspecTemplate;208template<typename T>209struct UnspecTemplate<void (T::*)(void)> {210 static_assert(sizeof(int T::*) == kUnspecifiedDataSize, "");211 static_assert(sizeof(void (T::*)()) == kUnspecifiedFunctionSize, "");212};213 214struct NewUnspecified;215SingleTemplate<void (IncSingle::*)()> tmpl_single;216UnspecTemplate<void (NewUnspecified::*)()> tmpl_unspec;217 218struct NewUnspecified { };219 220static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, "");221 222template <typename T>223struct MemPtrInTemplate {224 // We can't require that the template arg be complete until we're225 // instantiated.226 int T::*data_ptr;227 void (T::*func_ptr)();228};229 230#ifdef VMB231int Virtual::*CastTest = reinterpret_cast<int Virtual::*>(&AA::x);232 // expected-error@-1 {{cannot reinterpret_cast from member pointer type}}233#endif234 235namespace ErrorTest {236template <typename T, typename U> struct __single_inheritance A;237 // expected-warning@-1 {{inheritance model ignored on primary template}}238template <typename T> struct __multiple_inheritance A<T, T>;239 // expected-warning@-1 {{inheritance model ignored on partial specialization}}240template <> struct __single_inheritance A<int, float>;241 242struct B {}; // expected-note {{'B' defined here}}243struct __multiple_inheritance B; // expected-error{{inheritance model does not match definition}}244 245struct __multiple_inheritance C {}; // expected-error{{inheritance model does not match definition}}246 // expected-note@-1 {{'C' defined here}}247 248struct __virtual_inheritance D;249struct D : virtual B {};250}251#ifdef VMB252 253namespace PR20017 {254template <typename T>255struct A {256 int T::*f();257};258 259struct B;260 261auto a = &A<B>::f;262 263struct B {};264 265void q() {266 A<B> b;267 (b.*a)();268}269}270 271#pragma pointers_to_members(full_generality, multiple_inheritance)272struct TrulySingleInheritance;273static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, "");274#pragma pointers_to_members(best_case)275// This definition shouldn't conflict with the increased generality that the276// multiple_inheritance model gave to TrulySingleInheritance.277struct TrulySingleInheritance {};278 279// Even if a definition proceeds the first mention of a pointer to member, we280// still give the record the fully general representation.281#pragma pointers_to_members(full_generality, virtual_inheritance)282struct SingleInheritanceAsVirtualAfterPragma {};283static_assert(sizeof(int SingleInheritanceAsVirtualAfterPragma::*) == 12, "");284 285#pragma pointers_to_members(best_case)286 287// The above holds even if the pragma comes after the definition.288struct SingleInheritanceAsVirtualBeforePragma {};289#pragma pointers_to_members(virtual_inheritance)290static_assert(sizeof(int SingleInheritanceAsVirtualBeforePragma::*) == 12, "");291 292#pragma pointers_to_members(single) // expected-error{{unexpected 'single'}}293#endif294 295namespace merging {296struct __single_inheritance S;297struct __single_inheritance S;298 299struct __single_inheritance M; // expected-note{{previous inheritance model specified here}}300struct __multiple_inheritance M; // expected-error{{inheritance model does not match previous declaration}}301}302