Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify -DVMB %s
      2 // RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMB %s
      3 // RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMV -fms-memptr-rep=virtual %s
      4 //
      5 // This file should also give no diagnostics when run through cl.exe from MSVS
      6 // 2012, which supports C++11 and static_assert.  It should pass for both 64-bit
      7 // and 32-bit x86.
      8 //
      9 // Test the size of various member pointer combinations:
     10 // - complete and incomplete
     11 // - single, multiple, and virtual inheritance (and unspecified for incomplete)
     12 // - data and function pointers
     13 // - templated with declared specializations with annotations
     14 // - template that can be instantiated
     15 
     16 // http://llvm.org/PR12070
     17 struct Foo {
     18   typedef int Foo::*FooInt;
     19   int f;
     20 };
     21 
     22 #ifdef VMB
     23 enum {
     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 data
     28   // member pointers on x64 (ugh).
     29   kMultipleFunctionAlign       = 8,
     30 #ifdef _M_X64
     31   kVirtualDataAlign            = 4,
     32 #else
     33   kVirtualDataAlign            = 8,
     34 #endif
     35   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 VMV
     49 enum {
     50   // Everything with more than 1 field is 8 byte aligned, except virtual data
     51   // member pointers on x64 (ugh).
     52 #ifdef _M_X64
     53   kVirtualDataAlign = 4,
     54 #else
     55   kVirtualDataAlign = 8,
     56 #endif
     57   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 #else
     76 #error "test doesn't yet support this mode!"
     77 #endif
     78 
     79 // incomplete types
     80 #ifdef VMB
     81 class __single_inheritance IncSingle;
     82 class __multiple_inheritance IncMultiple;
     83 class __virtual_inheritance IncVirtual;
     84 #else
     85 class IncSingle;
     86 class IncMultiple;
     87 class IncVirtual;
     88 #endif
     89 static_assert(sizeof(int IncSingle::*)        == kSingleDataSize, "");
     90 static_assert(sizeof(int IncMultiple::*)      == kMultipleDataSize, "");
     91 static_assert(sizeof(int IncVirtual::*)       == kVirtualDataSize, "");
     92 static_assert(sizeof(void (IncSingle::*)())   == kSingleFunctionSize, "");
     93 static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, "");
     94 static_assert(sizeof(void (IncVirtual::*)())  == kVirtualFunctionSize, "");
     95 
     96 static_assert(__alignof(int IncSingle::*)        == __alignof(void *), "");
     97 static_assert(__alignof(int IncMultiple::*)      == __alignof(void *), "");
     98 static_assert(__alignof(int IncVirtual::*)       == __alignof(void *), "");
     99 static_assert(__alignof(void (IncSingle::*)())   == __alignof(void *), "");
    100 static_assert(__alignof(void (IncMultiple::*)()) == __alignof(void *), "");
    101 static_assert(__alignof(void (IncVirtual::*)())  == __alignof(void *), "");
    102 
    103 // An incomplete type with an unspecified inheritance model seems to take one
    104 // more slot than virtual.
    105 class IncUnspecified;
    106 static_assert(sizeof(int IncUnspecified::*) == kUnspecifiedDataSize, "");
    107 static_assert(sizeof(void (IncUnspecified::*)()) == kUnspecifiedFunctionSize, "");
    108 
    109 // complete types
    110 struct B1 { };
    111 struct B2 { };
    112 struct Single { };
    113 struct Multiple : B1, B2 { };
    114 struct Virtual : virtual B1 { };
    115 static_assert(sizeof(int Single::*)        == kSingleDataSize, "");
    116 static_assert(sizeof(int Multiple::*)      == kMultipleDataSize, "");
    117 static_assert(sizeof(int Virtual::*)       == kVirtualDataSize, "");
    118 static_assert(sizeof(void (Single::*)())   == kSingleFunctionSize, "");
    119 static_assert(sizeof(void (Multiple::*)()) == kMultipleFunctionSize, "");
    120 static_assert(sizeof(void (Virtual::*)())  == kVirtualFunctionSize, "");
    121 
    122 // Test both declared and defined templates.
    123 template <typename T> class X;
    124 #ifdef VMB
    125 template <> class __single_inheritance   X<IncSingle>;
    126 template <> class __multiple_inheritance X<IncMultiple>;
    127 template <> class __virtual_inheritance  X<IncVirtual>;
    128 #else
    129 template <> class X<IncSingle>;
    130 template <> class X<IncMultiple>;
    131 template <> class X<IncVirtual>;
    132 #endif
    133 // Don't declare X<IncUnspecified>.
    134 static_assert(sizeof(int X<IncSingle>::*)           == kSingleDataSize, "");
    135 static_assert(sizeof(int X<IncMultiple>::*)         == kMultipleDataSize, "");
    136 static_assert(sizeof(int X<IncVirtual>::*)          == kVirtualDataSize, "");
    137 static_assert(sizeof(int X<IncUnspecified>::*)      == kUnspecifiedDataSize, "");
    138 static_assert(sizeof(void (X<IncSingle>::*)())      == kSingleFunctionSize, "");
    139 static_assert(sizeof(void (X<IncMultiple>::*)())    == kMultipleFunctionSize, "");
    140 static_assert(sizeof(void (X<IncVirtual>::*)())     == kVirtualFunctionSize, "");
    141 static_assert(sizeof(void (X<IncUnspecified>::*)()) == kUnspecifiedFunctionSize, "");
    142 
    143 template <typename T>
    144 struct Y : T { };
    145 static_assert(sizeof(int Y<Single>::*)        == kSingleDataSize, "");
    146 static_assert(sizeof(int Y<Multiple>::*)      == kMultipleDataSize, "");
    147 static_assert(sizeof(int Y<Virtual>::*)       == kVirtualDataSize, "");
    148 static_assert(sizeof(void (Y<Single>::*)())   == kSingleFunctionSize, "");
    149 static_assert(sizeof(void (Y<Multiple>::*)()) == kMultipleFunctionSize, "");
    150 static_assert(sizeof(void (Y<Virtual>::*)())  == kVirtualFunctionSize, "");
    151 
    152 struct A { int x; void bar(); };
    153 struct B : A { virtual void foo(); };
    154 static_assert(sizeof(int B::*) == kSingleDataSize, "");
    155 // A non-primary base class uses the multiple inheritance model for member
    156 // pointers.
    157 static_assert(sizeof(void (B::*)()) == kMultipleFunctionSize, "");
    158 
    159 struct AA { int x; virtual void foo(); };
    160 struct BB : AA { void bar(); };
    161 struct CC : BB { virtual void baz(); };
    162 static_assert(sizeof(void (CC::*)()) == kSingleFunctionSize, "");
    163 
    164 // We start out unspecified.
    165 struct ForwardDecl1;
    166 struct ForwardDecl2;
    167 
    168 // Re-declare to force us to iterate decls when adding attributes.
    169 struct ForwardDecl1;
    170 struct ForwardDecl2;
    171 
    172 typedef int ForwardDecl1::*MemPtr1;
    173 typedef int ForwardDecl2::*MemPtr2;
    174 MemPtr1 variable_forces_sizing;
    175 
    176 struct ForwardDecl1 : B {
    177   virtual void foo();
    178 };
    179 struct ForwardDecl2 : B {
    180   virtual void foo();
    181 };
    182 
    183 static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, "");
    184 static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, "");
    185 static_assert(sizeof(MemPtr2) == kSingleDataSize, "");
    186 
    187 struct MemPtrInBody {
    188   typedef int MemPtrInBody::*MemPtr;
    189   int a;
    190   operator MemPtr() const {
    191     return a ? &MemPtrInBody::a : 0;
    192   }
    193 };
    194 
    195 static_assert(sizeof(MemPtrInBody::MemPtr) == kSingleDataSize, "");
    196 
    197 // Passing a member pointer through a template should get the right size.
    198 template<typename T>
    199 struct SingleTemplate;
    200 template<typename T>
    201 struct SingleTemplate<void (T::*)(void)> {
    202   static_assert(sizeof(int T::*) == kSingleDataSize, "");
    203   static_assert(sizeof(void (T::*)()) == kSingleFunctionSize, "");
    204 };
    205 
    206 template<typename T>
    207 struct UnspecTemplate;
    208 template<typename T>
    209 struct UnspecTemplate<void (T::*)(void)> {
    210   static_assert(sizeof(int T::*) == kUnspecifiedDataSize, "");
    211   static_assert(sizeof(void (T::*)()) == kUnspecifiedFunctionSize, "");
    212 };
    213 
    214 struct NewUnspecified;
    215 SingleTemplate<void (IncSingle::*)()> tmpl_single;
    216 UnspecTemplate<void (NewUnspecified::*)()> tmpl_unspec;
    217 
    218 struct NewUnspecified { };
    219 
    220 static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, "");
    221 
    222 template <typename T>
    223 struct MemPtrInTemplate {
    224   // We can't require that the template arg be complete until we're
    225   // instantiated.
    226   int T::*data_ptr;
    227   void (T::*func_ptr)();
    228 };
    229 
    230 #ifdef VMB
    231 int Virtual::*CastTest = reinterpret_cast<int Virtual::*>(&AA::x);
    232   // expected-error@-1 {{cannot reinterpret_cast from member pointer type}}
    233 #endif
    234 
    235 namespace ErrorTest {
    236 template <typename T, typename U> struct __single_inheritance A;
    237   // expected-warning@-1 {{inheritance model ignored on primary template}}
    238 template <typename T> struct __multiple_inheritance A<T, T>;
    239   // expected-warning@-1 {{inheritance model ignored on partial specialization}}
    240 template <> struct __single_inheritance A<int, float>;
    241 
    242 struct B {}; // expected-note {{B defined here}}
    243 struct __multiple_inheritance B; // expected-error{{inheritance model does not match definition}}
    244 
    245 struct __multiple_inheritance C {}; // expected-error{{inheritance model does not match definition}}
    246  // expected-note@-1 {{C defined here}}
    247 
    248 struct __virtual_inheritance D;
    249 struct D : virtual B {};
    250 }
    251 #ifdef VMB
    252 
    253 namespace PR20017 {
    254 template <typename T>
    255 struct A {
    256   int T::*f();
    257 };
    258 
    259 struct B;
    260 
    261 auto a = &A<B>::f;
    262 
    263 struct B {};
    264 
    265 void q() {
    266   A<B> b;
    267   (b.*a)();
    268 }
    269 }
    270 
    271 #pragma pointers_to_members(full_generality, multiple_inheritance)
    272 struct TrulySingleInheritance;
    273 static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, "");
    274 #pragma pointers_to_members(best_case)
    275 // This definition shouldn't conflict with the increased generality that the
    276 // multiple_inheritance model gave to TrulySingleInheritance.
    277 struct TrulySingleInheritance {};
    278 
    279 // Even if a definition proceeds the first mention of a pointer to member, we
    280 // still give the record the fully general representation.
    281 #pragma pointers_to_members(full_generality, virtual_inheritance)
    282 struct SingleInheritanceAsVirtualAfterPragma {};
    283 static_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.
    288 struct SingleInheritanceAsVirtualBeforePragma {};
    289 #pragma pointers_to_members(virtual_inheritance)
    290 static_assert(sizeof(int SingleInheritanceAsVirtualBeforePragma::*) == 12, "");
    291 
    292 #pragma pointers_to_members(single) // expected-error{{unexpected 'single'}}
    293 #endif
    294