// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s // RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify %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; }; 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 *), }; // incomplete types class __single_inheritance IncSingle; class __multiple_inheritance IncMultiple; class __virtual_inheritance IncVirtual; 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::*) == 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; 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 class X; template <> class __single_inheritance X; template <> class __multiple_inheritance X; template <> class __virtual_inheritance X; // Don't declare X. static_assert(sizeof(int X::*) == kSingleDataSize, ""); static_assert(sizeof(int X::*) == kMultipleDataSize, ""); static_assert(sizeof(int X::*) == kVirtualDataSize, ""); static_assert(sizeof(int X::*) == kUnspecifiedDataSize, ""); static_assert(sizeof(void (X::*)()) == kSingleFunctionSize, ""); static_assert(sizeof(void (X::*)()) == kMultipleFunctionSize, ""); static_assert(sizeof(void (X::*)()) == kVirtualFunctionSize, ""); static_assert(sizeof(void (X::*)()) == kUnspecifiedFunctionSize, ""); template struct Y : T { }; static_assert(sizeof(int Y::*) == kSingleDataSize, ""); static_assert(sizeof(int Y::*) == kMultipleDataSize, ""); static_assert(sizeof(int Y::*) == kVirtualDataSize, ""); static_assert(sizeof(void (Y::*)()) == kSingleFunctionSize, ""); static_assert(sizeof(void (Y::*)()) == kMultipleFunctionSize, ""); static_assert(sizeof(void (Y::*)()) == 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 struct SingleTemplate; template struct SingleTemplate { static_assert(sizeof(int T::*) == kSingleDataSize, ""); static_assert(sizeof(void (T::*)()) == kSingleFunctionSize, ""); }; template struct UnspecTemplate; template struct UnspecTemplate { static_assert(sizeof(int T::*) == kUnspecifiedDataSize, ""); static_assert(sizeof(void (T::*)()) == kUnspecifiedFunctionSize, ""); }; struct NewUnspecified; SingleTemplate tmpl_single; UnspecTemplate tmpl_unspec; struct NewUnspecified { }; static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, ""); template struct MemPtrInTemplate { // We can't require that the template arg be complete until we're // instantiated. int T::*data_ptr; void (T::*func_ptr)(); }; int Virtual::*CastTest = reinterpret_cast(&AA::x); // expected-error@-1 {{cannot reinterpret_cast from member pointer type}} namespace ErrorTest { template struct __single_inheritance A; // expected-warning@-1 {{inheritance model ignored on primary template}} template struct __multiple_inheritance A; // expected-warning@-1 {{inheritance model ignored on partial specialization}} template <> struct __single_inheritance A; 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 {}; }