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