Skip to content

Commit

Permalink
Refactor overridden methods iteration to avoid double lookups.
Browse files Browse the repository at this point in the history
Convert most uses to range-for loops. No functionality change intended.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@320954 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
d0k committed Dec 17, 2017
1 parent 054fd17 commit 25836be
Show file tree
Hide file tree
Showing 14 changed files with 52 additions and 88 deletions.
2 changes: 1 addition & 1 deletion include/clang/AST/DeclCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -2015,7 +2015,7 @@ class CXXMethodDecl : public FunctionDecl {
if (CD->isVirtualAsWritten() || CD->isPure())
return true;

return (CD->begin_overridden_methods() != CD->end_overridden_methods());
return CD->size_overridden_methods() != 0;
}

/// If it's possible to devirtualize a call to this method, return the called
Expand Down
26 changes: 9 additions & 17 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1378,35 +1378,27 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst,

ASTContext::overridden_cxx_method_iterator
ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =
OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
return nullptr;
return Pos->second.begin();
return overridden_methods(Method).begin();
}

ASTContext::overridden_cxx_method_iterator
ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =
OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
return nullptr;
return Pos->second.end();
return overridden_methods(Method).end();
}

unsigned
ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const {
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =
OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
return 0;
return Pos->second.size();
auto Range = overridden_methods(Method);
return Range.end() - Range.begin();
}

ASTContext::overridden_method_range
ASTContext::overridden_methods(const CXXMethodDecl *Method) const {
return overridden_method_range(overridden_methods_begin(Method),
overridden_methods_end(Method));
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =
OverriddenMethods.find(Method->getCanonicalDecl());
if (Pos == OverriddenMethods.end())
return overridden_method_range(nullptr, nullptr);
return overridden_method_range(Pos->second.begin(), Pos->second.end());
}

void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
Expand Down
7 changes: 3 additions & 4 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1195,12 +1195,11 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
};

