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