1 // RUN: %clang_cc1 -std=c++14 -fno-rtti -fms-extensions -triple i686-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 \
3 // RUN: %clang_cc1 -std=c++14 -fno-rtti -fms-extensions -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>/dev/null \
4 // RUN: | FileCheck %s -check-prefix CHECK-X64
6 extern "C" int printf(const char *fmt
, ...);
10 B0() : a(0xf00000B0) {}
11 virtual void f() { printf("B0"); }
14 struct __declspec(align(16)) B1
{
16 B1() : a(0xf00000B1) {}
17 virtual void f() { printf("B1"); }
20 struct __declspec(align(16)) Align16
{};
21 struct __declspec(align(32)) Align32
{};
22 struct VAlign16
: virtual Align16
{};
23 struct VAlign32
: virtual Align32
{};
25 struct A
: virtual B0
, virtual B1
{
27 A() : a(0xf000000A) {}
28 virtual void f() { printf("A"); }
29 virtual void g() { printf("A"); }
32 // CHECK-LABEL: 0 | struct A{{$}}
33 // CHECK-NEXT: 0 | (A vftable pointer)
34 // CHECK-NEXT: 4 | (A vbtable pointer)
35 // CHECK-NEXT: 8 | int a
36 // CHECK-NEXT: 16 | (vtordisp for vbase B0)
37 // CHECK-NEXT: 20 | struct B0 (virtual base)
38 // CHECK-NEXT: 20 | (B0 vftable pointer)
39 // CHECK-NEXT: 24 | int a
40 // CHECK-NEXT: 44 | (vtordisp for vbase B1)
41 // CHECK-NEXT: 48 | struct B1 (virtual base)
42 // CHECK-NEXT: 48 | (B1 vftable pointer)
43 // CHECK-NEXT: 52 | int a
44 // CHECK-NEXT: | [sizeof=64, align=16
45 // CHECK-NEXT: | nvsize=12, nvalign=16]
46 // CHECK-X64-LABEL: 0 | struct A{{$}}
47 // CHECK-X64-NEXT: 0 | (A vftable pointer)
48 // CHECK-X64-NEXT: 8 | (A vbtable pointer)
49 // CHECK-X64-NEXT: 16 | int a
50 // CHECK-X64-NEXT: 36 | (vtordisp for vbase B0)
51 // CHECK-X64-NEXT: 40 | struct B0 (virtual base)
52 // CHECK-X64-NEXT: 40 | (B0 vftable pointer)
53 // CHECK-X64-NEXT: 48 | int a
54 // CHECK-X64-NEXT: 76 | (vtordisp for vbase B1)
55 // CHECK-X64-NEXT: 80 | struct B1 (virtual base)
56 // CHECK-X64-NEXT: 80 | (B1 vftable pointer)
57 // CHECK-X64-NEXT: 88 | int a
58 // CHECK-X64-NEXT: | [sizeof=96, align=16
59 // CHECK-X64-NEXT: | nvsize=24, nvalign=16]
61 struct C
: virtual B0
, virtual B1
, VAlign32
{
63 C() : a(0xf000000C) {}
64 virtual void f() { printf("C"); }
65 virtual void g() { printf("C"); }
68 // CHECK-LABEL: 0 | struct C{{$}}
69 // CHECK-NEXT: 0 | (C vftable pointer)
70 // CHECK-NEXT: 32 | struct VAlign32 (base)
71 // CHECK-NEXT: 32 | (VAlign32 vbtable pointer)
72 // CHECK-NEXT: 36 | int a
73 // CHECK-NEXT: 64 | (vtordisp for vbase B0)
74 // CHECK-NEXT: 68 | struct B0 (virtual base)
75 // CHECK-NEXT: 68 | (B0 vftable pointer)
76 // CHECK-NEXT: 72 | int a
77 // CHECK-NEXT: 108 | (vtordisp for vbase B1)
78 // CHECK-NEXT: 112 | struct B1 (virtual base)
79 // CHECK-NEXT: 112 | (B1 vftable pointer)
80 // CHECK-NEXT: 116 | int a
81 // CHECK-NEXT: 128 | struct Align32 (virtual base) (empty)
82 // CHECK-NEXT: | [sizeof=128, align=32
83 // CHECK-NEXT: | nvsize=64, nvalign=32]
84 // CHECK-X64-LABEL: 0 | struct C{{$}}
85 // CHECK-X64-NEXT: 0 | (C vftable pointer)
86 // CHECK-X64-NEXT: 32 | struct VAlign32 (base)
87 // CHECK-X64-NEXT: 32 | (VAlign32 vbtable pointer)
88 // CHECK-X64-NEXT: 40 | int a
89 // CHECK-X64-NEXT: 68 | (vtordisp for vbase B0)
90 // CHECK-X64-NEXT: 72 | struct B0 (virtual base)
91 // CHECK-X64-NEXT: 72 | (B0 vftable pointer)
92 // CHECK-X64-NEXT: 80 | int a
93 // CHECK-X64-NEXT: 108 | (vtordisp for vbase B1)
94 // CHECK-X64-NEXT: 112 | struct B1 (virtual base)
95 // CHECK-X64-NEXT: 112 | (B1 vftable pointer)
96 // CHECK-X64-NEXT: 120 | int a
97 // CHECK-X64-NEXT: 128 | struct Align32 (virtual base) (empty)
98 // CHECK-X64-NEXT: | [sizeof=128, align=32
99 // CHECK-X64-NEXT: | nvsize=64, nvalign=32]
101 struct __declspec(align(32)) D
: virtual B0
, virtual B1
{
103 D() : a(0xf000000D) {}
104 virtual void f() { printf("D"); }
105 virtual void g() { printf("D"); }
108 // CHECK-LABEL: 0 | struct D{{$}}
109 // CHECK-NEXT: 0 | (D vftable pointer)
110 // CHECK-NEXT: 4 | (D vbtable pointer)
111 // CHECK-NEXT: 8 | int a
112 // CHECK-NEXT: 32 | (vtordisp for vbase B0)
113 // CHECK-NEXT: 36 | struct B0 (virtual base)
114 // CHECK-NEXT: 36 | (B0 vftable pointer)
115 // CHECK-NEXT: 40 | int a
116 // CHECK-NEXT: 76 | (vtordisp for vbase B1)
117 // CHECK-NEXT: 80 | struct B1 (virtual base)
118 // CHECK-NEXT: 80 | (B1 vftable pointer)
119 // CHECK-NEXT: 84 | int a
120 // CHECK-NEXT: | [sizeof=96, align=32
121 // CHECK-NEXT: | nvsize=12, nvalign=32]
122 // CHECK-X64-LABEL: 0 | struct D{{$}}
123 // CHECK-X64-NEXT: 0 | (D vftable pointer)
124 // CHECK-X64-NEXT: 8 | (D vbtable pointer)
125 // CHECK-X64-NEXT: 16 | int a
126 // CHECK-X64-NEXT: 36 | (vtordisp for vbase B0)
127 // CHECK-X64-NEXT: 40 | struct B0 (virtual base)
128 // CHECK-X64-NEXT: 40 | (B0 vftable pointer)
129 // CHECK-X64-NEXT: 48 | int a
130 // CHECK-X64-NEXT: 76 | (vtordisp for vbase B1)
131 // CHECK-X64-NEXT: 80 | struct B1 (virtual base)
132 // CHECK-X64-NEXT: 80 | (B1 vftable pointer)
133 // CHECK-X64-NEXT: 88 | int a
134 // CHECK-X64-NEXT: | [sizeof=96, align=32
135 // CHECK-X64-NEXT: | nvsize=24, nvalign=32]
140 struct CT
: virtual AT
{
145 // CHECK-LABEL: 0 | struct CT{{$}}
146 // CHECK-NEXT: 0 | (CT vbtable pointer)
147 // CHECK-NEXT: 4 | struct AT (virtual base)
148 // CHECK-NEXT: 4 | (AT vftable pointer)
149 // CHECK-NEXT: | [sizeof=8, align=4
150 // CHECK-NEXT: | nvsize=4, nvalign=4]
151 // CHECK-X64-LABEL: 0 | struct CT{{$}}
152 // CHECK-X64-NEXT: 0 | (CT vbtable pointer)
153 // CHECK-X64-NEXT: 8 | struct AT (virtual base)
154 // CHECK-X64-NEXT: 8 | (AT vftable pointer)
155 // CHECK-X64-NEXT: | [sizeof=16, align=8
156 // CHECK-X64-NEXT: | nvsize=8, nvalign=8]
159 XA() { printf("XA"); }
163 XB() { printf("XB"); }
164 virtual void foo() {}
167 struct XC
: virtual XB
{
168 XC() { printf("XC"); }
169 virtual void foo() {}
172 // CHECK-LABEL: 0 | struct XC{{$}}
173 // CHECK-NEXT: 0 | (XC vbtable pointer)
174 // CHECK-NEXT: 4 | (vtordisp for vbase XB)
175 // CHECK-NEXT: 8 | struct XB (virtual base)
176 // CHECK-NEXT: 8 | (XB vftable pointer)
177 // CHECK-NEXT: 16 | struct XA (base)
178 // CHECK-NEXT: 16 | long long ll
179 // CHECK-NEXT: 24 | int b
180 // CHECK-NEXT: | [sizeof=32, align=8
181 // CHECK-NEXT: | nvsize=4, nvalign=8]
182 // CHECK-X64-LABEL: 0 | struct XC{{$}}
183 // CHECK-X64-NEXT: 0 | (XC vbtable pointer)
184 // CHECK-X64-NEXT: 12 | (vtordisp for vbase XB)
185 // CHECK-X64-NEXT: 16 | struct XB (virtual base)
186 // CHECK-X64-NEXT: 16 | (XB vftable pointer)
187 // CHECK-X64-NEXT: 24 | struct XA (base)
188 // CHECK-X64-NEXT: 24 | long long ll
189 // CHECK-X64-NEXT: 32 | int b
190 // CHECK-X64-NEXT: | [sizeof=40, align=8
191 // CHECK-X64-NEXT: | nvsize=8, nvalign=8]
193 namespace pragma_test1
{
194 // No overrides means no vtordisps by default.
195 struct A
{ virtual ~A(); virtual void foo(); int a
; };
196 struct B
: virtual A
{ virtual ~B(); virtual void bar(); int b
; };
197 struct C
: virtual B
{ int c
; };
198 // CHECK-LABEL: 0 | struct pragma_test1::C{{$}}
199 // CHECK-NEXT: 0 | (C vbtable pointer)
200 // CHECK-NEXT: 4 | int c
201 // CHECK-NEXT: 8 | struct pragma_test1::A (virtual base)
202 // CHECK-NEXT: 8 | (A vftable pointer)
203 // CHECK-NEXT: 12 | int a
204 // CHECK-NEXT: 16 | struct pragma_test1::B (virtual base)
205 // CHECK-NEXT: 16 | (B vftable pointer)
206 // CHECK-NEXT: 20 | (B vbtable pointer)
207 // CHECK-NEXT: 24 | int b
208 // CHECK-NEXT: | [sizeof=28, align=4
209 // CHECK-NEXT: | nvsize=8, nvalign=4]
212 namespace pragma_test2
{
213 struct A
{ virtual ~A(); virtual void foo(); int a
; };
214 #pragma vtordisp(push,2)
215 struct B
: virtual A
{ virtual ~B(); virtual void bar(); int b
; };
216 struct C
: virtual B
{ int c
; };
217 #pragma vtordisp(pop)
218 // CHECK-LABEL: 0 | struct pragma_test2::C{{$}}
219 // CHECK-NEXT: 0 | (C vbtable pointer)
220 // CHECK-NEXT: 4 | int c
221 // CHECK-NEXT: 8 | (vtordisp for vbase A)
222 // CHECK-NEXT: 12 | struct pragma_test2::A (virtual base)
223 // CHECK-NEXT: 12 | (A vftable pointer)
224 // CHECK-NEXT: 16 | int a
225 // By adding a virtual method and vftable to B, now we need a vtordisp.
226 // CHECK-NEXT: 20 | (vtordisp for vbase B)
227 // CHECK-NEXT: 24 | struct pragma_test2::B (virtual base)
228 // CHECK-NEXT: 24 | (B vftable pointer)
229 // CHECK-NEXT: 28 | (B vbtable pointer)
230 // CHECK-NEXT: 32 | int b
231 // CHECK-NEXT: | [sizeof=36, align=4
232 // CHECK-NEXT: | nvsize=8, nvalign=4]
235 namespace pragma_test3
{
236 struct A
{ virtual ~A(); virtual void foo(); int a
; };
237 #pragma vtordisp(push,2)
238 struct B
: virtual A
{ virtual ~B(); virtual void foo(); int b
; };
239 struct C
: virtual B
{ int c
; };
240 #pragma vtordisp(pop)
241 // CHECK-LABEL: 0 | struct pragma_test3::C{{$}}
242 // CHECK-NEXT: 0 | (C vbtable pointer)
243 // CHECK-NEXT: 4 | int c
244 // CHECK-NEXT: 8 | (vtordisp for vbase A)
245 // CHECK-NEXT: 12 | struct pragma_test3::A (virtual base)
246 // CHECK-NEXT: 12 | (A vftable pointer)
247 // CHECK-NEXT: 16 | int a
248 // No vtordisp before B! It doesn't have its own vftable.
249 // CHECK-NEXT: 20 | struct pragma_test3::B (virtual base)
250 // CHECK-NEXT: 20 | (B vbtable pointer)
251 // CHECK-NEXT: 24 | int b
252 // CHECK-NEXT: | [sizeof=28, align=4
253 // CHECK-NEXT: | nvsize=8, nvalign=4]
256 namespace pragma_test4
{
263 // Make sure the pragma applies to class template decls before they've been
265 #pragma vtordisp(push,2)
266 template <typename T
>
267 struct B
: virtual A
{
273 #pragma vtordisp(pop)
275 struct C
: virtual B
<int> { int c
; };
276 // CHECK-LABEL: 0 | struct pragma_test4::C{{$}}
277 // CHECK-NEXT: 0 | (C vbtable pointer)
278 // CHECK-NEXT: 4 | int c
279 // Pragma applies to B, which has vbase A.
280 // CHECK-NEXT: 8 | (vtordisp for vbase A)
281 // CHECK-NEXT: 12 | struct pragma_test4::A (virtual base)
282 // CHECK-NEXT: 12 | (A vftable pointer)
283 // CHECK-NEXT: 16 | int a
284 // Pragma does not apply to C, and B doesn't usually need a vtordisp in C.
285 // CHECK-NEXT: 20 | struct pragma_test4::B<int> (virtual base)
286 // CHECK-NEXT: 20 | (B vftable pointer)
287 // CHECK-NEXT: 24 | (B vbtable pointer)
288 // CHECK-NEXT: 28 | int b
289 // CHECK-NEXT: | [sizeof=32, align=4
290 // CHECK-NEXT: | nvsize=8, nvalign=4]
294 virtual void fun() {}
296 struct GB
: public GA
{};
297 struct GC
: public virtual GA
{
298 virtual void fun() {}
301 struct GD
: public virtual GC
, public virtual GB
{};
303 // CHECK-LABEL: 0 | struct GD{{$}}
304 // CHECK-NEXT: 0 | (GD vbtable pointer)
305 // CHECK-NEXT: 4 | (vtordisp for vbase GA)
306 // CHECK-NEXT: 8 | struct GA (virtual base)
307 // CHECK-NEXT: 8 | (GA vftable pointer)
308 // CHECK-NEXT: 12 | struct GC (virtual base)
309 // CHECK-NEXT: 12 | (GC vbtable pointer)
310 // CHECK-NEXT: 16 | struct GB (virtual base)
311 // CHECK-NEXT: 16 | struct GA (primary base)
312 // CHECK-NEXT: 16 | (GA vftable pointer)
313 // CHECK-NEXT: | [sizeof=20, align=4
314 // CHECK-NEXT: | nvsize=4, nvalign=4]
315 // CHECK-X64-LABEL: 0 | struct GD{{$}}
316 // CHECK-X64-NEXT: 0 | (GD vbtable pointer)
317 // CHECK-X64-NEXT: 12 | (vtordisp for vbase GA)
318 // CHECK-X64-NEXT: 16 | struct GA (virtual base)
319 // CHECK-X64-NEXT: 16 | (GA vftable pointer)
320 // CHECK-X64-NEXT: 24 | struct GC (virtual base)
321 // CHECK-X64-NEXT: 24 | (GC vbtable pointer)
322 // CHECK-X64-NEXT: 32 | struct GB (virtual base)
323 // CHECK-X64-NEXT: 32 | struct GA (primary base)
324 // CHECK-X64-NEXT: 32 | (GA vftable pointer)
325 // CHECK-X64-NEXT: | [sizeof=40, align=8
326 // CHECK-X64-NEXT: | nvsize=8, nvalign=8]
329 virtual void fun() {}
331 #pragma vtordisp(push, 2)
332 struct HB
: virtual HA
{};
333 #pragma vtordisp(pop)
334 #pragma vtordisp(push, 0)
335 struct HC
: virtual HB
{};
336 #pragma vtordisp(pop)
338 // CHECK-LABEL: 0 | struct HC{{$}}
339 // CHECK-NEXT: 0 | (HC vbtable pointer)
340 // CHECK-NEXT: 4 | (vtordisp for vbase HA)
341 // CHECK-NEXT: 8 | struct HA (virtual base)
342 // CHECK-NEXT: 8 | (HA vftable pointer)
343 // CHECK-NEXT: 12 | struct HB (virtual base)
344 // CHECK-NEXT: 12 | (HB vbtable pointer)
345 // CHECK-NEXT: | [sizeof=16, align=4
346 // CHECK-NEXT: | nvsize=4, nvalign=4]
347 // CHECK-X64-LABEL: 0 | struct HC{{$}}
348 // CHECK-X64-NEXT: 0 | (HC vbtable pointer)
349 // CHECK-X64-NEXT: 12 | (vtordisp for vbase HA)
350 // CHECK-X64-NEXT: 16 | struct HA (virtual base)
351 // CHECK-X64-NEXT: 16 | (HA vftable pointer)
352 // CHECK-X64-NEXT: 24 | struct HB (virtual base)
353 // CHECK-X64-NEXT: 24 | (HB vbtable pointer)
354 // CHECK-X64-NEXT: | [sizeof=32, align=8
355 // CHECK-X64-NEXT: | nvsize=8, nvalign=8]
360 struct __declspec(dllexport
) IB
: virtual IA
{
361 virtual void f() = 0;
365 // CHECK-LABEL: 0 | struct IB{{$}}
366 // CHECK-NEXT: 0 | (IB vbtable pointer)
367 // CHECK-NEXT: 4 | struct IA (virtual base)
368 // CHECK-NEXT: 4 | (IA vftable pointer)
369 // CHECK-NEXT: | [sizeof=8, align=4
370 // CHECK-NEXT: | nvsize=4, nvalign=4]
371 // CHECK-X64-LABEL: 0 | struct IB{{$}}
372 // CHECK-X64-NEXT: 0 | (IB vbtable pointer)
373 // CHECK-X64-NEXT: 8 | struct IA (virtual base)
374 // CHECK-X64-NEXT: 8 | (IA vftable pointer)
375 // CHECK-X64-NEXT: | [sizeof=16, align=8
376 // CHECK-X64-NEXT: | nvsize=8, nvalign=8]
384 sizeof(pragma_test1::C
)+
385 sizeof(pragma_test2::C
)+
386 sizeof(pragma_test3::C
)+
387 sizeof(pragma_test4::C
)+