diff options
author | Anders Carlsson <andersca@mac.com> | 2009-11-22 19:13:51 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-11-22 19:13:51 +0000 |
commit | e4fc0d97420e13d13c9664a3c27c17aa7c1e47b9 (patch) | |
tree | 60beeb21c2402d1e0ccab1db42b00b4df82ba6df | |
parent | a7601999342df118f9b9f1acdcf96c0478239638 (diff) |
When laying out bitfields, make sure that the data size is always aligned to a byte. This fixes PR5580.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89611 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 30 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.h | 9 | ||||
-rw-r--r-- | test/SemaCXX/class-layout.cpp | 17 |
3 files changed, 45 insertions, 11 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 8e4e160746..5bc27b9d06 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -22,9 +22,9 @@ using namespace clang; ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) - : Ctx(Ctx), Size(0), Alignment(8), Packed(false), MaxFieldAlignment(0), - DataSize(0), IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8), - PrimaryBase(0), PrimaryBaseWasVirtual(false) {} + : Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0), + MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0), + NonVirtualAlignment(8), PrimaryBase(0), PrimaryBaseWasVirtual(false) {} /// LayoutVtable - Lay out the vtable and set PrimaryBase. void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) { @@ -521,7 +521,7 @@ void ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); - uint64_t FieldOffset = IsUnion ? 0 : DataSize; + uint64_t FieldOffset = IsUnion ? 0 : (DataSize - UnfilledBitsInLastByte); uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Ctx).getZExtValue(); std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType()); @@ -549,14 +549,19 @@ void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // Place this field at the current location. FieldOffsets.push_back(FieldOffset); - // Reserve space for this field. - if (IsUnion) - Size = std::max(Size, FieldSize); - else - Size = FieldOffset + FieldSize; + // Update DataSize to include the last byte containing (part of) the bitfield. + if (IsUnion) { + // FIXME: I think FieldSize should be TypeSize here. + DataSize = std::max(DataSize, FieldSize); + } else { + uint64_t NewSizeInBits = FieldOffset + FieldSize; + + DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8); + UnfilledBitsInLastByte = DataSize - NewSizeInBits; + } - // Update the data size. - DataSize = Size; + // Update the size. + Size = std::max(Size, DataSize); // Remember max struct/class alignment. UpdateAlignment(FieldAlign); @@ -568,6 +573,9 @@ void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { return; } + // Reset the unfilled bits. + UnfilledBitsInLastByte = 0; + bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); uint64_t FieldOffset = IsUnion ? 0 : DataSize; uint64_t FieldSize; diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index c738e31beb..fe02d882ce 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -27,12 +27,21 @@ namespace clang { class ASTRecordLayoutBuilder { ASTContext &Ctx; + /// Size - The current size of the record layout. uint64_t Size; + + /// Alignment - The current alignment of the record layout. unsigned Alignment; + llvm::SmallVector<uint64_t, 16> FieldOffsets; /// Packed - Whether the record is packed or not. bool Packed; + + /// UnfilledBitsInLastByte - If the last field laid out was a bitfield, + /// this contains the number of bits in the last byte that can be used for + /// an adjacent bitfield if necessary. + unsigned char UnfilledBitsInLastByte; /// MaxFieldAlignment - The maximum allowed field alignment. This is set by /// #pragma pack. diff --git a/test/SemaCXX/class-layout.cpp b/test/SemaCXX/class-layout.cpp index 56f41bfbdb..b5971723a7 100644 --- a/test/SemaCXX/class-layout.cpp +++ b/test/SemaCXX/class-layout.cpp @@ -47,3 +47,20 @@ struct G { G(); }; struct H : G { }; SA(6, sizeof(H) == 1); + +// PR5580 +namespace PR5580 { + +class A { bool iv0 : 1; }; +SA(7, sizeof(A) == 1); + +class B : A { bool iv0 : 1; }; +SA(8, sizeof(B) == 2); + +struct C { bool iv0 : 1; }; +SA(9, sizeof(C) == 1); + +struct D : C { bool iv0 : 1; }; +SA(10, sizeof(D) == 2); + +} |