From: Warren Hunt Date: Wed, 6 Nov 2013 00:54:59 +0000 (+0000) Subject: Microsoft adds weird padding before virtual bases if the last field was a bitfield X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=92563d0c04d9f06e528439bb93073e41ecbdc07b;p=clang 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194115 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 87d00bc9f5..08c9da3587 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/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 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 index 0000000000..e11ef67a63 --- /dev/null +++ b/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)];