xref: /llvm-project/clang/test/Sema/ms_class_layout.cpp (revision 5e9534b0aead93fa921b0feb5beea3f4d7e34c9b)
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 #pragma pack(pop)
65 
66 // This needs only for building layouts.
67 // Without this clang doesn`t dump record layouts.
68 int main() {
69   // This avoid "Can't yet mangle constructors!" for MS ABI.
70   C* c;
71   c->foo();
72   DerivedStruct* v;
73   H* g;
74   BaseStruct* u;
75   return 0;
76 }
77 
78 // CHECK:       0 | class D
79 // CHECK-NEXT:  0 |   (D vtable pointer)
80 // CHECK-NEXT:  8 |   double a
81 
82 // CHECK-NEXT: sizeof=16, dsize=16, align=8
83 // CHECK-NEXT: nvsize=16, nvalign=8
84 
85 // CHECK:       0 | class B
86 // CHECK-NEXT:  0 |   (B vtable pointer)
87 // CHECK-NEXT:  4 |   int b_field
88 
89 // CHECK-NEXT: sizeof=8, dsize=8, align=4
90 // CHECK-NEXT: nvsize=8, nvalign=4
91 
92 // CHECK:       0 | class A
93 // CHECK-NEXT:  0 |   class B (primary base)
94 // CHECK-NEXT:  0 |     (B vtable pointer)
95 // CHECK-NEXT:  4 |     int b_field
96 // CHECK-NEXT:  8 |   int a_field
97 // CHECK-NEXT: 12 |   char one
98 
99 // CHECK-NEXT: sizeof=16, dsize=16, align=4
100 // CHECK-NEXT: nvsize=16, nvalign=4
101 
102 // CHECK:       0 | class C
103 // CHECK-NEXT:  0 |   class D (primary base)
104 // CHECK-NEXT:  0 |     (D vtable pointer)
105 // CHECK-NEXT:  8 |     double a
106 // CHECK-NEXT: 16 |   class B (base)
107 // CHECK-NEXT: 16 |     (B vtable pointer)
108 // CHECK-NEXT: 20 |     int b_field
109 // CHECK-NEXT: 24 |   (C vbtable pointer)
110 // CHECK-NEXT: 32 |   double c1_field
111 // CHECK-NEXT: 40 |   int c2_field
112 // CHECK-NEXT: 48 |   double c3_field
113 // CHECK-NEXT: 56 |   int c4_field
114 // CHECK-NEXT: 64 |   class A (virtual base)
115 // CHECK-NEXT: 64 |     class B (primary base)
116 // CHECK-NEXT: 64 |       (B vtable pointer)
117 // CHECK-NEXT: 68 |       int b_field
118 // CHECK-NEXT: 72 |     int a_field
119 // CHECK-NEXT: 76 |     char one
120 
121 // CHECK-NEXT: sizeof=80, dsize=80, align=8
122 // CHECK-NEXT: nvsize=80, nvalign=8
123 
124 // CHECK:       0 | struct BaseStruct
125 // CHECK-NEXT:  0 |   double v0
126 // CHECK-NEXT:  8 |   float v1
127 // CHECK-NEXT: 16 |   class C fg
128 // CHECK-NEXT: 16 |     class D (primary base)
129 // CHECK-NEXT: 16 |       (D vtable pointer)
130 // CHECK-NEXT: 24 |       double a
131 // CHECK-NEXT: 32 |     class B (base)
132 // CHECK-NEXT: 32 |       (B vtable pointer)
133 // CHECK-NEXT: 36 |       int b_field
134 // CHECK-NEXT: 40 |     (C vbtable pointer)
135 // CHECK-NEXT: 48 |     double c1_field
136 // CHECK-NEXT: 56 |     int c2_field
137 // CHECK-NEXT: 64 |     double c3_field
138 // CHECK-NEXT: 72 |     int c4_field
139 // CHECK-NEXT: 80 |     class A (virtual base)
140 // CHECK-NEXT: 80 |       class B (primary base)
141 // CHECK-NEXT: 80 |         (B vtable pointer)
142 // CHECK-NEXT: 84 |         int b_field
143 // CHECK-NEXT: 88 |       int a_field
144 // CHECK-NEXT: 92 |       char one
145 
146 // CHECK-NEXT: sizeof=80, dsize=80, align=8
147 // CHECK-NEXT: nvsize=80, nvalign=8
148 
149 // CHECK: sizeof=96, dsize=96, align=8
150 // CHECK-NEXT: nvsize=96, nvalign=8
151 
152 // CHECK:       0 | struct DerivedStruct
153 // CHECK-NEXT:  0 |   struct BaseStruct (base)
154 // CHECK-NEXT:  0 |     double v0
155 // CHECK-NEXT:  8 |     float v1
156 // CHECK-NEXT: 16 |     class C fg
157 // CHECK-NEXT: 16 |       class D (primary base)
158 // CHECK-NEXT: 16 |         (D vtable pointer)
159 // CHECK-NEXT: 24 |         double a
160 // CHECK-NEXT: 32 |       class B (base)
161 // CHECK-NEXT: 32 |         (B vtable pointer)
162 // CHECK-NEXT: 36 |         int b_field
163 // CHECK-NEXT: 40 |       (C vbtable pointer)
164 // CHECK-NEXT: 48 |       double c1_field
165 // CHECK-NEXT: 56 |       int c2_field
166 // CHECK-NEXT: 64 |       double c3_field
167 // CHECK-NEXT: 72 |       int c4_field
168 // CHECK-NEXT: 80 |       class A (virtual base)
169 // CHECK-NEXT: 80 |         class B (primary base)
170 // CHECK-NEXT: 80 |           (B vtable pointer)
171 // CHECK-NEXT: 84 |           int b_field
172 // CHECK-NEXT: 88 |         int a_field
173 // CHECK-NEXT: 92 |         char one
174 // CHECK-NEXT: sizeof=80, dsize=80, align=8
175 // CHECK-NEXT: nvsize=80, nvalign=8
176 
177 // CHECK: 96 |   int x
178 // CHECK-NEXT: sizeof=104, dsize=104, align=8
179 // CHECK-NEXT: nvsize=104, nvalign=8
180 
181 // CHECK:      0 | struct G
182 // CHECK-NEXT: 0 |   int g_field
183 // CHECK-NEXT: sizeof=4, dsize=4, align=4
184 // CHECK-NEXT: nvsize=4, nvalign=4
185 
186 // FIXME: Dump should not be showing vfptr, and vbptr is in the wrong order.
187 // CHECK:       0 | struct H
188 // CHECK-NEXT:  0 |   (H vtable pointer)
189 // CHECK-NEXT:  4 |   (H vbtable pointer)
190 // CHECK-NEXT:  0 |   struct G (base)
191 // CHECK-NEXT:  0 |     int g_field
192 // CHECK-NEXT:  8 |   class D (virtual base)
193 // CHECK-NEXT:  8 |     (D vtable pointer)
194 // CHECK-NEXT: 16 |     double a
195 // CHECK-NEXT: sizeof=24, dsize=24, align=8
196 // CHECK-NEXT: nvsize=24, nvalign=8
197