class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
public ASTMatchFinder {
public:
- MatchASTVisitor(
- std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *
- MatcherCallbackPairs)
- : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(nullptr) {}
+ MatchASTVisitor(const MatchFinder::MatchersByType *Matchers)
+ : Matchers(Matchers), ActiveASTContext(nullptr) {}
void onStartOfTranslationUnit() {
- for (std::vector<std::pair<internal::DynTypedMatcher,
- MatchCallback *> >::const_iterator
- I = MatcherCallbackPairs->begin(),
- E = MatcherCallbackPairs->end();
- I != E; ++I) {
- I->second->onStartOfTranslationUnit();
- }
+ for (MatchCallback *MC : Matchers->AllCallbacks)
+ MC->onStartOfTranslationUnit();
}
void onEndOfTranslationUnit() {
- for (std::vector<std::pair<internal::DynTypedMatcher,
- MatchCallback *> >::const_iterator
- I = MatcherCallbackPairs->begin(),
- E = MatcherCallbackPairs->end();
- I != E; ++I) {
- I->second->onEndOfTranslationUnit();
- }
+ for (MatchCallback *MC : Matchers->AllCallbacks)
+ MC->onEndOfTranslationUnit();
}
void set_active_ast_context(ASTContext *NewActiveASTContext) {
// Matches all registered matchers on the given node and calls the
// result callback for every node that matches.
- void match(const ast_type_traits::DynTypedNode& Node) {
- for (std::vector<std::pair<internal::DynTypedMatcher,
- MatchCallback *> >::const_iterator
- I = MatcherCallbackPairs->begin(),
- E = MatcherCallbackPairs->end();
- I != E; ++I) {
- BoundNodesTreeBuilder Builder;
- if (I->first.matches(Node, this, &Builder)) {
- MatchVisitor Visitor(ActiveASTContext, I->second);
- Builder.visitMatches(&Visitor);
- }
+ void match(const ast_type_traits::DynTypedNode &Node) {
+ // FIXME: Improve this with a switch or a visitor pattern.
+ if (auto *N = Node.get<Decl>()) {
+ match(*N);
+ } else if (auto *N = Node.get<Stmt>()) {
+ match(*N);
+ } else if (auto *N = Node.get<Type>()) {
+ match(*N);
+ } else if (auto *N = Node.get<QualType>()) {
+ 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) {
- match(ast_type_traits::DynTypedNode::create(Node));
+ matchDispatch(&Node);
}
// Implements ASTMatchFinder::getASTContext.
bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
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.
//
// The order of matching ((which can lead to different nodes being bound in
return false;
}
- std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *const
- MatcherCallbackPairs;
+ const MatchFinder::MatchersByType *Matchers;
ASTContext *ActiveASTContext;
// Maps a canonical type to its TypedefDecls.
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
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,
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,
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,
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,
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,
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,
void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
ASTContext &Context) {
- internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
+ internal::MatchASTVisitor Visitor(&Matchers);
Visitor.set_active_ast_context(&Context);
Visitor.match(Node);
}
void MatchFinder::matchAST(ASTContext &Context) {
- internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
+ internal::MatchASTVisitor Visitor(&Matchers);
Visitor.set_active_ast_context(&Context);
Visitor.onStartOfTranslationUnit();
Visitor.TraverseDecl(Context.getTranslationUnitDecl());