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::*)        == kSingleDataAlign, "");
97 static_assert(__alignof(int IncMultiple::*)      == kMultipleDataAlign, "");
98 static_assert(__alignof(int IncVirtual::*)       == kVirtualDataAlign, "");
99 static_assert(__alignof(void (IncSingle::*)())   == kSingleFunctionAlign, "");
100 static_assert(__alignof(void (IncMultiple::*)()) == kMultipleFunctionAlign, "");
101 static_assert(__alignof(void (IncVirtual::*)())  == kVirtualFunctionAlign, "");
102 
103 // An incomplete type with an unspecified inheritance model seems to take one
104 // more slot than virtual.  It's not clear what it's used for yet.
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;
operator MemPtrMemPtrInBody190   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 
q()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