Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h =================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchFinder.h @@ -173,11 +173,23 @@ /// 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 > - MatcherCallbackPairs; + struct MatchersByType { + std::vector> Decl; + std::vector> Type; + std::vector> Stmt; + std::vector> + NestedNameSpecifier; + std::vector> + NestedNameSpecifierLoc; + std::vector> TypeLoc; + /// \brief All the callbacks in one container to simplify iteration. + std::vector AllCallbacks; + }; + +private: + MatchersByType Matchers; /// \brief Called when parsing is done. ParsingDoneTestCallback *ParsingDone; Index: cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp =================================================================== --- cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp +++ cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp @@ -292,29 +292,17 @@ class MatchASTVisitor : public RecursiveASTVisitor, public ASTMatchFinder { public: - MatchASTVisitor( - std::vector > * - MatcherCallbackPairs) - : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(nullptr) {} + MatchASTVisitor(const MatchFinder::MatchersByType *Matchers) + : Matchers(Matchers), ActiveASTContext(nullptr) {} void onStartOfTranslationUnit() { - for (std::vector >::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 >::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 @@ // 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 >::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()) { + match(*N); + } else if (auto *N = Node.get()) { + match(*N); + } else if (auto *N = Node.get()) { + match(*N); + } else if (auto *N = Node.get()) { + match(*N); + } else if (auto *N = Node.get()) { + match(*N); + } else if (auto *N = Node.get()) { + match(*N); + } else if (auto *N = Node.get()) { + match(*N); } } template void match(const T &Node) { - match(ast_type_traits::DynTypedNode::create(Node)); + matchDispatch(&Node); } // Implements ASTMatchFinder::getASTContext. @@ -475,6 +468,40 @@ bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; } private: + /// \brief Runs all the \p Matchers on \p Node. + /// + /// Used by \c matchDispatch() below. + template + 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 @@ return false; } - std::vector > *const - MatcherCallbackPairs; + const MatchFinder::MatchersByType *Matchers; ASTContext *ActiveASTContext; // Maps a canonical type to its TypedefDecls. @@ -772,32 +798,38 @@ 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 @@ 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());