From 53c8f75fed4219958a6c7141322ea4be6c5c81ca Mon Sep 17 00:00:00 2001 From: Warren Hunt Date: Tue, 10 Dec 2013 01:44:39 +0000 Subject: [PATCH] [ms-abi] 64-bit fixes for r196549 In order to address latent bugs that were easier to expose in 64-bit mode, we move the application of __declspec(align) to before the layout of vbases rather than after. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196861 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/RecordLayoutBuilder.cpp | 27 +++++++++++------- .../Layout/ms-x86-alias-avoidance-padding.cpp | 6 ++-- test/Layout/ms-x86-empty-virtual-base.cpp | 28 ++++++++++++++++++- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index a3ea6b9f38..a5b07384dc 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -2060,12 +2060,13 @@ public: /// \brief Lays out a single zero-width bit-field in the record and handles /// special cases associated with zero-width bit-fields. void layoutZeroWidthBitField(const FieldDecl *FD); + void fixSizeAndAlignment(const RecordDecl *FD); void layoutVirtualBases(const CXXRecordDecl *RD); void layoutVirtualBase(const CXXRecordDecl *RD, bool HasVtordisp); /// \brief Flushes the lazy virtual base and conditionally rounds up to /// alignment. void finalizeCXXLayout(const CXXRecordDecl *RD); - void honorDeclspecAlign(const RecordDecl *RD); + void finalizeLayout(const RecordDecl *RD); /// \brief Updates the alignment of the type. This function doesn't take any /// properties (such as packedness) into account. getAdjustedFieldInfo() @@ -2233,7 +2234,8 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) { void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) { initializeLayout(RD); layoutFields(RD); - honorDeclspecAlign(RD); + fixSizeAndAlignment(RD); + finalizeLayout(RD); } void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) { @@ -2243,11 +2245,10 @@ void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) { layoutNonVirtualBases(RD); layoutVBPtr(RD); layoutFields(RD); - DataSize = Size; - NonVirtualAlignment = Alignment; + fixSizeAndAlignment(RD); layoutVirtualBases(RD); finalizeCXXLayout(RD); - honorDeclspecAlign(RD); + finalizeLayout(RD); } void @@ -2543,6 +2544,13 @@ MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) { } } +void MicrosoftRecordLayoutBuilder::fixSizeAndAlignment(const RecordDecl *RD) { + DataSize = Size; + NonVirtualAlignment = Alignment; + RequiredAlignment = std::max(RequiredAlignment, + Context.toCharUnitsFromBits(RD->getMaxAlignment())); +} + void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { if (!HasVBPtr) return; @@ -2581,8 +2589,9 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBase(const CXXRecordDecl *RD, // bytes (in both 32 and 64 bits modes), we don't know why. if (PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() && Layout.leadsWithZeroSizedBase()) - Size = Size.RoundUpToAlignment(Alignment) + - std::max(CharUnits::fromQuantity(4), Layout.getAlignment()); + Size = Size.RoundUpToAlignment(std::max(CharUnits::fromQuantity(4), + RequiredAlignment)) + + CharUnits::fromQuantity(4); CharUnits BaseNVSize = Layout.getNonVirtualSize(); CharUnits BaseAlign = getBaseAlignment(Layout); @@ -2612,9 +2621,7 @@ void MicrosoftRecordLayoutBuilder::finalizeCXXLayout(const CXXRecordDecl *RD) { } } -void MicrosoftRecordLayoutBuilder::honorDeclspecAlign(const RecordDecl *RD) { - RequiredAlignment = std::max(RequiredAlignment, - Context.toCharUnitsFromBits(RD->getMaxAlignment())); +void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) { if (!RequiredAlignment.isZero()) { updateAlignment(RequiredAlignment); Size = Size.RoundUpToAlignment(Alignment); diff --git a/test/Layout/ms-x86-alias-avoidance-padding.cpp b/test/Layout/ms-x86-alias-avoidance-padding.cpp index 86b3cebe24..78957cf747 100644 --- a/test/Layout/ms-x86-alias-avoidance-padding.cpp +++ b/test/Layout/ms-x86-alias-avoidance-padding.cpp @@ -166,9 +166,9 @@ struct __declspec(align(1)) T3 : virtual T1, virtual T2 { // CHECK-X64: 8 | struct T0 (base) (empty) // CHECK-X64: 8 | struct AT (base) (empty) // CHECK-X64: 8 | char a -// CHECK-X64: 20 | struct T2 (virtual base) -// CHECK-X64: 20 | struct AT (base) (empty) -// CHECK-X64: 20 | char a +// CHECK-X64: 16 | struct T2 (virtual base) +// CHECK-X64: 16 | struct AT (base) (empty) +// CHECK-X64: 16 | char a // CHECK-X64: | [sizeof=24, align=8 // CHECK-X64: | nvsize=8, nvalign=8] diff --git a/test/Layout/ms-x86-empty-virtual-base.cpp b/test/Layout/ms-x86-empty-virtual-base.cpp index ef6f08175e..8377969aa9 100644 --- a/test/Layout/ms-x86-empty-virtual-base.cpp +++ b/test/Layout/ms-x86-empty-virtual-base.cpp @@ -679,6 +679,31 @@ struct __declspec(align(32)) V : virtual D1 { // CHECK-X64: | [sizeof=32, align=32 // CHECK-X64: | nvsize=16, nvalign=8] +struct T0 {}; +struct T1 : T0 { char a; }; +struct T3 : virtual T1, virtual T0 { long long a; }; + +// CHECK: *** Dumping AST Record Layout +// CHECK: 0 | struct T3 +// CHECK: 0 | (T3 vbtable pointer) +// CHECK: 8 | long long a +// CHECK: 16 | struct T1 (virtual base) +// CHECK: 16 | struct T0 (base) (empty) +// CHECK: 16 | char a +// CHECK: 24 | struct T0 (virtual base) (empty) +// CHECK: | [sizeof=24, align=8 +// CHECK: | nvsize=16, nvalign=8] +// CHECK-X64: *** Dumping AST Record Layout +// CHECK-X64: 0 | struct T3 +// CHECK-X64: 0 | (T3 vbtable pointer) +// CHECK-X64: 8 | long long a +// CHECK-X64: 16 | struct T1 (virtual base) +// CHECK-X64: 16 | struct T0 (base) (empty) +// CHECK-X64: 16 | char a +// CHECK-X64: 24 | struct T0 (virtual base) (empty) +// CHECK-X64: | [sizeof=24, align=8 +// CHECK-X64: | nvsize=16, nvalign=8] + int a[ sizeof(A)+ sizeof(B)+ @@ -701,4 +726,5 @@ sizeof(R)+ sizeof(S)+ sizeof(T)+ sizeof(U)+ -sizeof(V)]; \ No newline at end of file +sizeof(V)+ +sizeof(T3)]; \ No newline at end of file -- 2.40.0