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