]> granicus.if.org Git - clang/commitdiff
[ms-abi] Adjusting Rules for Padding Between Bases
authorWarren Hunt <whunt@google.com>
Fri, 10 Jan 2014 23:32:32 +0000 (23:32 +0000)
committerWarren Hunt <whunt@google.com>
Fri, 10 Jan 2014 23:32:32 +0000 (23:32 +0000)
The presence of a VBPtr suppresses the presence of zero sized
sub-objects in the non-virtual portion of the object in the context of
determining if two base objects need alias-avoidance padding placed
between them.

Test cases included.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@198975 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/RecordLayoutBuilder.cpp
test/Layout/ms-x86-alias-avoidance-padding.cpp

index 30293c27c179cdd3054bda9604cf4b27822efea8..6a708a7e8d70c65776f38ce46ffb1a82b489232a 100644 (file)
@@ -2477,6 +2477,9 @@ void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) {
          i->second += Offset;
   // Update the object alignment.
   updateAlignment(PointerInfo.Alignment);
+  // The presence of a vbptr suppresses zero sized objects that are not in
+  // virtual bases.
+  HasZeroSizedSubObject = false;
 }
 
 void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {
@@ -2566,6 +2569,9 @@ void MicrosoftRecordLayoutBuilder::injectVPtrs(const CXXRecordDecl *RD) {
     }
   }
   layoutFields(RD);
+  // The presence of a vbptr suppresses zero sized objects that are not in
+  // virtual bases.
+  HasZeroSizedSubObject = false;
 }
 
 void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
index 1b5d25cd5b79ab1e48ac3a07aa2471501c6f8ca9..48249137017969f8c85af35221bc397c960bb29e 100644 (file)
@@ -139,29 +139,29 @@ struct BT3 : BT0, BT2 {
 
 struct T0 : AT {
        T0() {
-               printf("T0 (this) : %d\n", (char*)this - buffer);
+               printf("T0 (this) : %d\n", (int)((char*)this - buffer));
        }
 };
 
 struct T1 : T0 {
        char a;
        T1() {
-               printf("T1 (this) : %d\n", (char*)this - buffer);
-               printf("T1 (fiel) : %d\n", (char*)&a - buffer);
+               printf("T1 (this) : %d\n", (int)((char*)this - buffer));
+               printf("T1 (fiel) : %d\n", (int)((char*)&a - buffer));
        }
 };
 
 struct T2 : AT {
        char a;
        T2() {
-               printf("T2 (this) : %d\n", (char*)this - buffer);
-               printf("T2 (fiel) : %d\n", (char*)&a - buffer);
+               printf("T2 (this) : %d\n", (int)((char*)this - buffer));
+               printf("T2 (fiel) : %d\n", (int)((char*)&a - buffer));
        }
 };
 
 struct __declspec(align(1)) T3 : virtual T1, virtual T2 {
        T3() {
-               printf("T3 (this) : %d\n", (char*)this - buffer);
+               printf("T3 (this) : %d\n", (int)((char*)this - buffer));
        }
 };
 
@@ -196,7 +196,69 @@ struct __declspec(align(1)) T3 : virtual T1, virtual T2 {
 // CHECK-X64-NEXT:      | [sizeof=24, align=8
 // CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
 
+struct B {};
+struct C { int a; };
+struct D : B, virtual C { B b; };
+struct E : D, B {};
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT:    0 | struct E
+// CHECK-NEXT:    0 |   struct D (base)
+// CHECK-NEXT:    4 |     struct B (base) (empty)
+// CHECK-NEXT:    0 |     (D vbtable pointer)
+// CHECK-NEXT:    4 |     struct B b (empty)
+// CHECK:         8 |   struct B (base) (empty)
+// CHECK-NEXT:    8 |   struct C (virtual base)
+// CHECK-NEXT:    8 |     int a
+// CHECK-NEXT:      | [sizeof=12, align=4
+// CHECK-NEXT:      |  nvsize=8, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT:   0 | struct E
+// CHECK-X64-NEXT:   0 |   struct D (base)
+// CHECK-X64-NEXT:   8 |     struct B (base) (empty)
+// CHECK-X64-NEXT:   0 |     (D vbtable pointer)
+// CHECK-X64-NEXT:   8 |     struct B b (empty)
+// CHECK-X64:       16 |   struct B (base) (empty)
+// CHECK-X64-NEXT:  16 |   struct C (virtual base)
+// CHECK-X64-NEXT:  16 |     int a
+// CHECK-X64-NEXT:     | [sizeof=24, align=8
+// CHECK-X64-NEXT:     |  nvsize=16, nvalign=8]
+
+struct F : virtual D, virtual B {};
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT:    0 | struct F
+// CHECK-NEXT:    0 |   (F vbtable pointer)
+// CHECK-NEXT:    4 |   struct C (virtual base)
+// CHECK-NEXT:    4 |     int a
+// CHECK-NEXT:    8 |   struct D (virtual base)
+// CHECK-NEXT:   12 |     struct B (base) (empty)
+// CHECK-NEXT:    8 |     (D vbtable pointer)
+// CHECK-NEXT:   12 |     struct B b (empty)
+// CHECK:        16 |   struct B (virtual base) (empty)
+// CHECK-NEXT:      | [sizeof=16, align=4
+// CHECK-NEXT:      |  nvsize=4, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT:    0 | struct F
+// CHECK-X64-NEXT:    0 |   (F vbtable pointer)
+// CHECK-X64-NEXT:    8 |   struct C (virtual base)
+// CHECK-X64-NEXT:    8 |     int a
+// CHECK-X64-NEXT:   16 |   struct D (virtual base)
+// CHECK-X64-NEXT:   24 |     struct B (base) (empty)
+// CHECK-X64-NEXT:   16 |     (D vbtable pointer)
+// CHECK-X64-NEXT:   24 |     struct B b (empty)
+// CHECK-X64:        32 |   struct B (virtual base) (empty)
+// CHECK-X64-NEXT:      | [sizeof=32, align=8
+// CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
+
 int a[
 sizeof(AT3) +
 sizeof(BT3) +
-sizeof(T3)];
+sizeof(T3) +
+sizeof(E) +
+sizeof(F) +
+0];