summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp76
-rw-r--r--clang/test/Layout/ms-x86-aligned-tail-padding.cpp66
-rw-r--r--clang/test/Layout/ms-x86-basic-layout.cpp120
-rw-r--r--clang/test/Layout/ms-x86-empty-virtual-base.cpp2
-rw-r--r--clang/test/Layout/ms-x86-lazy-empty-nonvirtual-base.cpp10
-rw-r--r--clang/test/Layout/ms-x86-vfvb-alignment.cpp66
-rw-r--r--clang/test/Layout/ms-x86-vfvb-sharing.cpp24
7 files changed, 148 insertions, 216 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index cb5b1093436..0c21bde3820 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2137,7 +2137,6 @@ public:
const ASTRecordLayout *&PreviousBaseLayout);
void injectVFPtr(const CXXRecordDecl *RD);
void injectVBPtr(const CXXRecordDecl *RD);
- void injectVPtrs(const CXXRecordDecl *RD);
/// \brief Lays out the fields of the record. Also rounds size up to
/// alignment.
void layoutFields(const RecordDecl *RD);
@@ -2300,7 +2299,10 @@ void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
initializeCXXLayout(RD);
layoutNonVirtualBases(RD);
layoutFields(RD);
- injectVPtrs(RD);
+ injectVBPtr(RD);
+ injectVFPtr(RD);
+ if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
+ Alignment = std::max(Alignment, PointerInfo.Alignment);
NonVirtualSize = Size = Size.RoundUpToAlignment(Alignment);
RequiredAlignment = std::max(
RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
@@ -2570,76 +2572,6 @@ void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {
i->second += Offset;
}
-void MicrosoftRecordLayoutBuilder::injectVPtrs(const CXXRecordDecl *RD) {
- if (!(HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase)))
- return;
- if (!Is64BitMode || RequiredAlignment <= CharUnits::fromQuantity(8)) {
- // Note that the VBPtr is injected first. It depends on the alignment of
- // the object *before* the alignment is updated by inserting a pointer into
- // the record.
- injectVBPtr(RD);
- injectVFPtr(RD);
- Alignment = std::max(Alignment, PointerInfo.Alignment);
- return;
- }
- // In 64-bit mode, structs with RequiredAlignment greater than 8 get special
- // layout rules. Likely this is to avoid excessive padding intruced around
- // the vfptrs and vbptrs. The special rules involve re-laying out the struct
- // and inserting the vfptr and vbptr as if they were fields/bases.
- FieldOffsets.clear();
- Bases.clear();
- Size = CharUnits::Zero();
- Alignment = std::max(Alignment, PointerInfo.Alignment);
- if (HasOwnVFPtr)
- Size = PointerInfo.Size;
- layoutNonVirtualBases(RD);
- if (HasVBPtr && !SharedVBPtrBase) {
- const CXXRecordDecl *PenultBaseDecl = 0;
- const CXXRecordDecl *LastBaseDecl = 0;
- // Iterate through the bases and find the last two non-virtual bases.
- for (const auto &I : RD->bases()) {
- if (I.isVirtual())
- continue;
- const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
- if (!LastBaseDecl || Bases[BaseDecl] > Bases[LastBaseDecl]) {
- PenultBaseDecl = LastBaseDecl;
- LastBaseDecl = BaseDecl;
- }
- }
- const ASTRecordLayout *PenultBaseLayout = PenultBaseDecl ?
- &Context.getASTRecordLayout(PenultBaseDecl) : 0;
- const ASTRecordLayout *LastBaseLayout = LastBaseDecl ?
- &Context.getASTRecordLayout(LastBaseDecl) : 0;
- // Calculate the vbptr offset. The rule is different than in the general
- // case layout. Particularly, if the last two non-virtual bases are both
- // zero sized, the site of the vbptr is *before* the padding that occurs
- // between the two zero sized bases and the vbptr potentially aliases with
- // the first of these two bases. We have no understanding of why this is
- // different from the general case layout but it may have to do with lazy
- // placement of zero sized bases.
- VBPtrOffset = Size;
- if (LastBaseLayout && LastBaseLayout->getNonVirtualSize().isZero()) {
- VBPtrOffset = Bases[LastBaseDecl];
- if (PenultBaseLayout && PenultBaseLayout->getNonVirtualSize().isZero())
- VBPtrOffset = Bases[PenultBaseDecl];
- }
- // Once we've located a spot for the vbptr, place it.
- VBPtrOffset = VBPtrOffset.RoundUpToAlignment(PointerInfo.Alignment);
- Size = VBPtrOffset + PointerInfo.Size;
- if (LastBaseLayout && LastBaseLayout->getNonVirtualSize().isZero()) {
- // Add the padding between zero sized bases after the vbptr.
- if (PenultBaseLayout && PenultBaseLayout->getNonVirtualSize().isZero())
- Size += CharUnits::One();
- Size = Size.RoundUpToAlignment(LastBaseLayout->getRequiredAlignment());
- Bases[LastBaseDecl] = Size;
- }
- }
- 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) {
if (!HasVBPtr)
return;
diff --git a/clang/test/Layout/ms-x86-aligned-tail-padding.cpp b/clang/test/Layout/ms-x86-aligned-tail-padding.cpp
index 36f7b973453..f919766546e 100644
--- a/clang/test/Layout/ms-x86-aligned-tail-padding.cpp
+++ b/clang/test/Layout/ms-x86-aligned-tail-padding.cpp
@@ -105,11 +105,11 @@ struct A : B1, B0, B2, virtual V {
// CHECK-X64-NEXT: 16 | struct B2 (base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 32 | (A vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 48 | struct V (virtual base)
-// CHECK-X64-NEXT: 48 | char a
-// CHECK-X64-NEXT: | [sizeof=64, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct V (virtual base)
+// CHECK-X64-NEXT: 64 | char a
+// CHECK-X64-NEXT: | [sizeof=80, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct B : B2, B0, B1, virtual V {
int a;
@@ -139,7 +139,7 @@ struct B : B2, B0, B1, virtual V {
// CHECK-X64-NEXT: 32 | struct B1 (base)
// CHECK-X64-NEXT: 32 | int a
// CHECK-X64-NEXT: 40 | (B vbtable pointer)
-// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 52 | int a
// CHECK-X64-NEXT: 64 | struct V (virtual base)
// CHECK-X64-NEXT: 64 | char a
// CHECK-X64-NEXT: | [sizeof=80, align=16
@@ -171,12 +171,12 @@ struct C : B1, B0, virtual V {
// CHECK-X64-NEXT: 4 | struct B0 (base)
// CHECK-X64-NEXT: 4 | int a
// CHECK-X64-NEXT: 8 | (C vbtable pointer)
-// CHECK-X64-NEXT: 16 | int a
-// CHECK-X64-NEXT: 24 | long long a1
-// CHECK-X64-NEXT: 32 | struct V (virtual base)
-// CHECK-X64-NEXT: 32 | char a
-// CHECK-X64-NEXT: | [sizeof=48, align=16
-// CHECK-X64-NEXT: | nvsize=32, nvalign=16]
+// CHECK-X64-NEXT: 24 | int a
+// CHECK-X64-NEXT: 32 | long long a1
+// CHECK-X64-NEXT: 48 | struct V (virtual base)
+// CHECK-X64-NEXT: 48 | char a
+// CHECK-X64-NEXT: | [sizeof=64, align=16
+// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
struct D : B2, B0, virtual V {
int a;
@@ -202,7 +202,7 @@ struct D : B2, B0, virtual V {
// CHECK-X64-NEXT: 16 | struct B0 (base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 24 | (D vbtable pointer)
-// CHECK-X64-NEXT: 32 | int a
+// CHECK-X64-NEXT: 36 | int a
// CHECK-X64-NEXT: 48 | struct V (virtual base)
// CHECK-X64-NEXT: 48 | char a
// CHECK-X64-NEXT: | [sizeof=64, align=16
@@ -236,7 +236,7 @@ struct E : B3, B0, virtual V {
// CHECK-X64-NEXT: 16 | struct B0 (base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 24 | (E vbtable pointer)
-// CHECK-X64-NEXT: 32 | int a
+// CHECK-X64-NEXT: 36 | int a
// CHECK-X64-NEXT: 48 | struct V (virtual base)
// CHECK-X64-NEXT: 48 | char a
// CHECK-X64-NEXT: | [sizeof=64, align=16
@@ -269,13 +269,13 @@ struct F : B0, virtual V1 {
// CHECK-X64-NEXT: 0 | struct B0 (base)
// CHECK-X64-NEXT: 0 | int a
// CHECK-X64-NEXT: 8 | (F vbtable pointer)
-// CHECK-X64-NEXT: 16 | int a
-// CHECK-X64-NEXT: 60 | (vtordisp for vbase V1)
-// CHECK-X64-NEXT: 64 | struct V1 (virtual base)
-// CHECK-X64-NEXT: 64 | (V1 vftable pointer)
-// CHECK-X64-NEXT: 96 | struct A16 (base) (empty)
-// CHECK-X64-NEXT: | [sizeof=96, align=32
-// CHECK-X64-NEXT: | nvsize=32, nvalign=32]
+// CHECK-X64-NEXT: 32 | int a
+// CHECK-X64-NEXT: 92 | (vtordisp for vbase V1)
+// CHECK-X64-NEXT: 96 | struct V1 (virtual base)
+// CHECK-X64-NEXT: 96 | (V1 vftable pointer)
+// CHECK-X64-NEXT: 128 | struct A16 (base) (empty)
+// CHECK-X64-NEXT: | [sizeof=128, align=32
+// CHECK-X64-NEXT: | nvsize=48, nvalign=32]
struct G : virtual V2, virtual V3 {
int a;
@@ -389,7 +389,7 @@ struct AX : B0X, virtual B2X, virtual B6X, virtual B3X {
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 20 | int a1
// CHECK-X64-NEXT: 24 | (AX vbtable pointer)
-// CHECK-X64-NEXT: 32 | int a
+// CHECK-X64-NEXT: 40 | int a
// CHECK-X64-NEXT: 48 | struct B2X (virtual base)
// CHECK-X64-NEXT: 48 | int a
// CHECK-X64-NEXT: 52 | struct B6X (virtual base)
@@ -439,17 +439,17 @@ struct BX : B4X, virtual B2X, virtual B6X, virtual B3X {
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 20 | int a1
// CHECK-X64-NEXT: 32 | (BX vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 48 | struct B2X (virtual base)
-// CHECK-X64-NEXT: 48 | int a
-// CHECK-X64-NEXT: 52 | struct B6X (virtual base)
-// CHECK-X64-NEXT: 52 | int a
-// CHECK-X64-NEXT: 76 | (vtordisp for vbase B3X)
-// CHECK-X64-NEXT: 80 | struct B3X (virtual base)
-// CHECK-X64-NEXT: 80 | (B3X vftable pointer)
-// CHECK-X64-NEXT: 88 | int a
-// CHECK-X64-NEXT: | [sizeof=96, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct B2X (virtual base)
+// CHECK-X64-NEXT: 64 | int a
+// CHECK-X64-NEXT: 68 | struct B6X (virtual base)
+// CHECK-X64-NEXT: 68 | int a
+// CHECK-X64-NEXT: 92 | (vtordisp for vbase B3X)
+// CHECK-X64-NEXT: 96 | struct B3X (virtual base)
+// CHECK-X64-NEXT: 96 | (B3X vftable pointer)
+// CHECK-X64-NEXT: 104 | int a
+// CHECK-X64-NEXT: | [sizeof=112, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct CX : B5X, virtual B2X, virtual B6X, virtual B3X {
int a;
diff --git a/clang/test/Layout/ms-x86-basic-layout.cpp b/clang/test/Layout/ms-x86-basic-layout.cpp
index c7501a6cbb2..b6ffeee7114 100644
--- a/clang/test/Layout/ms-x86-basic-layout.cpp
+++ b/clang/test/Layout/ms-x86-basic-layout.cpp
@@ -428,12 +428,12 @@ struct TestFB : A16, virtual C16 {
// CHECK-X64-NEXT: 16 | struct A16 (base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 32 | (TestFB vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 48 | struct C16 (virtual base)
-// CHECK-X64-NEXT: 48 | (C16 vftable pointer)
-// CHECK-X64-NEXT: 64 | int a
-// CHECK-X64-NEXT: | [sizeof=80, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct C16 (virtual base)
+// CHECK-X64-NEXT: 64 | (C16 vftable pointer)
+// CHECK-X64-NEXT: 80 | int a
+// CHECK-X64-NEXT: | [sizeof=96, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct TestFC : TestFB, A4 {
int a;
@@ -464,15 +464,15 @@ struct TestFC : TestFB, A4 {
// CHECK-X64-NEXT: 16 | struct A16 (base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 32 | (TestFB vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 48 | struct A4 (base)
// CHECK-X64-NEXT: 48 | int a
-// CHECK-X64-NEXT: 52 | int a
-// CHECK-X64-NEXT: 64 | struct C16 (virtual base)
-// CHECK-X64-NEXT: 64 | (C16 vftable pointer)
-// CHECK-X64-NEXT: 80 | int a
-// CHECK-X64-NEXT: | [sizeof=96, align=16
-// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
+// CHECK-X64-NEXT: 64 | struct A4 (base)
+// CHECK-X64-NEXT: 64 | int a
+// CHECK-X64-NEXT: 68 | int a
+// CHECK-X64-NEXT: 80 | struct C16 (virtual base)
+// CHECK-X64-NEXT: 80 | (C16 vftable pointer)
+// CHECK-X64-NEXT: 96 | int a
+// CHECK-X64-NEXT: | [sizeof=112, align=16
+// CHECK-X64-NEXT: | nvsize=80, nvalign=16]
struct A16f {
@@ -525,22 +525,22 @@ struct F0 : A4, B {
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct F0
// CHECK-X64-NEXT: 0 | (F0 vftable pointer)
-// CHECK-X64-NEXT: 8 | struct A4 (base)
-// CHECK-X64-NEXT: 8 | int a
-// CHECK-X64-NEXT: 16 | struct B (base)
-// CHECK-X64-NEXT: 16 | struct A4 (base)
-// CHECK-X64-NEXT: 16 | int a
-// CHECK-X64-NEXT: 20 | struct Y (base)
-// CHECK-X64-NEXT: 20 | char y
-// CHECK-X64-NEXT: 32 | struct X (base)
-// CHECK-X64-NEXT: 32 | (X vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 48 | int a
-// CHECK-X64-NEXT: 64 | struct A16f (virtual base)
-// CHECK-X64-NEXT: 64 | (A16f vftable pointer)
-// CHECK-X64-NEXT: 80 | int a
-// CHECK-X64-NEXT: | [sizeof=96, align=16
-// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
+// CHECK-X64-NEXT: 16 | struct A4 (base)
+// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 32 | struct B (base)
+// CHECK-X64-NEXT: 32 | struct A4 (base)
+// CHECK-X64-NEXT: 32 | int a
+// CHECK-X64-NEXT: 36 | struct Y (base)
+// CHECK-X64-NEXT: 36 | char y
+// CHECK-X64-NEXT: 48 | struct X (base)
+// CHECK-X64-NEXT: 48 | (X vbtable pointer)
+// CHECK-X64-NEXT: 56 | int a
+// CHECK-X64-NEXT: 64 | int a
+// CHECK-X64-NEXT: 80 | struct A16f (virtual base)
+// CHECK-X64-NEXT: 80 | (A16f vftable pointer)
+// CHECK-X64-NEXT: 96 | int a
+// CHECK-X64-NEXT: | [sizeof=112, align=16
+// CHECK-X64-NEXT: | nvsize=80, nvalign=16]
struct F1 : B, A4 {
int a;
@@ -639,15 +639,15 @@ struct F3 : A4, virtual A16f {
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct F3
// CHECK-X64-NEXT: 0 | (F3 vftable pointer)
-// CHECK-X64-NEXT: 8 | struct A4 (base)
-// CHECK-X64-NEXT: 8 | int a
-// CHECK-X64-NEXT: 16 | (F3 vbtable pointer)
-// CHECK-X64-NEXT: 32 | int a
-// CHECK-X64-NEXT: 48 | struct A16f (virtual base)
-// CHECK-X64-NEXT: 48 | (A16f vftable pointer)
-// CHECK-X64-NEXT: 64 | int a
-// CHECK-X64-NEXT: | [sizeof=80, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 16 | struct A4 (base)
+// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 24 | (F3 vbtable pointer)
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct A16f (virtual base)
+// CHECK-X64-NEXT: 64 | (A16f vftable pointer)
+// CHECK-X64-NEXT: 80 | int a
+// CHECK-X64-NEXT: | [sizeof=96, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct F4 : A4, B {
__declspec(align(16)) int a;
@@ -677,22 +677,22 @@ struct F4 : A4, B {
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct F4
// CHECK-X64-NEXT: 0 | (F4 vftable pointer)
-// CHECK-X64-NEXT: 8 | struct A4 (base)
-// CHECK-X64-NEXT: 8 | int a
-// CHECK-X64-NEXT: 16 | struct B (base)
-// CHECK-X64-NEXT: 16 | struct A4 (base)
-// CHECK-X64-NEXT: 16 | int a
-// CHECK-X64-NEXT: 20 | struct Y (base)
-// CHECK-X64-NEXT: 20 | char y
-// CHECK-X64-NEXT: 32 | struct X (base)
-// CHECK-X64-NEXT: 32 | (X vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 48 | int a
-// CHECK-X64-NEXT: 64 | struct A16f (virtual base)
-// CHECK-X64-NEXT: 64 | (A16f vftable pointer)
-// CHECK-X64-NEXT: 80 | int a
-// CHECK-X64-NEXT: | [sizeof=96, align=16
-// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
+// CHECK-X64-NEXT: 16 | struct A4 (base)
+// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 32 | struct B (base)
+// CHECK-X64-NEXT: 32 | struct A4 (base)
+// CHECK-X64-NEXT: 32 | int a
+// CHECK-X64-NEXT: 36 | struct Y (base)
+// CHECK-X64-NEXT: 36 | char y
+// CHECK-X64-NEXT: 48 | struct X (base)
+// CHECK-X64-NEXT: 48 | (X vbtable pointer)
+// CHECK-X64-NEXT: 56 | int a
+// CHECK-X64-NEXT: 64 | int a
+// CHECK-X64-NEXT: 80 | struct A16f (virtual base)
+// CHECK-X64-NEXT: 80 | (A16f vftable pointer)
+// CHECK-X64-NEXT: 96 | int a
+// CHECK-X64-NEXT: | [sizeof=112, align=16
+// CHECK-X64-NEXT: | nvsize=80, nvalign=16]
struct F5 : A16f, virtual A4 {
int a;
@@ -717,11 +717,11 @@ struct F5 : A16f, virtual A4 {
// CHECK-X64-NEXT: 0 | (A16f vftable pointer)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 32 | (F5 vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 48 | struct A4 (virtual base)
-// CHECK-X64-NEXT: 48 | int a
-// CHECK-X64-NEXT: | [sizeof=64, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct A4 (virtual base)
+// CHECK-X64-NEXT: 64 | int a
+// CHECK-X64-NEXT: | [sizeof=80, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct F6 : virtual A16f, A4, virtual B {
int a;
diff --git a/clang/test/Layout/ms-x86-empty-virtual-base.cpp b/clang/test/Layout/ms-x86-empty-virtual-base.cpp
index 267f82afef7..23e287acf93 100644
--- a/clang/test/Layout/ms-x86-empty-virtual-base.cpp
+++ b/clang/test/Layout/ms-x86-empty-virtual-base.cpp
@@ -240,7 +240,7 @@ struct G : virtual C0, virtual B0, virtual B1, D0, virtual C1 {
// CHECK-X64-NEXT: 0 | struct D0 (primary base)
// CHECK-X64-NEXT: 0 | (D0 vftable pointer)
// CHECK-X64-NEXT: 8 | (G vbtable pointer)
-// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 24 | int a
// CHECK-X64-NEXT: 32 | struct C0 (virtual base)
// CHECK-X64-NEXT: 32 | int a
// CHECK-X64-NEXT: 40 | struct B0 (virtual base) (empty)
diff --git a/clang/test/Layout/ms-x86-lazy-empty-nonvirtual-base.cpp b/clang/test/Layout/ms-x86-lazy-empty-nonvirtual-base.cpp
index 991bd4a22c2..5bea872ae11 100644
--- a/clang/test/Layout/ms-x86-lazy-empty-nonvirtual-base.cpp
+++ b/clang/test/Layout/ms-x86-lazy-empty-nonvirtual-base.cpp
@@ -612,9 +612,9 @@ struct G : B8, B1, virtual B0 {
// CHECK-X64-NEXT: 0 | struct G
// CHECK-X64-NEXT: 0 | struct B8 (base)
// CHECK-X64-NEXT: 0 | char [5] c
-// CHECK-X64-NEXT: 16 | struct B1 (base) (empty)
+// CHECK-X64-NEXT: 21 | struct B1 (base) (empty)
// CHECK-X64-NEXT: 8 | (G vbtable pointer)
-// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 24 | int a
// CHECK-X64-NEXT: 32 | int a1
// CHECK-X64-NEXT: 48 | struct B0 (virtual base) (empty)
// CHECK-X64-NEXT: | [sizeof=48, align=16
@@ -651,7 +651,7 @@ struct AX : B1X, B2X, B3X, B4X, virtual B0X {
// CHECK-X64-NEXT: 0 | struct B1X (base) (empty)
// CHECK-X64-NEXT: 16 | struct B2X (base) (empty)
// CHECK-X64-NEXT: 18 | struct B3X (base) (empty)
-// CHECK-X64-NEXT: 33 | struct B4X (base) (empty)
+// CHECK-X64-NEXT: 35 | struct B4X (base) (empty)
// CHECK-X64-NEXT: 24 | (AX vbtable pointer)
// CHECK-X64-NEXT: 36 | int a
// CHECK-X64-NEXT: 48 | struct B0X (virtual base) (empty)
@@ -679,7 +679,7 @@ struct BX : B2X, B1X, B3X, B4X, virtual B0X {
// CHECK-X64-NEXT: 0 | struct B2X (base) (empty)
// CHECK-X64-NEXT: 1 | struct B1X (base) (empty)
// CHECK-X64-NEXT: 2 | struct B3X (base) (empty)
-// CHECK-X64-NEXT: 17 | struct B4X (base) (empty)
+// CHECK-X64-NEXT: 19 | struct B4X (base) (empty)
// CHECK-X64-NEXT: 8 | (BX vbtable pointer)
// CHECK-X64-NEXT: 20 | int a
// CHECK-X64-NEXT: 32 | struct B0X (virtual base) (empty)
@@ -706,7 +706,7 @@ struct CX : B1X, B3X, B2X, virtual B0X {
// CHECK-X64-NEXT: 0 | struct B1X (base) (empty)
// CHECK-X64-NEXT: 2 | struct B3X (base) (empty)
// CHECK-X64-NEXT: 32 | struct B2X (base) (empty)
-// CHECK-X64-NEXT: 8 | (CX vbtable pointer)
+// CHECK-X64-NEXT: 16 | (CX vbtable pointer)
// CHECK-X64-NEXT: 32 | int a
// CHECK-X64-NEXT: 48 | struct B0X (virtual base) (empty)
// CHECK-X64-NEXT: | [sizeof=48, align=16
diff --git a/clang/test/Layout/ms-x86-vfvb-alignment.cpp b/clang/test/Layout/ms-x86-vfvb-alignment.cpp
index f65adc15a66..54f74ac16d1 100644
--- a/clang/test/Layout/ms-x86-vfvb-alignment.cpp
+++ b/clang/test/Layout/ms-x86-vfvb-alignment.cpp
@@ -33,14 +33,14 @@ struct A : B0, virtual B1 { __declspec(align(16)) int a; A() : a(0xf000000A) {}
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct A
// CHECK-X64-NEXT: 0 | (A vftable pointer)
-// CHECK-X64-NEXT: 8 | struct B0 (base)
-// CHECK-X64-NEXT: 8 | int a
-// CHECK-X64-NEXT: 16 | (A vbtable pointer)
-// CHECK-X64-NEXT: 32 | int a
-// CHECK-X64-NEXT: 48 | struct B1 (virtual base)
-// CHECK-X64-NEXT: 48 | char a
-// CHECK-X64-NEXT: | [sizeof=64, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 16 | struct B0 (base)
+// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 24 | (A vbtable pointer)
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct B1 (virtual base)
+// CHECK-X64-NEXT: 64 | char a
+// CHECK-X64-NEXT: | [sizeof=80, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct B : A, B2 { int a; B() : a(0xf000000B) {} virtual void f() { printf("B"); } };
@@ -66,18 +66,18 @@ struct B : A, B2 { int a; B() : a(0xf000000B) {} virtual void f() { printf("B");
// CHECK-X64-NEXT: 0 | struct B
// CHECK-X64-NEXT: 0 | struct A (primary base)
// CHECK-X64-NEXT: 0 | (A vftable pointer)
-// CHECK-X64-NEXT: 8 | struct B0 (base)
-// CHECK-X64-NEXT: 8 | int a
-// CHECK-X64-NEXT: 16 | (A vbtable pointer)
-// CHECK-X64-NEXT: 32 | int a
-// CHECK-X64-NEXT: 48 | struct B2 (base)
-// CHECK-X64-NEXT: 48 | (B2 vbtable pointer)
-// CHECK-X64-NEXT: 56 | int a
-// CHECK-X64-NEXT: 64 | int a
-// CHECK-X64-NEXT: 80 | struct B1 (virtual base)
-// CHECK-X64-NEXT: 80 | char a
-// CHECK-X64-NEXT: | [sizeof=96, align=16
-// CHECK-X64-NEXT: | nvsize=80, nvalign=16]
+// CHECK-X64-NEXT: 16 | struct B0 (base)
+// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 24 | (A vbtable pointer)
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct B2 (base)
+// CHECK-X64-NEXT: 64 | (B2 vbtable pointer)
+// CHECK-X64-NEXT: 72 | int a
+// CHECK-X64-NEXT: 80 | int a
+// CHECK-X64-NEXT: 96 | struct B1 (virtual base)
+// CHECK-X64-NEXT: 96 | char a
+// CHECK-X64-NEXT: | [sizeof=112, align=16
+// CHECK-X64-NEXT: | nvsize=96, nvalign=16]
struct C : B4 { int a; C() : a(0xf000000C) {} virtual void f() { printf("C"); } };
@@ -189,11 +189,11 @@ struct F : B3, virtual B0 { int a; F() : a(0xf000000F) {} virtual void f() { pri
// CHECK-X64-NEXT: 16 | struct B3 (base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 32 | (F vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 48 | struct B0 (virtual base)
-// CHECK-X64-NEXT: 48 | int a
-// CHECK-X64-NEXT: | [sizeof=64, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct B0 (virtual base)
+// CHECK-X64-NEXT: 64 | int a
+// CHECK-X64-NEXT: | [sizeof=80, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct G : B2, B6, virtual B1 { int a; G() : a(0xf0000010) {} };
@@ -274,8 +274,8 @@ struct I : B0, virtual B1 { int a; int a1; __declspec(align(16)) int a2; I() : a
// CHECK-X64-NEXT: 0 | struct B0 (base)
// CHECK-X64-NEXT: 0 | int a
// CHECK-X64-NEXT: 8 | (I vbtable pointer)
-// CHECK-X64-NEXT: 16 | int a
-// CHECK-X64-NEXT: 20 | int a1
+// CHECK-X64-NEXT: 20 | int a
+// CHECK-X64-NEXT: 24 | int a1
// CHECK-X64-NEXT: 32 | int a2
// CHECK-X64-NEXT: 48 | struct B1 (virtual base)
// CHECK-X64-NEXT: 48 | char a
@@ -304,12 +304,12 @@ struct J : B0, B3, virtual B1 { int a; int a1; J() : a(0xf0000012), a1(0xf000001
// CHECK-X64-NEXT: 16 | struct B3 (base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 32 | (J vbtable pointer)
-// CHECK-X64-NEXT: 40 | int a
-// CHECK-X64-NEXT: 44 | int a1
-// CHECK-X64-NEXT: 48 | struct B1 (virtual base)
-// CHECK-X64-NEXT: 48 | char a
-// CHECK-X64-NEXT: | [sizeof=64, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 52 | int a1
+// CHECK-X64-NEXT: 64 | struct B1 (virtual base)
+// CHECK-X64-NEXT: 64 | char a
+// CHECK-X64-NEXT: | [sizeof=80, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct K { int a; K() : a(0xf0000013) {} virtual void f() { printf("K"); } };
diff --git a/clang/test/Layout/ms-x86-vfvb-sharing.cpp b/clang/test/Layout/ms-x86-vfvb-sharing.cpp
index 981fe688589..91f194f2a5e 100644
--- a/clang/test/Layout/ms-x86-vfvb-sharing.cpp
+++ b/clang/test/Layout/ms-x86-vfvb-sharing.cpp
@@ -35,14 +35,14 @@ struct A : B0, virtual B1 {
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct A
// CHECK-X64-NEXT: 0 | (A vftable pointer)
-// CHECK-X64-NEXT: 8 | struct B0 (base)
-// CHECK-X64-NEXT: 8 | int a
-// CHECK-X64-NEXT: 16 | (A vbtable pointer)
-// CHECK-X64-NEXT: 32 | int a
-// CHECK-X64-NEXT: 48 | struct B1 (virtual base)
-// CHECK-X64-NEXT: 48 | int a
-// CHECK-X64-NEXT: | [sizeof=64, align=16
-// CHECK-X64-NEXT: | nvsize=48, nvalign=16]
+// CHECK-X64-NEXT: 16 | struct B0 (base)
+// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 24 | (A vbtable pointer)
+// CHECK-X64-NEXT: 48 | int a
+// CHECK-X64-NEXT: 64 | struct B1 (virtual base)
+// CHECK-X64-NEXT: 64 | int a
+// CHECK-X64-NEXT: | [sizeof=80, align=16
+// CHECK-X64-NEXT: | nvsize=64, nvalign=16]
struct B : B2, B0, virtual B1 {
__declspec(align(16)) int a;
@@ -100,10 +100,10 @@ struct C : B3, B0, virtual B1 {
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct C
// CHECK-X64-NEXT: 0 | (C vftable pointer)
-// CHECK-X64-NEXT: 8 | struct B3 (base)
-// CHECK-X64-NEXT: 8 | (B3 vbtable pointer)
-// CHECK-X64-NEXT: 16 | struct B0 (base)
-// CHECK-X64-NEXT: 16 | int a
+// CHECK-X64-NEXT: 16 | struct B3 (base)
+// CHECK-X64-NEXT: 16 | (B3 vbtable pointer)
+// CHECK-X64-NEXT: 24 | struct B0 (base)
+// CHECK-X64-NEXT: 24 | int a
// CHECK-X64-NEXT: 32 | int a
// CHECK-X64-NEXT: 48 | struct B1 (virtual base)
// CHECK-X64-NEXT: 48 | int a
OpenPOWER on IntegriCloud