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