|  | // Compile with "cl /c /Zi /GR- SimplePaddingTest.cpp" | 
|  | // Link with "link SimplePaddingTest.obj /debug /nodefaultlib /entry:main" | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | extern "C" using at_exit_handler = void(); | 
|  |  | 
|  | int atexit(at_exit_handler handler) { return 0; } | 
|  |  | 
|  | struct SimplePadNoPadding { | 
|  | int32_t X; | 
|  | int32_t Y; | 
|  | // No padding anywhere, sizeof(T) = 8 | 
|  | } A; | 
|  |  | 
|  | struct SimplePadUnion { | 
|  | union { | 
|  | int32_t X; | 
|  | int64_t Y; | 
|  | struct { | 
|  | int32_t X; | 
|  | // 4 bytes of padding here | 
|  | int64_t Y; | 
|  | } Z; | 
|  | }; | 
|  | // Since the padding occurs at a location that is occupied by other storage | 
|  | // (namely the Y member), the storage will still be considered used, and so | 
|  | // there will be no unused bytes in the larger class.  But in the debug | 
|  | // info for the nested struct, we should see padding. | 
|  | // sizeof(SimplePadUnion) == sizeof(Z) == 16 | 
|  | } B; | 
|  |  | 
|  | struct SimplePadNoPadding2 { | 
|  | bool A; | 
|  | bool B; | 
|  | bool C; | 
|  | bool D; | 
|  | // No padding anywhere, sizeof(T) = 4 | 
|  | } C; | 
|  |  | 
|  | struct alignas(4) SimplePadFields1 { | 
|  | char A; | 
|  | char B; | 
|  | char C; | 
|  | // 1 byte of padding here, sizeof(T) = 4 | 
|  | } E; | 
|  |  | 
|  | struct SimplePadFields2 { | 
|  | int32_t Y; | 
|  | char X; | 
|  | } F; | 
|  |  | 
|  | struct SimplePadBase { | 
|  | // Make sure this class is 4 bytes, and the derived class requires 8 byte | 
|  | // alignment, so that padding is inserted between base and derived. | 
|  | int32_t X; | 
|  | // No padding here | 
|  | } G; | 
|  |  | 
|  | struct SimplePadDerived : public SimplePadBase { | 
|  | // 4 bytes of padding here due to Y requiring 8 byte alignment. | 
|  | // Thus, sizeof(T) = 16 | 
|  | int64_t Y; | 
|  | } H; | 
|  |  | 
|  | struct SimplePadEmptyBase1 {}; | 
|  | struct SimplePadEmptyBase2 {}; | 
|  |  | 
|  | struct SimplePadEmpty : public SimplePadEmptyBase1, SimplePadEmptyBase2 { | 
|  | // Bases have to occupy at least 1 byte of storage, so this requires | 
|  | // 2 bytes of padding, plus 1 byte for each base, yielding sizeof(T) = 8 | 
|  | int32_t X; | 
|  | } I; | 
|  |  | 
|  | struct SimplePadVfptr { | 
|  | virtual ~SimplePadVfptr() {} | 
|  | static void operator delete(void *ptr, size_t sz) {} | 
|  | int32_t X; | 
|  | } J; | 
|  |  | 
|  | struct NonEmptyBase1 { | 
|  | bool X; | 
|  | }; | 
|  |  | 
|  | struct NonEmptyBase2 { | 
|  | bool Y; | 
|  | }; | 
|  |  | 
|  | struct SimplePadMultiInherit : public NonEmptyBase1, public NonEmptyBase2 { | 
|  | // X and Y from the 2 bases will get squished together, leaving 2 bytes | 
|  | // of padding necessary for proper alignment of an int32. | 
|  | // Therefore, sizeof(T) = 2 + 2 + 4 = 8 | 
|  | int32_t X; | 
|  | } K; | 
|  |  | 
|  | struct SimplePadMultiInherit2 : public SimplePadFields1, SimplePadFields2 { | 
|  | // There should be 1 byte of padding after the first class, and | 
|  | // 3 bytes of padding after the second class. | 
|  | int32_t X; | 
|  | } L; | 
|  |  | 
|  | struct OneLevelInherit : public NonEmptyBase1 { | 
|  | short Y; | 
|  | }; | 
|  |  | 
|  | struct SimplePadTwoLevelInherit : public OneLevelInherit { | 
|  | // OneLevelInherit has nested padding because of its base, | 
|  | // and then padding again because of this class.  So each | 
|  | // class should be 4 bytes, yielding sizeof(T) = 12. | 
|  | int64_t Z; | 
|  | } M; | 
|  |  | 
|  | struct SimplePadAggregate { | 
|  | NonEmptyBase1 X; | 
|  | int32_t Y; | 
|  | // the presence of X will cause 3 bytes of padding to be injected. | 
|  | SimplePadFields1 Fields; | 
|  | } N; | 
|  |  | 
|  | struct SimplePadVtable1 { | 
|  | static void operator delete(void *ptr, size_t sz) {} | 
|  | virtual ~SimplePadVtable1() {} | 
|  | virtual void A1() {} | 
|  | virtual void B1() {} | 
|  | } O; | 
|  |  | 
|  | struct SimplePadVtable2 { | 
|  | static void operator delete(void *ptr, size_t sz) {} | 
|  | virtual ~SimplePadVtable2() {} | 
|  | virtual void X2() {} | 
|  | virtual void Y2() {} | 
|  | virtual void Z2() {} | 
|  | } P; | 
|  |  | 
|  | struct SimplePadVtable3 { | 
|  | static void operator delete(void *ptr, size_t sz) {} | 
|  | virtual ~SimplePadVtable3() {} | 
|  | virtual void Foo3() {} | 
|  | virtual void Bar3() {} | 
|  | virtual void Baz3() {} | 
|  | virtual void Buzz3() {} | 
|  | } Q; | 
|  |  | 
|  | struct SimplePadMultiVTables | 
|  | : public SimplePadVtable1, | 
|  | public SimplePadVtable2, | 
|  | public SimplePadVtable3 { | 
|  |  | 
|  | ~SimplePadMultiVTables() override {} | 
|  | static void operator delete(void *ptr, size_t sz) {} | 
|  |  | 
|  | // SimplePadVtable1 overrides | 
|  | void A1() override {} | 
|  |  | 
|  | // SimplePadVtable2 overrides | 
|  | void Y2() override {} | 
|  | void Z2() override {} | 
|  |  | 
|  | // SimplePadVtable3 overrides | 
|  | void Bar3() override {} | 
|  | void Baz3() override {} | 
|  | void Buzz3() override {} | 
|  | } R; | 
|  |  | 
|  | int main(int argc, char **argv) { | 
|  |  | 
|  | return 0; | 
|  | } |