forked from OSchip/llvm-project
parent
dc2dba306c
commit
77904f1d5b
|
@ -912,6 +912,27 @@ VtableBuilder::AddVCallAndVBaseOffsets(const CXXRecordDecl *RD,
|
|||
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
|
||||
|
@ -1008,13 +1029,22 @@ VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) {
|
|||
|
||||
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.
|
||||
|
@ -1137,7 +1167,11 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
|
|||
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;
|
||||
|
|
|
@ -340,3 +340,28 @@ struct B : A {
|
|||
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() { }
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue