From: Reid Kleckner Date: Fri, 28 Feb 2014 01:03:09 +0000 (+0000) Subject: -fdump-record-layouts: Sort nvbases by offset before printing them X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=73fb313c19d3772f335be4b66d271c5c64e541df;p=clang -fdump-record-layouts: Sort nvbases by offset before printing them It makes our -fdump-record-layouts a little more sane. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202457 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 11835c901c..06f6ecb3dd 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -3102,19 +3102,34 @@ static void DumpCXXRecordLayout(raw_ostream &OS, OS << '(' << *RD << " vftable pointer)\n"; } - // Dump (non-virtual) bases + // Collect nvbases. + SmallVector Bases; for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { + E = RD->bases_end(); + I != E; ++I) { assert(!I->getType()->isDependentType() && "Cannot layout class with dependent bases."); - if (I->isVirtual()) - continue; + if (!I->isVirtual()) + Bases.push_back(I->getType()->getAsCXXRecordDecl()); + } - const CXXRecordDecl *Base = - cast(I->getType()->getAs()->getDecl()); + // Sort nvbases by offset. + struct BaseOffsetComparator { + const ASTRecordLayout &RL; + BaseOffsetComparator(const ASTRecordLayout &RL) : RL(RL) {} + bool operator()(const CXXRecordDecl *L, const CXXRecordDecl *R) const { + return RL.getBaseClassOffset(L) < RL.getBaseClassOffset(R); + } + }; + BaseOffsetComparator Cmp(Layout); + std::stable_sort(Bases.begin(), Bases.end(), Cmp); + // Dump (non-virtual) bases + for (SmallVectorImpl::iterator I = Bases.begin(), + E = Bases.end(); + I != E; ++I) { + const CXXRecordDecl *Base = *I; CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base); - DumpCXXRecordLayout(OS, Base, C, BaseOffset, IndentLevel, Base == PrimaryBase ? "(primary base)" : "(base)", /*IncludeVirtualBases=*/false); diff --git a/test/Layout/ms-x86-primary-bases.cpp b/test/Layout/ms-x86-primary-bases.cpp index bb6b89c6fc..b5bd041fa1 100644 --- a/test/Layout/ms-x86-primary-bases.cpp +++ b/test/Layout/ms-x86-primary-bases.cpp @@ -170,11 +170,11 @@ struct AX : B0X, B1X { int a; AX() : a(0xf000000A) {} virtual void f() { printf( // CHECK: *** Dumping AST Record Layout // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct AX -// CHECK-NEXT: 8 | struct B0X (base) -// CHECK-NEXT: 8 | int a // CHECK-NEXT: 0 | struct B1X (primary base) // CHECK-NEXT: 0 | (B1X vftable pointer) // CHECK-NEXT: 4 | int a +// CHECK-NEXT: 8 | struct B0X (base) +// CHECK-NEXT: 8 | int a // CHECK-NEXT: 12 | int a // CHECK-NEXT: | [sizeof=16, align=4 // CHECK-NEXT: | nvsize=16, nvalign=4] @@ -182,11 +182,11 @@ struct AX : B0X, B1X { int a; AX() : a(0xf000000A) {} virtual void f() { printf( // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct AX -// CHECK-X64-NEXT: 16 | struct B0X (base) -// CHECK-X64-NEXT: 16 | int a // CHECK-X64-NEXT: 0 | struct B1X (primary base) // CHECK-X64-NEXT: 0 | (B1X vftable pointer) // CHECK-X64-NEXT: 8 | int a +// CHECK-X64-NEXT: 16 | struct B0X (base) +// CHECK-X64-NEXT: 16 | int a // CHECK-X64-NEXT: 20 | int a // CHECK-X64-NEXT: | [sizeof=24, align=8 // CHECK-X64-NEXT: | nvsize=24, nvalign=8] @@ -195,21 +195,21 @@ struct BX : B0X, B1X { int a; BX() : a(0xf000000B) {} virtual void g() { printf( // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct BX -// CHECK-NEXT: 8 | struct B0X (base) -// CHECK-NEXT: 8 | int a // CHECK-NEXT: 0 | struct B1X (primary base) // CHECK-NEXT: 0 | (B1X vftable pointer) // CHECK-NEXT: 4 | int a +// CHECK-NEXT: 8 | struct B0X (base) +// CHECK-NEXT: 8 | int a // CHECK-NEXT: 12 | int a // CHECK-NEXT: | [sizeof=16, align=4 // CHECK-NEXT: | nvsize=16, nvalign=4] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct BX -// CHECK-X64-NEXT: 16 | struct B0X (base) -// CHECK-X64-NEXT: 16 | int a // CHECK-X64-NEXT: 0 | struct B1X (primary base) // CHECK-X64-NEXT: 0 | (B1X vftable pointer) // CHECK-X64-NEXT: 8 | int a +// CHECK-X64-NEXT: 16 | struct B0X (base) +// CHECK-X64-NEXT: 16 | int a // CHECK-X64-NEXT: 20 | int a // CHECK-X64-NEXT: | [sizeof=24, align=8 // CHECK-X64-NEXT: | nvsize=24, nvalign=8] diff --git a/test/Layout/ms-x86-vfvb-alignment.cpp b/test/Layout/ms-x86-vfvb-alignment.cpp index 7ec0c5f466..f65adc15a6 100644 --- a/test/Layout/ms-x86-vfvb-alignment.cpp +++ b/test/Layout/ms-x86-vfvb-alignment.cpp @@ -200,12 +200,12 @@ struct G : B2, B6, virtual B1 { int a; G() : a(0xf0000010) {} }; // CHECK: *** Dumping AST Record Layout // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct G -// CHECK-NEXT: 8 | struct B2 (base) -// CHECK-NEXT: 8 | (B2 vbtable pointer) -// CHECK-NEXT: 12 | int a // CHECK-NEXT: 0 | struct B6 (primary base) // CHECK-NEXT: 0 | (B6 vftable pointer) // CHECK-NEXT: 4 | int a +// CHECK-NEXT: 8 | struct B2 (base) +// CHECK-NEXT: 8 | (B2 vbtable pointer) +// CHECK-NEXT: 12 | int a // CHECK-NEXT: 16 | int a // CHECK-NEXT: 20 | struct B1 (virtual base) // CHECK-NEXT: 20 | char a @@ -214,12 +214,12 @@ struct G : B2, B6, virtual B1 { int a; G() : a(0xf0000010) {} }; // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct G -// CHECK-X64-NEXT: 16 | struct B2 (base) -// CHECK-X64-NEXT: 16 | (B2 vbtable pointer) -// CHECK-X64-NEXT: 24 | int a // CHECK-X64-NEXT: 0 | struct B6 (primary base) // CHECK-X64-NEXT: 0 | (B6 vftable pointer) // CHECK-X64-NEXT: 8 | int a +// CHECK-X64-NEXT: 16 | struct B2 (base) +// CHECK-X64-NEXT: 16 | (B2 vbtable pointer) +// CHECK-X64-NEXT: 24 | int a // CHECK-X64-NEXT: 32 | int a // CHECK-X64-NEXT: 40 | struct B1 (virtual base) // CHECK-X64-NEXT: 40 | char a diff --git a/test/Sema/ms_class_layout.cpp b/test/Sema/ms_class_layout.cpp index eea310ad67..896d3edfda 100644 --- a/test/Sema/ms_class_layout.cpp +++ b/test/Sema/ms_class_layout.cpp @@ -470,12 +470,12 @@ int main() { // CHECK: %struct.DV = type { %struct.BV } // CHECK: 0 | struct EV -// CHECK-NEXT: 4 | struct CV (base) -// CHECK-NEXT: 4 | (CV vbtable pointer) // CHECK-NEXT: 0 | struct DV (primary base) // CHECK-NEXT: 0 | struct BV (primary base) // CHECK-NEXT: 0 | struct AV (primary base) // CHECK-NEXT: 0 | (AV vftable pointer) +// CHECK-NEXT: 4 | struct CV (base) +// CHECK-NEXT: 4 | (CV vbtable pointer) // CHECK-NEXT: 8 | (vtordisp for vbase BV) // CHECK-NEXT: 12 | struct BV (virtual base) // CHECK-NEXT: 12 | struct AV (primary base)