Home | History | Annotate | Download | only in Inputs
      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