diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index 75525ad1d62eccb1b8780ed9951bed05958fa16a..dfd414f35be48ff6fed5ee7031c15cc0b54e1e0c 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -173,11 +173,23 @@ public: /// Each call to FindAll(...) will call the closure once. void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); -private: - /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called + /// \brief For each \c Matcher<> a \c MatchCallback that will be called /// when it matches. - std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > - MatcherCallbackPairs; + struct MatchersByType { + 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. ParsingDoneTestCallback *ParsingDone; diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp index 6c5bc3c3727de8d510cb008fe19465d2a7ff82f1..47f45bc3ad9e38dbcad01fd1d17702f8b09d9ddb 100644 --- a/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/lib/ASTMatchers/ASTMatchFinder.cpp @@ -292,29 +292,17 @@ private: 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) { @@ -447,22 +435,27 @@ public: // 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. @@ -475,6 +468,40 @@ public: 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 @@ -602,8 +629,7 @@ private: return false; } - std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *const - MatcherCallbackPairs; + const MatchFinder::MatchersByType *Matchers; ASTContext *ActiveASTContext; // Maps a canonical type to its TypedefDecls. @@ -772,32 +798,38 @@ MatchFinder::~MatchFinder() {} 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, @@ -830,13 +862,13 @@ std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() { 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());