From: Mike Stump Date: Wed, 12 Aug 2009 21:50:08 +0000 (+0000) Subject: Refine primary vbase selection ordering. WIP. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d76264e0b20470267249660ab947197cf6d6e31f;p=clang Refine primary vbase selection ordering. WIP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78844 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 8e09e9e65b..2a7477c449 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -93,6 +93,30 @@ void ASTRecordLayoutBuilder::SelectPrimaryForBase(const CXXRecordDecl *RD, } } +void ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD, + const CXXRecordDecl *&FirstPrimary, + llvm::SmallSet &IndirectPrimary) { + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast(i->getType()->getAs()->getDecl()); + if (!i->isVirtual()) { + SelectPrimaryVBase(Base, FirstPrimary, IndirectPrimary); + if (PrimaryBase) + return; + continue; + } + if (IsNearlyEmpty(Base)) { + if (FirstPrimary==0) + FirstPrimary = Base; + if (!IndirectPrimary.count(Base)) { + setPrimaryBase(Base, true); + return; + } + } + } +} + /// SelectPrimaryBase - Selects the primary base for the given class and /// record that with setPrimaryBase. void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { @@ -110,6 +134,8 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { } } + setPrimaryBase(0, false); + // Otherwise, it is the first nearly empty virtual base that is not an // indirect primary virtual base class, if one exists. @@ -117,7 +143,6 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { // is expensive. // FIXME: audit indirect virtual bases if (RD->getNumVBases() == 0) { - setPrimaryBase(0, false); return; } @@ -133,20 +158,7 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { } // Then we can search for the first nearly empty virtual base itself. - // FIXME: audit indirect virtual bases and order (backwards?) - for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(), - e = RD->vbases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast(i->getType()->getAs()->getDecl()); - if (IsNearlyEmpty(Base)) { - if (FirstPrimary==0) - FirstPrimary = Base; - if (!IndirectPrimary.count(Base)) { - setPrimaryBase(Base, true); - return; - } - } - } + SelectPrimaryVBase(RD, FirstPrimary, IndirectPrimary); // Otherwise if is the first nearly empty virtual base, if one exists, // otherwise there is no primary base class. diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index 488f6662c0..31bbdd7530 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -54,6 +54,9 @@ class ASTRecordLayoutBuilder { void LayoutField(const FieldDecl *D); void SelectPrimaryBase(const CXXRecordDecl *RD); + void SelectPrimaryVBase(const CXXRecordDecl *RD, + const CXXRecordDecl *&FirstPrimary, + llvm::SmallSet &IndirectPrimary); void SelectPrimaryForBase(const CXXRecordDecl *RD, llvm::SmallSet &IndirectPrimary); void setPrimaryBase(const CXXRecordDecl *PB, bool Virtual) { diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index d9e8664460..7a1e2c31ed 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -164,6 +164,131 @@ struct test4_D : virtual B, virtual C { // CHECK-LP64: .quad __ZN1B4bar2Ev +struct test5_B3 { virtual void funcB3(); }; +struct test5_B2 : virtual test5_B3 { virtual void funcB2(); }; +struct test5_B1 : virtual test5_B2 { virtual void funcB1(); }; + +struct test5_B23 { virtual void funcB23(); }; +struct test5_B22 : virtual test5_B23 { virtual void funcB22(); }; +struct test5_B21 : virtual test5_B22 { virtual void funcB21(); }; + + +struct B232 { virtual void funcB232(); }; +struct B231 { virtual void funcB231(); }; + +struct test5_B33 { virtual void funcB33(); }; +struct test5_B32 : virtual test5_B33, virtual B232 { virtual void funcB32(); }; +struct test5_B31 : virtual test5_B32, virtual B231 { virtual void funcB31(); }; + +struct test5_D : virtual test5_B1, virtual test5_B21, virtual test5_B31 { + virtual void funcD() { } +}; + +// CHECK-LP32:__ZTV7test5_D: +// CHECK-LP32 .long 16 +// CHECK-LP32 .long 12 +// CHECK-LP32 .long 8 +// CHECK-LP32 .long 8 +// CHECK-LP32 .long 8 +// CHECK-LP32 .long 4 +// CHECK-LP32 .long 4 +// CHECK-LP32 .long 4 +// CHECK-LP32: .space 4 +// CHECK-LP32: .space 4 +// CHECK-LP32: .space 4 +// CHECK-LP32: .space 4 +// CHECK-LP32: .space 4 +// CHECK-LP32: .space 4 +// CHECK-LP32: .space 4 +// CHECK-LP32: .long __ZTI7test5_D +// CHECK-LP32: .long __ZN8test5_B36funcB3Ev +// CHECK-LP32: .long __ZN8test5_B26funcB2Ev +// CHECK-LP32: .long __ZN8test5_B16funcB1Ev +// CHECK-LP32: .long __ZN7test5_D5funcDEv +// CHECK-LP32 .space 4 +// CHECK-LP32 .space 4 +// CHECK-LP32 .space 4 +// CHECK-LP32 .space 4 +// CHECK-LP32: .space 4 +// CHECK-LP32 .long -4 +// CHECK-LP32: .long __ZTI7test5_D +// CHECK-LP32: .long __ZN9test5_B237funcB23Ev +// CHECK-LP32: .long __ZN9test5_B227funcB22Ev +// CHECK-LP32 .long __ZN9test5_B217funcB21Ev +// CHECK-LP32 .space 4 +// CHECK-LP32 .long 8 +// CHECK-LP32 .space 4 +// CHECK-LP32 .space 4 +// CHECK-LP32 .long 4 +// CHECK-LP32 .space 4 +// CHECK-LP32: .space 4 +// CHECK-LP32 .long -8 +// CHECK-LP32 .long __ZTI7test5_D +// CHECK-LP32 .long __ZN9test5_B337funcB33Ev +// CHECK-LP32 .long __ZN9test5_B327funcB32Ev +// CHECK-LP32 .long __ZN9test5_B317funcB31Ev +// CHECK-LP32: .space 4 +// CHECK-LP32 .long -12 +// CHECK-LP32: .long __ZTI7test5_D +// CHECK-LP32: .long __ZN4B2328funcB232Ev +// CHECK-LP32: .space 4 +// CHECK-LP32 .long -16 +// CHECK-LP32: .long __ZTI7test5_D +// CHECK-LP32: .long __ZN4B2318funcB231Ev + +// CHECK-LP64:__ZTV7test5_D: +// CHECK-LP64 .quad 32 +// CHECK-LP64 .quad 24 +// CHECK-LP64 .quad 16 +// CHECK-LP64 .quad 16 +// CHECK-LP64 .quad 16 +// CHECK-LP64 .quad 8 +// CHECK-LP64 .quad 8 +// CHECK-LP64 .quad 8 +// CHECK-LP64: .space 8 +// CHECK-LP64: .space 8 +// CHECK-LP64: .space 8 +// CHECK-LP64: .space 8 +// CHECK-LP64: .space 8 +// CHECK-LP64: .space 8 +// CHECK-LP64: .space 8 +// CHECK-LP64: .quad __ZTI7test5_D +// CHECK-LP64: .quad __ZN8test5_B36funcB3Ev +// CHECK-LP64: .quad __ZN8test5_B26funcB2Ev +// CHECK-LP64: .quad __ZN8test5_B16funcB1Ev +// CHECK-LP64: .quad __ZN7test5_D5funcDEv +// CHECK-LP64 .space 8 +// CHECK-LP64 .space 8 +// CHECK-LP64 .space 8 +// CHECK-LP64 .space 8 +// CHECK-LP64: .space 8 +// CHECK-LP64 .quad 18446744073709551608 +// CHECK-LP64: .quad __ZTI7test5_D +// CHECK-LP64: .quad __ZN9test5_B237funcB23Ev +// CHECK-LP64: .quad __ZN9test5_B227funcB22Ev +// CHECK-LP64 .quad __ZN9test5_B217funcB21Ev +// CHECK-LP64 .space 8 +// CHECK-LP64 .quad 16 +// CHECK-LP64 .space 8 +// CHECK-LP64 .space 8 +// CHECK-LP64 .quad 8 +// CHECK-LP64 .space 8 +// CHECK-LP64: .space 8 +// CHECK-LP64 .quad 18446744073709551600 +// CHECK-LP64 .quad __ZTI7test5_D +// CHECK-LP64 .quad __ZN9test5_B337funcB33Ev +// CHECK-LP64 .quad __ZN9test5_B327funcB32Ev +// CHECK-LP64 .quad __ZN9test5_B317funcB31Ev +// CHECK-LP64: .space 8 +// CHECK-LP64 .quad 18446744073709551592 +// CHECK-LP64: .quad __ZTI7test5_D +// CHECK-LP64: .quad __ZN4B2328funcB232Ev +// CHECK-LP64: .space 8 +// CHECK-LP64 .quad 18446744073709551584 +// CHECK-LP64: .quad __ZTI7test5_D +// CHECK-LP64: .quad __ZN4B2318funcB231Ev + + // CHECK-LP64: __ZTV1B: @@ -245,5 +370,6 @@ struct test4_D : virtual B, virtual C { // CHECK-LP64: .quad __ZN2D14bar5Ev +test5_D d5; test4_D d4; test3_D d3;