1 | // RUN: %clang_cc1 -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts %s 2>/dev/null \ |
2 | // RUN: | FileCheck %s |
3 | |
4 | #pragma pack(push, 8) |
5 | |
6 | class B { |
7 | public: |
8 | virtual void b(){} |
9 | int b_field; |
10 | protected: |
11 | private: |
12 | }; |
13 | |
14 | class A : public B { |
15 | public: |
16 | int a_field; |
17 | virtual void a(){} |
18 | char one; |
19 | protected: |
20 | private: |
21 | }; |
22 | |
23 | class D { |
24 | public: |
25 | virtual void b(){} |
26 | double a; |
27 | }; |
28 | |
29 | class C : public virtual A, |
30 | public D, public B { |
31 | public: |
32 | double c1_field; |
33 | int c2_field; |
34 | double c3_field; |
35 | int c4_field; |
36 | virtual void foo(){} |
37 | virtual void bar(){} |
38 | protected: |
39 | private: |
40 | }; |
41 | |
42 | struct BaseStruct |
43 | { |
44 | BaseStruct(){} |
45 | double v0; |
46 | float v1; |
47 | C fg; |
48 | }; |
49 | |
50 | struct DerivedStruct : public BaseStruct { |
51 | int x; |
52 | }; |
53 | |
54 | struct G |
55 | { |
56 | int g_field; |
57 | }; |
58 | |
59 | struct H : public G, |
60 | public virtual D |
61 | { |
62 | }; |
63 | |
64 | struct I : public virtual D |
65 | { |
66 | virtual ~I(){} |
67 | double q; |
68 | }; |
69 | |
70 | struct K |
71 | { |
72 | int k; |
73 | }; |
74 | |
75 | struct L |
76 | { |
77 | int l; |
78 | }; |
79 | |
80 | struct M : public virtual K |
81 | { |
82 | int m; |
83 | }; |
84 | |
85 | struct N : public L, public M |
86 | { |
87 | virtual void f(){} |
88 | }; |
89 | |
90 | struct O : public H, public G { |
91 | virtual void fo(){} |
92 | }; |
93 | |
94 | struct P : public M, public virtual L { |
95 | int p; |
96 | }; |
97 | |
98 | struct R {}; |
99 | |
100 | class IA { |
101 | public: |
102 | virtual ~IA(){} |
103 | virtual void ia() = 0; |
104 | }; |
105 | |
106 | class ICh : public virtual IA { |
107 | public: |
108 | virtual ~ICh(){} |
109 | virtual void ia(){} |
110 | virtual void iCh(){} |
111 | }; |
112 | |
113 | struct f { |
114 | virtual int asd() {return -90;} |
115 | }; |
116 | |
117 | struct s : public virtual f { |
118 | virtual ~s(){} |
119 | int r; |
120 | virtual int asd() {return -9;} |
121 | }; |
122 | |
123 | struct sd : virtual s, virtual ICh { |
124 | virtual ~sd(){} |
125 | int q; |
126 | char y; |
127 | virtual int asd() {return -1;} |
128 | }; |
129 | struct AV { |
130 | virtual void foo(); |
131 | }; |
132 | struct BV : AV { |
133 | }; |
134 | struct CV : virtual BV { |
135 | CV(); |
136 | virtual void foo(); |
137 | }; |
138 | struct DV : BV { |
139 | }; |
140 | struct EV : CV, DV { |
141 | }; |
142 | #pragma pack(pop) |
143 | |
144 | // This needs only for building layouts. |
145 | // Without this clang doesn`t dump record layouts. |
146 | int main() { |
147 | // This avoid "Can't yet mangle constructors!" for MS ABI. |
148 | C* c; |
149 | c->foo(); |
150 | DerivedStruct* v; |
151 | H* g; |
152 | BaseStruct* u; |
153 | I* i; |
154 | N* n; |
155 | O* o; |
156 | P* p; |
157 | R* r; |
158 | sd *h; |
159 | EV *j; |
160 | return 0; |
161 | } |
162 | |
163 | // CHECK: 0 | class D |
164 | // CHECK-NEXT: 0 | (D vftable pointer) |
165 | // CHECK-NEXT: 8 | double a |
166 | |
167 | // CHECK-NEXT: sizeof=16, align=8 |
168 | // CHECK-NEXT: nvsize=16, nvalign=8 |
169 | |
170 | // CHECK: %class.D = type { i32 (...)**, double } |
171 | |
172 | // CHECK: 0 | class B |
173 | // CHECK-NEXT: 0 | (B vftable pointer) |
174 | // CHECK-NEXT: 4 | int b_field |
175 | |
176 | // CHECK-NEXT: sizeof=8, align=4 |
177 | // CHECK-NEXT: nvsize=8, nvalign=4 |
178 | |
179 | // CHECK: %class.B = type { i32 (...)**, i32 } |
180 | |
181 | // CHECK: 0 | class A |
182 | // CHECK-NEXT: 0 | class B (primary base) |
183 | // CHECK-NEXT: 0 | (B vftable pointer) |
184 | // CHECK-NEXT: 4 | int b_field |
185 | // CHECK-NEXT: 8 | int a_field |
186 | // CHECK-NEXT: 12 | char one |
187 | |
188 | // CHECK-NEXT: sizeof=16, align=4 |
189 | // CHECK-NEXT: nvsize=16, nvalign=4 |
190 | |
191 | // CHECK: 0 | class C |
192 | // CHECK-NEXT: 0 | class D (primary base) |
193 | // CHECK-NEXT: 0 | (D vftable pointer) |
194 | // CHECK-NEXT: 8 | double a |
195 | // CHECK-NEXT: 16 | class B (base) |
196 | // CHECK-NEXT: 16 | (B vftable pointer) |
197 | // CHECK-NEXT: 20 | int b_field |
198 | // CHECK-NEXT: 24 | (C vbtable pointer) |
199 | // CHECK-NEXT: 32 | double c1_field |
200 | // CHECK-NEXT: 40 | int c2_field |
201 | // CHECK-NEXT: 48 | double c3_field |
202 | // CHECK-NEXT: 56 | int c4_field |
203 | // CHECK-NEXT: 64 | class A (virtual base) |
204 | // CHECK-NEXT: 64 | class B (primary base) |
205 | // CHECK-NEXT: 64 | (B vftable pointer) |
206 | // CHECK-NEXT: 68 | int b_field |
207 | // CHECK-NEXT: 72 | int a_field |
208 | // CHECK-NEXT: 76 | char one |
209 | |
210 | // CHECK-NEXT: sizeof=80, align=8 |
211 | // CHECK-NEXT: nvsize=64, nvalign=8 |
212 | |
213 | // CHECK: %class.A = type { %class.B, i32, i8 } |
214 | |
215 | // CHECK: %class.C = type { %class.D, %class.B, i32*, double, i32, double, i32, [4 x i8], %class.A } |
216 | // CHECK: %class.C.base = type { %class.D, %class.B, i32*, double, i32, double, i32 } |
217 | |
218 | // CHECK: 0 | struct BaseStruct |
219 | // CHECK-NEXT: 0 | double v0 |
220 | // CHECK-NEXT: 8 | float v1 |
221 | // CHECK-NEXT: 16 | class C fg |
222 | // CHECK-NEXT: 16 | class D (primary base) |
223 | // CHECK-NEXT: 16 | (D vftable pointer) |
224 | // CHECK-NEXT: 24 | double a |
225 | // CHECK-NEXT: 32 | class B (base) |
226 | // CHECK-NEXT: 32 | (B vftable pointer) |
227 | // CHECK-NEXT: 36 | int b_field |
228 | // CHECK-NEXT: 40 | (C vbtable pointer) |
229 | // CHECK-NEXT: 48 | double c1_field |
230 | // CHECK-NEXT: 56 | int c2_field |
231 | // CHECK-NEXT: 64 | double c3_field |
232 | // CHECK-NEXT: 72 | int c4_field |
233 | // CHECK-NEXT: 80 | class A (virtual base) |
234 | // CHECK-NEXT: 80 | class B (primary base) |
235 | // CHECK-NEXT: 80 | (B vftable pointer) |
236 | // CHECK-NEXT: 84 | int b_field |
237 | // CHECK-NEXT: 88 | int a_field |
238 | // CHECK-NEXT: 92 | char one |
239 | // CHECK-NEXT: sizeof=96, align=8 |
240 | // CHECK-NEXT: nvsize=96, nvalign=8 |
241 | |
242 | // CHECK: %struct.BaseStruct = type { double, float, %class.C } |
243 | |
244 | // CHECK: 0 | struct DerivedStruct |
245 | // CHECK-NEXT: 0 | struct BaseStruct (base) |
246 | // CHECK-NEXT: 0 | double v0 |
247 | // CHECK-NEXT: 8 | float v1 |
248 | // CHECK-NEXT: 16 | class C fg |
249 | // CHECK-NEXT: 16 | class D (primary base) |
250 | // CHECK-NEXT: 16 | (D vftable pointer) |
251 | // CHECK-NEXT: 24 | double a |
252 | // CHECK-NEXT: 32 | class B (base) |
253 | // CHECK-NEXT: 32 | (B vftable pointer) |
254 | // CHECK-NEXT: 36 | int b_field |
255 | // CHECK-NEXT: 40 | (C vbtable pointer) |
256 | // CHECK-NEXT: 48 | double c1_field |
257 | // CHECK-NEXT: 56 | int c2_field |
258 | // CHECK-NEXT: 64 | double c3_field |
259 | // CHECK-NEXT: 72 | int c4_field |
260 | // CHECK-NEXT: 80 | class A (virtual base) |
261 | // CHECK-NEXT: 80 | class B (primary base) |
262 | // CHECK-NEXT: 80 | (B vftable pointer) |
263 | // CHECK-NEXT: 84 | int b_field |
264 | // CHECK-NEXT: 88 | int a_field |
265 | // CHECK-NEXT: 92 | char one |
266 | // CHECK-NEXT: 96 | int x |
267 | // CHECK-NEXT: sizeof=104, align=8 |
268 | // CHECK-NEXT: nvsize=104, nvalign=8 |
269 | |
270 | // CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 } |
271 | |
272 | // CHECK: 0 | struct G |
273 | // CHECK-NEXT: 0 | int g_field |
274 | // CHECK-NEXT: sizeof=4, align=4 |
275 | // CHECK-NEXT: nvsize=4, nvalign=4 |
276 | |
277 | // CHECK: 0 | struct H |
278 | // CHECK-NEXT: 0 | struct G (base) |
279 | // CHECK-NEXT: 0 | int g_field |
280 | // CHECK-NEXT: 4 | (H vbtable pointer) |
281 | // CHECK-NEXT: 8 | class D (virtual base) |
282 | // CHECK-NEXT: 8 | (D vftable pointer) |
283 | // CHECK-NEXT: 16 | double a |
284 | // CHECK-NEXT: sizeof=24, align=8 |
285 | // CHECK-NEXT: nvsize=8, nvalign=8 |
286 | |
287 | // CHECK: %struct.H = type { %struct.G, i32*, %class.D } |
288 | |
289 | // CHECK: 0 | struct I |
290 | // CHECK-NEXT: 0 | (I vftable pointer) |
291 | // CHECK-NEXT: 8 | (I vbtable pointer) |
292 | // CHECK-NEXT: 16 | double q |
293 | // CHECK-NEXT: 24 | class D (virtual base) |
294 | // CHECK-NEXT: 24 | (D vftable pointer) |
295 | // CHECK-NEXT: 32 | double a |
296 | // CHECK-NEXT: sizeof=40, align=8 |
297 | // CHECK-NEXT: nvsize=24, nvalign=8 |
298 | |
299 | // CHECK: %struct.I = type { i32 (...)**, [4 x i8], i32*, double, %class.D } |
300 | // CHECK: %struct.I.base = type { i32 (...)**, [4 x i8], i32*, double } |
301 | |
302 | // CHECK: 0 | struct L |
303 | // CHECK-NEXT: 0 | int l |
304 | // CHECK-NEXT: sizeof=4, align=4 |
305 | // CHECK-NEXT: nvsize=4, nvalign=4 |
306 | |
307 | // CHECK: 0 | struct K |
308 | // CHECK-NEXT: 0 | int k |
309 | // CHECK-NEXT: sizeof=4, align=4 |
310 | // CHECK-NEXT: nvsize=4, nvalign=4 |
311 | |
312 | // CHECK: 0 | struct M |
313 | // CHECK-NEXT: 0 | (M vbtable pointer) |
314 | // CHECK-NEXT: 4 | int m |
315 | // CHECK-NEXT: 8 | struct K (virtual base) |
316 | // CHECK-NEXT: 8 | int k |
317 | // CHECK-NEXT: sizeof=12, align=4 |
318 | |
319 | //CHECK: %struct.M = type { i32*, i32, %struct.K } |
320 | //CHECK: %struct.M.base = type { i32*, i32 } |
321 | |
322 | // CHECK: 0 | struct N |
323 | // CHECK-NEXT: 0 | (N vftable pointer) |
324 | // CHECK-NEXT: 4 | struct L (base) |
325 | // CHECK-NEXT: 4 | int l |
326 | // CHECK-NEXT: 8 | struct M (base) |
327 | // CHECK-NEXT: 8 | (M vbtable pointer) |
328 | // CHECK-NEXT: 12 | int m |
329 | // CHECK-NEXT: 16 | struct K (virtual base) |
330 | // CHECK-NEXT: 16 | int k |
331 | // CHECK-NEXT: sizeof=20, align=4 |
332 | // CHECK-NEXT: nvsize=16, nvalign=4 |
333 | |
334 | //CHECK: %struct.N = type { i32 (...)**, %struct.L, %struct.M.base, %struct.K } |
335 | |
336 | // CHECK: 0 | struct O |
337 | // CHECK-NEXT: 0 | (O vftable pointer) |
338 | // CHECK-NEXT: 8 | struct H (base) |
339 | // CHECK-NEXT: 8 | struct G (base) |
340 | // CHECK-NEXT: 8 | int g_field |
341 | // CHECK-NEXT: 12 | (H vbtable pointer) |
342 | // CHECK-NEXT: 16 | struct G (base) |
343 | // CHECK-NEXT: 16 | int g_field |
344 | // CHECK-NEXT: 24 | class D (virtual base) |
345 | // CHECK-NEXT: 24 | (D vftable pointer) |
346 | // CHECK-NEXT: 32 | double a |
347 | // CHECK-NEXT: | [sizeof=40, align=8 |
348 | // CHECK-NEXT: | nvsize=24, nvalign=8] |
349 | |
350 | // CHECK: struct.O = type { i32 (...)**, [4 x i8], %struct.H.base, %struct.G, %class.D } |
351 | // CHECK: struct.O.base = type { i32 (...)**, [4 x i8], %struct.H.base, %struct.G, [4 x i8] } |
352 | |
353 | |
354 | // CHECK: 0 | struct P |
355 | // CHECK-NEXT: 0 | struct M (base) |
356 | // CHECK-NEXT: 0 | (M vbtable pointer) |
357 | // CHECK-NEXT: 4 | int m |
358 | // CHECK-NEXT: 8 | int p |
359 | // CHECK-NEXT: 12 | struct K (virtual base) |
360 | // CHECK-NEXT: 12 | int k |
361 | // CHECK-NEXT: 16 | struct L (virtual base) |
362 | // CHECK-NEXT: 16 | int l |
363 | // CHECK-NEXT: sizeof=20, align=4 |
364 | // CHECK-NEXT: nvsize=12, nvalign=4 |
365 | |
366 | //CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L } |
367 | |
368 | // CHECK: 0 | struct R (empty) |
369 | // CHECK-NEXT: sizeof=1, align=1 |
370 | // CHECK-NEXT: nvsize=0, nvalign=1 |
371 | |
372 | //CHECK: %struct.R = type { i8 } |
373 | |
374 | // CHECK: 0 | struct f |
375 | // CHECK-NEXT: 0 | (f vftable pointer) |
376 | // CHECK-NEXT: sizeof=4, align=4 |
377 | // CHECK-NEXT: nvsize=4, nvalign=4 |
378 | |
379 | // CHECK: 0 | struct s |
380 | // CHECK-NEXT: 0 | (s vftable pointer) |
381 | // CHECK-NEXT: 4 | (s vbtable pointer) |
382 | // CHECK-NEXT: 8 | int r |
383 | // CHECK-NEXT: 12 | (vtordisp for vbase f) |
384 | // CHECK-NEXT: 16 | struct f (virtual base) |
385 | // CHECK-NEXT: 16 | (f vftable pointer) |
386 | // CHECK-NEXT: sizeof=20, align=4 |
387 | // CHECK-NEXT: nvsize=12, nvalign=4 |
388 | |
389 | // CHECK: 0 | class IA |
390 | // CHECK-NEXT: 0 | (IA vftable pointer) |
391 | // CHECK-NEXT: sizeof=4, align=4 |
392 | // CHECK-NEXT: nvsize=4, nvalign=4 |
393 | |
394 | // CHECK: 0 | class ICh |
395 | // CHECK-NEXT: 0 | (ICh vftable pointer) |
396 | // CHECK-NEXT: 4 | (ICh vbtable pointer) |
397 | // CHECK-NEXT: 8 | (vtordisp for vbase IA) |
398 | // CHECK-NEXT: 12 | class IA (virtual base) |
399 | // CHECK-NEXT: 12 | (IA vftable pointer) |
400 | // CHECK-NEXT: sizeof=16, align=4 |
401 | // CHECK-NEXT: nvsize=8, nvalign=4 |
402 | |
403 | // CHECK: 0 | struct sd |
404 | // CHECK-NEXT: 0 | (sd vbtable pointer) |
405 | // CHECK-NEXT: 4 | int q |
406 | // CHECK-NEXT: 8 | char y |
407 | // CHECK-NEXT: 12 | (vtordisp for vbase f) |
408 | // CHECK-NEXT: 16 | struct f (virtual base) |
409 | // CHECK-NEXT: 16 | (f vftable pointer) |
410 | // CHECK-NEXT: 20 | struct s (virtual base) |
411 | // CHECK-NEXT: 20 | (s vftable pointer) |
412 | // CHECK-NEXT: 24 | (s vbtable pointer) |
413 | // CHECK-NEXT: 28 | int r |
414 | // CHECK-NEXT: 32 | (vtordisp for vbase IA) |
415 | // CHECK-NEXT: 36 | class IA (virtual base) |
416 | // CHECK-NEXT: 36 | (IA vftable pointer) |
417 | // CHECK-NEXT: 40 | class ICh (virtual base) |
418 | // CHECK-NEXT: 40 | (ICh vftable pointer) |
419 | // CHECK-NEXT: 44 | (ICh vbtable pointer) |
420 | // CHECK-NEXT: sizeof=48, align=4 |
421 | // CHECK-NEXT: nvsize=12, nvalign=4 |
422 | |
423 | // CHECK: %struct.f = type { i32 (...)** } |
424 | // CHECK: %struct.s = type { i32 (...)**, i32*, i32, i32, %struct.f } |
425 | // CHECK: %class.IA = type { i32 (...)** } |
426 | // CHECK: %class.ICh = type { i32 (...)**, i32*, i32, %class.IA } |
427 | // CHECK: %struct.sd = type { i32*, i32, i8, i32, %struct.f, %struct.s.base, i32, %class.IA, %class.ICh.base } |
428 | |
429 | // CHECK: 0 | struct AV |
430 | // CHECK-NEXT: 0 | (AV vftable pointer) |
431 | // CHECK-NEXT: sizeof=4, align=4 |
432 | // CHECK-NEXT: nvsize=4, nvalign=4 |
433 | |
434 | |
435 | // CHECK: 0 | struct BV |
436 | // CHECK-NEXT: 0 | struct AV (primary base) |
437 | // CHECK-NEXT: 0 | (AV vftable pointer) |
438 | // CHECK-NEXT: sizeof=4, align=4 |
439 | // CHECK-NEXT: nvsize=4, nvalign=4 |
440 | |
441 | |
442 | // CHECK: 0 | struct CV |
443 | // CHECK-NEXT: 0 | (CV vbtable pointer) |
444 | // CHECK-NEXT: 4 | (vtordisp for vbase BV) |
445 | // CHECK-NEXT: 8 | struct BV (virtual base) |
446 | // CHECK-NEXT: 8 | struct AV (primary base) |
447 | // CHECK-NEXT: 8 | (AV vftable pointer) |
448 | // CHECK-NEXT: sizeof=12, align=4 |
449 | // CHECK-NEXT: nvsize=4, nvalign=4 |
450 | |
451 | // CHECK: %struct.AV = type { i32 (...)** } |
452 | // CHECK: %struct.BV = type { %struct.AV } |
453 | // CHECK: %struct.CV = type { i32*, i32, %struct.BV } |
454 | // CHECK: %struct.CV.base = type { i32* } |
455 | |
456 | // CHECK: 0 | struct DV |
457 | // CHECK-NEXT: 0 | struct BV (primary base) |
458 | // CHECK-NEXT: 0 | struct AV (primary base) |
459 | // CHECK-NEXT: 0 | (AV vftable pointer) |
460 | // CHECK-NEXT: sizeof=4, align=4 |
461 | // CHECK-NEXT: nvsize=4, nvalign=4 |
462 | |
463 | // CHECK: %struct.DV = type { %struct.BV } |
464 | |
465 | // CHECK: 0 | struct EV |
466 | // CHECK-NEXT: 0 | struct DV (primary base) |
467 | // CHECK-NEXT: 0 | struct BV (primary base) |
468 | // CHECK-NEXT: 0 | struct AV (primary base) |
469 | // CHECK-NEXT: 0 | (AV vftable pointer) |
470 | // CHECK-NEXT: 4 | struct CV (base) |
471 | // CHECK-NEXT: 4 | (CV vbtable pointer) |
472 | // CHECK-NEXT: 8 | (vtordisp for vbase BV) |
473 | // CHECK-NEXT: 12 | struct BV (virtual base) |
474 | // CHECK-NEXT: 12 | struct AV (primary base) |
475 | // CHECK-NEXT: 12 | (AV vftable pointer) |
476 | // CHECK-NEXT: sizeof=16, align=4 |
477 | // CHECK-NEXT: nvsize=8, nvalign=4 |
478 | |
479 | // CHECK: %struct.EV = type { %struct.DV, %struct.CV.base, i32, %struct.BV } |
480 | // CHECK: %struct.EV.base = type { %struct.DV, %struct.CV.base } |
481 | |
482 | // Overriding a method means that all the vbases containing that |
483 | // method need a vtordisp. Note: this code will cause an error in cl.exe. |
484 | namespace test1 { |
485 | struct A { virtual void foo(); }; |
486 | struct B : A {}; |
487 | struct C : virtual A, virtual B { C(); virtual void foo(); }; |
488 | void test() { C *c; } |
489 | |
490 | // CHECK: 0 | struct test1::C |
491 | // CHECK-NEXT: 0 | (C vbtable pointer) |
492 | // CHECK-NEXT: 4 | (vtordisp for vbase A) |
493 | // CHECK-NEXT: 8 | struct test1::A (virtual base) |
494 | // CHECK-NEXT: 8 | (A vftable pointer) |
495 | // CHECK-NEXT: 12 | (vtordisp for vbase B) |
496 | // CHECK-NEXT: 16 | struct test1::B (virtual base) |
497 | // CHECK-NEXT: 16 | struct test1::A (primary base) |
498 | // CHECK-NEXT: 16 | (A vftable pointer) |
499 | // CHECK-NEXT: sizeof=20, align=4 |
500 | // CHECK-NEXT: nvsize=4, nvalign=4 |
501 | } |
502 | |