brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.7 KiB · 3271ff0 Raw
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