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 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 { 76 virtual ~SimplePadVfptr() {} 77 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 { 121 static void operator delete(void *ptr, size_t sz) {} 122 virtual ~SimplePadVtable1() {} 123 virtual void A1() {} 124 virtual void B1() {} 125 } O; 126 127 struct SimplePadVtable2 { 128 static void operator delete(void *ptr, size_t sz) {} 129 virtual ~SimplePadVtable2() {} 130 virtual void X2() {} 131 virtual void Y2() {} 132 virtual void Z2() {} 133 } P; 134 135 struct SimplePadVtable3 { 136 static void operator delete(void *ptr, size_t sz) {} 137 virtual ~SimplePadVtable3() {} 138 virtual void Foo3() {} 139 virtual void Bar3() {} 140 virtual void Baz3() {} 141 virtual void Buzz3() {} 142 } Q; 143 144 struct SimplePadMultiVTables 145 : public SimplePadVtable1, 146 public SimplePadVtable2, 147 public SimplePadVtable3 { 148 149 ~SimplePadMultiVTables() override {} 150 static void operator delete(void *ptr, size_t sz) {} 151 152 // SimplePadVtable1 overrides 153 void A1() override {} 154 155 // SimplePadVtable2 overrides 156 void Y2() override {} 157 void Z2() override {} 158 159 // SimplePadVtable3 overrides 160 void Bar3() override {} 161 void Baz3() override {} 162 void Buzz3() override {} 163 } R; 164 165 int main(int argc, char **argv) { 166 167 return 0; 168 } 169