1 // RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s
2 // RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify %s
3 //
4 // This file should also give no diagnostics when run through cl.exe from MSVS
5 // 2012, which supports C++11 and static_assert.  It should pass for both 64-bit
6 // and 32-bit x86.
7 //
8 // Test the size of various member pointer combinations:
9 // - complete and incomplete
10 // - single, multiple, and virtual inheritance (and unspecified for incomplete)
11 // - data and function pointers
12 // - templated with declared specializations with annotations
13 // - template that can be instantiated
14 
15 // http://llvm.org/PR12070
16 struct Foo {
17   typedef int Foo::*FooInt;
18   int f;
19 };
20 
21 enum {
22   kSingleDataSize             = 1 * sizeof(int),
23   kSingleFunctionSize         = 1 * sizeof(void *),
24   kMultipleDataSize           = 1 * sizeof(int),
25   kMultipleFunctionSize       = 2 * sizeof(void *),
26   kVirtualDataSize            = 2 * sizeof(int),
27   kVirtualFunctionSize        = 2 * sizeof(int) + 1 * sizeof(void *),
28   // Unspecified is weird, it's 1 more slot than virtual.
29   kUnspecifiedDataSize        = kVirtualDataSize + 1 * sizeof(int),
30   kUnspecifiedFunctionSize    = kVirtualFunctionSize + 1 * sizeof(void *),
31 };
32 
33 // incomplete types
34 class __single_inheritance IncSingle;
35 class __multiple_inheritance IncMultiple;
36 class __virtual_inheritance IncVirtual;
37 static_assert(sizeof(int IncSingle::*)        == kSingleDataSize, "");
38 static_assert(sizeof(int IncMultiple::*)      == kMultipleDataSize, "");
39 static_assert(sizeof(int IncVirtual::*)       == kVirtualDataSize, "");
40 static_assert(sizeof(void (IncSingle::*)())   == kSingleFunctionSize, "");
41 static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, "");
42 static_assert(sizeof(void (IncVirtual::*)())  == kVirtualFunctionSize, "");
43 
44 // An incomplete type with an unspecified inheritance model seems to take one
45 // more slot than virtual.  It's not clear what it's used for yet.
46 class IncUnspecified;
47 static_assert(sizeof(int IncUnspecified::*) == kUnspecifiedDataSize, "");
48 static_assert(sizeof(void (IncUnspecified::*)()) == kUnspecifiedFunctionSize, "");
49 
50 // complete types
51 struct B1 { };
52 struct B2 { };
53 struct Single { };
54 struct Multiple : B1, B2 { };
55 struct Virtual : virtual B1 { };
56 static_assert(sizeof(int Single::*)        == kSingleDataSize, "");
57 static_assert(sizeof(int Multiple::*)      == kMultipleDataSize, "");
58 static_assert(sizeof(int Virtual::*)       == kVirtualDataSize, "");
59 static_assert(sizeof(void (Single::*)())   == kSingleFunctionSize, "");
60 static_assert(sizeof(void (Multiple::*)()) == kMultipleFunctionSize, "");
61 static_assert(sizeof(void (Virtual::*)())  == kVirtualFunctionSize, "");
62 
63 // Test both declared and defined templates.
64 template <typename T> class X;
65 template <> class __single_inheritance   X<IncSingle>;
66 template <> class __multiple_inheritance X<IncMultiple>;
67 template <> class __virtual_inheritance  X<IncVirtual>;
68 // Don't declare X<IncUnspecified>.
69 static_assert(sizeof(int X<IncSingle>::*)           == kSingleDataSize, "");
70 static_assert(sizeof(int X<IncMultiple>::*)         == kMultipleDataSize, "");
71 static_assert(sizeof(int X<IncVirtual>::*)          == kVirtualDataSize, "");
72 static_assert(sizeof(int X<IncUnspecified>::*)      == kUnspecifiedDataSize, "");
73 static_assert(sizeof(void (X<IncSingle>::*)())      == kSingleFunctionSize, "");
74 static_assert(sizeof(void (X<IncMultiple>::*)())    == kMultipleFunctionSize, "");
75 static_assert(sizeof(void (X<IncVirtual>::*)())     == kVirtualFunctionSize, "");
76 static_assert(sizeof(void (X<IncUnspecified>::*)()) == kUnspecifiedFunctionSize, "");
77 
78 template <typename T>
79 struct Y : T { };
80 static_assert(sizeof(int Y<Single>::*)        == kSingleDataSize, "");
81 static_assert(sizeof(int Y<Multiple>::*)      == kMultipleDataSize, "");
82 static_assert(sizeof(int Y<Virtual>::*)       == kVirtualDataSize, "");
83 static_assert(sizeof(void (Y<Single>::*)())   == kSingleFunctionSize, "");
84 static_assert(sizeof(void (Y<Multiple>::*)()) == kMultipleFunctionSize, "");
85 static_assert(sizeof(void (Y<Virtual>::*)())  == kVirtualFunctionSize, "");
86 
87 struct A { int x; void bar(); };
88 struct B : A { virtual void foo(); };
89 static_assert(sizeof(int B::*) == kSingleDataSize, "");
90 // A non-primary base class uses the multiple inheritance model for member
91 // pointers.
92 static_assert(sizeof(void (B::*)()) == kMultipleFunctionSize, "");
93 
94 struct AA { int x; virtual void foo(); };
95 struct BB : AA { void bar(); };
96 struct CC : BB { virtual void baz(); };
97 static_assert(sizeof(void (CC::*)()) == kSingleFunctionSize, "");
98 
99 // We start out unspecified.
100 struct ForwardDecl1;
101 struct ForwardDecl2;
102 
103 // Re-declare to force us to iterate decls when adding attributes.
104 struct ForwardDecl1;
105 struct ForwardDecl2;
106 
107 typedef int ForwardDecl1::*MemPtr1;
108 typedef int ForwardDecl2::*MemPtr2;
109 MemPtr1 variable_forces_sizing;
110 
111 struct ForwardDecl1 : B {
112   virtual void foo();
113 };
114 struct ForwardDecl2 : B {
115   virtual void foo();
116 };
117 
118 static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, "");
119 static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, "");
120 // FIXME: Clang fails this assert because it locks in the inheritance model at
121 // the point of the typedef instead of the first usage, while MSVC does not.
122 //static_assert(sizeof(MemPtr2) == kSingleDataSize, "");
123 
124 struct MemPtrInBody {
125   typedef int MemPtrInBody::*MemPtr;
126   int a;
127   operator MemPtr() const {
128     return a ? &MemPtrInBody::a : 0;
129   }
130 };
131 
132 static_assert(sizeof(MemPtrInBody::MemPtr) == kSingleDataSize, "");
133 
134 // Passing a member pointer through a template should get the right size.
135 template<typename T>
136 struct SingleTemplate;
137 template<typename T>
138 struct SingleTemplate<void (T::*)(void)> {
139   static_assert(sizeof(int T::*) == kSingleDataSize, "");
140   static_assert(sizeof(void (T::*)()) == kSingleFunctionSize, "");
141 };
142 
143 template<typename T>
144 struct UnspecTemplate;
145 template<typename T>
146 struct UnspecTemplate<void (T::*)(void)> {
147   static_assert(sizeof(int T::*) == kUnspecifiedDataSize, "");
148   static_assert(sizeof(void (T::*)()) == kUnspecifiedFunctionSize, "");
149 };
150 
151 struct NewUnspecified;
152 SingleTemplate<void (IncSingle::*)()> tmpl_single;
153 UnspecTemplate<void (NewUnspecified::*)()> tmpl_unspec;
154 
155 struct NewUnspecified { };
156 
157 static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, "");
158 
159 template <typename T>
160 struct MemPtrInTemplate {
161   // We can't require that the template arg be complete until we're
162   // instantiated.
163   int T::*data_ptr;
164   void (T::*func_ptr)();
165 };
166 
167 int Virtual::*CastTest = reinterpret_cast<int Virtual::*>(&AA::x);
168   // expected-error@-1 {{cannot reinterpret_cast from member pointer type}}
169