forked from OSchip/llvm-project
Separate the matchers by type and statically dispatch to the right list.
Summary: Separate the matchers by type and statically dispatch to the right list. For any node type that we support, it reduces the number of matchers we run it through. For node types we do not support, it makes match() a noop. This change improves our clang-tidy related benchmark by ~30%. Reviewers: klimek Subscribers: klimek, cfe-commits Differential Revision: http://reviews.llvm.org/D5197 llvm-svn: 217274
This commit is contained in:
parent
e89756f32a
commit
7ec2cb2fda
|
@ -173,11 +173,23 @@ public:
|
||||||
/// Each call to FindAll(...) will call the closure once.
|
/// Each call to FindAll(...) will call the closure once.
|
||||||
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
|
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
|
||||||
|
|
||||||
private:
|
/// \brief For each \c Matcher<> a \c MatchCallback that will be called
|
||||||
/// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
|
|
||||||
/// when it matches.
|
/// when it matches.
|
||||||
std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> >
|
struct MatchersByType {
|
||||||
MatcherCallbackPairs;
|
std::vector<std::pair<DeclarationMatcher, MatchCallback *>> Decl;
|
||||||
|
std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
|
||||||
|
std::vector<std::pair<StatementMatcher, MatchCallback *>> Stmt;
|
||||||
|
std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
|
||||||
|
NestedNameSpecifier;
|
||||||
|
std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
|
||||||
|
NestedNameSpecifierLoc;
|
||||||
|
std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
|
||||||
|
/// \brief All the callbacks in one container to simplify iteration.
|
||||||
|
std::vector<MatchCallback *> AllCallbacks;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
MatchersByType Matchers;
|
||||||
|
|
||||||
/// \brief Called when parsing is done.
|
/// \brief Called when parsing is done.
|
||||||
ParsingDoneTestCallback *ParsingDone;
|
ParsingDoneTestCallback *ParsingDone;
|
||||||
|
|
|
@ -292,29 +292,17 @@ private:
|
||||||
class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
|
class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
|
||||||
public ASTMatchFinder {
|
public ASTMatchFinder {
|
||||||
public:
|
public:
|
||||||
MatchASTVisitor(
|
MatchASTVisitor(const MatchFinder::MatchersByType *Matchers)
|
||||||
std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *
|
: Matchers(Matchers), ActiveASTContext(nullptr) {}
|
||||||
MatcherCallbackPairs)
|
|
||||||
: MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(nullptr) {}
|
|
||||||
|
|
||||||
void onStartOfTranslationUnit() {
|
void onStartOfTranslationUnit() {
|
||||||
for (std::vector<std::pair<internal::DynTypedMatcher,
|
for (MatchCallback *MC : Matchers->AllCallbacks)
|
||||||
MatchCallback *> >::const_iterator
|
MC->onStartOfTranslationUnit();
|
||||||
I = MatcherCallbackPairs->begin(),
|
|
||||||
E = MatcherCallbackPairs->end();
|
|
||||||
I != E; ++I) {
|
|
||||||
I->second->onStartOfTranslationUnit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onEndOfTranslationUnit() {
|
void onEndOfTranslationUnit() {
|
||||||
for (std::vector<std::pair<internal::DynTypedMatcher,
|
for (MatchCallback *MC : Matchers->AllCallbacks)
|
||||||
MatchCallback *> >::const_iterator
|
MC->onEndOfTranslationUnit();
|
||||||
I = MatcherCallbackPairs->begin(),
|
|
||||||
E = MatcherCallbackPairs->end();
|
|
||||||
I != E; ++I) {
|
|
||||||
I->second->onEndOfTranslationUnit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_active_ast_context(ASTContext *NewActiveASTContext) {
|
void set_active_ast_context(ASTContext *NewActiveASTContext) {
|
||||||
|
@ -447,22 +435,27 @@ public:
|
||||||
|
|
||||||
// Matches all registered matchers on the given node and calls the
|
// Matches all registered matchers on the given node and calls the
|
||||||
// result callback for every node that matches.
|
// result callback for every node that matches.
|
||||||
void match(const ast_type_traits::DynTypedNode& Node) {
|
void match(const ast_type_traits::DynTypedNode &Node) {
|
||||||
for (std::vector<std::pair<internal::DynTypedMatcher,
|
// FIXME: Improve this with a switch or a visitor pattern.
|
||||||
MatchCallback *> >::const_iterator
|
if (auto *N = Node.get<Decl>()) {
|
||||||
I = MatcherCallbackPairs->begin(),
|
match(*N);
|
||||||
E = MatcherCallbackPairs->end();
|
} else if (auto *N = Node.get<Stmt>()) {
|
||||||
I != E; ++I) {
|
match(*N);
|
||||||
BoundNodesTreeBuilder Builder;
|
} else if (auto *N = Node.get<Type>()) {
|
||||||
if (I->first.matches(Node, this, &Builder)) {
|
match(*N);
|
||||||
MatchVisitor Visitor(ActiveASTContext, I->second);
|
} else if (auto *N = Node.get<QualType>()) {
|
||||||
Builder.visitMatches(&Visitor);
|
match(*N);
|
||||||
}
|
} else if (auto *N = Node.get<NestedNameSpecifier>()) {
|
||||||
|
match(*N);
|
||||||
|
} else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
|
||||||
|
match(*N);
|
||||||
|
} else if (auto *N = Node.get<TypeLoc>()) {
|
||||||
|
match(*N);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void match(const T &Node) {
|
template <typename T> void match(const T &Node) {
|
||||||
match(ast_type_traits::DynTypedNode::create(Node));
|
matchDispatch(&Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements ASTMatchFinder::getASTContext.
|
// Implements ASTMatchFinder::getASTContext.
|
||||||
|
@ -475,6 +468,40 @@ public:
|
||||||
bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
|
bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// \brief Runs all the \p Matchers on \p Node.
|
||||||
|
///
|
||||||
|
/// Used by \c matchDispatch() below.
|
||||||
|
template <typename T, typename MC>
|
||||||
|
void matchImpl(const T &Node, const MC &Matchers) {
|
||||||
|
for (const auto &MP : Matchers) {
|
||||||
|
BoundNodesTreeBuilder Builder;
|
||||||
|
if (MP.first.matches(Node, this, &Builder)) {
|
||||||
|
MatchVisitor Visitor(ActiveASTContext, MP.second);
|
||||||
|
Builder.visitMatches(&Visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @{
|
||||||
|
/// \brief Overloads to pair the different node types to their matchers.
|
||||||
|
void matchDispatch(const Decl *Node) { matchImpl(*Node, Matchers->Decl); }
|
||||||
|
void matchDispatch(const Stmt *Node) { matchImpl(*Node, Matchers->Stmt); }
|
||||||
|
void matchDispatch(const Type *Node) {
|
||||||
|
matchImpl(QualType(Node, 0), Matchers->Type);
|
||||||
|
}
|
||||||
|
void matchDispatch(const TypeLoc *Node) {
|
||||||
|
matchImpl(*Node, Matchers->TypeLoc);
|
||||||
|
}
|
||||||
|
void matchDispatch(const QualType *Node) { matchImpl(*Node, Matchers->Type); }
|
||||||
|
void matchDispatch(const NestedNameSpecifier *Node) {
|
||||||
|
matchImpl(*Node, Matchers->NestedNameSpecifier);
|
||||||
|
}
|
||||||
|
void matchDispatch(const NestedNameSpecifierLoc *Node) {
|
||||||
|
matchImpl(*Node, Matchers->NestedNameSpecifierLoc);
|
||||||
|
}
|
||||||
|
void matchDispatch(const void *) { /* Do nothing. */ }
|
||||||
|
/// @}
|
||||||
|
|
||||||
// Returns whether an ancestor of \p Node matches \p Matcher.
|
// Returns whether an ancestor of \p Node matches \p Matcher.
|
||||||
//
|
//
|
||||||
// The order of matching ((which can lead to different nodes being bound in
|
// The order of matching ((which can lead to different nodes being bound in
|
||||||
|
@ -602,8 +629,7 @@ private:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *const
|
const MatchFinder::MatchersByType *Matchers;
|
||||||
MatcherCallbackPairs;
|
|
||||||
ASTContext *ActiveASTContext;
|
ASTContext *ActiveASTContext;
|
||||||
|
|
||||||
// Maps a canonical type to its TypedefDecls.
|
// Maps a canonical type to its TypedefDecls.
|
||||||
|
@ -772,32 +798,38 @@ MatchFinder::~MatchFinder() {}
|
||||||
|
|
||||||
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
|
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
|
||||||
MatchCallback *Action) {
|
MatchCallback *Action) {
|
||||||
MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
|
Matchers.Decl.push_back(std::make_pair(NodeMatch, Action));
|
||||||
|
Matchers.AllCallbacks.push_back(Action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
|
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
|
||||||
MatchCallback *Action) {
|
MatchCallback *Action) {
|
||||||
MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
|
Matchers.Type.push_back(std::make_pair(NodeMatch, Action));
|
||||||
|
Matchers.AllCallbacks.push_back(Action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
|
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
|
||||||
MatchCallback *Action) {
|
MatchCallback *Action) {
|
||||||
MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
|
Matchers.Stmt.push_back(std::make_pair(NodeMatch, Action));
|
||||||
|
Matchers.AllCallbacks.push_back(Action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
|
void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
|
||||||
MatchCallback *Action) {
|
MatchCallback *Action) {
|
||||||
MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
|
Matchers.NestedNameSpecifier.push_back(std::make_pair(NodeMatch, Action));
|
||||||
|
Matchers.AllCallbacks.push_back(Action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
|
void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
|
||||||
MatchCallback *Action) {
|
MatchCallback *Action) {
|
||||||
MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
|
Matchers.NestedNameSpecifierLoc.push_back(std::make_pair(NodeMatch, Action));
|
||||||
|
Matchers.AllCallbacks.push_back(Action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
|
void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
|
||||||
MatchCallback *Action) {
|
MatchCallback *Action) {
|
||||||
MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
|
Matchers.TypeLoc.push_back(std::make_pair(NodeMatch, Action));
|
||||||
|
Matchers.AllCallbacks.push_back(Action);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
|
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
|
||||||
|
@ -830,13 +862,13 @@ std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
|
||||||
|
|
||||||
void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
|
void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
|
||||||
ASTContext &Context) {
|
ASTContext &Context) {
|
||||||
internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
|
internal::MatchASTVisitor Visitor(&Matchers);
|
||||||
Visitor.set_active_ast_context(&Context);
|
Visitor.set_active_ast_context(&Context);
|
||||||
Visitor.match(Node);
|
Visitor.match(Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchFinder::matchAST(ASTContext &Context) {
|
void MatchFinder::matchAST(ASTContext &Context) {
|
||||||
internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
|
internal::MatchASTVisitor Visitor(&Matchers);
|
||||||
Visitor.set_active_ast_context(&Context);
|
Visitor.set_active_ast_context(&Context);
|
||||||
Visitor.onStartOfTranslationUnit();
|
Visitor.onStartOfTranslationUnit();
|
||||||
Visitor.TraverseDecl(Context.getTranslationUnitDecl());
|
Visitor.TraverseDecl(Context.getTranslationUnitDecl());
|
||||||
|
|
Loading…
Reference in New Issue