[cfe-dev] !
John McCall
rjmccall at apple.com
Wed Feb 15 11:28:16 PST 2012
On Feb 15, 2012, at 4:37 AM, r4start wrote:
> Please see this patch.
You don't need the store both the set of vbases with vtordisps and the
additional information in the virtual-base-offset map. I would prefer that
you rely only on the second; it has the distinct virtual of imposing no
extra overload to the layouts of classes without virtual bases.
> I am not sure that new algorithm very efficient, but I think new algorithm is better than old one.
Why is this influenced by whether the class has a new virtual function?
Here's my suggested (untested) implementation:
void RecordLayoutBuilder::getRequiredVtorDisps(const CXXRecordDecl *RD, llvm::SmallPtrSet<const CXXRecordDecl*> &VBasesRequiringVtorDisp) {
if (RD->vbases_empty()) return;
// As an optimization, remember the set of virtual bases that we haven't decided yet.
llvm::SmallPtrSet<const CXXRecordDecl *> UndecidedVBases;
for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
E = RD->vbases_end(); I != E; ++I) {
UndecidedVBases.insert(*I);
}
// A virtual base requires a vtor disp if any of our base classes require it to have one.
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl();
const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
for (ASTRecordLayout::VBaseOffsetsMapTy::const_iterator
VI = BaseLayout.VBaseOffsetsMap.begin(), VE = BaseLayout.VBaseOffsetsMap.end(); VI != VE; ++VI) {
if (!VI->second.IsVtorDispPresent) continue;
if (!UndecidedVBases.erase(VI->first)) continue;
VBasesRequiringVtorDisp.insert(VI->first);
if (UndecidedVBases.empty()) return;
}
}
// Otherwise, a virtual base requires a vtor disp if any the non-destructor
// virtual methods declared in this class directly override a method provided
// by that virtual base.
// Collect the set of bases directly overridden by any method in this class.
// It's possible that some of these classes won't be virtual bases, or won't be
// provided by virtual bases, or won't be virtual bases in the overridden
// instance but are virtual bases elsewhere. Only the last matters for what
// we're doing, and we can ignore those: if we don't directly override
// a method provided by a virtual copy of a base class, but we do directly
// override a method provided by a non-virtual copy of that base class,
// then we must indirectly override the method provided by the virtual base,
// and so we should already have collected it in the loop above.
llvm::SmallPtrSet<const CXXRecordDecl*> OverriddenBases;
for (CXXRecordDecl::method_iterator M = RD->method_begin(),
E = RD->method_end(); M != E; ++M) {
if (!M->isVirtual() || isa<CXXDestructorDecl>(M)) continue;
for (CXXMethodDecl::method_iterator I = M->begin_overridden_methods(),
E = M->end_overridden_methods(); I != E; ++I) {
const CXXRecordDecl *OverriddenBase = (*I)->getParent();
// As an optimization, check immediately whether we're overriding
// something from the undecided set.
if (UndecidedVBases.erase(OverriddenBase)) {
VBasesRequiringVtorDisp.insert(OverriddenBase);
if (UndecidedVBases.empty()) return;
continue;
}
// Otherwise, just collect it.
OverriddenBases.insert(OverriddenBase);
}
}
// Walk the undecided v-bases and check whether they (non-virtually)
// provide any of the overridden bases.
for (llvm::SmallPtrSet<const CXXRecordDecl*>::const_iterator
I = UndecidedVBases.begin(), E = UndecidedVBases.end(); I != E; ++I) {
if (hasAnyNonVirtualBase(*I, OverriddenBases))
VBasesRequiringVtorDisp.insert(*I);
}
}
Where hasAnyNonVirtualBase just recursively walks the non-virtual
class hierarchy and checks whether any of the bases are in the set.
> Also I refactor condition in 1472 line RecordLayoutBuilder.cpp.
Yes, that part looks fine; you can separate that out as a different patch, I think.
John.
More information about the cfe-dev
mailing list