void VtableBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
int64_t OffsetToTop,
VisitedVirtualBasesSetTy &VBases) {
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ // Add vbase offsets.
+ 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 is a virtual base that we haven't visited before.
+ if (I->isVirtual() && VBases.insert(BaseDecl)) {
+ // FIXME: We shouldn't use / 8 here.
+ uint64_t Offset =
+ OffsetToTop + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl) / 8;
+
+ VCallAndVBaseOffsets.push_back(VtableComponent::MakeVBaseOffset(Offset));
+ }
+
+ // Check the base class looking for more vbase offsets.
+ AddVBaseOffsets(BaseDecl, OffsetToTop, VBases);
+ }
}
void
void VtableBuilder::LayoutVtable(BaseSubobject Base) {
const CXXRecordDecl *RD = Base.getBase();
-
assert(RD->isDynamicClass() && "class does not have a vtable!");
- // First, add the offset to top.
+ int64_t OffsetToTop = -(int64_t)Base.getBaseOffset() / 8;
+
+ // Add vcall and vbase offsets for this vtable.
+ VisitedVirtualBasesSetTy VBases;
+ AddVCallAndVBaseOffsets(RD, OffsetToTop, VBases);
+
+ // Reverse them and add them to the vtable components.
+ std::reverse(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end());
+ Components.append(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end());
+ VCallAndVBaseOffsets.clear();
+
+ // Add the offset to top.
// 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.
default:
assert(false && "Unhandled component kind!");
break;
-
+
+ case VtableComponent::CK_VBaseOffset:
+ Out << "vbase_offset (" << Component.getVBaseOffset() << ")";
+ break;
+
case VtableComponent::CK_OffsetToTop:
Out << "offset_to_top (" << Component.getOffsetToTop() << ")";
break;
void B::f() { }
}
+
+namespace Test9 {
+
+// Simple test of vbase offsets.
+
+struct A1 { int a1; };
+struct A2 { int a2; };
+
+// CHECK: Vtable for 'Test9::B' (5 entries).
+// CHECK-NEXT: 0 | vbase_offset (16)
+// CHECK-NEXT: 1 | vbase_offset (12)
+// CHECK-NEXT: 2 | offset_to_top (0)
+// CHECK-NEXT: 3 | Test9::B RTTI
+// CHECK-NEXT: -- (Test9::B, 0) vtable address --
+// CHECK-NEXT: 4 | void Test9::B::f()
+struct B : virtual A1, virtual A2 {
+ int b;
+
+ virtual void f();
+};
+
+
+void B::f() { }
+
+}