From: Warren Hunt Date: Mon, 13 Jan 2014 19:55:52 +0000 (+0000) Subject: [ms-abi] Leading VFPtrs don't suppress the leading zero sized flag X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4a95f51889dfdfbbbf5682339ad7aa7872eb7ca5;p=clang [ms-abi] Leading VFPtrs don't suppress the leading zero sized flag The MS-ABI tracks a bit that asserts that the first sub-object is zero sized. This bit is used to add padding between objects if there's the potential for zero sized objects to alias. The bit is still true even if the zero sized base is lead by a VFPtr. This patch makes clang mimic that behavior. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199132 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 885d4ff5fb..e9289a0f05 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -2302,8 +2302,10 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { if (!BaseLayout.hasExtendableVFPtr()) continue; // If we don't have a primary base, this one qualifies. - if (!PrimaryBase) + if (!PrimaryBase) { PrimaryBase = BaseDecl; + LeadsWithZeroSizedBase = BaseLayout.leadsWithZeroSizedBase(); + } // Lay out the base. layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout); } diff --git a/test/Layout/ms-x86-alias-avoidance-padding.cpp b/test/Layout/ms-x86-alias-avoidance-padding.cpp index 4824913701..3112b39c9b 100644 --- a/test/Layout/ms-x86-alias-avoidance-padding.cpp +++ b/test/Layout/ms-x86-alias-avoidance-padding.cpp @@ -255,10 +255,54 @@ struct F : virtual D, virtual B {}; // CHECK-X64-NEXT: | [sizeof=32, align=8 // CHECK-X64-NEXT: | nvsize=8, nvalign=8] +struct JC0 { + JC0() { printf("JC0 : %d\n", (int)((char*)this - buffer)); } +}; +struct JC1 : JC0 { + virtual void f() {} + JC1() { printf("JC1 : %d\n", (int)((char*)this - buffer)); } +}; +struct JC2 : JC1 { + JC2() { printf("JC2 : %d\n", (int)((char*)this - buffer)); } +}; +struct JC4 : JC1, JC2 { + JC4() { printf("JC4 : %d\n", (int)((char*)this - buffer)); } +}; + +// CHECK: *** Dumping AST Record Layout +// CHECK: *** Dumping AST Record Layout +// CHECK: *** Dumping AST Record Layout +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct JC4 +// CHECK-NEXT: 0 | struct JC1 (primary base) +// CHECK-NEXT: 0 | (JC1 vftable pointer) +// CHECK-NEXT: 4 | struct JC0 (base) (empty) +// CHECK-NEXT: 8 | struct JC2 (base) +// CHECK-NEXT: 8 | struct JC1 (primary base) +// CHECK-NEXT: 8 | (JC1 vftable pointer) +// CHECK-NEXT: 12 | struct JC0 (base) (empty) +// CHECK-NEXT: | [sizeof=12, align=4 +// CHECK-NEXT: | nvsize=12, nvalign=4] +// CHECK-x64: *** Dumping AST Record Layout +// CHECK-x64: *** Dumping AST Record Layout +// CHECK-x64: *** Dumping AST Record Layout +// CHECK-x64: *** Dumping AST Record Layout +// CHECK-x64-NEXT: 0 | struct JC4 +// CHECK-x64-NEXT: 0 | struct JC1 (primary base) +// CHECK-x64-NEXT: 0 | (JC1 vftable pointer) +// CHECK-x64-NEXT: 8 | struct JC0 (base) (empty) +// CHECK-x64-NEXT: 16 | struct JC2 (base) +// CHECK-x64-NEXT: 16 | struct JC1 (primary base) +// CHECK-x64-NEXT: 16 | (JC1 vftable pointer) +// CHECK-x64-NEXT: 24 | struct JC0 (base) (empty) +// CHECK-x64-NEXT: | [sizeof=24, align=8 +// CHECK-x64-NEXT: | nvsize=24, nvalign=8] + int a[ sizeof(AT3) + sizeof(BT3) + sizeof(T3) + sizeof(E) + sizeof(F) + +sizeof(JC4) + 0];