xref: /llvm-project/clang/test/Sema/ms_class_layout.cpp (revision 0153cd3027b668f85fe217e7517099e4de0033a5)
1 // RUN: %clang_cc1 -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -cxx-abi microsoft %s 2>&1 \
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 
99 #pragma pack(pop)
100 
101 // This needs only for building layouts.
102 // Without this clang doesn`t dump record layouts.
103 int main() {
104   // This avoid "Can't yet mangle constructors!" for MS ABI.
105   C* c;
106   c->foo();
107   DerivedStruct* v;
108   H* g;
109   BaseStruct* u;
110   I* i;
111   N* n;
112   O* o;
113   P* p;
114   return 0;
115 }
116 
117 // CHECK:       0 | class D
118 // CHECK-NEXT:  0 |   (D vftable pointer)
119 // CHECK-NEXT:  8 |   double a
120 
121 // CHECK-NEXT: sizeof=16, dsize=16, align=8
122 // CHECK-NEXT: nvsize=16, nvalign=8
123 
124 // CHECK: %class.D = type { i32 (...)**, double }
125 
126 // CHECK:       0 | class B
127 // CHECK-NEXT:  0 |   (B vftable pointer)
128 // CHECK-NEXT:  4 |   int b_field
129 
130 // CHECK-NEXT: sizeof=8, dsize=8, align=4
131 // CHECK-NEXT: nvsize=8, nvalign=4
132 
133 // CHECK: %class.B = type { i32 (...)**, i32 }
134 
135 // CHECK:       0 | class A
136 // CHECK-NEXT:  0 |   class B (primary base)
137 // CHECK-NEXT:  0 |     (B vftable pointer)
138 // CHECK-NEXT:  4 |     int b_field
139 // CHECK-NEXT:  8 |   int a_field
140 // CHECK-NEXT: 12 |   char one
141 
142 // CHECK-NEXT: sizeof=16, dsize=16, align=4
143 // CHECK-NEXT: nvsize=16, nvalign=4
144 
145 // CHECK:       0 | class C
146 // CHECK-NEXT:  0 |   class D (primary base)
147 // CHECK-NEXT:  0 |     (D vftable pointer)
148 // CHECK-NEXT:  8 |     double a
149 // CHECK-NEXT: 16 |   class B (base)
150 // CHECK-NEXT: 16 |     (B vftable pointer)
151 // CHECK-NEXT: 20 |     int b_field
152 // CHECK-NEXT: 24 |   (C vbtable pointer)
153 // CHECK-NEXT: 32 |   double c1_field
154 // CHECK-NEXT: 40 |   int c2_field
155 // CHECK-NEXT: 48 |   double c3_field
156 // CHECK-NEXT: 56 |   int c4_field
157 // CHECK-NEXT: 64 |   class A (virtual base)
158 // CHECK-NEXT: 64 |     class B (primary base)
159 // CHECK-NEXT: 64 |       (B vftable pointer)
160 // CHECK-NEXT: 68 |       int b_field
161 // CHECK-NEXT: 72 |     int a_field
162 // CHECK-NEXT: 76 |     char one
163 
164 // CHECK-NEXT: sizeof=80, dsize=80, align=8
165 // CHECK-NEXT: nvsize=64, nvalign=8
166 
167 // CHECK: %class.A = type { %class.B, i32, i8 }
168 
169 // CHECK: %class.C = type { %class.D, %class.B, i32*, double, i32, double, i32, [4 x i8], %class.A }
170 // CHECK: %class.C.base = type { %class.D, %class.B, i32*, double, i32, double, i32 }
171 
172 // CHECK:       0 | struct BaseStruct
173 // CHECK-NEXT:  0 |   double v0
174 // CHECK-NEXT:  8 |   float v1
175 // CHECK-NEXT: 16 |   class C fg
176 // CHECK-NEXT: 16 |     class D (primary base)
177 // CHECK-NEXT: 16 |       (D vftable pointer)
178 // CHECK-NEXT: 24 |       double a
179 // CHECK-NEXT: 32 |     class B (base)
180 // CHECK-NEXT: 32 |       (B vftable pointer)
181 // CHECK-NEXT: 36 |       int b_field
182 // CHECK-NEXT: 40 |     (C vbtable pointer)
183 // CHECK-NEXT: 48 |     double c1_field
184 // CHECK-NEXT: 56 |     int c2_field
185 // CHECK-NEXT: 64 |     double c3_field
186 // CHECK-NEXT: 72 |     int c4_field
187 // CHECK-NEXT: 80 |     class A (virtual base)
188 // CHECK-NEXT: 80 |       class B (primary base)
189 // CHECK-NEXT: 80 |         (B vftable pointer)
190 // CHECK-NEXT: 84 |         int b_field
191 // CHECK-NEXT: 88 |       int a_field
192 // CHECK-NEXT: 92 |       char one
193 
194 // CHECK-NEXT: sizeof=80, dsize=80, align=8
195 // CHECK-NEXT: nvsize=64, nvalign=8
196 
197 // CHECK: sizeof=96, dsize=96, align=8
198 // CHECK-NEXT: nvsize=96, nvalign=8
199 
200 // CHECK: %struct.BaseStruct = type { double, float, %class.C }
201 
202 // CHECK:       0 | struct DerivedStruct
203 // CHECK-NEXT:  0 |   struct BaseStruct (base)
204 // CHECK-NEXT:  0 |     double v0
205 // CHECK-NEXT:  8 |     float v1
206 // CHECK-NEXT: 16 |     class C fg
207 // CHECK-NEXT: 16 |       class D (primary base)
208 // CHECK-NEXT: 16 |         (D vftable pointer)
209 // CHECK-NEXT: 24 |         double a
210 // CHECK-NEXT: 32 |       class B (base)
211 // CHECK-NEXT: 32 |         (B vftable pointer)
212 // CHECK-NEXT: 36 |         int b_field
213 // CHECK-NEXT: 40 |       (C vbtable pointer)
214 // CHECK-NEXT: 48 |       double c1_field
215 // CHECK-NEXT: 56 |       int c2_field
216 // CHECK-NEXT: 64 |       double c3_field
217 // CHECK-NEXT: 72 |       int c4_field
218 // CHECK-NEXT: 80 |       class A (virtual base)
219 // CHECK-NEXT: 80 |         class B (primary base)
220 // CHECK-NEXT: 80 |           (B vftable pointer)
221 // CHECK-NEXT: 84 |           int b_field
222 // CHECK-NEXT: 88 |         int a_field
223 // CHECK-NEXT: 92 |         char one
224 // CHECK-NEXT: sizeof=80, dsize=80, align=8
225 // CHECK-NEXT: nvsize=64, nvalign=8
226 
227 // CHECK: 96 |   int x
228 // CHECK-NEXT: sizeof=104, dsize=104, align=8
229 // CHECK-NEXT: nvsize=104, nvalign=8
230 
231 // CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 }
232 
233 // CHECK:      0 | struct G
234 // CHECK-NEXT: 0 |   int g_field
235 // CHECK-NEXT: sizeof=4, dsize=4, align=4
236 // CHECK-NEXT: nvsize=4, nvalign=4
237 
238 // CHECK:       0 | struct H
239 // CHECK-NEXT:  0 |   struct G (base)
240 // CHECK-NEXT:  0 |     int g_field
241 // CHECK-NEXT:  4 |   (H vbtable pointer)
242 // CHECK-NEXT:  8 |   class D (virtual base)
243 // CHECK-NEXT:  8 |     (D vftable pointer)
244 // CHECK-NEXT: 16 |     double a
245 // CHECK-NEXT: sizeof=24, dsize=24, align=8
246 // CHECK-NEXT: nvsize=8, nvalign=4
247 
248 // CHECK: %struct.H = type { %struct.G, i32*, %class.D }
249 
250 // CHECK:       0 | struct I
251 // CHECK-NEXT:  0 |   (I vftable pointer)
252 // CHECK-NEXT:  8 |   (I vbtable pointer)
253 // CHECK-NEXT: 16 |   double q
254 // CHECK-NEXT: 24 |   class D (virtual base)
255 // CHECK-NEXT: 24 |     (D vftable pointer)
256 // CHECK-NEXT: 32 |     double a
257 // CHECK-NEXT: sizeof=40, dsize=40, align=8
258 // CHECK-NEXT: nvsize=24, nvalign=8
259 
260 // CHECK: %struct.I = type { i32 (...)**, [4 x i8], i32*, double, %class.D }
261 // CHECK: %struct.I.base = type { i32 (...)**, [4 x i8], i32*, double }
262 
263 // CHECK:       0 | struct L
264 // CHECK-NEXT:  0 |   int l
265 // CHECK-NEXT: sizeof=4, dsize=4, align=4
266 // CHECK-NEXT: nvsize=4, nvalign=4
267 
268 // CHECK:       0 | struct K
269 // CHECK-NEXT:  0 |   int k
270 // CHECK-NEXT: sizeof=4, dsize=4, align=4
271 // CHECK-NEXT: nvsize=4, nvalign=4
272 
273 // CHECK:       0 | struct M
274 // CHECK-NEXT:  0 |   (M vbtable pointer)
275 // CHECK-NEXT:  4 |   int m
276 // CHECK-NEXT:  8 |   struct K (virtual base)
277 // CHECK-NEXT:  8 |     int k
278 // CHECK-NEXT: sizeof=12, dsize=12, align=4
279 
280 //CHECK: %struct.M = type { i32*, i32, %struct.K }
281 //CHECK: %struct.M.base = type { i32*, i32 }
282 
283 // CHECK:       0 | struct N
284 // CHECK-NEXT:  4 |   struct L (base)
285 // CHECK-NEXT:  4 |     int l
286 // CHECK-NEXT:  8 |   struct M (base)
287 // CHECK-NEXT:  8 |     (M vbtable pointer)
288 // CHECK-NEXT: 12 |     int m
289 // CHECK-NEXT:  0 |   (N vftable pointer)
290 // CHECK-NEXT: 16 |   struct K (virtual base)
291 // CHECK-NEXT: 16 |     int k
292 // CHECK-NEXT: sizeof=20, dsize=20, align=4
293 // CHECK-NEXT: nvsize=16, nvalign=4
294 
295 //CHECK: %struct.N = type { i32 (...)**, %struct.L, %struct.M.base, %struct.K }
296 
297 // FIXME: MSVC place struct H at offset 8.
298 // CHECK:       0 | struct O
299 // CHECK-NEXT:  4 |   struct H (base)
300 // CHECK-NEXT:  4 |     struct G (base)
301 // CHECK-NEXT:  4 |       int g_field
302 // CHECK-NEXT:  8 |     (H vbtable pointer)
303 // CHECK-NEXT: 12 |   struct G (base)
304 // CHECK-NEXT: 12 |     int g_field
305 // CHECK-NEXT:  0 |   (O vftable pointer)
306 // CHECK-NEXT: 16 |   class D (virtual base)
307 // CHECK-NEXT: 16 |     (D vftable pointer)
308 // CHECK-NEXT: 24 |     double a
309 // CHECK-NEXT: sizeof=32, dsize=32, align=8
310 // CHECK-NEXT: nvsize=16, nvalign=4
311 
312 //CHECK: %struct.O = type { i32 (...)**, %struct.H.base, %struct.G, %class.D }
313 //CHECK: %struct.O.base = type { i32 (...)**, %struct.H.base, %struct.G }
314 
315 // CHECK:       0 | struct P
316 // CHECK-NEXT:  0 |   struct M (base)
317 // CHECK-NEXT:  0 |     (M vbtable pointer)
318 // CHECK-NEXT:  4 |     int m
319 // CHECK-NEXT:  8 |   int p
320 // CHECK-NEXT: 12 |   struct K (virtual base)
321 // CHECK-NEXT: 12 |     int k
322 // CHECK-NEXT: 16 |   struct L (virtual base)
323 // CHECK-NEXT: 16 |     int l
324 // CHECK-NEXT: sizeof=20, dsize=20, align=4
325 // CHECK-NEXT: nvsize=12, nvalign=4
326 
327 //CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L }
328