/// 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),
void VtableBuilder::LayoutVtable() {
LayoutPrimaryAndAndSecondaryVtables(BaseSubobject(MostDerivedClass, 0));
- // FIXME: Emit vtables for virtual bases here.
+ VisitedVirtualBasesSetTy VBases;
+ LayoutVtablesForVirtualBases(MostDerivedClass, VBases);
}
void VtableBuilder::LayoutPrimaryAndAndSecondaryVtables(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) {
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() { }
+
+}