The following program:
union A {
int f1: 3;
A();
};
A::A() {}
causes the failure of the assertion "DataSize % Context.getCharWidth() == 0" at
clang/lib/AST/RecordLayoutBuilder.cpp:754.
It happens because '2.4 Non-POD Class Types/II. Allocation of Members Other
Than Virtual Bases/1. bit-fileds' of C++ ABI
(http://mentorembedded.github.io/cxx-abi/abi.html#class-types) is implemented
incorrectly: dsize(C) is not updated to include the last byte containing (part
of) the bitfield.
http://reviews.llvm.org/D5775
Files:
lib/AST/RecordLayoutBuilder.cpp
test/Layout/union_regular_bit_field.cpp
test/Layout/union_wide_bit_field.cpp
Index: lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- lib/AST/RecordLayoutBuilder.cpp
+++ lib/AST/RecordLayoutBuilder.cpp
@@ -1345,6 +1345,14 @@
LayoutField(Field);
}
+// Rounds the specified field up to have it multiple of the char size.
+static uint64_t
+RoundUpFieldSizeToCharAlignment(const uint64_t FieldSize,
+ const ASTContext &Context) {
+ uint64_t CharAlignment = Context.getTargetInfo().getCharAlign();
+ return llvm::RoundUpToAlignment(FieldSize, CharAlignment);
+}
+
void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
uint64_t TypeSize,
bool FieldPacked,
@@ -1382,7 +1390,9 @@
uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
if (IsUnion) {
- setDataSize(std::max(getDataSizeInBits(), FieldSize));
+ uint64_t RoundedFieldSize = RoundUpFieldSizeToCharAlignment(FieldSize,
+ Context);
+ setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
FieldOffset = 0;
} else {
// The bitfield is allocated starting at the next offset aligned
@@ -1607,9 +1617,9 @@
// For unions, this is just a max operation, as usual.
if (IsUnion) {
- // FIXME: I think FieldSize should be TypeSize here.
- setDataSize(std::max(getDataSizeInBits(), FieldSize));
-
+ uint64_t RoundedFieldSize = RoundUpFieldSizeToCharAlignment(FieldSize,
+ Context);
+ setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
// For non-zero-width bitfields in ms_struct structs, allocate a new
// storage unit if necessary.
} else if (IsMsStruct && FieldSize) {
Index: test/Layout/union_regular_bit_field.cpp
===================================================================
--- /dev/null
+++ test/Layout/union_regular_bit_field.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple aarch64 -fdump-record-layouts %s 2>/dev/null \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64 -fdump-record-layouts %s 2>/dev/null \
+// RUN: | FileCheck %s
+
+union A {
+ int f1: 3;
+ A();
+};
+
+A::A() {}
+
+// CHECK: | [sizeof=4, dsize=1, align=4
+// CHECK-NEXT: | nvsize=1, nvalign=4]
+
Index: test/Layout/union_wide_bit_field.cpp
===================================================================
--- /dev/null
+++ test/Layout/union_wide_bit_field.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple aarch64 -fdump-record-layouts %s 2>/dev/null \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64 -fdump-record-layouts %s 2>/dev/null \
+// RUN: | FileCheck %s
+
+union A {
+ int f1: 69;
+ A();
+};
+
+A::A() {}
+
+// CHECK: | [sizeof=16, dsize=9, align=8
+// CHECK-NEXT: | nvsize=9, nvalign=8]
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits