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
6 extern "C" int printf(const char *fmt, ...);
7
8 struct B0 {
9 int a;
B0B010 B0() : a(0xf00000B0) {}
fB011 virtual void f() { printf("B0"); }
12 };
13
14 struct __declspec(align(16)) B1 {
15 int a;
B1B116 B1() : a(0xf00000B1) {}
fB117 virtual void f() { printf("B1"); }
18 };
19
20 struct __declspec(align(16)) Align16 {};
21 struct __declspec(align(32)) Align32 {};
22 struct VAlign16 : virtual Align16 {};
23 struct VAlign32 : virtual Align32 {};
24
25 struct A : virtual B0, virtual B1 {
26 int a;
AA27 A() : a(0xf000000A) {}
fA28 virtual void f() { printf("A"); }
gA29 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
67 struct C : virtual B0, virtual B1, VAlign32 {
68 int a;
CC69 C() : a(0xf000000C) {}
fC70 virtual void f() { printf("C"); }
gC71 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
113 struct __declspec(align(32)) D : virtual B0, virtual B1 {
114 int a;
DD115 D() : a(0xf000000D) {}
fD116 virtual void f() { printf("D"); }
gD117 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
151 struct AT {
~ATAT152 virtual ~AT(){}
153 };
154 struct CT : virtual AT {
155 virtual ~CT();
156 };
~CT()157 CT::~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
176 struct XA {
XAXA177 XA() { printf("XA"); }
178 long long ll;
179 };
180 struct XB : XA {
XBXB181 XB() { printf("XB"); }
fooXB182 virtual void foo() {}
183 int b;
184 };
185 struct XC : virtual XB {
XCXC186 XC() { printf("XC"); }
fooXC187 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
217 namespace pragma_test1 {
218 // No overrides means no vtordisps by default.
219 struct A { virtual ~A(); virtual void foo(); int a; };
220 struct B : virtual A { virtual ~B(); virtual void bar(); int b; };
221 struct 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
242 namespace pragma_test2 {
243 struct A { virtual ~A(); virtual void foo(); int a; };
244 #pragma vtordisp(push,2)
245 struct B : virtual A { virtual ~B(); virtual void bar(); int b; };
246 struct 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
271 namespace pragma_test3 {
272 struct A { virtual ~A(); virtual void foo(); int a; };
273 #pragma vtordisp(push,2)
274 struct B : virtual A { virtual ~B(); virtual void foo(); int b; };
275 struct 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
298 namespace pragma_test4 {
299 struct 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)
308 template <typename T>
309 struct B : virtual A {
310 B();
311 virtual ~B();
312 virtual void bar();
313 T b;
314 };
315 #pragma vtordisp(pop)
316
317 struct 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
341 struct GA {
funGA342 virtual void fun() {}
343 };
344 struct GB: public GA {};
345 struct GC: public virtual GA {
funGC346 virtual void fun() {}
GCGC347 GC() {}
348 };
349 struct 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
384 struct HA {
funHA385 virtual void fun() {}
386 };
387 #pragma vtordisp(push, 2)
388 struct HB : virtual HA {};
389 #pragma vtordisp(pop)
390 #pragma vtordisp(push, 0)
391 struct 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
419 struct IA {
420 virtual void f();
421 };
422 struct __declspec(dllexport) IB : virtual IA {
423 virtual void f() = 0;
IBIB424 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
444 int a[
445 sizeof(A)+
446 sizeof(C)+
447 sizeof(D)+
448 sizeof(CT)+
449 sizeof(XC)+
450 sizeof(pragma_test1::C)+
451 sizeof(pragma_test2::C)+
452 sizeof(pragma_test3::C)+
453 sizeof(pragma_test4::C)+
454 sizeof(GD)+
455 sizeof(HC)+
456 sizeof(IB)+
457 0];
458