You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			169 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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;
 | |
| }
 |