xref: /llvm-project/clang/test/SemaCXX/member-pointer-ms.cpp (revision 98c9ee2068dc94d2b3f595545b10ef57503acd4b)
1 // RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s
2 // RUN: %clang_cc1 -std=c++11 -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   kSingleDataAlign             = 1 * sizeof(int),
23   kSingleFunctionAlign         = 1 * sizeof(void *),
24   kMultipleDataAlign           = 1 * sizeof(int),
25   // Everything with more than 1 field is 8 byte aligned, except virtual data
26   // member pointers on x64 (ugh).
27   kMultipleFunctionAlign       = 8,
28 #ifdef _M_X64
29   kVirtualDataAlign            = 4,
30 #else
31   kVirtualDataAlign            = 8,
32 #endif
33   kVirtualFunctionAlign        = 8,
34   kUnspecifiedDataAlign        = 8,
35   kUnspecifiedFunctionAlign    = 8,
36 
37   kSingleDataSize             = 1 * sizeof(int),
38   kSingleFunctionSize         = 1 * sizeof(void *),
39   kMultipleDataSize           = 1 * sizeof(int),
40   kMultipleFunctionSize       = 2 * sizeof(void *),
41   kVirtualDataSize            = 2 * sizeof(int),
42   kVirtualFunctionSize        = 2 * sizeof(int) + 1 * sizeof(void *),
43   kUnspecifiedDataSize        = 3 * sizeof(int),
44   kUnspecifiedFunctionSize    = 2 * sizeof(int) + 2 * sizeof(void *),
45 };
46 
47 // incomplete types
48 class __single_inheritance IncSingle;
49 class __multiple_inheritance IncMultiple;
50 class __virtual_inheritance IncVirtual;
51 static_assert(sizeof(int IncSingle::*)        == kSingleDataSize, "");
52 static_assert(sizeof(int IncMultiple::*)      == kMultipleDataSize, "");
53 static_assert(sizeof(int IncVirtual::*)       == kVirtualDataSize, "");
54 static_assert(sizeof(void (IncSingle::*)())   == kSingleFunctionSize, "");
55 static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, "");
56 static_assert(sizeof(void (IncVirtual::*)())  == kVirtualFunctionSize, "");
57 
58 static_assert(__alignof(int IncSingle::*)        == kSingleDataAlign, "");
59 static_assert(__alignof(int IncMultiple::*)      == kMultipleDataAlign, "");
60 static_assert(__alignof(int IncVirtual::*)       == kVirtualDataAlign, "");
61 static_assert(__alignof(void (IncSingle::*)())   == kSingleFunctionAlign, "");
62 static_assert(__alignof(void (IncMultiple::*)()) == kMultipleFunctionAlign, "");
63 static_assert(__alignof(void (IncVirtual::*)())  == kVirtualFunctionAlign, "");
64 
65 // An incomplete type with an unspecified inheritance model seems to take one
66 // more slot than virtual.  It's not clear what it's used for yet.
67 class IncUnspecified;
68 static_assert(sizeof(int IncUnspecified::*) == kUnspecifiedDataSize, "");
69 static_assert(sizeof(void (IncUnspecified::*)()) == kUnspecifiedFunctionSize, "");
70 
71 // complete types
72 struct B1 { };
73 struct B2 { };
74 struct Single { };
75 struct Multiple : B1, B2 { };
76 struct Virtual : virtual B1 { };
77 static_assert(sizeof(int Single::*)        == kSingleDataSize, "");
78 static_assert(sizeof(int Multiple::*)      == kMultipleDataSize, "");
79 static_assert(sizeof(int Virtual::*)       == kVirtualDataSize, "");
80 static_assert(sizeof(void (Single::*)())   == kSingleFunctionSize, "");
81 static_assert(sizeof(void (Multiple::*)()) == kMultipleFunctionSize, "");
82 static_assert(sizeof(void (Virtual::*)())  == kVirtualFunctionSize, "");
83 
84 // Test both declared and defined templates.
85 template <typename T> class X;
86 template <> class __single_inheritance   X<IncSingle>;
87 template <> class __multiple_inheritance X<IncMultiple>;
88 template <> class __virtual_inheritance  X<IncVirtual>;
89 // Don't declare X<IncUnspecified>.
90 static_assert(sizeof(int X<IncSingle>::*)           == kSingleDataSize, "");
91 static_assert(sizeof(int X<IncMultiple>::*)         == kMultipleDataSize, "");
92 static_assert(sizeof(int X<IncVirtual>::*)          == kVirtualDataSize, "");
93 static_assert(sizeof(int X<IncUnspecified>::*)      == kUnspecifiedDataSize, "");
94 static_assert(sizeof(void (X<IncSingle>::*)())      == kSingleFunctionSize, "");
95 static_assert(sizeof(void (X<IncMultiple>::*)())    == kMultipleFunctionSize, "");
96 static_assert(sizeof(void (X<IncVirtual>::*)())     == kVirtualFunctionSize, "");
97 static_assert(sizeof(void (X<IncUnspecified>::*)()) == kUnspecifiedFunctionSize, "");
98 
99 template <typename T>
100 struct Y : T { };
101 static_assert(sizeof(int Y<Single>::*)        == kSingleDataSize, "");
102 static_assert(sizeof(int Y<Multiple>::*)      == kMultipleDataSize, "");
103 static_assert(sizeof(int Y<Virtual>::*)       == kVirtualDataSize, "");
104 static_assert(sizeof(void (Y<Single>::*)())   == kSingleFunctionSize, "");
105 static_assert(sizeof(void (Y<Multiple>::*)()) == kMultipleFunctionSize, "");
106 static_assert(sizeof(void (Y<Virtual>::*)())  == kVirtualFunctionSize, "");
107 
108 struct A { int x; void bar(); };
109 struct B : A { virtual void foo(); };
110 static_assert(sizeof(int B::*) == kSingleDataSize, "");
111 // A non-primary base class uses the multiple inheritance model for member
112 // pointers.
113 static_assert(sizeof(void (B::*)()) == kMultipleFunctionSize, "");
114 
115 struct AA { int x; virtual void foo(); };
116 struct BB : AA { void bar(); };
117 struct CC : BB { virtual void baz(); };
118 static_assert(sizeof(void (CC::*)()) == kSingleFunctionSize, "");
119 
120 // We start out unspecified.
121 struct ForwardDecl1;
122 struct ForwardDecl2;
123 
124 // Re-declare to force us to iterate decls when adding attributes.
125 struct ForwardDecl1;
126 struct ForwardDecl2;
127 
128 typedef int ForwardDecl1::*MemPtr1;
129 typedef int ForwardDecl2::*MemPtr2;
130 MemPtr1 variable_forces_sizing;
131 
132 struct ForwardDecl1 : B {
133   virtual void foo();
134 };
135 struct ForwardDecl2 : B {
136   virtual void foo();
137 };
138 
139 static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, "");
140 static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, "");
141 static_assert(sizeof(MemPtr2) == kSingleDataSize, "");
142 
143 struct MemPtrInBody {
144   typedef int MemPtrInBody::*MemPtr;
145   int a;
146   operator MemPtr() const {
147     return a ? &MemPtrInBody::a : 0;
148   }
149 };
150 
151 static_assert(sizeof(MemPtrInBody::MemPtr) == kSingleDataSize, "");
152 
153 // Passing a member pointer through a template should get the right size.
154 template<typename T>
155 struct SingleTemplate;
156 template<typename T>
157 struct SingleTemplate<void (T::*)(void)> {
158   static_assert(sizeof(int T::*) == kSingleDataSize, "");
159   static_assert(sizeof(void (T::*)()) == kSingleFunctionSize, "");
160 };
161 
162 template<typename T>
163 struct UnspecTemplate;
164 template<typename T>
165 struct UnspecTemplate<void (T::*)(void)> {
166   static_assert(sizeof(int T::*) == kUnspecifiedDataSize, "");
167   static_assert(sizeof(void (T::*)()) == kUnspecifiedFunctionSize, "");
168 };
169 
170 struct NewUnspecified;
171 SingleTemplate<void (IncSingle::*)()> tmpl_single;
172 UnspecTemplate<void (NewUnspecified::*)()> tmpl_unspec;
173 
174 struct NewUnspecified { };
175 
176 static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, "");
177 
178 template <typename T>
179 struct MemPtrInTemplate {
180   // We can't require that the template arg be complete until we're
181   // instantiated.
182   int T::*data_ptr;
183   void (T::*func_ptr)();
184 };
185 
186 int Virtual::*CastTest = reinterpret_cast<int Virtual::*>(&AA::x);
187   // expected-error@-1 {{cannot reinterpret_cast from member pointer type}}
188 
189 namespace ErrorTest {
190 template <typename T, typename U> struct __single_inheritance A;
191   // expected-warning@-1 {{inheritance model ignored on primary template}}
192 template <typename T> struct __multiple_inheritance A<T, T>;
193   // expected-warning@-1 {{inheritance model ignored on partial specialization}}
194 template <> struct __single_inheritance A<int, float>;
195 
196 struct B {}; // expected-note {{B defined here}}
197 struct __multiple_inheritance B; // expected-error{{inheritance model does not match definition}}
198 
199 struct __multiple_inheritance C {}; // expected-error{{inheritance model does not match definition}}
200  // expected-note@-1 {{C defined here}}
201 
202 struct __virtual_inheritance D;
203 struct D : virtual B {};
204 }
205