diff options
| author | Anders Carlsson <andersca@mac.com> | 2010-02-16 16:49:35 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2010-02-16 16:49:35 +0000 |
| commit | 13f0f66223655dcbe4f04582c3e030c4f0a1830c (patch) | |
| tree | b0d23b36c1fcf3546245b9c36a60aa32c3623f45 | |
| parent | b716a543c9adec6d1586e0d0e43f05b3b6644ee5 (diff) | |
| download | bcm5719-llvm-13f0f66223655dcbe4f04582c3e030c4f0a1830c.tar.gz bcm5719-llvm-13f0f66223655dcbe4f04582c3e030c4f0a1830c.zip | |
Handle layout of vtables for virtual bases.
llvm-svn: 96355
| -rw-r--r-- | clang/lib/CodeGen/CGVtable.cpp | 42 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/vtable-layout.cpp | 27 |
2 files changed, 68 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index b9d6332b686..b60d470b395 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -831,6 +831,11 @@ private: /// subobject. void LayoutSecondaryVtables(BaseSubobject Base); + /// LayoutVtablesForVirtualBases - Layout vtables for all virtual bases of the + /// given base (excluding any primary bases). + void LayoutVtablesForVirtualBases(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases); + public: VtableBuilder(CGVtableInfo &VtableInfo, const CXXRecordDecl *MostDerivedClass) : VtableInfo(VtableInfo), MostDerivedClass(MostDerivedClass), @@ -1039,7 +1044,8 @@ VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) { void VtableBuilder::LayoutVtable() { LayoutPrimaryAndAndSecondaryVtables(BaseSubobject(MostDerivedClass, 0)); - // FIXME: Emit vtables for virtual bases here. + VisitedVirtualBasesSetTy VBases; + LayoutVtablesForVirtualBases(MostDerivedClass, VBases); } void VtableBuilder::LayoutPrimaryAndAndSecondaryVtables(BaseSubobject Base) { @@ -1128,6 +1134,40 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base) { } } +void +VtableBuilder::LayoutVtablesForVirtualBases(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases) { + // Itanium C++ ABI 2.5.2: + // Then come the virtual base virtual tables, also in inheritance graph + // order, and again excluding primary bases (which share virtual tables with + // the classes for which they are primary). + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Check if this base needs a vtable. (If it's virtual, and we haven't + // visited it before). + if (I->isVirtual() && BaseDecl->isDynamicClass() && + BaseDecl != PrimaryBase && VBases.insert(BaseDecl)) { + const ASTRecordLayout &MostDerivedClassLayout = + Context.getASTRecordLayout(MostDerivedClass); + uint64_t BaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + + LayoutPrimaryAndAndSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset)); + } + + // We only need to check the base for virtual base vtables if it actually + // has virtual bases. + if (BaseDecl->getNumVBases()) + LayoutVtablesForVirtualBases(BaseDecl, VBases); + } +} + /// dumpLayout - Dump the vtable layout. void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) { diff --git a/clang/test/CodeGenCXX/vtable-layout.cpp b/clang/test/CodeGenCXX/vtable-layout.cpp index b714511a382..bb5996707f0 100644 --- a/clang/test/CodeGenCXX/vtable-layout.cpp +++ b/clang/test/CodeGenCXX/vtable-layout.cpp @@ -395,3 +395,30 @@ struct C : B { void C::f() { } } + +namespace Test11 { + +// Very simple test of vtables for virtual bases. +struct A1 { int a; }; +struct A2 { int b; }; + +struct B : A1, virtual A2 { + int b; +}; + +// CHECK: Vtable for 'Test11::C' (8 entries). +// CHECK-NEXT: 0 | vbase_offset (24) +// CHECK-NEXT: 1 | vbase_offset (8) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test11::C RTTI +// CHECK-NEXT: -- (Test11::C, 0) vtable address -- +// CHECK-NEXT: 4 | void Test11::C::f() +// CHECK-NEXT: 5 | vbase_offset (16) +// CHECK-NEXT: 6 | offset_to_top (-8) +// CHECK-NEXT: 7 | Test11::C RTTI +struct C : virtual B { + virtual void f(); +}; +void C::f() { } + +} |

