You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.0 KiB
169 lines
4.0 KiB
4 months ago
|
// 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;
|
||
|
}
|