1// RUN: %clang_cc1 -fno-rtti -fms-extensions -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 \
2// RUN:            | FileCheck %s
3// RUN: %clang_cc1 -fno-rtti -fms-extensions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>/dev/null \
4// RUN:            | FileCheck %s -check-prefix CHECK-X64
5
6extern "C" int printf(const char *fmt, ...);
7
8struct B0 {
9	int a;
10	B0() : a(0xf00000B0) {}
11	virtual void f() { printf("B0"); }
12};
13
14struct __declspec(align(16)) B1 {
15	int a;
16	B1() : a(0xf00000B1) {}
17	virtual void f() { printf("B1"); }
18};
19
20struct __declspec(align(16)) Align16 {};
21struct __declspec(align(32)) Align32 {};
22struct VAlign16 : virtual Align16 {};
23struct VAlign32 : virtual Align32 {};
24
25struct A : virtual B0, virtual B1 {
26	int a;
27	A() : a(0xf000000A) {}
28	virtual void f() { printf("A"); }
29	virtual void g() { printf("A"); }
30};
31
32// CHECK: *** Dumping AST Record Layout
33// CHECK: *** Dumping AST Record Layout
34// CHECK: *** Dumping AST Record Layout
35// CHECK-NEXT:    0 | struct A
36// CHECK-NEXT:    0 |   (A vftable pointer)
37// CHECK-NEXT:    4 |   (A vbtable pointer)
38// CHECK-NEXT:    8 |   int a
39// CHECK-NEXT:   16 |   (vtordisp for vbase B0)
40// CHECK-NEXT:   20 |   struct B0 (virtual base)
41// CHECK-NEXT:   20 |     (B0 vftable pointer)
42// CHECK-NEXT:   24 |     int a
43// CHECK-NEXT:   44 |   (vtordisp for vbase B1)
44// CHECK-NEXT:   48 |   struct B1 (virtual base)
45// CHECK-NEXT:   48 |     (B1 vftable pointer)
46// CHECK-NEXT:   52 |     int a
47// CHECK-NEXT:      | [sizeof=64, align=16
48// CHECK-NEXT:      |  nvsize=12, nvalign=16]
49// CHECK-X64: *** Dumping AST Record Layout
50// CHECK-X64: *** Dumping AST Record Layout
51// CHECK-X64: *** Dumping AST Record Layout
52// CHECK-X64-NEXT:    0 | struct A
53// CHECK-X64-NEXT:    0 |   (A vftable pointer)
54// CHECK-X64-NEXT:    8 |   (A vbtable pointer)
55// CHECK-X64-NEXT:   16 |   int a
56// CHECK-X64-NEXT:   36 |   (vtordisp for vbase B0)
57// CHECK-X64-NEXT:   40 |   struct B0 (virtual base)
58// CHECK-X64-NEXT:   40 |     (B0 vftable pointer)
59// CHECK-X64-NEXT:   48 |     int a
60// CHECK-X64-NEXT:   76 |   (vtordisp for vbase B1)
61// CHECK-X64-NEXT:   80 |   struct B1 (virtual base)
62// CHECK-X64-NEXT:   80 |     (B1 vftable pointer)
63// CHECK-X64-NEXT:   88 |     int a
64// CHECK-X64-NEXT:      | [sizeof=96, align=16
65// CHECK-X64-NEXT:      |  nvsize=24, nvalign=16]
66
67struct C : virtual B0, virtual B1, VAlign32 {
68	int a;
69	C() : a(0xf000000C) {}
70	virtual void f() { printf("C"); }
71	virtual void g() { printf("C"); }
72};
73
74// CHECK: *** Dumping AST Record Layout
75// CHECK: *** Dumping AST Record Layout
76// CHECK: *** Dumping AST Record Layout
77// CHECK-NEXT:    0 | struct C
78// CHECK-NEXT:    0 |   (C vftable pointer)
79// CHECK-NEXT:   32 |   struct VAlign32 (base)
80// CHECK-NEXT:   32 |     (VAlign32 vbtable pointer)
81// CHECK-NEXT:   36 |   int a
82// CHECK-NEXT:   64 |   (vtordisp for vbase B0)
83// CHECK-NEXT:   68 |   struct B0 (virtual base)
84// CHECK-NEXT:   68 |     (B0 vftable pointer)
85// CHECK-NEXT:   72 |     int a
86// CHECK-NEXT:  108 |   (vtordisp for vbase B1)
87// CHECK-NEXT:  112 |   struct B1 (virtual base)
88// CHECK-NEXT:  112 |     (B1 vftable pointer)
89// CHECK-NEXT:  116 |     int a
90// CHECK-NEXT:  128 |   struct Align32 (virtual base) (empty)
91// CHECK-NEXT:      | [sizeof=128, align=32
92// CHECK-NEXT:      |  nvsize=64, nvalign=32]
93// CHECK-X64: *** Dumping AST Record Layout
94// CHECK-X64: *** Dumping AST Record Layout
95// CHECK-X64: *** Dumping AST Record Layout
96// CHECK-X64-NEXT:    0 | struct C
97// CHECK-X64-NEXT:    0 |   (C vftable pointer)
98// CHECK-X64-NEXT:   32 |   struct VAlign32 (base)
99// CHECK-X64-NEXT:   32 |     (VAlign32 vbtable pointer)
100// CHECK-X64-NEXT:   40 |   int a
101// CHECK-X64-NEXT:   68 |   (vtordisp for vbase B0)
102// CHECK-X64-NEXT:   72 |   struct B0 (virtual base)
103// CHECK-X64-NEXT:   72 |     (B0 vftable pointer)
104// CHECK-X64-NEXT:   80 |     int a
105// CHECK-X64-NEXT:  108 |   (vtordisp for vbase B1)
106// CHECK-X64-NEXT:  112 |   struct B1 (virtual base)
107// CHECK-X64-NEXT:  112 |     (B1 vftable pointer)
108// CHECK-X64-NEXT:  120 |     int a
109// CHECK-X64-NEXT:  128 |   struct Align32 (virtual base) (empty)
110// CHECK-X64-NEXT:      | [sizeof=128, align=32
111// CHECK-X64-NEXT:      |  nvsize=64, nvalign=32]
112
113struct __declspec(align(32)) D : virtual B0, virtual B1  {
114	int a;
115	D() : a(0xf000000D) {}
116	virtual void f() { printf("D"); }
117	virtual void g() { printf("D"); }
118};
119
120// CHECK: *** Dumping AST Record Layout
121// CHECK-NEXT:    0 | struct D
122// CHECK-NEXT:    0 |   (D vftable pointer)
123// CHECK-NEXT:    4 |   (D vbtable pointer)
124// CHECK-NEXT:    8 |   int a
125// CHECK-NEXT:   32 |   (vtordisp for vbase B0)
126// CHECK-NEXT:   36 |   struct B0 (virtual base)
127// CHECK-NEXT:   36 |     (B0 vftable pointer)
128// CHECK-NEXT:   40 |     int a
129// CHECK-NEXT:   76 |   (vtordisp for vbase B1)
130// CHECK-NEXT:   80 |   struct B1 (virtual base)
131// CHECK-NEXT:   80 |     (B1 vftable pointer)
132// CHECK-NEXT:   84 |     int a
133// CHECK-NEXT:      | [sizeof=96, align=32
134// CHECK-NEXT:      |  nvsize=12, nvalign=32]
135// CHECK-X64: *** Dumping AST Record Layout
136// CHECK-X64-NEXT:    0 | struct D
137// CHECK-X64-NEXT:    0 |   (D vftable pointer)
138// CHECK-X64-NEXT:    8 |   (D vbtable pointer)
139// CHECK-X64-NEXT:   16 |   int a
140// CHECK-X64-NEXT:   36 |   (vtordisp for vbase B0)
141// CHECK-X64-NEXT:   40 |   struct B0 (virtual base)
142// CHECK-X64-NEXT:   40 |     (B0 vftable pointer)
143// CHECK-X64-NEXT:   48 |     int a
144// CHECK-X64-NEXT:   76 |   (vtordisp for vbase B1)
145// CHECK-X64-NEXT:   80 |   struct B1 (virtual base)
146// CHECK-X64-NEXT:   80 |     (B1 vftable pointer)
147// CHECK-X64-NEXT:   88 |     int a
148// CHECK-X64-NEXT:      | [sizeof=96, align=32
149// CHECK-X64-NEXT:      |  nvsize=24, nvalign=32]
150
151struct AT {
152	virtual ~AT(){}
153};
154struct CT : virtual AT {
155	virtual ~CT();
156};
157CT::~CT(){}
158
159// CHECK: *** Dumping AST Record Layout
160// CHECK: *** Dumping AST Record Layout
161// CHECK-NEXT:    0 | struct CT
162// CHECK-NEXT:    0 |   (CT vbtable pointer)
163// CHECK-NEXT:    4 |   struct AT (virtual base)
164// CHECK-NEXT:    4 |     (AT vftable pointer)
165// CHECK-NEXT:      | [sizeof=8, align=4
166// CHECK-NEXT:      |  nvsize=4, nvalign=4]
167// CHECK-X64: *** Dumping AST Record Layout
168// CHECK-X64: *** Dumping AST Record Layout
169// CHECK-X64-NEXT:    0 | struct CT
170// CHECK-X64-NEXT:    0 |   (CT vbtable pointer)
171// CHECK-X64-NEXT:    8 |   struct AT (virtual base)
172// CHECK-X64-NEXT:    8 |     (AT vftable pointer)
173// CHECK-X64-NEXT:      | [sizeof=16, align=8
174// CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
175
176struct XA {
177	XA() { printf("XA"); }
178	long long ll;
179};
180struct XB : XA {
181	XB() { printf("XB"); }
182	virtual void foo() {}
183	int b;
184};
185struct XC : virtual XB {
186	XC() { printf("XC"); }
187	virtual void foo() {}
188};
189
190// CHECK: *** Dumping AST Record Layout
191// CHECK: *** Dumping AST Record Layout
192// CHECK: *** Dumping AST Record Layout
193// CHECK-NEXT:    0 | struct XC
194// CHECK-NEXT:    0 |   (XC vbtable pointer)
195// CHECK-NEXT:    4 |   (vtordisp for vbase XB)
196// CHECK-NEXT:    8 |   struct XB (virtual base)
197// CHECK-NEXT:    8 |     (XB vftable pointer)
198// CHECK-NEXT:   16 |     struct XA (base)
199// CHECK-NEXT:   16 |       long long ll
200// CHECK-NEXT:   24 |     int b
201// CHECK-NEXT:      | [sizeof=32, align=8
202// CHECK-NEXT:      |  nvsize=4, nvalign=8]
203// CHECK-X64: *** Dumping AST Record Layout
204// CHECK-X64: *** Dumping AST Record Layout
205// CHECK-X64: *** Dumping AST Record Layout
206// CHECK-X64-NEXT:    0 | struct XC
207// CHECK-X64-NEXT:    0 |   (XC vbtable pointer)
208// CHECK-X64-NEXT:   12 |   (vtordisp for vbase XB)
209// CHECK-X64-NEXT:   16 |   struct XB (virtual base)
210// CHECK-X64-NEXT:   16 |     (XB vftable pointer)
211// CHECK-X64-NEXT:   24 |     struct XA (base)
212// CHECK-X64-NEXT:   24 |       long long ll
213// CHECK-X64-NEXT:   32 |     int b
214// CHECK-X64-NEXT:      | [sizeof=40, align=8
215// CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
216
217namespace pragma_test1 {
218// No overrides means no vtordisps by default.
219struct A { virtual ~A(); virtual void foo(); int a; };
220struct B : virtual A { virtual ~B(); virtual void bar(); int b; };
221struct C : virtual B { int c; };
222// CHECK: *** Dumping AST Record Layout
223// CHECK: *** Dumping AST Record Layout
224// CHECK: *** Dumping AST Record Layout
225// CHECK-NEXT:    0 | struct pragma_test1::C
226// CHECK-NEXT:    0 |   (C vbtable pointer)
227// CHECK-NEXT:    4 |   int c
228// CHECK-NEXT:    8 |   struct pragma_test1::A (virtual base)
229// CHECK-NEXT:    8 |     (A vftable pointer)
230// CHECK-NEXT:   12 |     int a
231// CHECK-NEXT:   16 |   struct pragma_test1::B (virtual base)
232// CHECK-NEXT:   16 |     (B vftable pointer)
233// CHECK-NEXT:   20 |     (B vbtable pointer)
234// CHECK-NEXT:   24 |     int b
235// CHECK-NEXT:      | [sizeof=28, align=4
236// CHECK-NEXT:      |  nvsize=8, nvalign=4]
237// CHECK-X64: *** Dumping AST Record Layout
238// CHECK-X64: *** Dumping AST Record Layout
239// CHECK-X64: *** Dumping AST Record Layout
240}
241
242namespace pragma_test2 {
243struct A { virtual ~A(); virtual void foo(); int a; };
244#pragma vtordisp(push,2)
245struct B : virtual A { virtual ~B(); virtual void bar(); int b; };
246struct C : virtual B { int c; };
247#pragma vtordisp(pop)
248// CHECK: *** Dumping AST Record Layout
249// CHECK: *** Dumping AST Record Layout
250// CHECK: *** Dumping AST Record Layout
251// CHECK-NEXT:    0 | struct pragma_test2::C
252// CHECK-NEXT:    0 |   (C vbtable pointer)
253// CHECK-NEXT:    4 |   int c
254// CHECK-NEXT:    8 |   (vtordisp for vbase A)
255// CHECK-NEXT:   12 |   struct pragma_test2::A (virtual base)
256// CHECK-NEXT:   12 |     (A vftable pointer)
257// CHECK-NEXT:   16 |     int a
258//   By adding a virtual method and vftable to B, now we need a vtordisp.
259// CHECK-NEXT:   20 |   (vtordisp for vbase B)
260// CHECK-NEXT:   24 |   struct pragma_test2::B (virtual base)
261// CHECK-NEXT:   24 |     (B vftable pointer)
262// CHECK-NEXT:   28 |     (B vbtable pointer)
263// CHECK-NEXT:   32 |     int b
264// CHECK-NEXT:      | [sizeof=36, align=4
265// CHECK-NEXT:      |  nvsize=8, nvalign=4]
266// CHECK-X64: *** Dumping AST Record Layout
267// CHECK-X64: *** Dumping AST Record Layout
268// CHECK-X64: *** Dumping AST Record Layout
269}
270
271namespace pragma_test3 {
272struct A { virtual ~A(); virtual void foo(); int a; };
273#pragma vtordisp(push,2)
274struct B : virtual A { virtual ~B(); virtual void foo(); int b; };
275struct C : virtual B { int c; };
276#pragma vtordisp(pop)
277// CHECK: *** Dumping AST Record Layout
278// CHECK: *** Dumping AST Record Layout
279// CHECK: *** Dumping AST Record Layout
280// CHECK-NEXT:    0 | struct pragma_test3::C
281// CHECK-NEXT:    0 |   (C vbtable pointer)
282// CHECK-NEXT:    4 |   int c
283// CHECK-NEXT:    8 |   (vtordisp for vbase A)
284// CHECK-NEXT:   12 |   struct pragma_test3::A (virtual base)
285// CHECK-NEXT:   12 |     (A vftable pointer)
286// CHECK-NEXT:   16 |     int a
287//   No vtordisp before B!  It doesn't have its own vftable.
288// CHECK-NEXT:   20 |   struct pragma_test3::B (virtual base)
289// CHECK-NEXT:   20 |     (B vbtable pointer)
290// CHECK-NEXT:   24 |     int b
291// CHECK-NEXT:      | [sizeof=28, align=4
292// CHECK-NEXT:      |  nvsize=8, nvalign=4]
293// CHECK-X64: *** Dumping AST Record Layout
294// CHECK-X64: *** Dumping AST Record Layout
295// CHECK-X64: *** Dumping AST Record Layout
296}
297
298namespace pragma_test4 {
299struct A {
300  A();
301  virtual void foo();
302  int a;
303};
304
305// Make sure the pragma applies to class template decls before they've been
306// instantiated.
307#pragma vtordisp(push,2)
308template <typename T>
309struct B : virtual A {
310  B();
311  virtual ~B();
312  virtual void bar();
313  T b;
314};
315#pragma vtordisp(pop)
316
317struct C : virtual B<int> { int c; };
318// CHECK: *** Dumping AST Record Layout
319// CHECK: *** Dumping AST Record Layout
320// CHECK: *** Dumping AST Record Layout
321// CHECK-NEXT:    0 | struct pragma_test4::C
322// CHECK-NEXT:    0 |   (C vbtable pointer)
323// CHECK-NEXT:    4 |   int c
324//   Pragma applies to B, which has vbase A.
325// CHECK-NEXT:    8 |   (vtordisp for vbase A)
326// CHECK-NEXT:   12 |   struct pragma_test4::A (virtual base)
327// CHECK-NEXT:   12 |     (A vftable pointer)
328// CHECK-NEXT:   16 |     int a
329//   Pragma does not apply to C, and B doesn't usually need a vtordisp in C.
330// CHECK-NEXT:   20 |   struct pragma_test4::B<int> (virtual base)
331// CHECK-NEXT:   20 |     (B vftable pointer)
332// CHECK-NEXT:   24 |     (B vbtable pointer)
333// CHECK-NEXT:   28 |     int b
334// CHECK-NEXT:      | [sizeof=32, align=4
335// CHECK-NEXT:      |  nvsize=8, nvalign=4]
336// CHECK-X64: *** Dumping AST Record Layout
337// CHECK-X64: *** Dumping AST Record Layout
338// CHECK-X64: *** Dumping AST Record Layout
339}
340
341struct GA {
342	virtual void fun() {}
343};
344struct GB: public GA {};
345struct GC: public virtual GA {
346	virtual void fun() {}
347	GC() {}
348};
349struct GD: public virtual GC, public virtual GB {};
350
351// CHECK: *** Dumping AST Record Layout
352// CHECK: *** Dumping AST Record Layout
353// CHECK: *** Dumping AST Record Layout
354// CHECK: *** Dumping AST Record Layout
355// CHECK-NEXT:    0 | struct GD
356// CHECK-NEXT:    0 |   (GD vbtable pointer)
357// CHECK-NEXT:    4 |   (vtordisp for vbase GA)
358// CHECK-NEXT:    8 |   struct GA (virtual base)
359// CHECK-NEXT:    8 |     (GA vftable pointer)
360// CHECK-NEXT:   12 |   struct GC (virtual base)
361// CHECK-NEXT:   12 |     (GC vbtable pointer)
362// CHECK-NEXT:   16 |   struct GB (virtual base)
363// CHECK-NEXT:   16 |     struct GA (primary base)
364// CHECK-NEXT:   16 |       (GA vftable pointer)
365// CHECK-NEXT:      | [sizeof=20, align=4
366// CHECK-NEXT:      |  nvsize=4, nvalign=4]
367// CHECK-X64: *** Dumping AST Record Layout
368// CHECK-X64: *** Dumping AST Record Layout
369// CHECK-X64: *** Dumping AST Record Layout
370// CHECK-X64: *** Dumping AST Record Layout
371// CHECK-X64-NEXT:    0 | struct GD
372// CHECK-X64-NEXT:    0 |   (GD vbtable pointer)
373// CHECK-X64-NEXT:   12 |   (vtordisp for vbase GA)
374// CHECK-X64-NEXT:   16 |   struct GA (virtual base)
375// CHECK-X64-NEXT:   16 |     (GA vftable pointer)
376// CHECK-X64-NEXT:   24 |   struct GC (virtual base)
377// CHECK-X64-NEXT:   24 |     (GC vbtable pointer)
378// CHECK-X64-NEXT:   32 |   struct GB (virtual base)
379// CHECK-X64-NEXT:   32 |     struct GA (primary base)
380// CHECK-X64-NEXT:   32 |       (GA vftable pointer)
381// CHECK-X64-NEXT:      | [sizeof=40, align=8
382// CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
383
384struct HA {
385  virtual void fun() {}
386};
387#pragma vtordisp(push, 2)
388struct HB : virtual HA {};
389#pragma vtordisp(pop)
390#pragma vtordisp(push, 0)
391struct HC : virtual HB {};
392#pragma vtordisp(pop)
393
394// CHECK: *** Dumping AST Record Layout
395// CHECK: *** Dumping AST Record Layout
396// CHECK: *** Dumping AST Record Layout
397// CHECK-NEXT:    0 | struct HC
398// CHECK-NEXT:    0 |   (HC vbtable pointer)
399// CHECK-NEXT:    4 |   (vtordisp for vbase HA)
400// CHECK-NEXT:    8 |   struct HA (virtual base)
401// CHECK-NEXT:    8 |     (HA vftable pointer)
402// CHECK-NEXT:   12 |   struct HB (virtual base)
403// CHECK-NEXT:   12 |     (HB vbtable pointer)
404// CHECK-NEXT:      | [sizeof=16, align=4
405// CHECK-NEXT:      |  nvsize=4, nvalign=4]
406// CHECK-X64: *** Dumping AST Record Layout
407// CHECK-X64: *** Dumping AST Record Layout
408// CHECK-X64: *** Dumping AST Record Layout
409// CHECK-X64-NEXT:    0 | struct HC
410// CHECK-X64-NEXT:    0 |   (HC vbtable pointer)
411// CHECK-X64-NEXT:   12 |   (vtordisp for vbase HA)
412// CHECK-X64-NEXT:   16 |   struct HA (virtual base)
413// CHECK-X64-NEXT:   16 |     (HA vftable pointer)
414// CHECK-X64-NEXT:   24 |   struct HB (virtual base)
415// CHECK-X64-NEXT:   24 |     (HB vbtable pointer)
416// CHECK-X64-NEXT:      | [sizeof=32, align=8
417// CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
418
419struct IA {
420  virtual void f();
421};
422struct __declspec(dllexport) IB : virtual IA {
423  virtual void f() = 0;
424  IB() {}
425};
426
427// CHECK: *** Dumping AST Record Layout
428// CHECK: *** Dumping AST Record Layout
429// CHECK-NEXT:    0 | struct IB
430// CHECK-NEXT:    0 |   (IB vbtable pointer)
431// CHECK-NEXT:    4 |   struct IA (virtual base)
432// CHECK-NEXT:    4 |     (IA vftable pointer)
433// CHECK-NEXT:      | [sizeof=8, align=4
434// CHECK-NEXT:      |  nvsize=4, nvalign=4]
435// CHECK-X64: *** Dumping AST Record Layout
436// CHECK-X64: *** Dumping AST Record Layout
437// CHECK-X64-NEXT:    0 | struct IB
438// CHECK-X64-NEXT:    0 |   (IB vbtable pointer)
439// CHECK-X64-NEXT:    8 |   struct IA (virtual base)
440// CHECK-X64-NEXT:    8 |     (IA vftable pointer)
441// CHECK-X64-NEXT:      | [sizeof=16, align=8
442// CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
443
444int a[
445sizeof(A)+
446sizeof(C)+
447sizeof(D)+
448sizeof(CT)+
449sizeof(XC)+
450sizeof(pragma_test1::C)+
451sizeof(pragma_test2::C)+
452sizeof(pragma_test3::C)+
453sizeof(pragma_test4::C)+
454sizeof(GD)+
455sizeof(HC)+
456sizeof(IB)+
4570];
458