xref: /llvm-project/llvm/test/tools/llvm-pdbutil/Inputs/SimplePaddingTest.cpp (revision c9c55cf89b0d4ddd4b778da8ecf59fe740283bec)
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