xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/ASTMatchers/ASTMatchFinder.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- ASTMatchFinder.cpp - Structural query framework ------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg //  Implements an algorithm to efficiently search for matches on AST nodes.
107330f729Sjoerg //  Uses memoization to support recursive matches like HasDescendant.
117330f729Sjoerg //
127330f729Sjoerg //  The general idea is to visit all AST nodes with a RecursiveASTVisitor,
137330f729Sjoerg //  calling the Matches(...) method of each matcher we are running on each
147330f729Sjoerg //  AST node. The matcher can recurse via the ASTMatchFinder interface.
157330f729Sjoerg //
167330f729Sjoerg //===----------------------------------------------------------------------===//
177330f729Sjoerg 
187330f729Sjoerg #include "clang/ASTMatchers/ASTMatchFinder.h"
197330f729Sjoerg #include "clang/AST/ASTConsumer.h"
207330f729Sjoerg #include "clang/AST/ASTContext.h"
217330f729Sjoerg #include "clang/AST/RecursiveASTVisitor.h"
227330f729Sjoerg #include "llvm/ADT/DenseMap.h"
237330f729Sjoerg #include "llvm/ADT/StringMap.h"
247330f729Sjoerg #include "llvm/Support/Timer.h"
257330f729Sjoerg #include <deque>
267330f729Sjoerg #include <memory>
277330f729Sjoerg #include <set>
287330f729Sjoerg 
297330f729Sjoerg namespace clang {
307330f729Sjoerg namespace ast_matchers {
317330f729Sjoerg namespace internal {
327330f729Sjoerg namespace {
337330f729Sjoerg 
347330f729Sjoerg typedef MatchFinder::MatchCallback MatchCallback;
357330f729Sjoerg 
367330f729Sjoerg // The maximum number of memoization entries to store.
377330f729Sjoerg // 10k has been experimentally found to give a good trade-off
387330f729Sjoerg // of performance vs. memory consumption by running matcher
397330f729Sjoerg // that match on every statement over a very large codebase.
407330f729Sjoerg //
417330f729Sjoerg // FIXME: Do some performance optimization in general and
427330f729Sjoerg // revisit this number; also, put up micro-benchmarks that we can
437330f729Sjoerg // optimize this on.
447330f729Sjoerg static const unsigned MaxMemoizationEntries = 10000;
457330f729Sjoerg 
46*e038c9c4Sjoerg enum class MatchType {
47*e038c9c4Sjoerg   Ancestors,
48*e038c9c4Sjoerg 
49*e038c9c4Sjoerg   Descendants,
50*e038c9c4Sjoerg   Child,
51*e038c9c4Sjoerg };
52*e038c9c4Sjoerg 
537330f729Sjoerg // We use memoization to avoid running the same matcher on the same
547330f729Sjoerg // AST node twice.  This struct is the key for looking up match
557330f729Sjoerg // result.  It consists of an ID of the MatcherInterface (for
567330f729Sjoerg // identifying the matcher), a pointer to the AST node and the
577330f729Sjoerg // bound nodes before the matcher was executed.
587330f729Sjoerg //
597330f729Sjoerg // We currently only memoize on nodes whose pointers identify the
607330f729Sjoerg // nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
617330f729Sjoerg // For \c QualType and \c TypeLoc it is possible to implement
627330f729Sjoerg // generation of keys for each type.
637330f729Sjoerg // FIXME: Benchmark whether memoization of non-pointer typed nodes
647330f729Sjoerg // provides enough benefit for the additional amount of code.
657330f729Sjoerg struct MatchKey {
667330f729Sjoerg   DynTypedMatcher::MatcherIDType MatcherID;
67*e038c9c4Sjoerg   DynTypedNode Node;
687330f729Sjoerg   BoundNodesTreeBuilder BoundNodes;
69*e038c9c4Sjoerg   TraversalKind Traversal = TK_AsIs;
70*e038c9c4Sjoerg   MatchType Type;
717330f729Sjoerg 
operator <clang::ast_matchers::internal::__anon62d4f9200111::MatchKey727330f729Sjoerg   bool operator<(const MatchKey &Other) const {
73*e038c9c4Sjoerg     return std::tie(Traversal, Type, MatcherID, Node, BoundNodes) <
74*e038c9c4Sjoerg            std::tie(Other.Traversal, Other.Type, Other.MatcherID, Other.Node,
75*e038c9c4Sjoerg                     Other.BoundNodes);
767330f729Sjoerg   }
777330f729Sjoerg };
787330f729Sjoerg 
797330f729Sjoerg // Used to store the result of a match and possibly bound nodes.
807330f729Sjoerg struct MemoizedMatchResult {
817330f729Sjoerg   bool ResultOfMatch;
827330f729Sjoerg   BoundNodesTreeBuilder Nodes;
837330f729Sjoerg };
847330f729Sjoerg 
857330f729Sjoerg // A RecursiveASTVisitor that traverses all children or all descendants of
867330f729Sjoerg // a node.
877330f729Sjoerg class MatchChildASTVisitor
887330f729Sjoerg     : public RecursiveASTVisitor<MatchChildASTVisitor> {
897330f729Sjoerg public:
907330f729Sjoerg   typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
917330f729Sjoerg 
927330f729Sjoerg   // Creates an AST visitor that matches 'matcher' on all children or
937330f729Sjoerg   // descendants of a traversed node. max_depth is the maximum depth
947330f729Sjoerg   // to traverse: use 1 for matching the children and INT_MAX for
957330f729Sjoerg   // matching the descendants.
MatchChildASTVisitor(const DynTypedMatcher * Matcher,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,int MaxDepth,bool IgnoreImplicitChildren,ASTMatchFinder::BindKind Bind)967330f729Sjoerg   MatchChildASTVisitor(const DynTypedMatcher *Matcher, ASTMatchFinder *Finder,
977330f729Sjoerg                        BoundNodesTreeBuilder *Builder, int MaxDepth,
98*e038c9c4Sjoerg                        bool IgnoreImplicitChildren,
997330f729Sjoerg                        ASTMatchFinder::BindKind Bind)
1007330f729Sjoerg       : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0),
101*e038c9c4Sjoerg         MaxDepth(MaxDepth), IgnoreImplicitChildren(IgnoreImplicitChildren),
102*e038c9c4Sjoerg         Bind(Bind), Matches(false) {}
1037330f729Sjoerg 
1047330f729Sjoerg   // Returns true if a match is found in the subtree rooted at the
1057330f729Sjoerg   // given AST node. This is done via a set of mutually recursive
1067330f729Sjoerg   // functions. Here's how the recursion is done (the  *wildcard can
1077330f729Sjoerg   // actually be Decl, Stmt, or Type):
1087330f729Sjoerg   //
1097330f729Sjoerg   //   - Traverse(node) calls BaseTraverse(node) when it needs
1107330f729Sjoerg   //     to visit the descendants of node.
1117330f729Sjoerg   //   - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
1127330f729Sjoerg   //     Traverse*(c) for each child c of 'node'.
1137330f729Sjoerg   //   - Traverse*(c) in turn calls Traverse(c), completing the
1147330f729Sjoerg   //     recursion.
findMatch(const DynTypedNode & DynNode)115*e038c9c4Sjoerg   bool findMatch(const DynTypedNode &DynNode) {
1167330f729Sjoerg     reset();
1177330f729Sjoerg     if (const Decl *D = DynNode.get<Decl>())
1187330f729Sjoerg       traverse(*D);
1197330f729Sjoerg     else if (const Stmt *S = DynNode.get<Stmt>())
1207330f729Sjoerg       traverse(*S);
1217330f729Sjoerg     else if (const NestedNameSpecifier *NNS =
1227330f729Sjoerg              DynNode.get<NestedNameSpecifier>())
1237330f729Sjoerg       traverse(*NNS);
1247330f729Sjoerg     else if (const NestedNameSpecifierLoc *NNSLoc =
1257330f729Sjoerg              DynNode.get<NestedNameSpecifierLoc>())
1267330f729Sjoerg       traverse(*NNSLoc);
1277330f729Sjoerg     else if (const QualType *Q = DynNode.get<QualType>())
1287330f729Sjoerg       traverse(*Q);
1297330f729Sjoerg     else if (const TypeLoc *T = DynNode.get<TypeLoc>())
1307330f729Sjoerg       traverse(*T);
1317330f729Sjoerg     else if (const auto *C = DynNode.get<CXXCtorInitializer>())
1327330f729Sjoerg       traverse(*C);
133*e038c9c4Sjoerg     else if (const TemplateArgumentLoc *TALoc =
134*e038c9c4Sjoerg                  DynNode.get<TemplateArgumentLoc>())
135*e038c9c4Sjoerg       traverse(*TALoc);
1367330f729Sjoerg     // FIXME: Add other base types after adding tests.
1377330f729Sjoerg 
1387330f729Sjoerg     // It's OK to always overwrite the bound nodes, as if there was
1397330f729Sjoerg     // no match in this recursive branch, the result set is empty
1407330f729Sjoerg     // anyway.
1417330f729Sjoerg     *Builder = ResultBindings;
1427330f729Sjoerg 
1437330f729Sjoerg     return Matches;
1447330f729Sjoerg   }
1457330f729Sjoerg 
1467330f729Sjoerg   // The following are overriding methods from the base visitor class.
1477330f729Sjoerg   // They are public only to allow CRTP to work. They are *not *part
1487330f729Sjoerg   // of the public API of this class.
TraverseDecl(Decl * DeclNode)1497330f729Sjoerg   bool TraverseDecl(Decl *DeclNode) {
150*e038c9c4Sjoerg 
151*e038c9c4Sjoerg     if (DeclNode && DeclNode->isImplicit() &&
152*e038c9c4Sjoerg         Finder->isTraversalIgnoringImplicitNodes())
153*e038c9c4Sjoerg       return baseTraverse(*DeclNode);
154*e038c9c4Sjoerg 
1557330f729Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
1567330f729Sjoerg     return (DeclNode == nullptr) || traverse(*DeclNode);
1577330f729Sjoerg   }
158*e038c9c4Sjoerg 
getStmtToTraverse(Stmt * StmtNode)159*e038c9c4Sjoerg   Stmt *getStmtToTraverse(Stmt *StmtNode) {
160*e038c9c4Sjoerg     Stmt *StmtToTraverse = StmtNode;
161*e038c9c4Sjoerg     if (auto *ExprNode = dyn_cast_or_null<Expr>(StmtNode)) {
162*e038c9c4Sjoerg       auto *LambdaNode = dyn_cast_or_null<LambdaExpr>(StmtNode);
163*e038c9c4Sjoerg       if (LambdaNode && Finder->isTraversalIgnoringImplicitNodes())
164*e038c9c4Sjoerg         StmtToTraverse = LambdaNode;
165*e038c9c4Sjoerg       else
166*e038c9c4Sjoerg         StmtToTraverse =
167*e038c9c4Sjoerg             Finder->getASTContext().getParentMapContext().traverseIgnored(
168*e038c9c4Sjoerg                 ExprNode);
169*e038c9c4Sjoerg     }
170*e038c9c4Sjoerg     return StmtToTraverse;
171*e038c9c4Sjoerg   }
172*e038c9c4Sjoerg 
TraverseStmt(Stmt * StmtNode,DataRecursionQueue * Queue=nullptr)1737330f729Sjoerg   bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) {
1747330f729Sjoerg     // If we need to keep track of the depth, we can't perform data recursion.
1757330f729Sjoerg     if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX))
1767330f729Sjoerg       Queue = nullptr;
1777330f729Sjoerg 
1787330f729Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
179*e038c9c4Sjoerg     Stmt *StmtToTraverse = getStmtToTraverse(StmtNode);
1807330f729Sjoerg     if (!StmtToTraverse)
1817330f729Sjoerg       return true;
182*e038c9c4Sjoerg 
183*e038c9c4Sjoerg     if (IgnoreImplicitChildren && isa<CXXDefaultArgExpr>(StmtNode))
184*e038c9c4Sjoerg       return true;
185*e038c9c4Sjoerg 
1867330f729Sjoerg     if (!match(*StmtToTraverse))
1877330f729Sjoerg       return false;
1887330f729Sjoerg     return VisitorBase::TraverseStmt(StmtToTraverse, Queue);
1897330f729Sjoerg   }
1907330f729Sjoerg   // We assume that the QualType and the contained type are on the same
1917330f729Sjoerg   // hierarchy level. Thus, we try to match either of them.
TraverseType(QualType TypeNode)1927330f729Sjoerg   bool TraverseType(QualType TypeNode) {
1937330f729Sjoerg     if (TypeNode.isNull())
1947330f729Sjoerg       return true;
1957330f729Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
1967330f729Sjoerg     // Match the Type.
1977330f729Sjoerg     if (!match(*TypeNode))
1987330f729Sjoerg       return false;
1997330f729Sjoerg     // The QualType is matched inside traverse.
2007330f729Sjoerg     return traverse(TypeNode);
2017330f729Sjoerg   }
2027330f729Sjoerg   // We assume that the TypeLoc, contained QualType and contained Type all are
2037330f729Sjoerg   // on the same hierarchy level. Thus, we try to match all of them.
TraverseTypeLoc(TypeLoc TypeLocNode)2047330f729Sjoerg   bool TraverseTypeLoc(TypeLoc TypeLocNode) {
2057330f729Sjoerg     if (TypeLocNode.isNull())
2067330f729Sjoerg       return true;
2077330f729Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
2087330f729Sjoerg     // Match the Type.
2097330f729Sjoerg     if (!match(*TypeLocNode.getType()))
2107330f729Sjoerg       return false;
2117330f729Sjoerg     // Match the QualType.
2127330f729Sjoerg     if (!match(TypeLocNode.getType()))
2137330f729Sjoerg       return false;
2147330f729Sjoerg     // The TypeLoc is matched inside traverse.
2157330f729Sjoerg     return traverse(TypeLocNode);
2167330f729Sjoerg   }
TraverseNestedNameSpecifier(NestedNameSpecifier * NNS)2177330f729Sjoerg   bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
2187330f729Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
2197330f729Sjoerg     return (NNS == nullptr) || traverse(*NNS);
2207330f729Sjoerg   }
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)2217330f729Sjoerg   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
2227330f729Sjoerg     if (!NNS)
2237330f729Sjoerg       return true;
2247330f729Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
2257330f729Sjoerg     if (!match(*NNS.getNestedNameSpecifier()))
2267330f729Sjoerg       return false;
2277330f729Sjoerg     return traverse(NNS);
2287330f729Sjoerg   }
TraverseConstructorInitializer(CXXCtorInitializer * CtorInit)2297330f729Sjoerg   bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
2307330f729Sjoerg     if (!CtorInit)
2317330f729Sjoerg       return true;
2327330f729Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
2337330f729Sjoerg     return traverse(*CtorInit);
2347330f729Sjoerg   }
TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL)235*e038c9c4Sjoerg   bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
236*e038c9c4Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
237*e038c9c4Sjoerg     return traverse(TAL);
238*e038c9c4Sjoerg   }
TraverseCXXForRangeStmt(CXXForRangeStmt * Node)239*e038c9c4Sjoerg   bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) {
240*e038c9c4Sjoerg     if (!Finder->isTraversalIgnoringImplicitNodes())
241*e038c9c4Sjoerg       return VisitorBase::TraverseCXXForRangeStmt(Node);
242*e038c9c4Sjoerg     if (!Node)
243*e038c9c4Sjoerg       return true;
244*e038c9c4Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
245*e038c9c4Sjoerg     if (auto *Init = Node->getInit())
246*e038c9c4Sjoerg       if (!traverse(*Init))
247*e038c9c4Sjoerg         return false;
248*e038c9c4Sjoerg     if (!match(*Node->getLoopVariable()))
249*e038c9c4Sjoerg       return false;
250*e038c9c4Sjoerg     if (match(*Node->getRangeInit()))
251*e038c9c4Sjoerg       if (!VisitorBase::TraverseStmt(Node->getRangeInit()))
252*e038c9c4Sjoerg         return false;
253*e038c9c4Sjoerg     if (!match(*Node->getBody()))
254*e038c9c4Sjoerg       return false;
255*e038c9c4Sjoerg     return VisitorBase::TraverseStmt(Node->getBody());
256*e038c9c4Sjoerg   }
TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator * Node)257*e038c9c4Sjoerg   bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *Node) {
258*e038c9c4Sjoerg     if (!Finder->isTraversalIgnoringImplicitNodes())
259*e038c9c4Sjoerg       return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node);
260*e038c9c4Sjoerg     if (!Node)
261*e038c9c4Sjoerg       return true;
262*e038c9c4Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
263*e038c9c4Sjoerg 
264*e038c9c4Sjoerg     return match(*Node->getLHS()) && match(*Node->getRHS());
265*e038c9c4Sjoerg   }
TraverseLambdaExpr(LambdaExpr * Node)266*e038c9c4Sjoerg   bool TraverseLambdaExpr(LambdaExpr *Node) {
267*e038c9c4Sjoerg     if (!Finder->isTraversalIgnoringImplicitNodes())
268*e038c9c4Sjoerg       return VisitorBase::TraverseLambdaExpr(Node);
269*e038c9c4Sjoerg     if (!Node)
270*e038c9c4Sjoerg       return true;
271*e038c9c4Sjoerg     ScopedIncrement ScopedDepth(&CurrentDepth);
272*e038c9c4Sjoerg 
273*e038c9c4Sjoerg     for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
274*e038c9c4Sjoerg       const auto *C = Node->capture_begin() + I;
275*e038c9c4Sjoerg       if (!C->isExplicit())
276*e038c9c4Sjoerg         continue;
277*e038c9c4Sjoerg       if (Node->isInitCapture(C) && !match(*C->getCapturedVar()))
278*e038c9c4Sjoerg         return false;
279*e038c9c4Sjoerg       if (!match(*Node->capture_init_begin()[I]))
280*e038c9c4Sjoerg         return false;
281*e038c9c4Sjoerg     }
282*e038c9c4Sjoerg 
283*e038c9c4Sjoerg     if (const auto *TPL = Node->getTemplateParameterList()) {
284*e038c9c4Sjoerg       for (const auto *TP : *TPL) {
285*e038c9c4Sjoerg         if (!match(*TP))
286*e038c9c4Sjoerg           return false;
287*e038c9c4Sjoerg       }
288*e038c9c4Sjoerg     }
289*e038c9c4Sjoerg 
290*e038c9c4Sjoerg     for (const auto *P : Node->getCallOperator()->parameters()) {
291*e038c9c4Sjoerg       if (!match(*P))
292*e038c9c4Sjoerg         return false;
293*e038c9c4Sjoerg     }
294*e038c9c4Sjoerg 
295*e038c9c4Sjoerg     if (!match(*Node->getBody()))
296*e038c9c4Sjoerg       return false;
297*e038c9c4Sjoerg 
298*e038c9c4Sjoerg     return VisitorBase::TraverseStmt(Node->getBody());
299*e038c9c4Sjoerg   }
3007330f729Sjoerg 
shouldVisitTemplateInstantiations() const3017330f729Sjoerg   bool shouldVisitTemplateInstantiations() const { return true; }
shouldVisitImplicitCode() const302*e038c9c4Sjoerg   bool shouldVisitImplicitCode() const { return !IgnoreImplicitChildren; }
3037330f729Sjoerg 
3047330f729Sjoerg private:
3057330f729Sjoerg   // Used for updating the depth during traversal.
3067330f729Sjoerg   struct ScopedIncrement {
ScopedIncrementclang::ast_matchers::internal::__anon62d4f9200111::MatchChildASTVisitor::ScopedIncrement3077330f729Sjoerg     explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
~ScopedIncrementclang::ast_matchers::internal::__anon62d4f9200111::MatchChildASTVisitor::ScopedIncrement3087330f729Sjoerg     ~ScopedIncrement() { --(*Depth); }
3097330f729Sjoerg 
3107330f729Sjoerg    private:
3117330f729Sjoerg     int *Depth;
3127330f729Sjoerg   };
3137330f729Sjoerg 
3147330f729Sjoerg   // Resets the state of this object.
reset()3157330f729Sjoerg   void reset() {
3167330f729Sjoerg     Matches = false;
3177330f729Sjoerg     CurrentDepth = 0;
3187330f729Sjoerg   }
3197330f729Sjoerg 
3207330f729Sjoerg   // Forwards the call to the corresponding Traverse*() method in the
3217330f729Sjoerg   // base visitor class.
baseTraverse(const Decl & DeclNode)3227330f729Sjoerg   bool baseTraverse(const Decl &DeclNode) {
3237330f729Sjoerg     return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
3247330f729Sjoerg   }
baseTraverse(const Stmt & StmtNode)3257330f729Sjoerg   bool baseTraverse(const Stmt &StmtNode) {
3267330f729Sjoerg     return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
3277330f729Sjoerg   }
baseTraverse(QualType TypeNode)3287330f729Sjoerg   bool baseTraverse(QualType TypeNode) {
3297330f729Sjoerg     return VisitorBase::TraverseType(TypeNode);
3307330f729Sjoerg   }
baseTraverse(TypeLoc TypeLocNode)3317330f729Sjoerg   bool baseTraverse(TypeLoc TypeLocNode) {
3327330f729Sjoerg     return VisitorBase::TraverseTypeLoc(TypeLocNode);
3337330f729Sjoerg   }
baseTraverse(const NestedNameSpecifier & NNS)3347330f729Sjoerg   bool baseTraverse(const NestedNameSpecifier &NNS) {
3357330f729Sjoerg     return VisitorBase::TraverseNestedNameSpecifier(
3367330f729Sjoerg         const_cast<NestedNameSpecifier*>(&NNS));
3377330f729Sjoerg   }
baseTraverse(NestedNameSpecifierLoc NNS)3387330f729Sjoerg   bool baseTraverse(NestedNameSpecifierLoc NNS) {
3397330f729Sjoerg     return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
3407330f729Sjoerg   }
baseTraverse(const CXXCtorInitializer & CtorInit)3417330f729Sjoerg   bool baseTraverse(const CXXCtorInitializer &CtorInit) {
3427330f729Sjoerg     return VisitorBase::TraverseConstructorInitializer(
3437330f729Sjoerg         const_cast<CXXCtorInitializer *>(&CtorInit));
3447330f729Sjoerg   }
baseTraverse(TemplateArgumentLoc TAL)345*e038c9c4Sjoerg   bool baseTraverse(TemplateArgumentLoc TAL) {
346*e038c9c4Sjoerg     return VisitorBase::TraverseTemplateArgumentLoc(TAL);
347*e038c9c4Sjoerg   }
3487330f729Sjoerg 
3497330f729Sjoerg   // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
3507330f729Sjoerg   //   0 < CurrentDepth <= MaxDepth.
3517330f729Sjoerg   //
3527330f729Sjoerg   // Returns 'true' if traversal should continue after this function
3537330f729Sjoerg   // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
3547330f729Sjoerg   template <typename T>
match(const T & Node)3557330f729Sjoerg   bool match(const T &Node) {
3567330f729Sjoerg     if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
3577330f729Sjoerg       return true;
3587330f729Sjoerg     }
3597330f729Sjoerg     if (Bind != ASTMatchFinder::BK_All) {
3607330f729Sjoerg       BoundNodesTreeBuilder RecursiveBuilder(*Builder);
361*e038c9c4Sjoerg       if (Matcher->matches(DynTypedNode::create(Node), Finder,
3627330f729Sjoerg                            &RecursiveBuilder)) {
3637330f729Sjoerg         Matches = true;
3647330f729Sjoerg         ResultBindings.addMatch(RecursiveBuilder);
3657330f729Sjoerg         return false; // Abort as soon as a match is found.
3667330f729Sjoerg       }
3677330f729Sjoerg     } else {
3687330f729Sjoerg       BoundNodesTreeBuilder RecursiveBuilder(*Builder);
369*e038c9c4Sjoerg       if (Matcher->matches(DynTypedNode::create(Node), Finder,
3707330f729Sjoerg                            &RecursiveBuilder)) {
3717330f729Sjoerg         // After the first match the matcher succeeds.
3727330f729Sjoerg         Matches = true;
3737330f729Sjoerg         ResultBindings.addMatch(RecursiveBuilder);
3747330f729Sjoerg       }
3757330f729Sjoerg     }
3767330f729Sjoerg     return true;
3777330f729Sjoerg   }
3787330f729Sjoerg 
3797330f729Sjoerg   // Traverses the subtree rooted at 'Node'; returns true if the
3807330f729Sjoerg   // traversal should continue after this function returns.
3817330f729Sjoerg   template <typename T>
traverse(const T & Node)3827330f729Sjoerg   bool traverse(const T &Node) {
3837330f729Sjoerg     static_assert(IsBaseType<T>::value,
3847330f729Sjoerg                   "traverse can only be instantiated with base type");
3857330f729Sjoerg     if (!match(Node))
3867330f729Sjoerg       return false;
3877330f729Sjoerg     return baseTraverse(Node);
3887330f729Sjoerg   }
3897330f729Sjoerg 
3907330f729Sjoerg   const DynTypedMatcher *const Matcher;
3917330f729Sjoerg   ASTMatchFinder *const Finder;
3927330f729Sjoerg   BoundNodesTreeBuilder *const Builder;
3937330f729Sjoerg   BoundNodesTreeBuilder ResultBindings;
3947330f729Sjoerg   int CurrentDepth;
3957330f729Sjoerg   const int MaxDepth;
396*e038c9c4Sjoerg   const bool IgnoreImplicitChildren;
3977330f729Sjoerg   const ASTMatchFinder::BindKind Bind;
3987330f729Sjoerg   bool Matches;
3997330f729Sjoerg };
4007330f729Sjoerg 
4017330f729Sjoerg // Controls the outermost traversal of the AST and allows to match multiple
4027330f729Sjoerg // matchers.
4037330f729Sjoerg class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
4047330f729Sjoerg                         public ASTMatchFinder {
4057330f729Sjoerg public:
MatchASTVisitor(const MatchFinder::MatchersByType * Matchers,const MatchFinder::MatchFinderOptions & Options)4067330f729Sjoerg   MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
4077330f729Sjoerg                   const MatchFinder::MatchFinderOptions &Options)
4087330f729Sjoerg       : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
4097330f729Sjoerg 
~MatchASTVisitor()4107330f729Sjoerg   ~MatchASTVisitor() override {
4117330f729Sjoerg     if (Options.CheckProfiling) {
4127330f729Sjoerg       Options.CheckProfiling->Records = std::move(TimeByBucket);
4137330f729Sjoerg     }
4147330f729Sjoerg   }
4157330f729Sjoerg 
onStartOfTranslationUnit()4167330f729Sjoerg   void onStartOfTranslationUnit() {
4177330f729Sjoerg     const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
4187330f729Sjoerg     TimeBucketRegion Timer;
4197330f729Sjoerg     for (MatchCallback *MC : Matchers->AllCallbacks) {
4207330f729Sjoerg       if (EnableCheckProfiling)
4217330f729Sjoerg         Timer.setBucket(&TimeByBucket[MC->getID()]);
4227330f729Sjoerg       MC->onStartOfTranslationUnit();
4237330f729Sjoerg     }
4247330f729Sjoerg   }
4257330f729Sjoerg 
onEndOfTranslationUnit()4267330f729Sjoerg   void onEndOfTranslationUnit() {
4277330f729Sjoerg     const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
4287330f729Sjoerg     TimeBucketRegion Timer;
4297330f729Sjoerg     for (MatchCallback *MC : Matchers->AllCallbacks) {
4307330f729Sjoerg       if (EnableCheckProfiling)
4317330f729Sjoerg         Timer.setBucket(&TimeByBucket[MC->getID()]);
4327330f729Sjoerg       MC->onEndOfTranslationUnit();
4337330f729Sjoerg     }
4347330f729Sjoerg   }
4357330f729Sjoerg 
set_active_ast_context(ASTContext * NewActiveASTContext)4367330f729Sjoerg   void set_active_ast_context(ASTContext *NewActiveASTContext) {
4377330f729Sjoerg     ActiveASTContext = NewActiveASTContext;
4387330f729Sjoerg   }
4397330f729Sjoerg 
4407330f729Sjoerg   // The following Visit*() and Traverse*() functions "override"
4417330f729Sjoerg   // methods in RecursiveASTVisitor.
4427330f729Sjoerg 
VisitTypedefNameDecl(TypedefNameDecl * DeclNode)4437330f729Sjoerg   bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
4447330f729Sjoerg     // When we see 'typedef A B', we add name 'B' to the set of names
4457330f729Sjoerg     // A's canonical type maps to.  This is necessary for implementing
4467330f729Sjoerg     // isDerivedFrom(x) properly, where x can be the name of the base
4477330f729Sjoerg     // class or any of its aliases.
4487330f729Sjoerg     //
4497330f729Sjoerg     // In general, the is-alias-of (as defined by typedefs) relation
4507330f729Sjoerg     // is tree-shaped, as you can typedef a type more than once.  For
4517330f729Sjoerg     // example,
4527330f729Sjoerg     //
4537330f729Sjoerg     //   typedef A B;
4547330f729Sjoerg     //   typedef A C;
4557330f729Sjoerg     //   typedef C D;
4567330f729Sjoerg     //   typedef C E;
4577330f729Sjoerg     //
4587330f729Sjoerg     // gives you
4597330f729Sjoerg     //
4607330f729Sjoerg     //   A
4617330f729Sjoerg     //   |- B
4627330f729Sjoerg     //   `- C
4637330f729Sjoerg     //      |- D
4647330f729Sjoerg     //      `- E
4657330f729Sjoerg     //
4667330f729Sjoerg     // It is wrong to assume that the relation is a chain.  A correct
4677330f729Sjoerg     // implementation of isDerivedFrom() needs to recognize that B and
4687330f729Sjoerg     // E are aliases, even though neither is a typedef of the other.
4697330f729Sjoerg     // Therefore, we cannot simply walk through one typedef chain to
4707330f729Sjoerg     // find out whether the type name matches.
4717330f729Sjoerg     const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
4727330f729Sjoerg     const Type *CanonicalType =  // root of the typedef tree
4737330f729Sjoerg         ActiveASTContext->getCanonicalType(TypeNode);
4747330f729Sjoerg     TypeAliases[CanonicalType].insert(DeclNode);
4757330f729Sjoerg     return true;
4767330f729Sjoerg   }
4777330f729Sjoerg 
VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl * CAD)4787330f729Sjoerg   bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
4797330f729Sjoerg     const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface();
4807330f729Sjoerg     CompatibleAliases[InterfaceDecl].insert(CAD);
4817330f729Sjoerg     return true;
4827330f729Sjoerg   }
4837330f729Sjoerg 
4847330f729Sjoerg   bool TraverseDecl(Decl *DeclNode);
4857330f729Sjoerg   bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
4867330f729Sjoerg   bool TraverseType(QualType TypeNode);
4877330f729Sjoerg   bool TraverseTypeLoc(TypeLoc TypeNode);
4887330f729Sjoerg   bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
4897330f729Sjoerg   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
4907330f729Sjoerg   bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
491*e038c9c4Sjoerg   bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
492*e038c9c4Sjoerg 
dataTraverseNode(Stmt * S,DataRecursionQueue * Queue)493*e038c9c4Sjoerg   bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
494*e038c9c4Sjoerg     if (auto *RF = dyn_cast<CXXForRangeStmt>(S)) {
495*e038c9c4Sjoerg       {
496*e038c9c4Sjoerg         ASTNodeNotAsIsSourceScope RAII(this, true);
497*e038c9c4Sjoerg         TraverseStmt(RF->getInit());
498*e038c9c4Sjoerg         // Don't traverse under the loop variable
499*e038c9c4Sjoerg         match(*RF->getLoopVariable());
500*e038c9c4Sjoerg         TraverseStmt(RF->getRangeInit());
501*e038c9c4Sjoerg       }
502*e038c9c4Sjoerg       {
503*e038c9c4Sjoerg         ASTNodeNotSpelledInSourceScope RAII(this, true);
504*e038c9c4Sjoerg         for (auto *SubStmt : RF->children()) {
505*e038c9c4Sjoerg           if (SubStmt != RF->getBody())
506*e038c9c4Sjoerg             TraverseStmt(SubStmt);
507*e038c9c4Sjoerg         }
508*e038c9c4Sjoerg       }
509*e038c9c4Sjoerg       TraverseStmt(RF->getBody());
510*e038c9c4Sjoerg       return true;
511*e038c9c4Sjoerg     } else if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
512*e038c9c4Sjoerg       {
513*e038c9c4Sjoerg         ASTNodeNotAsIsSourceScope RAII(this, true);
514*e038c9c4Sjoerg         TraverseStmt(const_cast<Expr *>(RBO->getLHS()));
515*e038c9c4Sjoerg         TraverseStmt(const_cast<Expr *>(RBO->getRHS()));
516*e038c9c4Sjoerg       }
517*e038c9c4Sjoerg       {
518*e038c9c4Sjoerg         ASTNodeNotSpelledInSourceScope RAII(this, true);
519*e038c9c4Sjoerg         for (auto *SubStmt : RBO->children()) {
520*e038c9c4Sjoerg           TraverseStmt(SubStmt);
521*e038c9c4Sjoerg         }
522*e038c9c4Sjoerg       }
523*e038c9c4Sjoerg       return true;
524*e038c9c4Sjoerg     } else if (auto *LE = dyn_cast<LambdaExpr>(S)) {
525*e038c9c4Sjoerg       for (auto I : llvm::zip(LE->captures(), LE->capture_inits())) {
526*e038c9c4Sjoerg         auto C = std::get<0>(I);
527*e038c9c4Sjoerg         ASTNodeNotSpelledInSourceScope RAII(
528*e038c9c4Sjoerg             this, TraversingASTNodeNotSpelledInSource || !C.isExplicit());
529*e038c9c4Sjoerg         TraverseLambdaCapture(LE, &C, std::get<1>(I));
530*e038c9c4Sjoerg       }
531*e038c9c4Sjoerg 
532*e038c9c4Sjoerg       {
533*e038c9c4Sjoerg         ASTNodeNotSpelledInSourceScope RAII(this, true);
534*e038c9c4Sjoerg         TraverseDecl(LE->getLambdaClass());
535*e038c9c4Sjoerg       }
536*e038c9c4Sjoerg       {
537*e038c9c4Sjoerg         ASTNodeNotAsIsSourceScope RAII(this, true);
538*e038c9c4Sjoerg 
539*e038c9c4Sjoerg         // We need to poke around to find the bits that might be explicitly
540*e038c9c4Sjoerg         // written.
541*e038c9c4Sjoerg         TypeLoc TL = LE->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
542*e038c9c4Sjoerg         FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
543*e038c9c4Sjoerg 
544*e038c9c4Sjoerg         if (auto *TPL = LE->getTemplateParameterList()) {
545*e038c9c4Sjoerg           for (NamedDecl *D : *TPL) {
546*e038c9c4Sjoerg             TraverseDecl(D);
547*e038c9c4Sjoerg           }
548*e038c9c4Sjoerg           if (Expr *RequiresClause = TPL->getRequiresClause()) {
549*e038c9c4Sjoerg             TraverseStmt(RequiresClause);
550*e038c9c4Sjoerg           }
551*e038c9c4Sjoerg         }
552*e038c9c4Sjoerg 
553*e038c9c4Sjoerg         if (LE->hasExplicitParameters()) {
554*e038c9c4Sjoerg           // Visit parameters.
555*e038c9c4Sjoerg           for (ParmVarDecl *Param : Proto.getParams())
556*e038c9c4Sjoerg             TraverseDecl(Param);
557*e038c9c4Sjoerg         }
558*e038c9c4Sjoerg 
559*e038c9c4Sjoerg         const auto *T = Proto.getTypePtr();
560*e038c9c4Sjoerg         for (const auto &E : T->exceptions())
561*e038c9c4Sjoerg           TraverseType(E);
562*e038c9c4Sjoerg 
563*e038c9c4Sjoerg         if (Expr *NE = T->getNoexceptExpr())
564*e038c9c4Sjoerg           TraverseStmt(NE, Queue);
565*e038c9c4Sjoerg 
566*e038c9c4Sjoerg         if (LE->hasExplicitResultType())
567*e038c9c4Sjoerg           TraverseTypeLoc(Proto.getReturnLoc());
568*e038c9c4Sjoerg         TraverseStmt(LE->getTrailingRequiresClause());
569*e038c9c4Sjoerg       }
570*e038c9c4Sjoerg 
571*e038c9c4Sjoerg       TraverseStmt(LE->getBody());
572*e038c9c4Sjoerg       return true;
573*e038c9c4Sjoerg     }
574*e038c9c4Sjoerg     return RecursiveASTVisitor<MatchASTVisitor>::dataTraverseNode(S, Queue);
575*e038c9c4Sjoerg   }
5767330f729Sjoerg 
5777330f729Sjoerg   // Matches children or descendants of 'Node' with 'BaseMatcher'.
memoizedMatchesRecursively(const DynTypedNode & Node,ASTContext & Ctx,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,int MaxDepth,BindKind Bind)578*e038c9c4Sjoerg   bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx,
5797330f729Sjoerg                                   const DynTypedMatcher &Matcher,
5807330f729Sjoerg                                   BoundNodesTreeBuilder *Builder, int MaxDepth,
5817330f729Sjoerg                                   BindKind Bind) {
5827330f729Sjoerg     // For AST-nodes that don't have an identity, we can't memoize.
5837330f729Sjoerg     if (!Node.getMemoizationData() || !Builder->isComparable())
584*e038c9c4Sjoerg       return matchesRecursively(Node, Matcher, Builder, MaxDepth, Bind);
5857330f729Sjoerg 
5867330f729Sjoerg     MatchKey Key;
5877330f729Sjoerg     Key.MatcherID = Matcher.getID();
5887330f729Sjoerg     Key.Node = Node;
5897330f729Sjoerg     // Note that we key on the bindings *before* the match.
5907330f729Sjoerg     Key.BoundNodes = *Builder;
591*e038c9c4Sjoerg     Key.Traversal = Ctx.getParentMapContext().getTraversalKind();
592*e038c9c4Sjoerg     // Memoize result even doing a single-level match, it might be expensive.
593*e038c9c4Sjoerg     Key.Type = MaxDepth == 1 ? MatchType::Child : MatchType::Descendants;
5947330f729Sjoerg     MemoizationMap::iterator I = ResultCache.find(Key);
5957330f729Sjoerg     if (I != ResultCache.end()) {
5967330f729Sjoerg       *Builder = I->second.Nodes;
5977330f729Sjoerg       return I->second.ResultOfMatch;
5987330f729Sjoerg     }
5997330f729Sjoerg 
6007330f729Sjoerg     MemoizedMatchResult Result;
6017330f729Sjoerg     Result.Nodes = *Builder;
602*e038c9c4Sjoerg     Result.ResultOfMatch =
603*e038c9c4Sjoerg         matchesRecursively(Node, Matcher, &Result.Nodes, MaxDepth, Bind);
6047330f729Sjoerg 
6057330f729Sjoerg     MemoizedMatchResult &CachedResult = ResultCache[Key];
6067330f729Sjoerg     CachedResult = std::move(Result);
6077330f729Sjoerg 
6087330f729Sjoerg     *Builder = CachedResult.Nodes;
6097330f729Sjoerg     return CachedResult.ResultOfMatch;
6107330f729Sjoerg   }
6117330f729Sjoerg 
6127330f729Sjoerg   // Matches children or descendants of 'Node' with 'BaseMatcher'.
matchesRecursively(const DynTypedNode & Node,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,int MaxDepth,BindKind Bind)613*e038c9c4Sjoerg   bool matchesRecursively(const DynTypedNode &Node,
6147330f729Sjoerg                           const DynTypedMatcher &Matcher,
6157330f729Sjoerg                           BoundNodesTreeBuilder *Builder, int MaxDepth,
6167330f729Sjoerg                           BindKind Bind) {
617*e038c9c4Sjoerg     bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
618*e038c9c4Sjoerg                            TraversingASTChildrenNotSpelledInSource;
619*e038c9c4Sjoerg 
620*e038c9c4Sjoerg     bool IgnoreImplicitChildren = false;
621*e038c9c4Sjoerg 
622*e038c9c4Sjoerg     if (isTraversalIgnoringImplicitNodes()) {
623*e038c9c4Sjoerg       IgnoreImplicitChildren = true;
624*e038c9c4Sjoerg     }
625*e038c9c4Sjoerg 
626*e038c9c4Sjoerg     ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
627*e038c9c4Sjoerg 
628*e038c9c4Sjoerg     MatchChildASTVisitor Visitor(&Matcher, this, Builder, MaxDepth,
629*e038c9c4Sjoerg                                  IgnoreImplicitChildren, Bind);
6307330f729Sjoerg     return Visitor.findMatch(Node);
6317330f729Sjoerg   }
6327330f729Sjoerg 
6337330f729Sjoerg   bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
6347330f729Sjoerg                           const Matcher<NamedDecl> &Base,
6357330f729Sjoerg                           BoundNodesTreeBuilder *Builder,
6367330f729Sjoerg                           bool Directly) override;
6377330f729Sjoerg 
6387330f729Sjoerg   bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
6397330f729Sjoerg                               const Matcher<NamedDecl> &Base,
6407330f729Sjoerg                               BoundNodesTreeBuilder *Builder,
6417330f729Sjoerg                               bool Directly) override;
6427330f729Sjoerg 
6437330f729Sjoerg   // Implements ASTMatchFinder::matchesChildOf.
matchesChildOf(const DynTypedNode & Node,ASTContext & Ctx,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,BindKind Bind)644*e038c9c4Sjoerg   bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
6457330f729Sjoerg                       const DynTypedMatcher &Matcher,
646*e038c9c4Sjoerg                       BoundNodesTreeBuilder *Builder, BindKind Bind) override {
6477330f729Sjoerg     if (ResultCache.size() > MaxMemoizationEntries)
6487330f729Sjoerg       ResultCache.clear();
649*e038c9c4Sjoerg     return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, Bind);
6507330f729Sjoerg   }
6517330f729Sjoerg   // Implements ASTMatchFinder::matchesDescendantOf.
matchesDescendantOf(const DynTypedNode & Node,ASTContext & Ctx,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,BindKind Bind)652*e038c9c4Sjoerg   bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
6537330f729Sjoerg                            const DynTypedMatcher &Matcher,
6547330f729Sjoerg                            BoundNodesTreeBuilder *Builder,
6557330f729Sjoerg                            BindKind Bind) override {
6567330f729Sjoerg     if (ResultCache.size() > MaxMemoizationEntries)
6577330f729Sjoerg       ResultCache.clear();
658*e038c9c4Sjoerg     return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, INT_MAX,
6597330f729Sjoerg                                       Bind);
6607330f729Sjoerg   }
6617330f729Sjoerg   // Implements ASTMatchFinder::matchesAncestorOf.
matchesAncestorOf(const DynTypedNode & Node,ASTContext & Ctx,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,AncestorMatchMode MatchMode)662*e038c9c4Sjoerg   bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
6637330f729Sjoerg                          const DynTypedMatcher &Matcher,
6647330f729Sjoerg                          BoundNodesTreeBuilder *Builder,
6657330f729Sjoerg                          AncestorMatchMode MatchMode) override {
6667330f729Sjoerg     // Reset the cache outside of the recursive call to make sure we
6677330f729Sjoerg     // don't invalidate any iterators.
6687330f729Sjoerg     if (ResultCache.size() > MaxMemoizationEntries)
6697330f729Sjoerg       ResultCache.clear();
670*e038c9c4Sjoerg     if (MatchMode == AncestorMatchMode::AMM_ParentOnly)
671*e038c9c4Sjoerg       return matchesParentOf(Node, Matcher, Builder);
672*e038c9c4Sjoerg     return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
6737330f729Sjoerg   }
6747330f729Sjoerg 
6757330f729Sjoerg   // Matches all registered matchers on the given node and calls the
6767330f729Sjoerg   // result callback for every node that matches.
match(const DynTypedNode & Node)677*e038c9c4Sjoerg   void match(const DynTypedNode &Node) {
6787330f729Sjoerg     // FIXME: Improve this with a switch or a visitor pattern.
6797330f729Sjoerg     if (auto *N = Node.get<Decl>()) {
6807330f729Sjoerg       match(*N);
6817330f729Sjoerg     } else if (auto *N = Node.get<Stmt>()) {
6827330f729Sjoerg       match(*N);
6837330f729Sjoerg     } else if (auto *N = Node.get<Type>()) {
6847330f729Sjoerg       match(*N);
6857330f729Sjoerg     } else if (auto *N = Node.get<QualType>()) {
6867330f729Sjoerg       match(*N);
6877330f729Sjoerg     } else if (auto *N = Node.get<NestedNameSpecifier>()) {
6887330f729Sjoerg       match(*N);
6897330f729Sjoerg     } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
6907330f729Sjoerg       match(*N);
6917330f729Sjoerg     } else if (auto *N = Node.get<TypeLoc>()) {
6927330f729Sjoerg       match(*N);
6937330f729Sjoerg     } else if (auto *N = Node.get<CXXCtorInitializer>()) {
6947330f729Sjoerg       match(*N);
695*e038c9c4Sjoerg     } else if (auto *N = Node.get<TemplateArgumentLoc>()) {
696*e038c9c4Sjoerg       match(*N);
6977330f729Sjoerg     }
6987330f729Sjoerg   }
6997330f729Sjoerg 
match(const T & Node)7007330f729Sjoerg   template <typename T> void match(const T &Node) {
7017330f729Sjoerg     matchDispatch(&Node);
7027330f729Sjoerg   }
7037330f729Sjoerg 
7047330f729Sjoerg   // Implements ASTMatchFinder::getASTContext.
getASTContext() const7057330f729Sjoerg   ASTContext &getASTContext() const override { return *ActiveASTContext; }
7067330f729Sjoerg 
shouldVisitTemplateInstantiations() const7077330f729Sjoerg   bool shouldVisitTemplateInstantiations() const { return true; }
shouldVisitImplicitCode() const7087330f729Sjoerg   bool shouldVisitImplicitCode() const { return true; }
7097330f729Sjoerg 
710*e038c9c4Sjoerg   // We visit the lambda body explicitly, so instruct the RAV
711*e038c9c4Sjoerg   // to not visit it on our behalf too.
shouldVisitLambdaBody() const712*e038c9c4Sjoerg   bool shouldVisitLambdaBody() const { return false; }
713*e038c9c4Sjoerg 
IsMatchingInASTNodeNotSpelledInSource() const714*e038c9c4Sjoerg   bool IsMatchingInASTNodeNotSpelledInSource() const override {
715*e038c9c4Sjoerg     return TraversingASTNodeNotSpelledInSource;
716*e038c9c4Sjoerg   }
isMatchingChildrenNotSpelledInSource() const717*e038c9c4Sjoerg   bool isMatchingChildrenNotSpelledInSource() const override {
718*e038c9c4Sjoerg     return TraversingASTChildrenNotSpelledInSource;
719*e038c9c4Sjoerg   }
setMatchingChildrenNotSpelledInSource(bool Set)720*e038c9c4Sjoerg   void setMatchingChildrenNotSpelledInSource(bool Set) override {
721*e038c9c4Sjoerg     TraversingASTChildrenNotSpelledInSource = Set;
722*e038c9c4Sjoerg   }
723*e038c9c4Sjoerg 
IsMatchingInASTNodeNotAsIs() const724*e038c9c4Sjoerg   bool IsMatchingInASTNodeNotAsIs() const override {
725*e038c9c4Sjoerg     return TraversingASTNodeNotAsIs;
726*e038c9c4Sjoerg   }
727*e038c9c4Sjoerg 
TraverseTemplateInstantiations(ClassTemplateDecl * D)728*e038c9c4Sjoerg   bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
729*e038c9c4Sjoerg     ASTNodeNotSpelledInSourceScope RAII(this, true);
730*e038c9c4Sjoerg     return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
731*e038c9c4Sjoerg         D);
732*e038c9c4Sjoerg   }
733*e038c9c4Sjoerg 
TraverseTemplateInstantiations(VarTemplateDecl * D)734*e038c9c4Sjoerg   bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
735*e038c9c4Sjoerg     ASTNodeNotSpelledInSourceScope RAII(this, true);
736*e038c9c4Sjoerg     return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
737*e038c9c4Sjoerg         D);
738*e038c9c4Sjoerg   }
739*e038c9c4Sjoerg 
TraverseTemplateInstantiations(FunctionTemplateDecl * D)740*e038c9c4Sjoerg   bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
741*e038c9c4Sjoerg     ASTNodeNotSpelledInSourceScope RAII(this, true);
742*e038c9c4Sjoerg     return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
743*e038c9c4Sjoerg         D);
744*e038c9c4Sjoerg   }
745*e038c9c4Sjoerg 
7467330f729Sjoerg private:
747*e038c9c4Sjoerg   bool TraversingASTNodeNotSpelledInSource = false;
748*e038c9c4Sjoerg   bool TraversingASTNodeNotAsIs = false;
749*e038c9c4Sjoerg   bool TraversingASTChildrenNotSpelledInSource = false;
750*e038c9c4Sjoerg 
751*e038c9c4Sjoerg   struct ASTNodeNotSpelledInSourceScope {
ASTNodeNotSpelledInSourceScopeclang::ast_matchers::internal::__anon62d4f9200111::MatchASTVisitor::ASTNodeNotSpelledInSourceScope752*e038c9c4Sjoerg     ASTNodeNotSpelledInSourceScope(MatchASTVisitor *V, bool B)
753*e038c9c4Sjoerg         : MV(V), MB(V->TraversingASTNodeNotSpelledInSource) {
754*e038c9c4Sjoerg       V->TraversingASTNodeNotSpelledInSource = B;
755*e038c9c4Sjoerg     }
~ASTNodeNotSpelledInSourceScopeclang::ast_matchers::internal::__anon62d4f9200111::MatchASTVisitor::ASTNodeNotSpelledInSourceScope756*e038c9c4Sjoerg     ~ASTNodeNotSpelledInSourceScope() {
757*e038c9c4Sjoerg       MV->TraversingASTNodeNotSpelledInSource = MB;
758*e038c9c4Sjoerg     }
759*e038c9c4Sjoerg 
760*e038c9c4Sjoerg   private:
761*e038c9c4Sjoerg     MatchASTVisitor *MV;
762*e038c9c4Sjoerg     bool MB;
763*e038c9c4Sjoerg   };
764*e038c9c4Sjoerg 
765*e038c9c4Sjoerg   struct ASTNodeNotAsIsSourceScope {
ASTNodeNotAsIsSourceScopeclang::ast_matchers::internal::__anon62d4f9200111::MatchASTVisitor::ASTNodeNotAsIsSourceScope766*e038c9c4Sjoerg     ASTNodeNotAsIsSourceScope(MatchASTVisitor *V, bool B)
767*e038c9c4Sjoerg         : MV(V), MB(V->TraversingASTNodeNotAsIs) {
768*e038c9c4Sjoerg       V->TraversingASTNodeNotAsIs = B;
769*e038c9c4Sjoerg     }
~ASTNodeNotAsIsSourceScopeclang::ast_matchers::internal::__anon62d4f9200111::MatchASTVisitor::ASTNodeNotAsIsSourceScope770*e038c9c4Sjoerg     ~ASTNodeNotAsIsSourceScope() { MV->TraversingASTNodeNotAsIs = MB; }
771*e038c9c4Sjoerg 
772*e038c9c4Sjoerg   private:
773*e038c9c4Sjoerg     MatchASTVisitor *MV;
774*e038c9c4Sjoerg     bool MB;
775*e038c9c4Sjoerg   };
776*e038c9c4Sjoerg 
7777330f729Sjoerg   class TimeBucketRegion {
7787330f729Sjoerg   public:
TimeBucketRegion()7797330f729Sjoerg     TimeBucketRegion() : Bucket(nullptr) {}
~TimeBucketRegion()7807330f729Sjoerg     ~TimeBucketRegion() { setBucket(nullptr); }
7817330f729Sjoerg 
7827330f729Sjoerg     /// Start timing for \p NewBucket.
7837330f729Sjoerg     ///
7847330f729Sjoerg     /// If there was a bucket already set, it will finish the timing for that
7857330f729Sjoerg     /// other bucket.
7867330f729Sjoerg     /// \p NewBucket will be timed until the next call to \c setBucket() or
7877330f729Sjoerg     /// until the \c TimeBucketRegion is destroyed.
7887330f729Sjoerg     /// If \p NewBucket is the same as the currently timed bucket, this call
7897330f729Sjoerg     /// does nothing.
setBucket(llvm::TimeRecord * NewBucket)7907330f729Sjoerg     void setBucket(llvm::TimeRecord *NewBucket) {
7917330f729Sjoerg       if (Bucket != NewBucket) {
7927330f729Sjoerg         auto Now = llvm::TimeRecord::getCurrentTime(true);
7937330f729Sjoerg         if (Bucket)
7947330f729Sjoerg           *Bucket += Now;
7957330f729Sjoerg         if (NewBucket)
7967330f729Sjoerg           *NewBucket -= Now;
7977330f729Sjoerg         Bucket = NewBucket;
7987330f729Sjoerg       }
7997330f729Sjoerg     }
8007330f729Sjoerg 
8017330f729Sjoerg   private:
8027330f729Sjoerg     llvm::TimeRecord *Bucket;
8037330f729Sjoerg   };
8047330f729Sjoerg 
8057330f729Sjoerg   /// Runs all the \p Matchers on \p Node.
8067330f729Sjoerg   ///
8077330f729Sjoerg   /// Used by \c matchDispatch() below.
8087330f729Sjoerg   template <typename T, typename MC>
matchWithoutFilter(const T & Node,const MC & Matchers)8097330f729Sjoerg   void matchWithoutFilter(const T &Node, const MC &Matchers) {
8107330f729Sjoerg     const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
8117330f729Sjoerg     TimeBucketRegion Timer;
8127330f729Sjoerg     for (const auto &MP : Matchers) {
8137330f729Sjoerg       if (EnableCheckProfiling)
8147330f729Sjoerg         Timer.setBucket(&TimeByBucket[MP.second->getID()]);
8157330f729Sjoerg       BoundNodesTreeBuilder Builder;
8167330f729Sjoerg       if (MP.first.matches(Node, this, &Builder)) {
8177330f729Sjoerg         MatchVisitor Visitor(ActiveASTContext, MP.second);
8187330f729Sjoerg         Builder.visitMatches(&Visitor);
8197330f729Sjoerg       }
8207330f729Sjoerg     }
8217330f729Sjoerg   }
8227330f729Sjoerg 
matchWithFilter(const DynTypedNode & DynNode)823*e038c9c4Sjoerg   void matchWithFilter(const DynTypedNode &DynNode) {
8247330f729Sjoerg     auto Kind = DynNode.getNodeKind();
8257330f729Sjoerg     auto it = MatcherFiltersMap.find(Kind);
8267330f729Sjoerg     const auto &Filter =
8277330f729Sjoerg         it != MatcherFiltersMap.end() ? it->second : getFilterForKind(Kind);
8287330f729Sjoerg 
8297330f729Sjoerg     if (Filter.empty())
8307330f729Sjoerg       return;
8317330f729Sjoerg 
8327330f729Sjoerg     const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
8337330f729Sjoerg     TimeBucketRegion Timer;
8347330f729Sjoerg     auto &Matchers = this->Matchers->DeclOrStmt;
8357330f729Sjoerg     for (unsigned short I : Filter) {
8367330f729Sjoerg       auto &MP = Matchers[I];
8377330f729Sjoerg       if (EnableCheckProfiling)
8387330f729Sjoerg         Timer.setBucket(&TimeByBucket[MP.second->getID()]);
8397330f729Sjoerg       BoundNodesTreeBuilder Builder;
840*e038c9c4Sjoerg 
841*e038c9c4Sjoerg       {
842*e038c9c4Sjoerg         TraversalKindScope RAII(getASTContext(), MP.first.getTraversalKind());
843*e038c9c4Sjoerg         if (getASTContext().getParentMapContext().traverseIgnored(DynNode) !=
844*e038c9c4Sjoerg             DynNode)
845*e038c9c4Sjoerg           continue;
846*e038c9c4Sjoerg       }
847*e038c9c4Sjoerg 
848*e038c9c4Sjoerg       if (MP.first.matches(DynNode, this, &Builder)) {
8497330f729Sjoerg         MatchVisitor Visitor(ActiveASTContext, MP.second);
8507330f729Sjoerg         Builder.visitMatches(&Visitor);
8517330f729Sjoerg       }
8527330f729Sjoerg     }
8537330f729Sjoerg   }
8547330f729Sjoerg 
getFilterForKind(ASTNodeKind Kind)855*e038c9c4Sjoerg   const std::vector<unsigned short> &getFilterForKind(ASTNodeKind Kind) {
8567330f729Sjoerg     auto &Filter = MatcherFiltersMap[Kind];
8577330f729Sjoerg     auto &Matchers = this->Matchers->DeclOrStmt;
8587330f729Sjoerg     assert((Matchers.size() < USHRT_MAX) && "Too many matchers.");
8597330f729Sjoerg     for (unsigned I = 0, E = Matchers.size(); I != E; ++I) {
8607330f729Sjoerg       if (Matchers[I].first.canMatchNodesOfKind(Kind)) {
8617330f729Sjoerg         Filter.push_back(I);
8627330f729Sjoerg       }
8637330f729Sjoerg     }
8647330f729Sjoerg     return Filter;
8657330f729Sjoerg   }
8667330f729Sjoerg 
8677330f729Sjoerg   /// @{
8687330f729Sjoerg   /// Overloads to pair the different node types to their matchers.
matchDispatch(const Decl * Node)8697330f729Sjoerg   void matchDispatch(const Decl *Node) {
870*e038c9c4Sjoerg     return matchWithFilter(DynTypedNode::create(*Node));
8717330f729Sjoerg   }
matchDispatch(const Stmt * Node)8727330f729Sjoerg   void matchDispatch(const Stmt *Node) {
873*e038c9c4Sjoerg     return matchWithFilter(DynTypedNode::create(*Node));
8747330f729Sjoerg   }
8757330f729Sjoerg 
matchDispatch(const Type * Node)8767330f729Sjoerg   void matchDispatch(const Type *Node) {
8777330f729Sjoerg     matchWithoutFilter(QualType(Node, 0), Matchers->Type);
8787330f729Sjoerg   }
matchDispatch(const TypeLoc * Node)8797330f729Sjoerg   void matchDispatch(const TypeLoc *Node) {
8807330f729Sjoerg     matchWithoutFilter(*Node, Matchers->TypeLoc);
8817330f729Sjoerg   }
matchDispatch(const QualType * Node)8827330f729Sjoerg   void matchDispatch(const QualType *Node) {
8837330f729Sjoerg     matchWithoutFilter(*Node, Matchers->Type);
8847330f729Sjoerg   }
matchDispatch(const NestedNameSpecifier * Node)8857330f729Sjoerg   void matchDispatch(const NestedNameSpecifier *Node) {
8867330f729Sjoerg     matchWithoutFilter(*Node, Matchers->NestedNameSpecifier);
8877330f729Sjoerg   }
matchDispatch(const NestedNameSpecifierLoc * Node)8887330f729Sjoerg   void matchDispatch(const NestedNameSpecifierLoc *Node) {
8897330f729Sjoerg     matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
8907330f729Sjoerg   }
matchDispatch(const CXXCtorInitializer * Node)8917330f729Sjoerg   void matchDispatch(const CXXCtorInitializer *Node) {
8927330f729Sjoerg     matchWithoutFilter(*Node, Matchers->CtorInit);
8937330f729Sjoerg   }
matchDispatch(const TemplateArgumentLoc * Node)894*e038c9c4Sjoerg   void matchDispatch(const TemplateArgumentLoc *Node) {
895*e038c9c4Sjoerg     matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc);
896*e038c9c4Sjoerg   }
matchDispatch(const void *)8977330f729Sjoerg   void matchDispatch(const void *) { /* Do nothing. */ }
8987330f729Sjoerg   /// @}
8997330f729Sjoerg 
900*e038c9c4Sjoerg   // Returns whether a direct parent of \p Node matches \p Matcher.
901*e038c9c4Sjoerg   // Unlike matchesAnyAncestorOf there's no memoization: it doesn't save much.
matchesParentOf(const DynTypedNode & Node,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder)902*e038c9c4Sjoerg   bool matchesParentOf(const DynTypedNode &Node, const DynTypedMatcher &Matcher,
903*e038c9c4Sjoerg                        BoundNodesTreeBuilder *Builder) {
904*e038c9c4Sjoerg     for (const auto &Parent : ActiveASTContext->getParents(Node)) {
905*e038c9c4Sjoerg       BoundNodesTreeBuilder BuilderCopy = *Builder;
906*e038c9c4Sjoerg       if (Matcher.matches(Parent, this, &BuilderCopy)) {
907*e038c9c4Sjoerg         *Builder = std::move(BuilderCopy);
908*e038c9c4Sjoerg         return true;
909*e038c9c4Sjoerg       }
910*e038c9c4Sjoerg     }
911*e038c9c4Sjoerg     return false;
912*e038c9c4Sjoerg   }
913*e038c9c4Sjoerg 
9147330f729Sjoerg   // Returns whether an ancestor of \p Node matches \p Matcher.
9157330f729Sjoerg   //
916*e038c9c4Sjoerg   // The order of matching (which can lead to different nodes being bound in
9177330f729Sjoerg   // case there are multiple matches) is breadth first search.
9187330f729Sjoerg   //
9197330f729Sjoerg   // To allow memoization in the very common case of having deeply nested
9207330f729Sjoerg   // expressions inside a template function, we first walk up the AST, memoizing
9217330f729Sjoerg   // the result of the match along the way, as long as there is only a single
9227330f729Sjoerg   // parent.
9237330f729Sjoerg   //
9247330f729Sjoerg   // Once there are multiple parents, the breadth first search order does not
9257330f729Sjoerg   // allow simple memoization on the ancestors. Thus, we only memoize as long
9267330f729Sjoerg   // as there is a single parent.
927*e038c9c4Sjoerg   //
928*e038c9c4Sjoerg   // We avoid a recursive implementation to prevent excessive stack use on
929*e038c9c4Sjoerg   // very deep ASTs (similarly to RecursiveASTVisitor's data recursion).
matchesAnyAncestorOf(DynTypedNode Node,ASTContext & Ctx,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder)930*e038c9c4Sjoerg   bool matchesAnyAncestorOf(DynTypedNode Node, ASTContext &Ctx,
9317330f729Sjoerg                             const DynTypedMatcher &Matcher,
932*e038c9c4Sjoerg                             BoundNodesTreeBuilder *Builder) {
933*e038c9c4Sjoerg 
934*e038c9c4Sjoerg     // Memoization keys that can be updated with the result.
935*e038c9c4Sjoerg     // These are the memoizable nodes in the chain of unique parents, which
936*e038c9c4Sjoerg     // terminates when a node has multiple parents, or matches, or is the root.
937*e038c9c4Sjoerg     std::vector<MatchKey> Keys;
938*e038c9c4Sjoerg     // When returning, update the memoization cache.
939*e038c9c4Sjoerg     auto Finish = [&](bool Matched) {
940*e038c9c4Sjoerg       for (const auto &Key : Keys) {
941*e038c9c4Sjoerg         MemoizedMatchResult &CachedResult = ResultCache[Key];
942*e038c9c4Sjoerg         CachedResult.ResultOfMatch = Matched;
943*e038c9c4Sjoerg         CachedResult.Nodes = *Builder;
944*e038c9c4Sjoerg       }
945*e038c9c4Sjoerg       return Matched;
946*e038c9c4Sjoerg     };
947*e038c9c4Sjoerg 
948*e038c9c4Sjoerg     // Loop while there's a single parent and we want to attempt memoization.
949*e038c9c4Sjoerg     DynTypedNodeList Parents{ArrayRef<DynTypedNode>()}; // after loop: size != 1
950*e038c9c4Sjoerg     for (;;) {
951*e038c9c4Sjoerg       // A cache key only makes sense if memoization is possible.
952*e038c9c4Sjoerg       if (Builder->isComparable()) {
953*e038c9c4Sjoerg         Keys.emplace_back();
954*e038c9c4Sjoerg         Keys.back().MatcherID = Matcher.getID();
955*e038c9c4Sjoerg         Keys.back().Node = Node;
956*e038c9c4Sjoerg         Keys.back().BoundNodes = *Builder;
957*e038c9c4Sjoerg         Keys.back().Traversal = Ctx.getParentMapContext().getTraversalKind();
958*e038c9c4Sjoerg         Keys.back().Type = MatchType::Ancestors;
959*e038c9c4Sjoerg 
960*e038c9c4Sjoerg         // Check the cache.
961*e038c9c4Sjoerg         MemoizationMap::iterator I = ResultCache.find(Keys.back());
962*e038c9c4Sjoerg         if (I != ResultCache.end()) {
963*e038c9c4Sjoerg           Keys.pop_back(); // Don't populate the cache for the matching node!
964*e038c9c4Sjoerg           *Builder = I->second.Nodes;
965*e038c9c4Sjoerg           return Finish(I->second.ResultOfMatch);
966*e038c9c4Sjoerg         }
967*e038c9c4Sjoerg       }
968*e038c9c4Sjoerg 
969*e038c9c4Sjoerg       Parents = ActiveASTContext->getParents(Node);
970*e038c9c4Sjoerg       // Either no parents or multiple parents: leave chain+memoize mode and
971*e038c9c4Sjoerg       // enter bfs+forgetful mode.
972*e038c9c4Sjoerg       if (Parents.size() != 1)
973*e038c9c4Sjoerg         break;
974*e038c9c4Sjoerg 
975*e038c9c4Sjoerg       // Check the next parent.
976*e038c9c4Sjoerg       Node = *Parents.begin();
977*e038c9c4Sjoerg       BoundNodesTreeBuilder BuilderCopy = *Builder;
978*e038c9c4Sjoerg       if (Matcher.matches(Node, this, &BuilderCopy)) {
979*e038c9c4Sjoerg         *Builder = std::move(BuilderCopy);
980*e038c9c4Sjoerg         return Finish(true);
981*e038c9c4Sjoerg       }
982*e038c9c4Sjoerg     }
983*e038c9c4Sjoerg     // We reached the end of the chain.
984*e038c9c4Sjoerg 
9857330f729Sjoerg     if (Parents.empty()) {
9867330f729Sjoerg       // Nodes may have no parents if:
9877330f729Sjoerg       //  a) the node is the TranslationUnitDecl
9887330f729Sjoerg       //  b) we have a limited traversal scope that excludes the parent edges
9897330f729Sjoerg       //  c) there is a bug in the AST, and the node is not reachable
9907330f729Sjoerg       // Usually the traversal scope is the whole AST, which precludes b.
9917330f729Sjoerg       // Bugs are common enough that it's worthwhile asserting when we can.
9927330f729Sjoerg #ifndef NDEBUG
9937330f729Sjoerg       if (!Node.get<TranslationUnitDecl>() &&
9947330f729Sjoerg           /* Traversal scope is full AST if any of the bounds are the TU */
9957330f729Sjoerg           llvm::any_of(ActiveASTContext->getTraversalScope(), [](Decl *D) {
9967330f729Sjoerg             return D->getKind() == Decl::TranslationUnit;
9977330f729Sjoerg           })) {
9987330f729Sjoerg         llvm::errs() << "Tried to match orphan node:\n";
999*e038c9c4Sjoerg         Node.dump(llvm::errs(), *ActiveASTContext);
10007330f729Sjoerg         llvm_unreachable("Parent map should be complete!");
10017330f729Sjoerg       }
10027330f729Sjoerg #endif
10037330f729Sjoerg     } else {
1004*e038c9c4Sjoerg       assert(Parents.size() > 1);
1005*e038c9c4Sjoerg       // BFS starting from the parents not yet considered.
1006*e038c9c4Sjoerg       // Memoization of newly visited nodes is not possible (but we still update
1007*e038c9c4Sjoerg       // results for the elements in the chain we found above).
1008*e038c9c4Sjoerg       std::deque<DynTypedNode> Queue(Parents.begin(), Parents.end());
10097330f729Sjoerg       llvm::DenseSet<const void *> Visited;
10107330f729Sjoerg       while (!Queue.empty()) {
10117330f729Sjoerg         BoundNodesTreeBuilder BuilderCopy = *Builder;
10127330f729Sjoerg         if (Matcher.matches(Queue.front(), this, &BuilderCopy)) {
10137330f729Sjoerg           *Builder = std::move(BuilderCopy);
1014*e038c9c4Sjoerg           return Finish(true);
10157330f729Sjoerg         }
1016*e038c9c4Sjoerg         for (const auto &Parent : ActiveASTContext->getParents(Queue.front())) {
10177330f729Sjoerg           // Make sure we do not visit the same node twice.
10187330f729Sjoerg           // Otherwise, we'll visit the common ancestors as often as there
10197330f729Sjoerg           // are splits on the way down.
10207330f729Sjoerg           if (Visited.insert(Parent.getMemoizationData()).second)
10217330f729Sjoerg             Queue.push_back(Parent);
10227330f729Sjoerg         }
10237330f729Sjoerg         Queue.pop_front();
10247330f729Sjoerg       }
10257330f729Sjoerg     }
1026*e038c9c4Sjoerg     return Finish(false);
10277330f729Sjoerg   }
10287330f729Sjoerg 
10297330f729Sjoerg   // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
10307330f729Sjoerg   // the aggregated bound nodes for each match.
10317330f729Sjoerg   class MatchVisitor : public BoundNodesTreeBuilder::Visitor {
10327330f729Sjoerg   public:
MatchVisitor(ASTContext * Context,MatchFinder::MatchCallback * Callback)10337330f729Sjoerg     MatchVisitor(ASTContext* Context,
10347330f729Sjoerg                  MatchFinder::MatchCallback* Callback)
10357330f729Sjoerg       : Context(Context),
10367330f729Sjoerg         Callback(Callback) {}
10377330f729Sjoerg 
visitMatch(const BoundNodes & BoundNodesView)10387330f729Sjoerg     void visitMatch(const BoundNodes& BoundNodesView) override {
1039*e038c9c4Sjoerg       TraversalKindScope RAII(*Context, Callback->getCheckTraversalKind());
10407330f729Sjoerg       Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
10417330f729Sjoerg     }
10427330f729Sjoerg 
10437330f729Sjoerg   private:
10447330f729Sjoerg     ASTContext* Context;
10457330f729Sjoerg     MatchFinder::MatchCallback* Callback;
10467330f729Sjoerg   };
10477330f729Sjoerg 
10487330f729Sjoerg   // Returns true if 'TypeNode' has an alias that matches the given matcher.
typeHasMatchingAlias(const Type * TypeNode,const Matcher<NamedDecl> & Matcher,BoundNodesTreeBuilder * Builder)10497330f729Sjoerg   bool typeHasMatchingAlias(const Type *TypeNode,
10507330f729Sjoerg                             const Matcher<NamedDecl> &Matcher,
10517330f729Sjoerg                             BoundNodesTreeBuilder *Builder) {
10527330f729Sjoerg     const Type *const CanonicalType =
10537330f729Sjoerg       ActiveASTContext->getCanonicalType(TypeNode);
10547330f729Sjoerg     auto Aliases = TypeAliases.find(CanonicalType);
10557330f729Sjoerg     if (Aliases == TypeAliases.end())
10567330f729Sjoerg       return false;
10577330f729Sjoerg     for (const TypedefNameDecl *Alias : Aliases->second) {
10587330f729Sjoerg       BoundNodesTreeBuilder Result(*Builder);
10597330f729Sjoerg       if (Matcher.matches(*Alias, this, &Result)) {
10607330f729Sjoerg         *Builder = std::move(Result);
10617330f729Sjoerg         return true;
10627330f729Sjoerg       }
10637330f729Sjoerg     }
10647330f729Sjoerg     return false;
10657330f729Sjoerg   }
10667330f729Sjoerg 
10677330f729Sjoerg   bool
objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl * InterfaceDecl,const Matcher<NamedDecl> & Matcher,BoundNodesTreeBuilder * Builder)10687330f729Sjoerg   objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl *InterfaceDecl,
10697330f729Sjoerg                                          const Matcher<NamedDecl> &Matcher,
10707330f729Sjoerg                                          BoundNodesTreeBuilder *Builder) {
10717330f729Sjoerg     auto Aliases = CompatibleAliases.find(InterfaceDecl);
10727330f729Sjoerg     if (Aliases == CompatibleAliases.end())
10737330f729Sjoerg       return false;
10747330f729Sjoerg     for (const ObjCCompatibleAliasDecl *Alias : Aliases->second) {
10757330f729Sjoerg       BoundNodesTreeBuilder Result(*Builder);
10767330f729Sjoerg       if (Matcher.matches(*Alias, this, &Result)) {
10777330f729Sjoerg         *Builder = std::move(Result);
10787330f729Sjoerg         return true;
10797330f729Sjoerg       }
10807330f729Sjoerg     }
10817330f729Sjoerg     return false;
10827330f729Sjoerg   }
10837330f729Sjoerg 
10847330f729Sjoerg   /// Bucket to record map.
10857330f729Sjoerg   ///
10867330f729Sjoerg   /// Used to get the appropriate bucket for each matcher.
10877330f729Sjoerg   llvm::StringMap<llvm::TimeRecord> TimeByBucket;
10887330f729Sjoerg 
10897330f729Sjoerg   const MatchFinder::MatchersByType *Matchers;
10907330f729Sjoerg 
10917330f729Sjoerg   /// Filtered list of matcher indices for each matcher kind.
10927330f729Sjoerg   ///
10937330f729Sjoerg   /// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
10947330f729Sjoerg   /// kind (and derived kinds) so it is a waste to try every matcher on every
10957330f729Sjoerg   /// node.
10967330f729Sjoerg   /// We precalculate a list of matchers that pass the toplevel restrict check.
1097*e038c9c4Sjoerg   llvm::DenseMap<ASTNodeKind, std::vector<unsigned short>> MatcherFiltersMap;
10987330f729Sjoerg 
10997330f729Sjoerg   const MatchFinder::MatchFinderOptions &Options;
11007330f729Sjoerg   ASTContext *ActiveASTContext;
11017330f729Sjoerg 
11027330f729Sjoerg   // Maps a canonical type to its TypedefDecls.
11037330f729Sjoerg   llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
11047330f729Sjoerg 
11057330f729Sjoerg   // Maps an Objective-C interface to its ObjCCompatibleAliasDecls.
11067330f729Sjoerg   llvm::DenseMap<const ObjCInterfaceDecl *,
11077330f729Sjoerg                  llvm::SmallPtrSet<const ObjCCompatibleAliasDecl *, 2>>
11087330f729Sjoerg       CompatibleAliases;
11097330f729Sjoerg 
11107330f729Sjoerg   // Maps (matcher, node) -> the match result for memoization.
11117330f729Sjoerg   typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
11127330f729Sjoerg   MemoizationMap ResultCache;
11137330f729Sjoerg };
11147330f729Sjoerg 
11157330f729Sjoerg static CXXRecordDecl *
getAsCXXRecordDeclOrPrimaryTemplate(const Type * TypeNode)11167330f729Sjoerg getAsCXXRecordDeclOrPrimaryTemplate(const Type *TypeNode) {
11177330f729Sjoerg   if (auto *RD = TypeNode->getAsCXXRecordDecl())
11187330f729Sjoerg     return RD;
11197330f729Sjoerg 
11207330f729Sjoerg   // Find the innermost TemplateSpecializationType that isn't an alias template.
11217330f729Sjoerg   auto *TemplateType = TypeNode->getAs<TemplateSpecializationType>();
11227330f729Sjoerg   while (TemplateType && TemplateType->isTypeAlias())
11237330f729Sjoerg     TemplateType =
11247330f729Sjoerg         TemplateType->getAliasedType()->getAs<TemplateSpecializationType>();
11257330f729Sjoerg 
11267330f729Sjoerg   // If this is the name of a (dependent) template specialization, use the
11277330f729Sjoerg   // definition of the template, even though it might be specialized later.
11287330f729Sjoerg   if (TemplateType)
11297330f729Sjoerg     if (auto *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(
11307330f729Sjoerg           TemplateType->getTemplateName().getAsTemplateDecl()))
11317330f729Sjoerg       return ClassTemplate->getTemplatedDecl();
11327330f729Sjoerg 
11337330f729Sjoerg   return nullptr;
11347330f729Sjoerg }
11357330f729Sjoerg 
11367330f729Sjoerg // Returns true if the given C++ class is directly or indirectly derived
11377330f729Sjoerg // from a base type with the given name.  A class is not considered to be
11387330f729Sjoerg // derived from itself.
classIsDerivedFrom(const CXXRecordDecl * Declaration,const Matcher<NamedDecl> & Base,BoundNodesTreeBuilder * Builder,bool Directly)11397330f729Sjoerg bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
11407330f729Sjoerg                                          const Matcher<NamedDecl> &Base,
11417330f729Sjoerg                                          BoundNodesTreeBuilder *Builder,
11427330f729Sjoerg                                          bool Directly) {
11437330f729Sjoerg   if (!Declaration->hasDefinition())
11447330f729Sjoerg     return false;
11457330f729Sjoerg   for (const auto &It : Declaration->bases()) {
11467330f729Sjoerg     const Type *TypeNode = It.getType().getTypePtr();
11477330f729Sjoerg 
11487330f729Sjoerg     if (typeHasMatchingAlias(TypeNode, Base, Builder))
11497330f729Sjoerg       return true;
11507330f729Sjoerg 
11517330f729Sjoerg     // FIXME: Going to the primary template here isn't really correct, but
11527330f729Sjoerg     // unfortunately we accept a Decl matcher for the base class not a Type
11537330f729Sjoerg     // matcher, so it's the best thing we can do with our current interface.
11547330f729Sjoerg     CXXRecordDecl *ClassDecl = getAsCXXRecordDeclOrPrimaryTemplate(TypeNode);
11557330f729Sjoerg     if (!ClassDecl)
11567330f729Sjoerg       continue;
11577330f729Sjoerg     if (ClassDecl == Declaration) {
1158*e038c9c4Sjoerg       // This can happen for recursive template definitions.
1159*e038c9c4Sjoerg       continue;
11607330f729Sjoerg     }
11617330f729Sjoerg     BoundNodesTreeBuilder Result(*Builder);
11627330f729Sjoerg     if (Base.matches(*ClassDecl, this, &Result)) {
11637330f729Sjoerg       *Builder = std::move(Result);
11647330f729Sjoerg       return true;
11657330f729Sjoerg     }
11667330f729Sjoerg     if (!Directly && classIsDerivedFrom(ClassDecl, Base, Builder, Directly))
11677330f729Sjoerg       return true;
11687330f729Sjoerg   }
11697330f729Sjoerg   return false;
11707330f729Sjoerg }
11717330f729Sjoerg 
11727330f729Sjoerg // Returns true if the given Objective-C class is directly or indirectly
11737330f729Sjoerg // derived from a matching base class. A class is not considered to be derived
11747330f729Sjoerg // from itself.
objcClassIsDerivedFrom(const ObjCInterfaceDecl * Declaration,const Matcher<NamedDecl> & Base,BoundNodesTreeBuilder * Builder,bool Directly)11757330f729Sjoerg bool MatchASTVisitor::objcClassIsDerivedFrom(
11767330f729Sjoerg     const ObjCInterfaceDecl *Declaration, const Matcher<NamedDecl> &Base,
11777330f729Sjoerg     BoundNodesTreeBuilder *Builder, bool Directly) {
11787330f729Sjoerg   // Check if any of the superclasses of the class match.
11797330f729Sjoerg   for (const ObjCInterfaceDecl *ClassDecl = Declaration->getSuperClass();
11807330f729Sjoerg        ClassDecl != nullptr; ClassDecl = ClassDecl->getSuperClass()) {
11817330f729Sjoerg     // Check if there are any matching compatibility aliases.
11827330f729Sjoerg     if (objcClassHasMatchingCompatibilityAlias(ClassDecl, Base, Builder))
11837330f729Sjoerg       return true;
11847330f729Sjoerg 
11857330f729Sjoerg     // Check if there are any matching type aliases.
11867330f729Sjoerg     const Type *TypeNode = ClassDecl->getTypeForDecl();
11877330f729Sjoerg     if (typeHasMatchingAlias(TypeNode, Base, Builder))
11887330f729Sjoerg       return true;
11897330f729Sjoerg 
11907330f729Sjoerg     if (Base.matches(*ClassDecl, this, Builder))
11917330f729Sjoerg       return true;
11927330f729Sjoerg 
1193*e038c9c4Sjoerg     // Not `return false` as a temporary workaround for PR43879.
11947330f729Sjoerg     if (Directly)
1195*e038c9c4Sjoerg       break;
11967330f729Sjoerg   }
11977330f729Sjoerg 
11987330f729Sjoerg   return false;
11997330f729Sjoerg }
12007330f729Sjoerg 
TraverseDecl(Decl * DeclNode)12017330f729Sjoerg bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
12027330f729Sjoerg   if (!DeclNode) {
12037330f729Sjoerg     return true;
12047330f729Sjoerg   }
1205*e038c9c4Sjoerg 
1206*e038c9c4Sjoerg   bool ScopedTraversal =
1207*e038c9c4Sjoerg       TraversingASTNodeNotSpelledInSource || DeclNode->isImplicit();
1208*e038c9c4Sjoerg   bool ScopedChildren = TraversingASTChildrenNotSpelledInSource;
1209*e038c9c4Sjoerg 
1210*e038c9c4Sjoerg   if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DeclNode)) {
1211*e038c9c4Sjoerg     auto SK = CTSD->getSpecializationKind();
1212*e038c9c4Sjoerg     if (SK == TSK_ExplicitInstantiationDeclaration ||
1213*e038c9c4Sjoerg         SK == TSK_ExplicitInstantiationDefinition)
1214*e038c9c4Sjoerg       ScopedChildren = true;
1215*e038c9c4Sjoerg   } else if (const auto *FD = dyn_cast<FunctionDecl>(DeclNode)) {
1216*e038c9c4Sjoerg     if (FD->isDefaulted())
1217*e038c9c4Sjoerg       ScopedChildren = true;
1218*e038c9c4Sjoerg     if (FD->isTemplateInstantiation())
1219*e038c9c4Sjoerg       ScopedTraversal = true;
1220*e038c9c4Sjoerg   } else if (isa<BindingDecl>(DeclNode)) {
1221*e038c9c4Sjoerg     ScopedChildren = true;
1222*e038c9c4Sjoerg   }
1223*e038c9c4Sjoerg 
1224*e038c9c4Sjoerg   ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
1225*e038c9c4Sjoerg   ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren);
1226*e038c9c4Sjoerg 
12277330f729Sjoerg   match(*DeclNode);
12287330f729Sjoerg   return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
12297330f729Sjoerg }
12307330f729Sjoerg 
TraverseStmt(Stmt * StmtNode,DataRecursionQueue * Queue)12317330f729Sjoerg bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
12327330f729Sjoerg   if (!StmtNode) {
12337330f729Sjoerg     return true;
12347330f729Sjoerg   }
1235*e038c9c4Sjoerg   bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
1236*e038c9c4Sjoerg                          TraversingASTChildrenNotSpelledInSource;
1237*e038c9c4Sjoerg 
1238*e038c9c4Sjoerg   ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
12397330f729Sjoerg   match(*StmtNode);
12407330f729Sjoerg   return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode, Queue);
12417330f729Sjoerg }
12427330f729Sjoerg 
TraverseType(QualType TypeNode)12437330f729Sjoerg bool MatchASTVisitor::TraverseType(QualType TypeNode) {
12447330f729Sjoerg   match(TypeNode);
12457330f729Sjoerg   return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
12467330f729Sjoerg }
12477330f729Sjoerg 
TraverseTypeLoc(TypeLoc TypeLocNode)12487330f729Sjoerg bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
12497330f729Sjoerg   // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
12507330f729Sjoerg   // We still want to find those types via matchers, so we match them here. Note
12517330f729Sjoerg   // that the TypeLocs are structurally a shadow-hierarchy to the expressed
12527330f729Sjoerg   // type, so we visit all involved parts of a compound type when matching on
12537330f729Sjoerg   // each TypeLoc.
12547330f729Sjoerg   match(TypeLocNode);
12557330f729Sjoerg   match(TypeLocNode.getType());
12567330f729Sjoerg   return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
12577330f729Sjoerg }
12587330f729Sjoerg 
TraverseNestedNameSpecifier(NestedNameSpecifier * NNS)12597330f729Sjoerg bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
12607330f729Sjoerg   match(*NNS);
12617330f729Sjoerg   return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
12627330f729Sjoerg }
12637330f729Sjoerg 
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)12647330f729Sjoerg bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
12657330f729Sjoerg     NestedNameSpecifierLoc NNS) {
12667330f729Sjoerg   if (!NNS)
12677330f729Sjoerg     return true;
12687330f729Sjoerg 
12697330f729Sjoerg   match(NNS);
12707330f729Sjoerg 
12717330f729Sjoerg   // We only match the nested name specifier here (as opposed to traversing it)
12727330f729Sjoerg   // because the traversal is already done in the parallel "Loc"-hierarchy.
12737330f729Sjoerg   if (NNS.hasQualifier())
12747330f729Sjoerg     match(*NNS.getNestedNameSpecifier());
12757330f729Sjoerg   return
12767330f729Sjoerg       RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
12777330f729Sjoerg }
12787330f729Sjoerg 
TraverseConstructorInitializer(CXXCtorInitializer * CtorInit)12797330f729Sjoerg bool MatchASTVisitor::TraverseConstructorInitializer(
12807330f729Sjoerg     CXXCtorInitializer *CtorInit) {
12817330f729Sjoerg   if (!CtorInit)
12827330f729Sjoerg     return true;
12837330f729Sjoerg 
1284*e038c9c4Sjoerg   bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
1285*e038c9c4Sjoerg                          TraversingASTChildrenNotSpelledInSource;
1286*e038c9c4Sjoerg 
1287*e038c9c4Sjoerg   if (!CtorInit->isWritten())
1288*e038c9c4Sjoerg     ScopedTraversal = true;
1289*e038c9c4Sjoerg 
1290*e038c9c4Sjoerg   ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
1291*e038c9c4Sjoerg 
12927330f729Sjoerg   match(*CtorInit);
12937330f729Sjoerg 
12947330f729Sjoerg   return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
12957330f729Sjoerg       CtorInit);
12967330f729Sjoerg }
12977330f729Sjoerg 
TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc)1298*e038c9c4Sjoerg bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
1299*e038c9c4Sjoerg   match(Loc);
1300*e038c9c4Sjoerg   return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
1301*e038c9c4Sjoerg }
1302*e038c9c4Sjoerg 
13037330f729Sjoerg class MatchASTConsumer : public ASTConsumer {
13047330f729Sjoerg public:
MatchASTConsumer(MatchFinder * Finder,MatchFinder::ParsingDoneTestCallback * ParsingDone)13057330f729Sjoerg   MatchASTConsumer(MatchFinder *Finder,
13067330f729Sjoerg                    MatchFinder::ParsingDoneTestCallback *ParsingDone)
13077330f729Sjoerg       : Finder(Finder), ParsingDone(ParsingDone) {}
13087330f729Sjoerg 
13097330f729Sjoerg private:
HandleTranslationUnit(ASTContext & Context)13107330f729Sjoerg   void HandleTranslationUnit(ASTContext &Context) override {
13117330f729Sjoerg     if (ParsingDone != nullptr) {
13127330f729Sjoerg       ParsingDone->run();
13137330f729Sjoerg     }
13147330f729Sjoerg     Finder->matchAST(Context);
13157330f729Sjoerg   }
13167330f729Sjoerg 
13177330f729Sjoerg   MatchFinder *Finder;
13187330f729Sjoerg   MatchFinder::ParsingDoneTestCallback *ParsingDone;
13197330f729Sjoerg };
13207330f729Sjoerg 
13217330f729Sjoerg } // end namespace
13227330f729Sjoerg } // end namespace internal
13237330f729Sjoerg 
MatchResult(const BoundNodes & Nodes,ASTContext * Context)13247330f729Sjoerg MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes,
13257330f729Sjoerg                                       ASTContext *Context)
13267330f729Sjoerg   : Nodes(Nodes), Context(Context),
13277330f729Sjoerg     SourceManager(&Context->getSourceManager()) {}
13287330f729Sjoerg 
~MatchCallback()13297330f729Sjoerg MatchFinder::MatchCallback::~MatchCallback() {}
~ParsingDoneTestCallback()13307330f729Sjoerg MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
13317330f729Sjoerg 
MatchFinder(MatchFinderOptions Options)13327330f729Sjoerg MatchFinder::MatchFinder(MatchFinderOptions Options)
13337330f729Sjoerg     : Options(std::move(Options)), ParsingDone(nullptr) {}
13347330f729Sjoerg 
~MatchFinder()13357330f729Sjoerg MatchFinder::~MatchFinder() {}
13367330f729Sjoerg 
addMatcher(const DeclarationMatcher & NodeMatch,MatchCallback * Action)13377330f729Sjoerg void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
13387330f729Sjoerg                              MatchCallback *Action) {
1339*e038c9c4Sjoerg   llvm::Optional<TraversalKind> TK;
1340*e038c9c4Sjoerg   if (Action)
1341*e038c9c4Sjoerg     TK = Action->getCheckTraversalKind();
1342*e038c9c4Sjoerg   if (TK)
1343*e038c9c4Sjoerg     Matchers.DeclOrStmt.emplace_back(traverse(*TK, NodeMatch), Action);
1344*e038c9c4Sjoerg   else
13457330f729Sjoerg     Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
13467330f729Sjoerg   Matchers.AllCallbacks.insert(Action);
13477330f729Sjoerg }
13487330f729Sjoerg 
addMatcher(const TypeMatcher & NodeMatch,MatchCallback * Action)13497330f729Sjoerg void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
13507330f729Sjoerg                              MatchCallback *Action) {
13517330f729Sjoerg   Matchers.Type.emplace_back(NodeMatch, Action);
13527330f729Sjoerg   Matchers.AllCallbacks.insert(Action);
13537330f729Sjoerg }
13547330f729Sjoerg 
addMatcher(const StatementMatcher & NodeMatch,MatchCallback * Action)13557330f729Sjoerg void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
13567330f729Sjoerg                              MatchCallback *Action) {
1357*e038c9c4Sjoerg   llvm::Optional<TraversalKind> TK;
1358*e038c9c4Sjoerg   if (Action)
1359*e038c9c4Sjoerg     TK = Action->getCheckTraversalKind();
1360*e038c9c4Sjoerg   if (TK)
1361*e038c9c4Sjoerg     Matchers.DeclOrStmt.emplace_back(traverse(*TK, NodeMatch), Action);
1362*e038c9c4Sjoerg   else
13637330f729Sjoerg     Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
13647330f729Sjoerg   Matchers.AllCallbacks.insert(Action);
13657330f729Sjoerg }
13667330f729Sjoerg 
addMatcher(const NestedNameSpecifierMatcher & NodeMatch,MatchCallback * Action)13677330f729Sjoerg void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
13687330f729Sjoerg                              MatchCallback *Action) {
13697330f729Sjoerg   Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action);
13707330f729Sjoerg   Matchers.AllCallbacks.insert(Action);
13717330f729Sjoerg }
13727330f729Sjoerg 
addMatcher(const NestedNameSpecifierLocMatcher & NodeMatch,MatchCallback * Action)13737330f729Sjoerg void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
13747330f729Sjoerg                              MatchCallback *Action) {
13757330f729Sjoerg   Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action);
13767330f729Sjoerg   Matchers.AllCallbacks.insert(Action);
13777330f729Sjoerg }
13787330f729Sjoerg 
addMatcher(const TypeLocMatcher & NodeMatch,MatchCallback * Action)13797330f729Sjoerg void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
13807330f729Sjoerg                              MatchCallback *Action) {
13817330f729Sjoerg   Matchers.TypeLoc.emplace_back(NodeMatch, Action);
13827330f729Sjoerg   Matchers.AllCallbacks.insert(Action);
13837330f729Sjoerg }
13847330f729Sjoerg 
addMatcher(const CXXCtorInitializerMatcher & NodeMatch,MatchCallback * Action)13857330f729Sjoerg void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
13867330f729Sjoerg                              MatchCallback *Action) {
13877330f729Sjoerg   Matchers.CtorInit.emplace_back(NodeMatch, Action);
13887330f729Sjoerg   Matchers.AllCallbacks.insert(Action);
13897330f729Sjoerg }
13907330f729Sjoerg 
addMatcher(const TemplateArgumentLocMatcher & NodeMatch,MatchCallback * Action)1391*e038c9c4Sjoerg void MatchFinder::addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
1392*e038c9c4Sjoerg                              MatchCallback *Action) {
1393*e038c9c4Sjoerg   Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action);
1394*e038c9c4Sjoerg   Matchers.AllCallbacks.insert(Action);
1395*e038c9c4Sjoerg }
1396*e038c9c4Sjoerg 
addDynamicMatcher(const internal::DynTypedMatcher & NodeMatch,MatchCallback * Action)13977330f729Sjoerg bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
13987330f729Sjoerg                                     MatchCallback *Action) {
13997330f729Sjoerg   if (NodeMatch.canConvertTo<Decl>()) {
14007330f729Sjoerg     addMatcher(NodeMatch.convertTo<Decl>(), Action);
14017330f729Sjoerg     return true;
14027330f729Sjoerg   } else if (NodeMatch.canConvertTo<QualType>()) {
14037330f729Sjoerg     addMatcher(NodeMatch.convertTo<QualType>(), Action);
14047330f729Sjoerg     return true;
14057330f729Sjoerg   } else if (NodeMatch.canConvertTo<Stmt>()) {
14067330f729Sjoerg     addMatcher(NodeMatch.convertTo<Stmt>(), Action);
14077330f729Sjoerg     return true;
14087330f729Sjoerg   } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) {
14097330f729Sjoerg     addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action);
14107330f729Sjoerg     return true;
14117330f729Sjoerg   } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) {
14127330f729Sjoerg     addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action);
14137330f729Sjoerg     return true;
14147330f729Sjoerg   } else if (NodeMatch.canConvertTo<TypeLoc>()) {
14157330f729Sjoerg     addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
14167330f729Sjoerg     return true;
14177330f729Sjoerg   } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
14187330f729Sjoerg     addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
14197330f729Sjoerg     return true;
1420*e038c9c4Sjoerg   } else if (NodeMatch.canConvertTo<TemplateArgumentLoc>()) {
1421*e038c9c4Sjoerg     addMatcher(NodeMatch.convertTo<TemplateArgumentLoc>(), Action);
1422*e038c9c4Sjoerg     return true;
14237330f729Sjoerg   }
14247330f729Sjoerg   return false;
14257330f729Sjoerg }
14267330f729Sjoerg 
newASTConsumer()14277330f729Sjoerg std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
14287330f729Sjoerg   return std::make_unique<internal::MatchASTConsumer>(this, ParsingDone);
14297330f729Sjoerg }
14307330f729Sjoerg 
match(const clang::DynTypedNode & Node,ASTContext & Context)1431*e038c9c4Sjoerg void MatchFinder::match(const clang::DynTypedNode &Node, ASTContext &Context) {
14327330f729Sjoerg   internal::MatchASTVisitor Visitor(&Matchers, Options);
14337330f729Sjoerg   Visitor.set_active_ast_context(&Context);
14347330f729Sjoerg   Visitor.match(Node);
14357330f729Sjoerg }
14367330f729Sjoerg 
matchAST(ASTContext & Context)14377330f729Sjoerg void MatchFinder::matchAST(ASTContext &Context) {
14387330f729Sjoerg   internal::MatchASTVisitor Visitor(&Matchers, Options);
14397330f729Sjoerg   Visitor.set_active_ast_context(&Context);
14407330f729Sjoerg   Visitor.onStartOfTranslationUnit();
14417330f729Sjoerg   Visitor.TraverseAST(Context);
14427330f729Sjoerg   Visitor.onEndOfTranslationUnit();
14437330f729Sjoerg }
14447330f729Sjoerg 
registerTestCallbackAfterParsing(MatchFinder::ParsingDoneTestCallback * NewParsingDone)14457330f729Sjoerg void MatchFinder::registerTestCallbackAfterParsing(
14467330f729Sjoerg     MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
14477330f729Sjoerg   ParsingDone = NewParsingDone;
14487330f729Sjoerg }
14497330f729Sjoerg 
getID() const14507330f729Sjoerg StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
14517330f729Sjoerg 
1452*e038c9c4Sjoerg llvm::Optional<TraversalKind>
getCheckTraversalKind() const1453*e038c9c4Sjoerg MatchFinder::MatchCallback::getCheckTraversalKind() const {
1454*e038c9c4Sjoerg   return llvm::None;
1455*e038c9c4Sjoerg }
1456*e038c9c4Sjoerg 
14577330f729Sjoerg } // end namespace ast_matchers
14587330f729Sjoerg } // end namespace clang
1459