/// primary bases to the vtable components vector.
void AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases);
- /// layoutSimpleVtable - A test function that will layout very simple vtables
- /// without any bases. Just used for testing for now.
- void layoutSimpleVtable(BaseSubobject Base);
+ /// layoutVtable - Layout a vtable and all its secondary vtables.
+ void layoutVtable(BaseSubobject Base);
public:
VtableBuilder(CGVtableInfo &VtableInfo, const CXXRecordDecl *MostDerivedClass)
: VtableInfo(VtableInfo), MostDerivedClass(MostDerivedClass),
Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass) {
- layoutSimpleVtable(BaseSubobject(MostDerivedClass, 0));
+ layoutVtable(BaseSubobject(MostDerivedClass, 0));
}
/// dumpLayout - Dump the vtable layout.
assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
"Primary base should have a zero offset!");
- AddMethods(BaseSubobject(PrimaryBase, 0), PrimaryBases);
+ AddMethods(BaseSubobject(PrimaryBase, Base.getBaseOffset()), PrimaryBases);
if (!PrimaryBases.insert(PrimaryBase))
assert(false && "Found a duplicate primary base!");
}
}
-void VtableBuilder::layoutSimpleVtable(BaseSubobject Base) {
+void VtableBuilder::layoutVtable(BaseSubobject Base) {
const CXXRecordDecl *RD = Base.getBase();
// First, add the offset to top.
- Components.push_back(VtableComponent::MakeOffsetToTop(0));
+ // FIXME: This is not going to be right for construction vtables.
+ // FIXME: We should not use -8 here.
+ int64_t OffsetToTop = -(int64_t)Base.getBaseOffset() / 8;
+ Components.push_back(VtableComponent::MakeOffsetToTop(OffsetToTop));
// Next, add the RTTI.
- Components.push_back(VtableComponent::MakeRTTI(RD));
+ Components.push_back(VtableComponent::MakeRTTI(MostDerivedClass));
uint64_t AddressPoint = Components.size();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
- // Traverse bases.
+ // Layout secondary vtables.
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
const CXXRecordDecl *BaseDecl =
assert(!I->isVirtual() && "FIXME: Handle virtual bases");
- assert(false && "FIXME: Handle secondary virtual tables!");
+ // Get the base offset of this base.
+ uint64_t BaseOffset = Base.getBaseOffset() +
+ Layout.getBaseClassOffset(BaseDecl);
+
+ // Layout this secondary vtable.
+ layoutVtable(BaseSubobject(BaseDecl, BaseOffset));
}
}
virtual void g();
virtual R3 *f() = 0;
};
-
void F::g() { }
}
+namespace Test5 {
+
+// Simple secondary vtables without this-adjustments.
+struct A {
+ virtual void f();
+ virtual void g();
+ int a;
+};
+
+struct B1 : A {
+ virtual void f();
+ int b1;
+};
+
+struct B2 : A {
+ virtual void g();
+ int b2;
+};
+
+// CHECK: Vtable for 'Test5::C' (9 entries).
+// CHECK-NEXT: 0 | offset_to_top (0)
+// CHECK-NEXT: 1 | Test5::C RTTI
+// CHECK-NEXT: -- (Test5::A, 0) vtable address --
+// CHECK-NEXT: -- (Test5::B1, 0) vtable address --
+// CHECK-NEXT: -- (Test5::C, 0) vtable address --
+// CHECK-NEXT: 2 | void Test5::B1::f()
+// CHECK-NEXT: 3 | void Test5::A::g()
+// CHECK-NEXT: 4 | void Test5::C::h()
+// CHECK-NEXT: 5 | offset_to_top (-16)
+// CHECK-NEXT: 6 | Test5::C RTTI
+// CHECK-NEXT: -- (Test5::A, 16) vtable address --
+// CHECK-NEXT: -- (Test5::B2, 16) vtable address --
+// CHECK-NEXT: 7 | void Test5::A::f()
+// CHECK-NEXT: 8 | void Test5::B2::g()
+struct C : B1, B2 {
+ virtual void h();
+};
+void C::h() { }
+}
+
// For now, just verify this doesn't crash.
namespace test0 {
struct Obj {};