From bf3d4301634240a29aadf5bd6be25b4acb08575d Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 16 Jul 2014 07:16:58 +0000 Subject: [PATCH] MS ABI: Up the required alignment after inserting padding between vbases We would correctly insert sufficiently aligned padding between vbases when our leading base was empty, however we would neglect to increase the required alignment of the most derived class. This fixes PR20315. llvm-svn: 213123 --- clang/lib/AST/RecordLayoutBuilder.cpp | 4 ++- clang/test/Layout/ms-x86-pack-and-align.cpp | 55 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 3c91360f..b5ebbee 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2613,8 +2613,10 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { // bytes (in both 32 and 64 bits modes) and always involves rounding up to // the required alignment, we don't know why. if ((PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() && - BaseLayout.leadsWithZeroSizedBase()) || HasVtordisp) + BaseLayout.leadsWithZeroSizedBase()) || HasVtordisp) { Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize; + RequiredAlignment = VtorDispAlignment; + } // Insert the virtual base. ElementInfo Info = getAdjustedElementInfo(BaseLayout); CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment); diff --git a/clang/test/Layout/ms-x86-pack-and-align.cpp b/clang/test/Layout/ms-x86-pack-and-align.cpp index be0499c..7398465 100644 --- a/clang/test/Layout/ms-x86-pack-and-align.cpp +++ b/clang/test/Layout/ms-x86-pack-and-align.cpp @@ -544,6 +544,60 @@ struct RE { // CHECK-X64-NEXT: | [sizeof=1029, align=1 // CHECK-X64-NEXT: | nvsize=1029, nvalign=1] +struct NA {}; +struct NB {}; +#pragma pack(push, 1) +struct NC : virtual NA, virtual NB {}; +#pragma pack(pop) +struct ND : NC {}; + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct NA (empty) +// CHECK-NEXT: | [sizeof=1, align=1 +// CHECK-NEXT: | nvsize=0, nvalign=1] +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct NB (empty) +// CHECK-NEXT: | [sizeof=1, align=1 +// CHECK-NEXT: | nvsize=0, nvalign=1] +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct NC +// CHECK-NEXT: 0 | (NC vbtable pointer) +// CHECK-NEXT: 4 | struct NA (virtual base) (empty) +// CHECK-NEXT: 8 | struct NB (virtual base) (empty) +// CHECK-NEXT: | [sizeof=8, align=1 +// CHECK-NEXT: | nvsize=4, nvalign=1] +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct ND +// CHECK-NEXT: 0 | struct NC (base) +// CHECK-NEXT: 0 | (NC vbtable pointer) +// CHECK-NEXT: 4 | struct NA (virtual base) (empty) +// CHECK-NEXT: 8 | struct NB (virtual base) (empty) +// CHECK-NEXT: | [sizeof=8, align=4 +// CHECK-NEXT: | nvsize=4, nvalign=4] +// CHECK-X64: *** Dumping AST Record Layout +// CHECK-X64-NEXT: 0 | struct NA (empty) +// CHECK-X64-NEXT: | [sizeof=1, align=1 +// CHECK-X64-NEXT: | nvsize=0, nvalign=1] +// CHECK-X64: *** Dumping AST Record Layout +// CHECK-X64-NEXT: 0 | struct NB (empty) +// CHECK-X64-NEXT: | [sizeof=1, align=1 +// CHECK-X64-NEXT: | nvsize=0, nvalign=1] +// CHECK-X64: *** Dumping AST Record Layout +// CHECK-X64-NEXT: 0 | struct NC +// CHECK-X64-NEXT: 0 | (NC vbtable pointer) +// CHECK-X64-NEXT: 8 | struct NA (virtual base) (empty) +// CHECK-X64-NEXT: 12 | struct NB (virtual base) (empty) +// CHECK-X64-NEXT: | [sizeof=12, align=1 +// CHECK-X64-NEXT: | nvsize=8, nvalign=1] +// CHECK-X64: *** Dumping AST Record Layout +// CHECK-X64-NEXT: 0 | struct ND +// CHECK-X64-NEXT: 0 | struct NC (base) +// CHECK-X64-NEXT: 0 | (NC vbtable pointer) +// CHECK-X64-NEXT: 8 | struct NA (virtual base) (empty) +// CHECK-X64-NEXT: 12 | struct NB (virtual base) (empty) +// CHECK-X64-NEXT: | [sizeof=12, align=4 +// CHECK-X64-NEXT: | nvsize=8, nvalign=4] + int a[ sizeof(X)+ sizeof(Y)+ @@ -568,4 +622,5 @@ sizeof(RB2)+ sizeof(RB3)+ sizeof(RC)+ sizeof(RE)+ +sizeof(ND)+ 0]; -- 2.7.4