dumpChild([=] {
auto FirstOverrideItr = MD->begin_overridden_methods();
auto Overrides = MD->overridden_methods();
OS << "Overrides: [ ";
dumpOverride(*FirstOverrideItr);
dumpOverride(*Overrides.begin());
for (const auto *Override :
llvm::make_range(FirstOverrideItr + 1,
MD->end_overridden_methods())) {
llvm::make_range(Overrides.begin() + 1, Overrides.end())) {
OS << ", ";
dumpOverride(Override);
}
Expand Down
19 changes: 8 additions & 11 deletions lib/AST/CXXInheritance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,9 +650,11 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
continue;

CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
using OverriddenMethodsRange =
llvm::iterator_range<CXXMethodDecl::method_iterator>;
OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods();

if (CanonM->begin_overridden_methods()
== CanonM->end_overridden_methods()) {
if (OverriddenMethods.begin() == OverriddenMethods.end()) {
// This is a new virtual function that does not override any
// other virtual function. Add it to the map of virtual
// functions for which we are tracking overridders.
Expand All @@ -671,11 +673,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
// overrider. To do so, we dig down to the original virtual
// functions using data recursion and update all of the methods it
// overrides.
using OverriddenMethods =
llvm::iterator_range<CXXMethodDecl::method_iterator>;
SmallVector<OverriddenMethods, 4> Stack;
Stack.push_back(llvm::make_range(CanonM->begin_overridden_methods(),
CanonM->end_overridden_methods()));
SmallVector<OverriddenMethodsRange, 4> Stack(1, OverriddenMethods);
while (!Stack.empty()) {
for (const CXXMethodDecl *OM : Stack.pop_back_val()) {
const CXXMethodDecl *CanonOM = OM->getCanonicalDecl();
Expand All @@ -693,14 +691,13 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
UniqueVirtualMethod(CanonM, SubobjectNumber,
InVirtualSubobject));

if (CanonOM->begin_overridden_methods()
== CanonOM->end_overridden_methods())
auto OverriddenMethods = CanonOM->overridden_methods();
if (OverriddenMethods.begin() == OverriddenMethods.end())
continue;

// Continue recursion to the methods that this virtual method
// overrides.
Stack.push_back(llvm::make_range(CanonOM->begin_overridden_methods(),
CanonOM->end_overridden_methods()));
Stack.push_back(OverriddenMethods);
}
}

Expand Down
4 changes: 1 addition & 3 deletions lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1642,9 +1642,7 @@ bool CXXMethodDecl::isStatic() const {

static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD,
const CXXMethodDecl *BaseMD) {
for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
E = DerivedMD->end_overridden_methods(); I != E; ++I) {
const CXXMethodDecl *MD = *I;
for (const CXXMethodDecl *MD : DerivedMD->overridden_methods()) {
if (MD->getCanonicalDecl() == BaseMD->getCanonicalDecl())
return true;
if (recursivelyOverrides(MD, BaseMD))
Expand Down
7 changes: 3 additions & 4 deletions lib/AST/RecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2895,13 +2895,12 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
Work.insert(MD);
while (!Work.empty()) {
const CXXMethodDecl *MD = *Work.begin();
CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(),
e = MD->end_overridden_methods();
auto MethodRange = MD->overridden_methods();
// If a virtual method has no-overrides it lives in its parent's vtable.
if (i == e)
if (MethodRange.begin() == MethodRange.end())
BasesWithOverriddenMethods.insert(MD->getParent());
else
Work.insert(i, e);
Work.insert(MethodRange.begin(), MethodRange.end());
// We've finished processing this element, remove it from the working set.
Work.erase(MD);
}
Expand Down
11 changes: 3 additions & 8 deletions lib/AST/VTableBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1079,9 +1079,7 @@ static void
visitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) {
assert(MD->isVirtual() && "Method is not virtual!");

for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods(); I != E; ++I) {
const CXXMethodDecl *OverriddenMD = *I;
for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) {
if (!Visitor(OverriddenMD))
continue;
visitAllOverriddenMethods(OverriddenMD, Visitor);
Expand Down Expand Up @@ -1329,11 +1327,8 @@ static bool OverridesIndirectMethodInBases(
ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
if (Bases.count(MD->getParent()))
return true;

for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods(); I != E; ++I) {
const CXXMethodDecl *OverriddenMD = *I;


for (const CXXMethodDecl *OverriddenMD : MD->overridden_methods()) {
// Check "indirect overriders".
if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
return true;
Expand Down
8 changes: 4 additions & 4 deletions lib/Analysis/ThreadSafetyCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,11 +319,11 @@ static bool hasCppPointerType(const til::SExpr *E) {
static const CXXMethodDecl *getFirstVirtualDecl(const CXXMethodDecl *D) {
while (true) {
D = D->getCanonicalDecl();
CXXMethodDecl::method_iterator I = D->begin_overridden_methods(),
E = D->end_overridden_methods();
if (I == E)
auto OverriddenMethods = D->overridden_methods();
if (OverriddenMethods.begin() == OverriddenMethods.end())
return D; // Method does not override anything
D = *I; // FIXME: this does not work with multiple inheritance.
// FIXME: this does not work with multiple inheritance.
D = *OverriddenMethods.begin();
}
return nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
// C++ ABI does not include all virtual methods from non-primary bases in
// the vtable for the most derived class. For example, if C inherits from
// A and B, C's primary vftable will not include B's virtual methods.
if (Method->begin_overridden_methods() == Method->end_overridden_methods())
if (Method->size_overridden_methods() == 0)
Flags |= llvm::DINode::FlagIntroducedVirtual;

// The 'this' adjustment accounts for both the virtual and non-virtual
Expand Down
5 changes: 2 additions & 3 deletions lib/Index/IndexDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,8 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
if (CXXMD->isVirtual())
Roles |= (unsigned)SymbolRole::Dynamic;
for (auto I = CXXMD->begin_overridden_methods(),
E = CXXMD->end_overridden_methods(); I != E; ++I) {
Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
}
}
gatherTemplatePseudoOverrides(D, Relations);
Expand Down
5 changes: 1 addition & 4 deletions lib/Sema/SemaCodeComplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3378,12 +3378,9 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
return;

PrintingPolicy Policy = getCompletionPrintingPolicy(S);
for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
MEnd = Method->end_overridden_methods();
M != MEnd; ++M) {
for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
const CXXMethodDecl *Overridden = *M;
if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
continue;

Expand Down
10 changes: 4 additions & 6 deletions lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7517,16 +7517,14 @@ enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD,
OverrideErrorKind OEK = OEK_All) {
S.Diag(MD->getLocation(), DiagID) << MD->getDeclName();
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods();
I != E; ++I) {
for (const CXXMethodDecl *O : MD->overridden_methods()) {
// This check (& the OEK parameter) could be replaced by a predicate, but
// without lambdas that would be overkill. This is still nicer than writing
// out the diag loop 3 times.
if ((OEK == OEK_All) ||
(OEK == OEK_NonDeleted && !(*I)->isDeleted()) ||
(OEK == OEK_Deleted && (*I)->isDeleted()))
S.Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
(OEK == OEK_NonDeleted && !O->isDeleted()) ||
(OEK == OEK_Deleted && O->isDeleted()))
S.Diag(O->getLocation(), diag::note_overridden_virtual_function);
}
}

Expand Down
28 changes: 10 additions & 18 deletions lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2748,8 +2748,7 @@ void Sema::CheckOverrideControl(NamedDecl *D) {
// If a function is marked with the virt-specifier override and
// does not override a member function of a base class, the program is
// ill-formed.
bool HasOverriddenMethods =
MD->begin_overridden_methods() != MD->end_overridden_methods();
bool HasOverriddenMethods = MD->size_overridden_methods() != 0;
if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods)
Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding)
<< MD->getDeclName();
Expand Down Expand Up @@ -7424,10 +7423,8 @@ struct FindHiddenVirtualMethod {
const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) {
if (MD->size_overridden_methods() == 0)
return Methods.count(MD->getCanonicalDecl());
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods();
I != E; ++I)
if (CheckMostOverridenMethods(*I, Methods))
for (const CXXMethodDecl *O : MD->overridden_methods())
if (CheckMostOverridenMethods(O, Methods))
return true;
return false;
}
Expand Down Expand Up @@ -7485,10 +7482,9 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD,
llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
if (MD->size_overridden_methods() == 0)
Methods.insert(MD->getCanonicalDecl());
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods();
I != E; ++I)
AddMostOverridenMethods(*I, Methods);
else
for (const CXXMethodDecl *O : MD->overridden_methods())
AddMostOverridenMethods(O, Methods);
}

/// \brief Check if a method overloads virtual methods in a base class without
Expand Down Expand Up @@ -14062,15 +14058,13 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
// non-deleted virtual function.
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
bool IssuedDiagnostic = false;
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods();
I != E; ++I) {
for (const CXXMethodDecl *O : MD->overridden_methods()) {
if (!(*MD->begin_overridden_methods())->isDeleted()) {
if (!IssuedDiagnostic) {
Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
IssuedDiagnostic = true;
}
Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
Diag(O->getLocation(), diag::note_overridden_virtual_function);
}
}
// If this function was implicitly deleted because it was defaulted,
Expand Down Expand Up @@ -14981,10 +14975,8 @@ void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,

if (Method->isVirtual()) {
// Check overrides, which we previously had to delay.
for (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(),
OEnd = Method->end_overridden_methods();
O != OEnd; ++O)
CheckOverridingFunctionExceptionSpec(Method, *O);
for (const CXXMethodDecl *O : Method->overridden_methods())
CheckOverridingFunctionExceptionSpec(Method, O);
}
}

Expand Down
6 changes: 2 additions & 4 deletions lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1267,10 +1267,8 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
VisitFunctionDecl(D);
if (D->isCanonicalDecl()) {
Record.push_back(D->size_overridden_methods());
for (CXXMethodDecl::method_iterator
I = D->begin_overridden_methods(), E = D->end_overridden_methods();
I != E; ++I)
Record.AddDeclRef(*I);
for (const CXXMethodDecl *MD : D->overridden_methods())
Record.AddDeclRef(MD);
} else {
// We only need to record overridden methods once for the canonical decl.
Record.push_back(0);
Expand Down

0 comments on commit 25836be

Please sign in to comment.