From d51b71c7b3abd27d82f3f97e09eb1eb1630f7f45 Mon Sep 17 00:00:00 2001 From: Warren Hunt Date: Fri, 10 Jan 2014 23:32:32 +0000 Subject: [PATCH] [ms-abi] Adjusting Rules for Padding Between Bases 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 | 6 ++ .../Layout/ms-x86-alias-avoidance-padding.cpp | 76 +++++++++++++++++-- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 30293c27c1..6a708a7e8d 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -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) { diff --git a/test/Layout/ms-x86-alias-avoidance-padding.cpp b/test/Layout/ms-x86-alias-avoidance-padding.cpp index 1b5d25cd5b..4824913701 100644 --- a/test/Layout/ms-x86-alias-avoidance-padding.cpp +++ b/test/Layout/ms-x86-alias-avoidance-padding.cpp @@ -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]; -- 2.40.0