]> granicus.if.org Git - clang/commitdiff
Microsoft adds weird padding before virtual bases if the last field was a bitfield
authorWarren Hunt <whunt@google.com>
Wed, 6 Nov 2013 00:54:59 +0000 (00:54 +0000)
committerWarren Hunt <whunt@google.com>
Wed, 6 Nov 2013 00:54:59 +0000 (00:54 +0000)
This patch adds the same behavior to clang.

Differential Revision: http://llvm-reviews.chandlerc.com/D2103

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194115 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/RecordLayoutBuilder.cpp
test/Layout/ms-x86-bitfields-vbases.cpp [new file with mode: 0644]

index 87d00bc9f5d1cff24c9d2379b3aac54bda82d317..08c9da35873ee28e1e889141203a33d79c39f6c1 100644 (file)
@@ -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/test/Layout/ms-x86-bitfields-vbases.cpp b/test/Layout/ms-x86-bitfields-vbases.cpp
new file mode 100644 (file)
index 0000000..e11ef67
--- /dev/null
@@ -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 { };\r
+\r
+struct A : virtual B0 { char a : 1; };\r
+
+// CHECK: *** Dumping AST Record Layout\r
+// CHECK:    0 | struct A\r
+// CHECK:    0 |   (A vbtable pointer)\r
+// CHECK:    4 |   char a\r
+// CHECK:    9 |   struct B0 (virtual base) (empty)\r
+// CHECK:      | [sizeof=9, align=4\r
+// CHECK:      |  nvsize=8, nvalign=4]\r
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64:    0 | struct A\r
+// CHECK-X64:    0 |   (A vbtable pointer)\r
+// CHECK-X64:    8 |   char a\r
+// CHECK-X64:   17 |   struct B0 (virtual base) (empty)\r
+// CHECK-X64:      | [sizeof=24, align=8\r
+// CHECK-X64:      |  nvsize=16, nvalign=8]\r
+
+struct B : virtual B0 { short a : 1; };\r
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK:    0 | struct B\r
+// CHECK:    0 |   (B vbtable pointer)\r
+// CHECK:    4 |   short a\r
+// CHECK:   10 |   struct B0 (virtual base) (empty)\r
+// CHECK:      | [sizeof=10, align=4\r
+// CHECK:      |  nvsize=8, nvalign=4]\r
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64:    0 | struct B\r
+// CHECK-X64:    0 |   (B vbtable pointer)\r
+// CHECK-X64:    8 |   short a\r
+// CHECK-X64:   18 |   struct B0 (virtual base) (empty)\r
+// CHECK-X64:      | [sizeof=24, align=8\r
+// CHECK-X64:      |  nvsize=16, nvalign=8]\r
+
+struct C : virtual B0 { char a : 1; char : 0; };\r
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK:    0 | struct C\r
+// CHECK:    0 |   (C vbtable pointer)\r
+// CHECK:    4 |   char a\r
+// CHECK:    5 |   char\r
+// CHECK:    8 |   struct B0 (virtual base) (empty)\r
+// CHECK:      | [sizeof=8, align=4\r
+// CHECK:      |  nvsize=8, nvalign=4]\r
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64:    0 | struct C\r
+// CHECK-X64:    0 |   (C vbtable pointer)\r
+// CHECK-X64:    8 |   char a\r
+// CHECK-X64:    9 |   char\r
+// CHECK-X64:   16 |   struct B0 (virtual base) (empty)\r
+// CHECK-X64:      | [sizeof=16, align=8\r
+// CHECK-X64:      |  nvsize=16, nvalign=8]\r
+
+struct D : virtual B0 { char a : 1; char b; };\r
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK:    0 | struct D\r
+// CHECK:    0 |   (D vbtable pointer)\r
+// CHECK:    4 |   char a\r
+// CHECK:    5 |   char b\r
+// CHECK:    8 |   struct B0 (virtual base) (empty)\r
+// CHECK:      | [sizeof=8, align=4\r
+// CHECK:      |  nvsize=8, nvalign=4]\r
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64:    0 | struct D\r
+// CHECK-X64:    0 |   (D vbtable pointer)\r
+// CHECK-X64:    8 |   char a\r
+// CHECK-X64:    9 |   char b\r
+// CHECK-X64:   16 |   struct B0 (virtual base) (empty)\r
+// CHECK-X64:      | [sizeof=16, align=8\r
+// CHECK-X64:      |  nvsize=16, nvalign=8]\r
+
+int a[
+sizeof(A)+
+sizeof(B)+
+sizeof(C)+
+sizeof(D)];