1 // Compile with "cl /c /Zi /GR- SimplePaddingTest.cpp"
2 // Link with "link SimplePaddingTest.obj /debug /nodefaultlib /entry:main"
3
4 #include <stdint.h>
5
6 extern "C" using at_exit_handler = void();
7
atexit(at_exit_handler handler)8 int atexit(at_exit_handler handler) { return 0; }
9
10 struct SimplePadNoPadding {
11 int32_t X;
12 int32_t Y;
13 // No padding anywhere, sizeof(T) = 8
14 } A;
15
16 struct SimplePadUnion {
17 union {
18 int32_t X;
19 int64_t Y;
20 struct {
21 int32_t X;
22 // 4 bytes of padding here
23 int64_t Y;
24 } Z;
25 };
26 // Since the padding occurs at a location that is occupied by other storage
27 // (namely the Y member), the storage will still be considered used, and so
28 // there will be no unused bytes in the larger class. But in the debug
29 // info for the nested struct, we should see padding.
30 // sizeof(SimplePadUnion) == sizeof(Z) == 16
31 } B;
32
33 struct SimplePadNoPadding2 {
34 bool A;
35 bool B;
36 bool C;
37 bool D;
38 // No padding anywhere, sizeof(T) = 4
39 } C;
40
41 struct alignas(4) SimplePadFields1 {
42 char A;
43 char B;
44 char C;
45 // 1 byte of padding here, sizeof(T) = 4
46 } E;
47
48 struct SimplePadFields2 {
49 int32_t Y;
50 char X;
51 } F;
52
53 struct SimplePadBase {
54 // Make sure this class is 4 bytes, and the derived class requires 8 byte
55 // alignment, so that padding is inserted between base and derived.
56 int32_t X;
57 // No padding here
58 } G;
59
60 struct SimplePadDerived : public SimplePadBase {
61 // 4 bytes of padding here due to Y requiring 8 byte alignment.
62 // Thus, sizeof(T) = 16
63 int64_t Y;
64 } H;
65
66 struct SimplePadEmptyBase1 {};
67 struct SimplePadEmptyBase2 {};
68
69 struct SimplePadEmpty : public SimplePadEmptyBase1, SimplePadEmptyBase2 {
70 // Bases have to occupy at least 1 byte of storage, so this requires
71 // 2 bytes of padding, plus 1 byte for each base, yielding sizeof(T) = 8
72 int32_t X;
73 } I;
74
75 struct SimplePadVfptr {
~SimplePadVfptrSimplePadVfptr76 virtual ~SimplePadVfptr() {}
operator deleteSimplePadVfptr77 static void operator delete(void *ptr, size_t sz) {}
78 int32_t X;
79 } J;
80
81 struct NonEmptyBase1 {
82 bool X;
83 };
84
85 struct NonEmptyBase2 {
86 bool Y;
87 };
88
89 struct SimplePadMultiInherit : public NonEmptyBase1, public NonEmptyBase2 {
90 // X and Y from the 2 bases will get squished together, leaving 2 bytes
91 // of padding necessary for proper alignment of an int32.
92 // Therefore, sizeof(T) = 2 + 2 + 4 = 8
93 int32_t X;
94 } K;
95
96 struct SimplePadMultiInherit2 : public SimplePadFields1, SimplePadFields2 {
97 // There should be 1 byte of padding after the first class, and
98 // 3 bytes of padding after the second class.
99 int32_t X;
100 } L;
101
102 struct OneLevelInherit : public NonEmptyBase1 {
103 short Y;
104 };
105
106 struct SimplePadTwoLevelInherit : public OneLevelInherit {
107 // OneLevelInherit has nested padding because of its base,
108 // and then padding again because of this class. So each
109 // class should be 4 bytes, yielding sizeof(T) = 12.
110 int64_t Z;
111 } M;
112
113 struct SimplePadAggregate {
114 NonEmptyBase1 X;
115 int32_t Y;
116 // the presence of X will cause 3 bytes of padding to be injected.
117 SimplePadFields1 Fields;
118 } N;
119
120 struct SimplePadVtable1 {
operator deleteSimplePadVtable1121 static void operator delete(void *ptr, size_t sz) {}
~SimplePadVtable1SimplePadVtable1122 virtual ~SimplePadVtable1() {}
A1SimplePadVtable1123 virtual void A1() {}
B1SimplePadVtable1124 virtual void B1() {}
125 } O;
126
127 struct SimplePadVtable2 {
operator deleteSimplePadVtable2128 static void operator delete(void *ptr, size_t sz) {}
~SimplePadVtable2SimplePadVtable2129 virtual ~SimplePadVtable2() {}
X2SimplePadVtable2130 virtual void X2() {}
Y2SimplePadVtable2131 virtual void Y2() {}
Z2SimplePadVtable2132 virtual void Z2() {}
133 } P;
134
135 struct SimplePadVtable3 {
operator deleteSimplePadVtable3136 static void operator delete(void *ptr, size_t sz) {}
~SimplePadVtable3SimplePadVtable3137 virtual ~SimplePadVtable3() {}
Foo3SimplePadVtable3138 virtual void Foo3() {}
Bar3SimplePadVtable3139 virtual void Bar3() {}
Baz3SimplePadVtable3140 virtual void Baz3() {}
Buzz3SimplePadVtable3141 virtual void Buzz3() {}
142 } Q;
143
144 struct SimplePadMultiVTables
145 : public SimplePadVtable1,
146 public SimplePadVtable2,
147 public SimplePadVtable3 {
148
~SimplePadMultiVTablesSimplePadMultiVTables149 ~SimplePadMultiVTables() override {}
operator deleteSimplePadMultiVTables150 static void operator delete(void *ptr, size_t sz) {}
151
152 // SimplePadVtable1 overrides
A1SimplePadMultiVTables153 void A1() override {}
154
155 // SimplePadVtable2 overrides
Y2SimplePadMultiVTables156 void Y2() override {}
Z2SimplePadMultiVTables157 void Z2() override {}
158
159 // SimplePadVtable3 overrides
Bar3SimplePadMultiVTables160 void Bar3() override {}
Baz3SimplePadMultiVTables161 void Baz3() override {}
Buzz3SimplePadMultiVTables162 void Buzz3() override {}
163 } R;
164
main(int argc,char ** argv)165 int main(int argc, char **argv) {
166
167 return 0;
168 }
169