From 130cf585e6ed502f101db8ff1f203719919d045d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 13 Jul 2018 21:07:42 +0000 Subject: [PATCH] Use external layout information to layout bit-fields for MS ABI. Patch by Aleksandr Urakov! Differential Revision: https://reviews.llvm.org/D49227 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337047 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/RecordLayoutBuilder.cpp | 10 +++++++++- .../Inputs/override-bit-field-layout.layout | 16 +++++++++++++++ test/CodeGenCXX/override-bit-field-layout.cpp | 20 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/CodeGenCXX/Inputs/override-bit-field-layout.layout create mode 100644 test/CodeGenCXX/override-bit-field-layout.cpp diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 988b88b39b..b4b09c7cec 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -2677,7 +2677,7 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { // Check to see if this bitfield fits into an existing allocation. Note: // MSVC refuses to pack bitfields of formal types with different sizes // into the same allocation. - if (!IsUnion && LastFieldIsNonZeroWidthBitfield && + if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield && CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) { placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField); RemainingBitsInField -= Width; @@ -2689,6 +2689,14 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { placeFieldAtOffset(CharUnits::Zero()); Size = std::max(Size, Info.Size); // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. + } else if (UseExternalLayout) { + auto FieldBitOffset = External.getExternalFieldOffset(FD); + placeFieldAtBitOffset(FieldBitOffset); + auto NewSize = Context.toCharUnitsFromBits( + llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth())); + assert(NewSize >= Size && "bit field offset already allocated"); + Size = NewSize; + Alignment = std::max(Alignment, Info.Alignment); } else { // Allocate a new block of memory and place the bitfield in it. CharUnits FieldOffset = Size.alignTo(Info.Alignment); diff --git a/test/CodeGenCXX/Inputs/override-bit-field-layout.layout b/test/CodeGenCXX/Inputs/override-bit-field-layout.layout new file mode 100644 index 0000000000..8e67dce650 --- /dev/null +++ b/test/CodeGenCXX/Inputs/override-bit-field-layout.layout @@ -0,0 +1,16 @@ + +*** Dumping AST Record Layout +Type: struct S1 + +Layout: + +*** Dumping AST Record Layout +Type: struct S2 + +Layout: diff --git a/test/CodeGenCXX/override-bit-field-layout.cpp b/test/CodeGenCXX/override-bit-field-layout.cpp new file mode 100644 index 0000000000..e84fcb0f45 --- /dev/null +++ b/test/CodeGenCXX/override-bit-field-layout.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-bit-field-layout.layout %s | FileCheck %s + +// CHECK: Type: struct S1 +// CHECK: FieldOffsets: [0, 11] +struct S1 { + short a : 3; + short b : 5; +}; + +// CHECK: Type: struct S2 +// CHECK: FieldOffsets: [64] +struct S2 { + virtual ~S2() = default; + short a : 3; +}; + +void use_structs() { + S1 s1s[sizeof(S1)]; + S2 s2s[sizeof(S2)]; +} -- 2.40.0