summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarren Hunt <whunt@google.com>2013-11-06 00:54:59 +0000
committerWarren Hunt <whunt@google.com>2013-11-06 00:54:59 +0000
commit6b7048ddd848f9d30eab74ea02b58f89f8681b6f (patch)
treea619b2b2c4844d355a0f967edee4fdb1452463e2
parentc13f43f4f95edcd0138e3385944c6ca84ad70617 (diff)
downloadbcm5719-llvm-6b7048ddd848f9d30eab74ea02b58f89f8681b6f.tar.gz
bcm5719-llvm-6b7048ddd848f9d30eab74ea02b58f89f8681b6f.zip
Microsoft adds weird padding before virtual bases if the last field was a bitfield
This patch adds the same behavior to clang. Differential Revision: http://llvm-reviews.chandlerc.com/D2103 llvm-svn: 194115
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp9
-rw-r--r--clang/test/Layout/ms-x86-bitfields-vbases.cpp84
2 files changed, 93 insertions, 0 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 87d00bc9f5d..08c9da35873 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2014,6 +2014,10 @@ static bool isMsLayout(const RecordDecl* D) {
// one.
// * The last zero size virtual base may be placed at the end of the struct.
// and can potentially alias a zero sized type in the next struct.
+// * If the last field is a non-zero length bitfield and we have any virtual
+// bases then some extra padding is added before the virtual bases for no
+// obvious reason.
+
namespace {
struct MicrosoftRecordLayoutBuilder {
@@ -2499,6 +2503,11 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp =
computeVtorDispSet(RD);
+ // If the last field we laid out was a non-zero length bitfield then add some
+ // extra padding for no obvious reason.
+ if (LastFieldIsNonZeroWidthBitfield)
+ Size += CurrentBitfieldSize;
+
// Iterate through the virtual bases and lay them out.
for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),
e = RD->vbases_end();
diff --git a/clang/test/Layout/ms-x86-bitfields-vbases.cpp b/clang/test/Layout/ms-x86-bitfields-vbases.cpp
new file mode 100644
index 00000000000..e11ef67a634
--- /dev/null
+++ b/clang/test/Layout/ms-x86-bitfields-vbases.cpp
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -fsyntax-only -cxx-abi microsoft %s 2>&1 \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only -cxx-abi microsoft %s 2>/dev/null \
+// RUN: | FileCheck %s -check-prefix CHECK-X64
+
+struct B0 { };
+
+struct A : virtual B0 { char a : 1; };
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK: 0 | struct A
+// CHECK: 0 | (A vbtable pointer)
+// CHECK: 4 | char a
+// CHECK: 9 | struct B0 (virtual base) (empty)
+// CHECK: | [sizeof=9, align=4
+// CHECK: | nvsize=8, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: 0 | struct A
+// CHECK-X64: 0 | (A vbtable pointer)
+// CHECK-X64: 8 | char a
+// CHECK-X64: 17 | struct B0 (virtual base) (empty)
+// CHECK-X64: | [sizeof=24, align=8
+// CHECK-X64: | nvsize=16, nvalign=8]
+
+struct B : virtual B0 { short a : 1; };
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK: 0 | struct B
+// CHECK: 0 | (B vbtable pointer)
+// CHECK: 4 | short a
+// CHECK: 10 | struct B0 (virtual base) (empty)
+// CHECK: | [sizeof=10, align=4
+// CHECK: | nvsize=8, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: 0 | struct B
+// CHECK-X64: 0 | (B vbtable pointer)
+// CHECK-X64: 8 | short a
+// CHECK-X64: 18 | struct B0 (virtual base) (empty)
+// CHECK-X64: | [sizeof=24, align=8
+// CHECK-X64: | nvsize=16, nvalign=8]
+
+struct C : virtual B0 { char a : 1; char : 0; };
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK: 0 | struct C
+// CHECK: 0 | (C vbtable pointer)
+// CHECK: 4 | char a
+// CHECK: 5 | char
+// CHECK: 8 | struct B0 (virtual base) (empty)
+// CHECK: | [sizeof=8, align=4
+// CHECK: | nvsize=8, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: 0 | struct C
+// CHECK-X64: 0 | (C vbtable pointer)
+// CHECK-X64: 8 | char a
+// CHECK-X64: 9 | char
+// CHECK-X64: 16 | struct B0 (virtual base) (empty)
+// CHECK-X64: | [sizeof=16, align=8
+// CHECK-X64: | nvsize=16, nvalign=8]
+
+struct D : virtual B0 { char a : 1; char b; };
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK: 0 | struct D
+// CHECK: 0 | (D vbtable pointer)
+// CHECK: 4 | char a
+// CHECK: 5 | char b
+// CHECK: 8 | struct B0 (virtual base) (empty)
+// CHECK: | [sizeof=8, align=4
+// CHECK: | nvsize=8, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: 0 | struct D
+// CHECK-X64: 0 | (D vbtable pointer)
+// CHECK-X64: 8 | char a
+// CHECK-X64: 9 | char b
+// CHECK-X64: 16 | struct B0 (virtual base) (empty)
+// CHECK-X64: | [sizeof=16, align=8
+// CHECK-X64: | nvsize=16, nvalign=8]
+
+int a[
+sizeof(A)+
+sizeof(B)+
+sizeof(C)+
+sizeof(D)];
OpenPOWER on IntegriCloud