xref: /minix3/external/bsd/llvm/dist/clang/lib/ASTMatchers/ASTMatchFinder.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- ASTMatchFinder.cpp - Structural query framework ------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc //  Implements an algorithm to efficiently search for matches on AST nodes.
11f4a2713aSLionel Sambuc //  Uses memoization to support recursive matches like HasDescendant.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //  The general idea is to visit all AST nodes with a RecursiveASTVisitor,
14f4a2713aSLionel Sambuc //  calling the Matches(...) method of each matcher we are running on each
15f4a2713aSLionel Sambuc //  AST node. The matcher can recurse via the ASTMatchFinder interface.
16f4a2713aSLionel Sambuc //
17f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
18f4a2713aSLionel Sambuc 
19f4a2713aSLionel Sambuc #include "clang/ASTMatchers/ASTMatchFinder.h"
20f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h"
21f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
22f4a2713aSLionel Sambuc #include "clang/AST/RecursiveASTVisitor.h"
23*0a6a1f1dSLionel Sambuc #include "llvm/ADT/DenseMap.h"
24*0a6a1f1dSLionel Sambuc #include "llvm/ADT/StringMap.h"
25*0a6a1f1dSLionel Sambuc #include "llvm/Support/Timer.h"
26f4a2713aSLionel Sambuc #include <deque>
27*0a6a1f1dSLionel Sambuc #include <memory>
28f4a2713aSLionel Sambuc #include <set>
29f4a2713aSLionel Sambuc 
30f4a2713aSLionel Sambuc namespace clang {
31f4a2713aSLionel Sambuc namespace ast_matchers {
32f4a2713aSLionel Sambuc namespace internal {
33f4a2713aSLionel Sambuc namespace {
34f4a2713aSLionel Sambuc 
35f4a2713aSLionel Sambuc typedef MatchFinder::MatchCallback MatchCallback;
36f4a2713aSLionel Sambuc 
37f4a2713aSLionel Sambuc // The maximum number of memoization entries to store.
38f4a2713aSLionel Sambuc // 10k has been experimentally found to give a good trade-off
39f4a2713aSLionel Sambuc // of performance vs. memory consumption by running matcher
40f4a2713aSLionel Sambuc // that match on every statement over a very large codebase.
41f4a2713aSLionel Sambuc //
42f4a2713aSLionel Sambuc // FIXME: Do some performance optimization in general and
43f4a2713aSLionel Sambuc // revisit this number; also, put up micro-benchmarks that we can
44f4a2713aSLionel Sambuc // optimize this on.
45f4a2713aSLionel Sambuc static const unsigned MaxMemoizationEntries = 10000;
46f4a2713aSLionel Sambuc 
47f4a2713aSLionel Sambuc // We use memoization to avoid running the same matcher on the same
48f4a2713aSLionel Sambuc // AST node twice.  This struct is the key for looking up match
49f4a2713aSLionel Sambuc // result.  It consists of an ID of the MatcherInterface (for
50f4a2713aSLionel Sambuc // identifying the matcher), a pointer to the AST node and the
51f4a2713aSLionel Sambuc // bound nodes before the matcher was executed.
52f4a2713aSLionel Sambuc //
53f4a2713aSLionel Sambuc // We currently only memoize on nodes whose pointers identify the
54f4a2713aSLionel Sambuc // nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
55f4a2713aSLionel Sambuc // For \c QualType and \c TypeLoc it is possible to implement
56f4a2713aSLionel Sambuc // generation of keys for each type.
57f4a2713aSLionel Sambuc // FIXME: Benchmark whether memoization of non-pointer typed nodes
58f4a2713aSLionel Sambuc // provides enough benefit for the additional amount of code.
59f4a2713aSLionel Sambuc struct MatchKey {
60*0a6a1f1dSLionel Sambuc   DynTypedMatcher::MatcherIDType MatcherID;
61f4a2713aSLionel Sambuc   ast_type_traits::DynTypedNode Node;
62f4a2713aSLionel Sambuc   BoundNodesTreeBuilder BoundNodes;
63f4a2713aSLionel Sambuc 
operator <clang::ast_matchers::internal::__anon0cad00880111::MatchKey64f4a2713aSLionel Sambuc   bool operator<(const MatchKey &Other) const {
65*0a6a1f1dSLionel Sambuc     return std::tie(MatcherID, Node, BoundNodes) <
66*0a6a1f1dSLionel Sambuc            std::tie(Other.MatcherID, Other.Node, Other.BoundNodes);
67f4a2713aSLionel Sambuc   }
68f4a2713aSLionel Sambuc };
69f4a2713aSLionel Sambuc 
70f4a2713aSLionel Sambuc // Used to store the result of a match and possibly bound nodes.
71f4a2713aSLionel Sambuc struct MemoizedMatchResult {
72f4a2713aSLionel Sambuc   bool ResultOfMatch;
73f4a2713aSLionel Sambuc   BoundNodesTreeBuilder Nodes;
74f4a2713aSLionel Sambuc };
75f4a2713aSLionel Sambuc 
76f4a2713aSLionel Sambuc // A RecursiveASTVisitor that traverses all children or all descendants of
77f4a2713aSLionel Sambuc // a node.
78f4a2713aSLionel Sambuc class MatchChildASTVisitor
79f4a2713aSLionel Sambuc     : public RecursiveASTVisitor<MatchChildASTVisitor> {
80f4a2713aSLionel Sambuc public:
81f4a2713aSLionel Sambuc   typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
82f4a2713aSLionel Sambuc 
83f4a2713aSLionel Sambuc   // Creates an AST visitor that matches 'matcher' on all children or
84f4a2713aSLionel Sambuc   // descendants of a traversed node. max_depth is the maximum depth
85f4a2713aSLionel Sambuc   // to traverse: use 1 for matching the children and INT_MAX for
86f4a2713aSLionel Sambuc   // matching the descendants.
MatchChildASTVisitor(const DynTypedMatcher * Matcher,ASTMatchFinder * Finder,BoundNodesTreeBuilder * Builder,int MaxDepth,ASTMatchFinder::TraversalKind Traversal,ASTMatchFinder::BindKind Bind)87f4a2713aSLionel Sambuc   MatchChildASTVisitor(const DynTypedMatcher *Matcher,
88f4a2713aSLionel Sambuc                        ASTMatchFinder *Finder,
89f4a2713aSLionel Sambuc                        BoundNodesTreeBuilder *Builder,
90f4a2713aSLionel Sambuc                        int MaxDepth,
91f4a2713aSLionel Sambuc                        ASTMatchFinder::TraversalKind Traversal,
92f4a2713aSLionel Sambuc                        ASTMatchFinder::BindKind Bind)
93f4a2713aSLionel Sambuc       : Matcher(Matcher),
94f4a2713aSLionel Sambuc         Finder(Finder),
95f4a2713aSLionel Sambuc         Builder(Builder),
96f4a2713aSLionel Sambuc         CurrentDepth(0),
97f4a2713aSLionel Sambuc         MaxDepth(MaxDepth),
98f4a2713aSLionel Sambuc         Traversal(Traversal),
99f4a2713aSLionel Sambuc         Bind(Bind),
100f4a2713aSLionel Sambuc         Matches(false) {}
101f4a2713aSLionel Sambuc 
102f4a2713aSLionel Sambuc   // Returns true if a match is found in the subtree rooted at the
103f4a2713aSLionel Sambuc   // given AST node. This is done via a set of mutually recursive
104f4a2713aSLionel Sambuc   // functions. Here's how the recursion is done (the  *wildcard can
105f4a2713aSLionel Sambuc   // actually be Decl, Stmt, or Type):
106f4a2713aSLionel Sambuc   //
107f4a2713aSLionel Sambuc   //   - Traverse(node) calls BaseTraverse(node) when it needs
108f4a2713aSLionel Sambuc   //     to visit the descendants of node.
109f4a2713aSLionel Sambuc   //   - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
110f4a2713aSLionel Sambuc   //     Traverse*(c) for each child c of 'node'.
111f4a2713aSLionel Sambuc   //   - Traverse*(c) in turn calls Traverse(c), completing the
112f4a2713aSLionel Sambuc   //     recursion.
findMatch(const ast_type_traits::DynTypedNode & DynNode)113f4a2713aSLionel Sambuc   bool findMatch(const ast_type_traits::DynTypedNode &DynNode) {
114f4a2713aSLionel Sambuc     reset();
115f4a2713aSLionel Sambuc     if (const Decl *D = DynNode.get<Decl>())
116f4a2713aSLionel Sambuc       traverse(*D);
117f4a2713aSLionel Sambuc     else if (const Stmt *S = DynNode.get<Stmt>())
118f4a2713aSLionel Sambuc       traverse(*S);
119f4a2713aSLionel Sambuc     else if (const NestedNameSpecifier *NNS =
120f4a2713aSLionel Sambuc              DynNode.get<NestedNameSpecifier>())
121f4a2713aSLionel Sambuc       traverse(*NNS);
122f4a2713aSLionel Sambuc     else if (const NestedNameSpecifierLoc *NNSLoc =
123f4a2713aSLionel Sambuc              DynNode.get<NestedNameSpecifierLoc>())
124f4a2713aSLionel Sambuc       traverse(*NNSLoc);
125f4a2713aSLionel Sambuc     else if (const QualType *Q = DynNode.get<QualType>())
126f4a2713aSLionel Sambuc       traverse(*Q);
127f4a2713aSLionel Sambuc     else if (const TypeLoc *T = DynNode.get<TypeLoc>())
128f4a2713aSLionel Sambuc       traverse(*T);
129f4a2713aSLionel Sambuc     // FIXME: Add other base types after adding tests.
130f4a2713aSLionel Sambuc 
131f4a2713aSLionel Sambuc     // It's OK to always overwrite the bound nodes, as if there was
132f4a2713aSLionel Sambuc     // no match in this recursive branch, the result set is empty
133f4a2713aSLionel Sambuc     // anyway.
134f4a2713aSLionel Sambuc     *Builder = ResultBindings;
135f4a2713aSLionel Sambuc 
136f4a2713aSLionel Sambuc     return Matches;
137f4a2713aSLionel Sambuc   }
138f4a2713aSLionel Sambuc 
139f4a2713aSLionel Sambuc   // The following are overriding methods from the base visitor class.
140f4a2713aSLionel Sambuc   // They are public only to allow CRTP to work. They are *not *part
141f4a2713aSLionel Sambuc   // of the public API of this class.
TraverseDecl(Decl * DeclNode)142f4a2713aSLionel Sambuc   bool TraverseDecl(Decl *DeclNode) {
143f4a2713aSLionel Sambuc     ScopedIncrement ScopedDepth(&CurrentDepth);
144*0a6a1f1dSLionel Sambuc     return (DeclNode == nullptr) || traverse(*DeclNode);
145f4a2713aSLionel Sambuc   }
TraverseStmt(Stmt * StmtNode)146f4a2713aSLionel Sambuc   bool TraverseStmt(Stmt *StmtNode) {
147f4a2713aSLionel Sambuc     ScopedIncrement ScopedDepth(&CurrentDepth);
148f4a2713aSLionel Sambuc     const Stmt *StmtToTraverse = StmtNode;
149f4a2713aSLionel Sambuc     if (Traversal ==
150f4a2713aSLionel Sambuc         ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) {
151f4a2713aSLionel Sambuc       const Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode);
152*0a6a1f1dSLionel Sambuc       if (ExprNode) {
153f4a2713aSLionel Sambuc         StmtToTraverse = ExprNode->IgnoreParenImpCasts();
154f4a2713aSLionel Sambuc       }
155f4a2713aSLionel Sambuc     }
156*0a6a1f1dSLionel Sambuc     return (StmtToTraverse == nullptr) || traverse(*StmtToTraverse);
157f4a2713aSLionel Sambuc   }
158f4a2713aSLionel Sambuc   // We assume that the QualType and the contained type are on the same
159f4a2713aSLionel Sambuc   // hierarchy level. Thus, we try to match either of them.
TraverseType(QualType TypeNode)160f4a2713aSLionel Sambuc   bool TraverseType(QualType TypeNode) {
161f4a2713aSLionel Sambuc     if (TypeNode.isNull())
162f4a2713aSLionel Sambuc       return true;
163f4a2713aSLionel Sambuc     ScopedIncrement ScopedDepth(&CurrentDepth);
164f4a2713aSLionel Sambuc     // Match the Type.
165f4a2713aSLionel Sambuc     if (!match(*TypeNode))
166f4a2713aSLionel Sambuc       return false;
167f4a2713aSLionel Sambuc     // The QualType is matched inside traverse.
168f4a2713aSLionel Sambuc     return traverse(TypeNode);
169f4a2713aSLionel Sambuc   }
170f4a2713aSLionel Sambuc   // We assume that the TypeLoc, contained QualType and contained Type all are
171f4a2713aSLionel Sambuc   // on the same hierarchy level. Thus, we try to match all of them.
TraverseTypeLoc(TypeLoc TypeLocNode)172f4a2713aSLionel Sambuc   bool TraverseTypeLoc(TypeLoc TypeLocNode) {
173f4a2713aSLionel Sambuc     if (TypeLocNode.isNull())
174f4a2713aSLionel Sambuc       return true;
175f4a2713aSLionel Sambuc     ScopedIncrement ScopedDepth(&CurrentDepth);
176f4a2713aSLionel Sambuc     // Match the Type.
177f4a2713aSLionel Sambuc     if (!match(*TypeLocNode.getType()))
178f4a2713aSLionel Sambuc       return false;
179f4a2713aSLionel Sambuc     // Match the QualType.
180f4a2713aSLionel Sambuc     if (!match(TypeLocNode.getType()))
181f4a2713aSLionel Sambuc       return false;
182f4a2713aSLionel Sambuc     // The TypeLoc is matched inside traverse.
183f4a2713aSLionel Sambuc     return traverse(TypeLocNode);
184f4a2713aSLionel Sambuc   }
TraverseNestedNameSpecifier(NestedNameSpecifier * NNS)185f4a2713aSLionel Sambuc   bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
186f4a2713aSLionel Sambuc     ScopedIncrement ScopedDepth(&CurrentDepth);
187*0a6a1f1dSLionel Sambuc     return (NNS == nullptr) || traverse(*NNS);
188f4a2713aSLionel Sambuc   }
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)189f4a2713aSLionel Sambuc   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
190f4a2713aSLionel Sambuc     if (!NNS)
191f4a2713aSLionel Sambuc       return true;
192f4a2713aSLionel Sambuc     ScopedIncrement ScopedDepth(&CurrentDepth);
193f4a2713aSLionel Sambuc     if (!match(*NNS.getNestedNameSpecifier()))
194f4a2713aSLionel Sambuc       return false;
195f4a2713aSLionel Sambuc     return traverse(NNS);
196f4a2713aSLionel Sambuc   }
197f4a2713aSLionel Sambuc 
shouldVisitTemplateInstantiations() const198f4a2713aSLionel Sambuc   bool shouldVisitTemplateInstantiations() const { return true; }
shouldVisitImplicitCode() const199f4a2713aSLionel Sambuc   bool shouldVisitImplicitCode() const { return true; }
200f4a2713aSLionel Sambuc   // Disables data recursion. We intercept Traverse* methods in the RAV, which
201f4a2713aSLionel Sambuc   // are not triggered during data recursion.
shouldUseDataRecursionFor(clang::Stmt * S) const202f4a2713aSLionel Sambuc   bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
203f4a2713aSLionel Sambuc 
204f4a2713aSLionel Sambuc private:
205f4a2713aSLionel Sambuc   // Used for updating the depth during traversal.
206f4a2713aSLionel Sambuc   struct ScopedIncrement {
ScopedIncrementclang::ast_matchers::internal::__anon0cad00880111::MatchChildASTVisitor::ScopedIncrement207f4a2713aSLionel Sambuc     explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
~ScopedIncrementclang::ast_matchers::internal::__anon0cad00880111::MatchChildASTVisitor::ScopedIncrement208f4a2713aSLionel Sambuc     ~ScopedIncrement() { --(*Depth); }
209f4a2713aSLionel Sambuc 
210f4a2713aSLionel Sambuc    private:
211f4a2713aSLionel Sambuc     int *Depth;
212f4a2713aSLionel Sambuc   };
213f4a2713aSLionel Sambuc 
214f4a2713aSLionel Sambuc   // Resets the state of this object.
reset()215f4a2713aSLionel Sambuc   void reset() {
216f4a2713aSLionel Sambuc     Matches = false;
217f4a2713aSLionel Sambuc     CurrentDepth = 0;
218f4a2713aSLionel Sambuc   }
219f4a2713aSLionel Sambuc 
220f4a2713aSLionel Sambuc   // Forwards the call to the corresponding Traverse*() method in the
221f4a2713aSLionel Sambuc   // base visitor class.
baseTraverse(const Decl & DeclNode)222f4a2713aSLionel Sambuc   bool baseTraverse(const Decl &DeclNode) {
223f4a2713aSLionel Sambuc     return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
224f4a2713aSLionel Sambuc   }
baseTraverse(const Stmt & StmtNode)225f4a2713aSLionel Sambuc   bool baseTraverse(const Stmt &StmtNode) {
226f4a2713aSLionel Sambuc     return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
227f4a2713aSLionel Sambuc   }
baseTraverse(QualType TypeNode)228f4a2713aSLionel Sambuc   bool baseTraverse(QualType TypeNode) {
229f4a2713aSLionel Sambuc     return VisitorBase::TraverseType(TypeNode);
230f4a2713aSLionel Sambuc   }
baseTraverse(TypeLoc TypeLocNode)231f4a2713aSLionel Sambuc   bool baseTraverse(TypeLoc TypeLocNode) {
232f4a2713aSLionel Sambuc     return VisitorBase::TraverseTypeLoc(TypeLocNode);
233f4a2713aSLionel Sambuc   }
baseTraverse(const NestedNameSpecifier & NNS)234f4a2713aSLionel Sambuc   bool baseTraverse(const NestedNameSpecifier &NNS) {
235f4a2713aSLionel Sambuc     return VisitorBase::TraverseNestedNameSpecifier(
236f4a2713aSLionel Sambuc         const_cast<NestedNameSpecifier*>(&NNS));
237f4a2713aSLionel Sambuc   }
baseTraverse(NestedNameSpecifierLoc NNS)238f4a2713aSLionel Sambuc   bool baseTraverse(NestedNameSpecifierLoc NNS) {
239f4a2713aSLionel Sambuc     return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
240f4a2713aSLionel Sambuc   }
241f4a2713aSLionel Sambuc 
242f4a2713aSLionel Sambuc   // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
243f4a2713aSLionel Sambuc   //   0 < CurrentDepth <= MaxDepth.
244f4a2713aSLionel Sambuc   //
245f4a2713aSLionel Sambuc   // Returns 'true' if traversal should continue after this function
246f4a2713aSLionel Sambuc   // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
247f4a2713aSLionel Sambuc   template <typename T>
match(const T & Node)248f4a2713aSLionel Sambuc   bool match(const T &Node) {
249f4a2713aSLionel Sambuc     if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
250f4a2713aSLionel Sambuc       return true;
251f4a2713aSLionel Sambuc     }
252f4a2713aSLionel Sambuc     if (Bind != ASTMatchFinder::BK_All) {
253f4a2713aSLionel Sambuc       BoundNodesTreeBuilder RecursiveBuilder(*Builder);
254f4a2713aSLionel Sambuc       if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
255f4a2713aSLionel Sambuc                            &RecursiveBuilder)) {
256f4a2713aSLionel Sambuc         Matches = true;
257f4a2713aSLionel Sambuc         ResultBindings.addMatch(RecursiveBuilder);
258f4a2713aSLionel Sambuc         return false; // Abort as soon as a match is found.
259f4a2713aSLionel Sambuc       }
260f4a2713aSLionel Sambuc     } else {
261f4a2713aSLionel Sambuc       BoundNodesTreeBuilder RecursiveBuilder(*Builder);
262f4a2713aSLionel Sambuc       if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
263f4a2713aSLionel Sambuc                            &RecursiveBuilder)) {
264f4a2713aSLionel Sambuc         // After the first match the matcher succeeds.
265f4a2713aSLionel Sambuc         Matches = true;
266f4a2713aSLionel Sambuc         ResultBindings.addMatch(RecursiveBuilder);
267f4a2713aSLionel Sambuc       }
268f4a2713aSLionel Sambuc     }
269f4a2713aSLionel Sambuc     return true;
270f4a2713aSLionel Sambuc   }
271f4a2713aSLionel Sambuc 
272f4a2713aSLionel Sambuc   // Traverses the subtree rooted at 'Node'; returns true if the
273f4a2713aSLionel Sambuc   // traversal should continue after this function returns.
274f4a2713aSLionel Sambuc   template <typename T>
traverse(const T & Node)275f4a2713aSLionel Sambuc   bool traverse(const T &Node) {
276*0a6a1f1dSLionel Sambuc     static_assert(IsBaseType<T>::value,
277*0a6a1f1dSLionel Sambuc                   "traverse can only be instantiated with base type");
278f4a2713aSLionel Sambuc     if (!match(Node))
279f4a2713aSLionel Sambuc       return false;
280f4a2713aSLionel Sambuc     return baseTraverse(Node);
281f4a2713aSLionel Sambuc   }
282f4a2713aSLionel Sambuc 
283f4a2713aSLionel Sambuc   const DynTypedMatcher *const Matcher;
284f4a2713aSLionel Sambuc   ASTMatchFinder *const Finder;
285f4a2713aSLionel Sambuc   BoundNodesTreeBuilder *const Builder;
286f4a2713aSLionel Sambuc   BoundNodesTreeBuilder ResultBindings;
287f4a2713aSLionel Sambuc   int CurrentDepth;
288f4a2713aSLionel Sambuc   const int MaxDepth;
289f4a2713aSLionel Sambuc   const ASTMatchFinder::TraversalKind Traversal;
290f4a2713aSLionel Sambuc   const ASTMatchFinder::BindKind Bind;
291f4a2713aSLionel Sambuc   bool Matches;
292f4a2713aSLionel Sambuc };
293f4a2713aSLionel Sambuc 
294f4a2713aSLionel Sambuc // Controls the outermost traversal of the AST and allows to match multiple
295f4a2713aSLionel Sambuc // matchers.
296f4a2713aSLionel Sambuc class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
297f4a2713aSLionel Sambuc                         public ASTMatchFinder {
298f4a2713aSLionel Sambuc public:
MatchASTVisitor(const MatchFinder::MatchersByType * Matchers,const MatchFinder::MatchFinderOptions & Options)299*0a6a1f1dSLionel Sambuc   MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
300*0a6a1f1dSLionel Sambuc                   const MatchFinder::MatchFinderOptions &Options)
301*0a6a1f1dSLionel Sambuc       : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
302*0a6a1f1dSLionel Sambuc 
~MatchASTVisitor()303*0a6a1f1dSLionel Sambuc   ~MatchASTVisitor() {
304*0a6a1f1dSLionel Sambuc     if (Options.CheckProfiling) {
305*0a6a1f1dSLionel Sambuc       Options.CheckProfiling->Records = std::move(TimeByBucket);
306*0a6a1f1dSLionel Sambuc     }
307*0a6a1f1dSLionel Sambuc   }
308f4a2713aSLionel Sambuc 
onStartOfTranslationUnit()309f4a2713aSLionel Sambuc   void onStartOfTranslationUnit() {
310*0a6a1f1dSLionel Sambuc     const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
311*0a6a1f1dSLionel Sambuc     TimeBucketRegion Timer;
312*0a6a1f1dSLionel Sambuc     for (MatchCallback *MC : Matchers->AllCallbacks) {
313*0a6a1f1dSLionel Sambuc       if (EnableCheckProfiling)
314*0a6a1f1dSLionel Sambuc         Timer.setBucket(&TimeByBucket[MC->getID()]);
315*0a6a1f1dSLionel Sambuc       MC->onStartOfTranslationUnit();
316f4a2713aSLionel Sambuc     }
317f4a2713aSLionel Sambuc   }
318f4a2713aSLionel Sambuc 
onEndOfTranslationUnit()319f4a2713aSLionel Sambuc   void onEndOfTranslationUnit() {
320*0a6a1f1dSLionel Sambuc     const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
321*0a6a1f1dSLionel Sambuc     TimeBucketRegion Timer;
322*0a6a1f1dSLionel Sambuc     for (MatchCallback *MC : Matchers->AllCallbacks) {
323*0a6a1f1dSLionel Sambuc       if (EnableCheckProfiling)
324*0a6a1f1dSLionel Sambuc         Timer.setBucket(&TimeByBucket[MC->getID()]);
325*0a6a1f1dSLionel Sambuc       MC->onEndOfTranslationUnit();
326f4a2713aSLionel Sambuc     }
327f4a2713aSLionel Sambuc   }
328f4a2713aSLionel Sambuc 
set_active_ast_context(ASTContext * NewActiveASTContext)329f4a2713aSLionel Sambuc   void set_active_ast_context(ASTContext *NewActiveASTContext) {
330f4a2713aSLionel Sambuc     ActiveASTContext = NewActiveASTContext;
331f4a2713aSLionel Sambuc   }
332f4a2713aSLionel Sambuc 
333f4a2713aSLionel Sambuc   // The following Visit*() and Traverse*() functions "override"
334f4a2713aSLionel Sambuc   // methods in RecursiveASTVisitor.
335f4a2713aSLionel Sambuc 
VisitTypedefNameDecl(TypedefNameDecl * DeclNode)336f4a2713aSLionel Sambuc   bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
337f4a2713aSLionel Sambuc     // When we see 'typedef A B', we add name 'B' to the set of names
338f4a2713aSLionel Sambuc     // A's canonical type maps to.  This is necessary for implementing
339f4a2713aSLionel Sambuc     // isDerivedFrom(x) properly, where x can be the name of the base
340f4a2713aSLionel Sambuc     // class or any of its aliases.
341f4a2713aSLionel Sambuc     //
342f4a2713aSLionel Sambuc     // In general, the is-alias-of (as defined by typedefs) relation
343f4a2713aSLionel Sambuc     // is tree-shaped, as you can typedef a type more than once.  For
344f4a2713aSLionel Sambuc     // example,
345f4a2713aSLionel Sambuc     //
346f4a2713aSLionel Sambuc     //   typedef A B;
347f4a2713aSLionel Sambuc     //   typedef A C;
348f4a2713aSLionel Sambuc     //   typedef C D;
349f4a2713aSLionel Sambuc     //   typedef C E;
350f4a2713aSLionel Sambuc     //
351f4a2713aSLionel Sambuc     // gives you
352f4a2713aSLionel Sambuc     //
353f4a2713aSLionel Sambuc     //   A
354f4a2713aSLionel Sambuc     //   |- B
355f4a2713aSLionel Sambuc     //   `- C
356f4a2713aSLionel Sambuc     //      |- D
357f4a2713aSLionel Sambuc     //      `- E
358f4a2713aSLionel Sambuc     //
359f4a2713aSLionel Sambuc     // It is wrong to assume that the relation is a chain.  A correct
360f4a2713aSLionel Sambuc     // implementation of isDerivedFrom() needs to recognize that B and
361f4a2713aSLionel Sambuc     // E are aliases, even though neither is a typedef of the other.
362f4a2713aSLionel Sambuc     // Therefore, we cannot simply walk through one typedef chain to
363f4a2713aSLionel Sambuc     // find out whether the type name matches.
364f4a2713aSLionel Sambuc     const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
365f4a2713aSLionel Sambuc     const Type *CanonicalType =  // root of the typedef tree
366f4a2713aSLionel Sambuc         ActiveASTContext->getCanonicalType(TypeNode);
367f4a2713aSLionel Sambuc     TypeAliases[CanonicalType].insert(DeclNode);
368f4a2713aSLionel Sambuc     return true;
369f4a2713aSLionel Sambuc   }
370f4a2713aSLionel Sambuc 
371f4a2713aSLionel Sambuc   bool TraverseDecl(Decl *DeclNode);
372f4a2713aSLionel Sambuc   bool TraverseStmt(Stmt *StmtNode);
373f4a2713aSLionel Sambuc   bool TraverseType(QualType TypeNode);
374f4a2713aSLionel Sambuc   bool TraverseTypeLoc(TypeLoc TypeNode);
375f4a2713aSLionel Sambuc   bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
376f4a2713aSLionel Sambuc   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
377f4a2713aSLionel Sambuc 
378f4a2713aSLionel Sambuc   // Matches children or descendants of 'Node' with 'BaseMatcher'.
memoizedMatchesRecursively(const ast_type_traits::DynTypedNode & Node,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,int MaxDepth,TraversalKind Traversal,BindKind Bind)379f4a2713aSLionel Sambuc   bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node,
380f4a2713aSLionel Sambuc                                   const DynTypedMatcher &Matcher,
381f4a2713aSLionel Sambuc                                   BoundNodesTreeBuilder *Builder, int MaxDepth,
382f4a2713aSLionel Sambuc                                   TraversalKind Traversal, BindKind Bind) {
383f4a2713aSLionel Sambuc     // For AST-nodes that don't have an identity, we can't memoize.
384*0a6a1f1dSLionel Sambuc     if (!Node.getMemoizationData() || !Builder->isComparable())
385f4a2713aSLionel Sambuc       return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal,
386f4a2713aSLionel Sambuc                                 Bind);
387f4a2713aSLionel Sambuc 
388f4a2713aSLionel Sambuc     MatchKey Key;
389f4a2713aSLionel Sambuc     Key.MatcherID = Matcher.getID();
390f4a2713aSLionel Sambuc     Key.Node = Node;
391f4a2713aSLionel Sambuc     // Note that we key on the bindings *before* the match.
392f4a2713aSLionel Sambuc     Key.BoundNodes = *Builder;
393f4a2713aSLionel Sambuc 
394f4a2713aSLionel Sambuc     MemoizationMap::iterator I = ResultCache.find(Key);
395f4a2713aSLionel Sambuc     if (I != ResultCache.end()) {
396f4a2713aSLionel Sambuc       *Builder = I->second.Nodes;
397f4a2713aSLionel Sambuc       return I->second.ResultOfMatch;
398f4a2713aSLionel Sambuc     }
399f4a2713aSLionel Sambuc 
400f4a2713aSLionel Sambuc     MemoizedMatchResult Result;
401f4a2713aSLionel Sambuc     Result.Nodes = *Builder;
402f4a2713aSLionel Sambuc     Result.ResultOfMatch = matchesRecursively(Node, Matcher, &Result.Nodes,
403f4a2713aSLionel Sambuc                                               MaxDepth, Traversal, Bind);
404*0a6a1f1dSLionel Sambuc 
405*0a6a1f1dSLionel Sambuc     MemoizedMatchResult &CachedResult = ResultCache[Key];
406*0a6a1f1dSLionel Sambuc     CachedResult = std::move(Result);
407*0a6a1f1dSLionel Sambuc 
408*0a6a1f1dSLionel Sambuc     *Builder = CachedResult.Nodes;
409*0a6a1f1dSLionel Sambuc     return CachedResult.ResultOfMatch;
410f4a2713aSLionel Sambuc   }
411f4a2713aSLionel Sambuc 
412f4a2713aSLionel Sambuc   // Matches children or descendants of 'Node' with 'BaseMatcher'.
matchesRecursively(const ast_type_traits::DynTypedNode & Node,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,int MaxDepth,TraversalKind Traversal,BindKind Bind)413f4a2713aSLionel Sambuc   bool matchesRecursively(const ast_type_traits::DynTypedNode &Node,
414f4a2713aSLionel Sambuc                           const DynTypedMatcher &Matcher,
415f4a2713aSLionel Sambuc                           BoundNodesTreeBuilder *Builder, int MaxDepth,
416f4a2713aSLionel Sambuc                           TraversalKind Traversal, BindKind Bind) {
417f4a2713aSLionel Sambuc     MatchChildASTVisitor Visitor(
418f4a2713aSLionel Sambuc       &Matcher, this, Builder, MaxDepth, Traversal, Bind);
419f4a2713aSLionel Sambuc     return Visitor.findMatch(Node);
420f4a2713aSLionel Sambuc   }
421f4a2713aSLionel Sambuc 
422*0a6a1f1dSLionel Sambuc   bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
423f4a2713aSLionel Sambuc                           const Matcher<NamedDecl> &Base,
424*0a6a1f1dSLionel Sambuc                           BoundNodesTreeBuilder *Builder) override;
425f4a2713aSLionel Sambuc 
426f4a2713aSLionel Sambuc   // Implements ASTMatchFinder::matchesChildOf.
matchesChildOf(const ast_type_traits::DynTypedNode & Node,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,TraversalKind Traversal,BindKind Bind)427*0a6a1f1dSLionel Sambuc   bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
428f4a2713aSLionel Sambuc                       const DynTypedMatcher &Matcher,
429f4a2713aSLionel Sambuc                       BoundNodesTreeBuilder *Builder,
430f4a2713aSLionel Sambuc                       TraversalKind Traversal,
431*0a6a1f1dSLionel Sambuc                       BindKind Bind) override {
432f4a2713aSLionel Sambuc     if (ResultCache.size() > MaxMemoizationEntries)
433f4a2713aSLionel Sambuc       ResultCache.clear();
434f4a2713aSLionel Sambuc     return memoizedMatchesRecursively(Node, Matcher, Builder, 1, Traversal,
435f4a2713aSLionel Sambuc                                       Bind);
436f4a2713aSLionel Sambuc   }
437f4a2713aSLionel Sambuc   // Implements ASTMatchFinder::matchesDescendantOf.
matchesDescendantOf(const ast_type_traits::DynTypedNode & Node,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,BindKind Bind)438*0a6a1f1dSLionel Sambuc   bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
439f4a2713aSLionel Sambuc                            const DynTypedMatcher &Matcher,
440f4a2713aSLionel Sambuc                            BoundNodesTreeBuilder *Builder,
441*0a6a1f1dSLionel Sambuc                            BindKind Bind) override {
442f4a2713aSLionel Sambuc     if (ResultCache.size() > MaxMemoizationEntries)
443f4a2713aSLionel Sambuc       ResultCache.clear();
444f4a2713aSLionel Sambuc     return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX,
445f4a2713aSLionel Sambuc                                       TK_AsIs, Bind);
446f4a2713aSLionel Sambuc   }
447f4a2713aSLionel Sambuc   // Implements ASTMatchFinder::matchesAncestorOf.
matchesAncestorOf(const ast_type_traits::DynTypedNode & Node,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,AncestorMatchMode MatchMode)448*0a6a1f1dSLionel Sambuc   bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
449f4a2713aSLionel Sambuc                          const DynTypedMatcher &Matcher,
450f4a2713aSLionel Sambuc                          BoundNodesTreeBuilder *Builder,
451*0a6a1f1dSLionel Sambuc                          AncestorMatchMode MatchMode) override {
452f4a2713aSLionel Sambuc     // Reset the cache outside of the recursive call to make sure we
453f4a2713aSLionel Sambuc     // don't invalidate any iterators.
454f4a2713aSLionel Sambuc     if (ResultCache.size() > MaxMemoizationEntries)
455f4a2713aSLionel Sambuc       ResultCache.clear();
456f4a2713aSLionel Sambuc     return memoizedMatchesAncestorOfRecursively(Node, Matcher, Builder,
457f4a2713aSLionel Sambuc                                                 MatchMode);
458f4a2713aSLionel Sambuc   }
459f4a2713aSLionel Sambuc 
460f4a2713aSLionel Sambuc   // Matches all registered matchers on the given node and calls the
461f4a2713aSLionel Sambuc   // result callback for every node that matches.
match(const ast_type_traits::DynTypedNode & Node)462f4a2713aSLionel Sambuc   void match(const ast_type_traits::DynTypedNode &Node) {
463*0a6a1f1dSLionel Sambuc     // FIXME: Improve this with a switch or a visitor pattern.
464*0a6a1f1dSLionel Sambuc     if (auto *N = Node.get<Decl>()) {
465*0a6a1f1dSLionel Sambuc       match(*N);
466*0a6a1f1dSLionel Sambuc     } else if (auto *N = Node.get<Stmt>()) {
467*0a6a1f1dSLionel Sambuc       match(*N);
468*0a6a1f1dSLionel Sambuc     } else if (auto *N = Node.get<Type>()) {
469*0a6a1f1dSLionel Sambuc       match(*N);
470*0a6a1f1dSLionel Sambuc     } else if (auto *N = Node.get<QualType>()) {
471*0a6a1f1dSLionel Sambuc       match(*N);
472*0a6a1f1dSLionel Sambuc     } else if (auto *N = Node.get<NestedNameSpecifier>()) {
473*0a6a1f1dSLionel Sambuc       match(*N);
474*0a6a1f1dSLionel Sambuc     } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
475*0a6a1f1dSLionel Sambuc       match(*N);
476*0a6a1f1dSLionel Sambuc     } else if (auto *N = Node.get<TypeLoc>()) {
477*0a6a1f1dSLionel Sambuc       match(*N);
478f4a2713aSLionel Sambuc     }
479f4a2713aSLionel Sambuc   }
480f4a2713aSLionel Sambuc 
match(const T & Node)481f4a2713aSLionel Sambuc   template <typename T> void match(const T &Node) {
482*0a6a1f1dSLionel Sambuc     matchDispatch(&Node);
483f4a2713aSLionel Sambuc   }
484f4a2713aSLionel Sambuc 
485f4a2713aSLionel Sambuc   // Implements ASTMatchFinder::getASTContext.
getASTContext() const486*0a6a1f1dSLionel Sambuc   ASTContext &getASTContext() const override { return *ActiveASTContext; }
487f4a2713aSLionel Sambuc 
shouldVisitTemplateInstantiations() const488f4a2713aSLionel Sambuc   bool shouldVisitTemplateInstantiations() const { return true; }
shouldVisitImplicitCode() const489f4a2713aSLionel Sambuc   bool shouldVisitImplicitCode() const { return true; }
490f4a2713aSLionel Sambuc   // Disables data recursion. We intercept Traverse* methods in the RAV, which
491f4a2713aSLionel Sambuc   // are not triggered during data recursion.
shouldUseDataRecursionFor(clang::Stmt * S) const492f4a2713aSLionel Sambuc   bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
493f4a2713aSLionel Sambuc 
494f4a2713aSLionel Sambuc private:
495*0a6a1f1dSLionel Sambuc   class TimeBucketRegion {
496*0a6a1f1dSLionel Sambuc   public:
TimeBucketRegion()497*0a6a1f1dSLionel Sambuc     TimeBucketRegion() : Bucket(nullptr) {}
~TimeBucketRegion()498*0a6a1f1dSLionel Sambuc     ~TimeBucketRegion() { setBucket(nullptr); }
499*0a6a1f1dSLionel Sambuc 
500*0a6a1f1dSLionel Sambuc     /// \brief Start timing for \p NewBucket.
501*0a6a1f1dSLionel Sambuc     ///
502*0a6a1f1dSLionel Sambuc     /// If there was a bucket already set, it will finish the timing for that
503*0a6a1f1dSLionel Sambuc     /// other bucket.
504*0a6a1f1dSLionel Sambuc     /// \p NewBucket will be timed until the next call to \c setBucket() or
505*0a6a1f1dSLionel Sambuc     /// until the \c TimeBucketRegion is destroyed.
506*0a6a1f1dSLionel Sambuc     /// If \p NewBucket is the same as the currently timed bucket, this call
507*0a6a1f1dSLionel Sambuc     /// does nothing.
setBucket(llvm::TimeRecord * NewBucket)508*0a6a1f1dSLionel Sambuc     void setBucket(llvm::TimeRecord *NewBucket) {
509*0a6a1f1dSLionel Sambuc       if (Bucket != NewBucket) {
510*0a6a1f1dSLionel Sambuc         auto Now = llvm::TimeRecord::getCurrentTime(true);
511*0a6a1f1dSLionel Sambuc         if (Bucket)
512*0a6a1f1dSLionel Sambuc           *Bucket += Now;
513*0a6a1f1dSLionel Sambuc         if (NewBucket)
514*0a6a1f1dSLionel Sambuc           *NewBucket -= Now;
515*0a6a1f1dSLionel Sambuc         Bucket = NewBucket;
516*0a6a1f1dSLionel Sambuc       }
517*0a6a1f1dSLionel Sambuc     }
518*0a6a1f1dSLionel Sambuc 
519*0a6a1f1dSLionel Sambuc   private:
520*0a6a1f1dSLionel Sambuc     llvm::TimeRecord *Bucket;
521*0a6a1f1dSLionel Sambuc   };
522*0a6a1f1dSLionel Sambuc 
523*0a6a1f1dSLionel Sambuc   /// \brief Runs all the \p Matchers on \p Node.
524*0a6a1f1dSLionel Sambuc   ///
525*0a6a1f1dSLionel Sambuc   /// Used by \c matchDispatch() below.
526*0a6a1f1dSLionel Sambuc   template <typename T, typename MC>
matchWithoutFilter(const T & Node,const MC & Matchers)527*0a6a1f1dSLionel Sambuc   void matchWithoutFilter(const T &Node, const MC &Matchers) {
528*0a6a1f1dSLionel Sambuc     const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
529*0a6a1f1dSLionel Sambuc     TimeBucketRegion Timer;
530*0a6a1f1dSLionel Sambuc     for (const auto &MP : Matchers) {
531*0a6a1f1dSLionel Sambuc       if (EnableCheckProfiling)
532*0a6a1f1dSLionel Sambuc         Timer.setBucket(&TimeByBucket[MP.second->getID()]);
533*0a6a1f1dSLionel Sambuc       BoundNodesTreeBuilder Builder;
534*0a6a1f1dSLionel Sambuc       if (MP.first.matches(Node, this, &Builder)) {
535*0a6a1f1dSLionel Sambuc         MatchVisitor Visitor(ActiveASTContext, MP.second);
536*0a6a1f1dSLionel Sambuc         Builder.visitMatches(&Visitor);
537*0a6a1f1dSLionel Sambuc       }
538*0a6a1f1dSLionel Sambuc     }
539*0a6a1f1dSLionel Sambuc   }
540*0a6a1f1dSLionel Sambuc 
matchWithFilter(const ast_type_traits::DynTypedNode & DynNode)541*0a6a1f1dSLionel Sambuc   void matchWithFilter(const ast_type_traits::DynTypedNode &DynNode) {
542*0a6a1f1dSLionel Sambuc     auto Kind = DynNode.getNodeKind();
543*0a6a1f1dSLionel Sambuc     auto it = MatcherFiltersMap.find(Kind);
544*0a6a1f1dSLionel Sambuc     const auto &Filter =
545*0a6a1f1dSLionel Sambuc         it != MatcherFiltersMap.end() ? it->second : getFilterForKind(Kind);
546*0a6a1f1dSLionel Sambuc 
547*0a6a1f1dSLionel Sambuc     if (Filter.empty())
548*0a6a1f1dSLionel Sambuc       return;
549*0a6a1f1dSLionel Sambuc 
550*0a6a1f1dSLionel Sambuc     const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
551*0a6a1f1dSLionel Sambuc     TimeBucketRegion Timer;
552*0a6a1f1dSLionel Sambuc     auto &Matchers = this->Matchers->DeclOrStmt;
553*0a6a1f1dSLionel Sambuc     for (unsigned short I : Filter) {
554*0a6a1f1dSLionel Sambuc       auto &MP = Matchers[I];
555*0a6a1f1dSLionel Sambuc       if (EnableCheckProfiling)
556*0a6a1f1dSLionel Sambuc         Timer.setBucket(&TimeByBucket[MP.second->getID()]);
557*0a6a1f1dSLionel Sambuc       BoundNodesTreeBuilder Builder;
558*0a6a1f1dSLionel Sambuc       if (MP.first.matchesNoKindCheck(DynNode, this, &Builder)) {
559*0a6a1f1dSLionel Sambuc         MatchVisitor Visitor(ActiveASTContext, MP.second);
560*0a6a1f1dSLionel Sambuc         Builder.visitMatches(&Visitor);
561*0a6a1f1dSLionel Sambuc       }
562*0a6a1f1dSLionel Sambuc     }
563*0a6a1f1dSLionel Sambuc   }
564*0a6a1f1dSLionel Sambuc 
565*0a6a1f1dSLionel Sambuc   const std::vector<unsigned short> &
getFilterForKind(ast_type_traits::ASTNodeKind Kind)566*0a6a1f1dSLionel Sambuc   getFilterForKind(ast_type_traits::ASTNodeKind Kind) {
567*0a6a1f1dSLionel Sambuc     auto &Filter = MatcherFiltersMap[Kind];
568*0a6a1f1dSLionel Sambuc     auto &Matchers = this->Matchers->DeclOrStmt;
569*0a6a1f1dSLionel Sambuc     assert((Matchers.size() < USHRT_MAX) && "Too many matchers.");
570*0a6a1f1dSLionel Sambuc     for (unsigned I = 0, E = Matchers.size(); I != E; ++I) {
571*0a6a1f1dSLionel Sambuc       if (Matchers[I].first.canMatchNodesOfKind(Kind)) {
572*0a6a1f1dSLionel Sambuc         Filter.push_back(I);
573*0a6a1f1dSLionel Sambuc       }
574*0a6a1f1dSLionel Sambuc     }
575*0a6a1f1dSLionel Sambuc     return Filter;
576*0a6a1f1dSLionel Sambuc   }
577*0a6a1f1dSLionel Sambuc 
578*0a6a1f1dSLionel Sambuc   /// @{
579*0a6a1f1dSLionel Sambuc   /// \brief Overloads to pair the different node types to their matchers.
matchDispatch(const Decl * Node)580*0a6a1f1dSLionel Sambuc   void matchDispatch(const Decl *Node) {
581*0a6a1f1dSLionel Sambuc     return matchWithFilter(ast_type_traits::DynTypedNode::create(*Node));
582*0a6a1f1dSLionel Sambuc   }
matchDispatch(const Stmt * Node)583*0a6a1f1dSLionel Sambuc   void matchDispatch(const Stmt *Node) {
584*0a6a1f1dSLionel Sambuc     return matchWithFilter(ast_type_traits::DynTypedNode::create(*Node));
585*0a6a1f1dSLionel Sambuc   }
586*0a6a1f1dSLionel Sambuc 
matchDispatch(const Type * Node)587*0a6a1f1dSLionel Sambuc   void matchDispatch(const Type *Node) {
588*0a6a1f1dSLionel Sambuc     matchWithoutFilter(QualType(Node, 0), Matchers->Type);
589*0a6a1f1dSLionel Sambuc   }
matchDispatch(const TypeLoc * Node)590*0a6a1f1dSLionel Sambuc   void matchDispatch(const TypeLoc *Node) {
591*0a6a1f1dSLionel Sambuc     matchWithoutFilter(*Node, Matchers->TypeLoc);
592*0a6a1f1dSLionel Sambuc   }
matchDispatch(const QualType * Node)593*0a6a1f1dSLionel Sambuc   void matchDispatch(const QualType *Node) {
594*0a6a1f1dSLionel Sambuc     matchWithoutFilter(*Node, Matchers->Type);
595*0a6a1f1dSLionel Sambuc   }
matchDispatch(const NestedNameSpecifier * Node)596*0a6a1f1dSLionel Sambuc   void matchDispatch(const NestedNameSpecifier *Node) {
597*0a6a1f1dSLionel Sambuc     matchWithoutFilter(*Node, Matchers->NestedNameSpecifier);
598*0a6a1f1dSLionel Sambuc   }
matchDispatch(const NestedNameSpecifierLoc * Node)599*0a6a1f1dSLionel Sambuc   void matchDispatch(const NestedNameSpecifierLoc *Node) {
600*0a6a1f1dSLionel Sambuc     matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
601*0a6a1f1dSLionel Sambuc   }
matchDispatch(const void *)602*0a6a1f1dSLionel Sambuc   void matchDispatch(const void *) { /* Do nothing. */ }
603*0a6a1f1dSLionel Sambuc   /// @}
604*0a6a1f1dSLionel Sambuc 
605f4a2713aSLionel Sambuc   // Returns whether an ancestor of \p Node matches \p Matcher.
606f4a2713aSLionel Sambuc   //
607f4a2713aSLionel Sambuc   // The order of matching ((which can lead to different nodes being bound in
608f4a2713aSLionel Sambuc   // case there are multiple matches) is breadth first search.
609f4a2713aSLionel Sambuc   //
610f4a2713aSLionel Sambuc   // To allow memoization in the very common case of having deeply nested
611f4a2713aSLionel Sambuc   // expressions inside a template function, we first walk up the AST, memoizing
612f4a2713aSLionel Sambuc   // the result of the match along the way, as long as there is only a single
613f4a2713aSLionel Sambuc   // parent.
614f4a2713aSLionel Sambuc   //
615f4a2713aSLionel Sambuc   // Once there are multiple parents, the breadth first search order does not
616f4a2713aSLionel Sambuc   // allow simple memoization on the ancestors. Thus, we only memoize as long
617f4a2713aSLionel Sambuc   // as there is a single parent.
memoizedMatchesAncestorOfRecursively(const ast_type_traits::DynTypedNode & Node,const DynTypedMatcher & Matcher,BoundNodesTreeBuilder * Builder,AncestorMatchMode MatchMode)618f4a2713aSLionel Sambuc   bool memoizedMatchesAncestorOfRecursively(
619f4a2713aSLionel Sambuc       const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher,
620f4a2713aSLionel Sambuc       BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) {
621f4a2713aSLionel Sambuc     if (Node.get<TranslationUnitDecl>() ==
622f4a2713aSLionel Sambuc         ActiveASTContext->getTranslationUnitDecl())
623f4a2713aSLionel Sambuc       return false;
624f4a2713aSLionel Sambuc     assert(Node.getMemoizationData() &&
625f4a2713aSLionel Sambuc            "Invariant broken: only nodes that support memoization may be "
626f4a2713aSLionel Sambuc            "used in the parent map.");
627*0a6a1f1dSLionel Sambuc 
628f4a2713aSLionel Sambuc     MatchKey Key;
629f4a2713aSLionel Sambuc     Key.MatcherID = Matcher.getID();
630f4a2713aSLionel Sambuc     Key.Node = Node;
631f4a2713aSLionel Sambuc     Key.BoundNodes = *Builder;
632f4a2713aSLionel Sambuc 
633f4a2713aSLionel Sambuc     // Note that we cannot use insert and reuse the iterator, as recursive
634f4a2713aSLionel Sambuc     // calls to match might invalidate the result cache iterators.
635f4a2713aSLionel Sambuc     MemoizationMap::iterator I = ResultCache.find(Key);
636f4a2713aSLionel Sambuc     if (I != ResultCache.end()) {
637f4a2713aSLionel Sambuc       *Builder = I->second.Nodes;
638f4a2713aSLionel Sambuc       return I->second.ResultOfMatch;
639f4a2713aSLionel Sambuc     }
640*0a6a1f1dSLionel Sambuc 
641f4a2713aSLionel Sambuc     MemoizedMatchResult Result;
642f4a2713aSLionel Sambuc     Result.ResultOfMatch = false;
643f4a2713aSLionel Sambuc     Result.Nodes = *Builder;
644*0a6a1f1dSLionel Sambuc 
645*0a6a1f1dSLionel Sambuc     const auto &Parents = ActiveASTContext->getParents(Node);
646*0a6a1f1dSLionel Sambuc     assert(!Parents.empty() && "Found node that is not in the parent map.");
647f4a2713aSLionel Sambuc     if (Parents.size() == 1) {
648f4a2713aSLionel Sambuc       // Only one parent - do recursive memoization.
649f4a2713aSLionel Sambuc       const ast_type_traits::DynTypedNode Parent = Parents[0];
650f4a2713aSLionel Sambuc       if (Matcher.matches(Parent, this, &Result.Nodes)) {
651f4a2713aSLionel Sambuc         Result.ResultOfMatch = true;
652f4a2713aSLionel Sambuc       } else if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
653f4a2713aSLionel Sambuc         // Reset the results to not include the bound nodes from the failed
654f4a2713aSLionel Sambuc         // match above.
655f4a2713aSLionel Sambuc         Result.Nodes = *Builder;
656f4a2713aSLionel Sambuc         Result.ResultOfMatch = memoizedMatchesAncestorOfRecursively(
657f4a2713aSLionel Sambuc             Parent, Matcher, &Result.Nodes, MatchMode);
658f4a2713aSLionel Sambuc         // Once we get back from the recursive call, the result will be the
659f4a2713aSLionel Sambuc         // same as the parent's result.
660f4a2713aSLionel Sambuc       }
661f4a2713aSLionel Sambuc     } else {
662f4a2713aSLionel Sambuc       // Multiple parents - BFS over the rest of the nodes.
663f4a2713aSLionel Sambuc       llvm::DenseSet<const void *> Visited;
664f4a2713aSLionel Sambuc       std::deque<ast_type_traits::DynTypedNode> Queue(Parents.begin(),
665f4a2713aSLionel Sambuc                                                       Parents.end());
666f4a2713aSLionel Sambuc       while (!Queue.empty()) {
667f4a2713aSLionel Sambuc         Result.Nodes = *Builder;
668f4a2713aSLionel Sambuc         if (Matcher.matches(Queue.front(), this, &Result.Nodes)) {
669f4a2713aSLionel Sambuc           Result.ResultOfMatch = true;
670f4a2713aSLionel Sambuc           break;
671f4a2713aSLionel Sambuc         }
672f4a2713aSLionel Sambuc         if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
673*0a6a1f1dSLionel Sambuc           for (const auto &Parent :
674*0a6a1f1dSLionel Sambuc                ActiveASTContext->getParents(Queue.front())) {
675f4a2713aSLionel Sambuc             // Make sure we do not visit the same node twice.
676f4a2713aSLionel Sambuc             // Otherwise, we'll visit the common ancestors as often as there
677f4a2713aSLionel Sambuc             // are splits on the way down.
678*0a6a1f1dSLionel Sambuc             if (Visited.insert(Parent.getMemoizationData()).second)
679*0a6a1f1dSLionel Sambuc               Queue.push_back(Parent);
680f4a2713aSLionel Sambuc           }
681f4a2713aSLionel Sambuc         }
682f4a2713aSLionel Sambuc         Queue.pop_front();
683f4a2713aSLionel Sambuc       }
684f4a2713aSLionel Sambuc     }
685f4a2713aSLionel Sambuc 
686*0a6a1f1dSLionel Sambuc     MemoizedMatchResult &CachedResult = ResultCache[Key];
687*0a6a1f1dSLionel Sambuc     CachedResult = std::move(Result);
688*0a6a1f1dSLionel Sambuc 
689*0a6a1f1dSLionel Sambuc     *Builder = CachedResult.Nodes;
690*0a6a1f1dSLionel Sambuc     return CachedResult.ResultOfMatch;
691f4a2713aSLionel Sambuc   }
692f4a2713aSLionel Sambuc 
693f4a2713aSLionel Sambuc   // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
694f4a2713aSLionel Sambuc   // the aggregated bound nodes for each match.
695f4a2713aSLionel Sambuc   class MatchVisitor : public BoundNodesTreeBuilder::Visitor {
696f4a2713aSLionel Sambuc   public:
MatchVisitor(ASTContext * Context,MatchFinder::MatchCallback * Callback)697f4a2713aSLionel Sambuc     MatchVisitor(ASTContext* Context,
698f4a2713aSLionel Sambuc                  MatchFinder::MatchCallback* Callback)
699f4a2713aSLionel Sambuc       : Context(Context),
700f4a2713aSLionel Sambuc         Callback(Callback) {}
701f4a2713aSLionel Sambuc 
visitMatch(const BoundNodes & BoundNodesView)702*0a6a1f1dSLionel Sambuc     void visitMatch(const BoundNodes& BoundNodesView) override {
703f4a2713aSLionel Sambuc       Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
704f4a2713aSLionel Sambuc     }
705f4a2713aSLionel Sambuc 
706f4a2713aSLionel Sambuc   private:
707f4a2713aSLionel Sambuc     ASTContext* Context;
708f4a2713aSLionel Sambuc     MatchFinder::MatchCallback* Callback;
709f4a2713aSLionel Sambuc   };
710f4a2713aSLionel Sambuc 
711f4a2713aSLionel Sambuc   // Returns true if 'TypeNode' has an alias that matches the given matcher.
typeHasMatchingAlias(const Type * TypeNode,const Matcher<NamedDecl> Matcher,BoundNodesTreeBuilder * Builder)712f4a2713aSLionel Sambuc   bool typeHasMatchingAlias(const Type *TypeNode,
713f4a2713aSLionel Sambuc                             const Matcher<NamedDecl> Matcher,
714f4a2713aSLionel Sambuc                             BoundNodesTreeBuilder *Builder) {
715f4a2713aSLionel Sambuc     const Type *const CanonicalType =
716f4a2713aSLionel Sambuc       ActiveASTContext->getCanonicalType(TypeNode);
717*0a6a1f1dSLionel Sambuc     for (const TypedefNameDecl *Alias : TypeAliases.lookup(CanonicalType)) {
718f4a2713aSLionel Sambuc       BoundNodesTreeBuilder Result(*Builder);
719*0a6a1f1dSLionel Sambuc       if (Matcher.matches(*Alias, this, &Result)) {
720*0a6a1f1dSLionel Sambuc         *Builder = std::move(Result);
721f4a2713aSLionel Sambuc         return true;
722f4a2713aSLionel Sambuc       }
723f4a2713aSLionel Sambuc     }
724f4a2713aSLionel Sambuc     return false;
725f4a2713aSLionel Sambuc   }
726f4a2713aSLionel Sambuc 
727*0a6a1f1dSLionel Sambuc   /// \brief Bucket to record map.
728*0a6a1f1dSLionel Sambuc   ///
729*0a6a1f1dSLionel Sambuc   /// Used to get the appropriate bucket for each matcher.
730*0a6a1f1dSLionel Sambuc   llvm::StringMap<llvm::TimeRecord> TimeByBucket;
731*0a6a1f1dSLionel Sambuc 
732*0a6a1f1dSLionel Sambuc   const MatchFinder::MatchersByType *Matchers;
733*0a6a1f1dSLionel Sambuc 
734*0a6a1f1dSLionel Sambuc   /// \brief Filtered list of matcher indices for each matcher kind.
735*0a6a1f1dSLionel Sambuc   ///
736*0a6a1f1dSLionel Sambuc   /// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
737*0a6a1f1dSLionel Sambuc   /// kind (and derived kinds) so it is a waste to try every matcher on every
738*0a6a1f1dSLionel Sambuc   /// node.
739*0a6a1f1dSLionel Sambuc   /// We precalculate a list of matchers that pass the toplevel restrict check.
740*0a6a1f1dSLionel Sambuc   /// This also allows us to skip the restrict check at matching time. See
741*0a6a1f1dSLionel Sambuc   /// use \c matchesNoKindCheck() above.
742*0a6a1f1dSLionel Sambuc   llvm::DenseMap<ast_type_traits::ASTNodeKind, std::vector<unsigned short>>
743*0a6a1f1dSLionel Sambuc       MatcherFiltersMap;
744*0a6a1f1dSLionel Sambuc 
745*0a6a1f1dSLionel Sambuc   const MatchFinder::MatchFinderOptions &Options;
746f4a2713aSLionel Sambuc   ASTContext *ActiveASTContext;
747f4a2713aSLionel Sambuc 
748f4a2713aSLionel Sambuc   // Maps a canonical type to its TypedefDecls.
749f4a2713aSLionel Sambuc   llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
750f4a2713aSLionel Sambuc 
751f4a2713aSLionel Sambuc   // Maps (matcher, node) -> the match result for memoization.
752f4a2713aSLionel Sambuc   typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
753f4a2713aSLionel Sambuc   MemoizationMap ResultCache;
754f4a2713aSLionel Sambuc };
755f4a2713aSLionel Sambuc 
getAsCXXRecordDecl(const Type * TypeNode)756f4a2713aSLionel Sambuc static CXXRecordDecl *getAsCXXRecordDecl(const Type *TypeNode) {
757f4a2713aSLionel Sambuc   // Type::getAs<...>() drills through typedefs.
758*0a6a1f1dSLionel Sambuc   if (TypeNode->getAs<DependentNameType>() != nullptr ||
759*0a6a1f1dSLionel Sambuc       TypeNode->getAs<DependentTemplateSpecializationType>() != nullptr ||
760*0a6a1f1dSLionel Sambuc       TypeNode->getAs<TemplateTypeParmType>() != nullptr)
761f4a2713aSLionel Sambuc     // Dependent names and template TypeNode parameters will be matched when
762f4a2713aSLionel Sambuc     // the template is instantiated.
763*0a6a1f1dSLionel Sambuc     return nullptr;
764f4a2713aSLionel Sambuc   TemplateSpecializationType const *TemplateType =
765f4a2713aSLionel Sambuc       TypeNode->getAs<TemplateSpecializationType>();
766*0a6a1f1dSLionel Sambuc   if (!TemplateType) {
767f4a2713aSLionel Sambuc     return TypeNode->getAsCXXRecordDecl();
768f4a2713aSLionel Sambuc   }
769f4a2713aSLionel Sambuc   if (TemplateType->getTemplateName().isDependent())
770f4a2713aSLionel Sambuc     // Dependent template specializations will be matched when the
771f4a2713aSLionel Sambuc     // template is instantiated.
772*0a6a1f1dSLionel Sambuc     return nullptr;
773f4a2713aSLionel Sambuc 
774f4a2713aSLionel Sambuc   // For template specialization types which are specializing a template
775f4a2713aSLionel Sambuc   // declaration which is an explicit or partial specialization of another
776f4a2713aSLionel Sambuc   // template declaration, getAsCXXRecordDecl() returns the corresponding
777f4a2713aSLionel Sambuc   // ClassTemplateSpecializationDecl.
778f4a2713aSLionel Sambuc   //
779f4a2713aSLionel Sambuc   // For template specialization types which are specializing a template
780f4a2713aSLionel Sambuc   // declaration which is neither an explicit nor partial specialization of
781f4a2713aSLionel Sambuc   // another template declaration, getAsCXXRecordDecl() returns NULL and
782f4a2713aSLionel Sambuc   // we get the CXXRecordDecl of the templated declaration.
783f4a2713aSLionel Sambuc   CXXRecordDecl *SpecializationDecl = TemplateType->getAsCXXRecordDecl();
784*0a6a1f1dSLionel Sambuc   if (SpecializationDecl) {
785f4a2713aSLionel Sambuc     return SpecializationDecl;
786f4a2713aSLionel Sambuc   }
787f4a2713aSLionel Sambuc   NamedDecl *Templated =
788f4a2713aSLionel Sambuc       TemplateType->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();
789f4a2713aSLionel Sambuc   if (CXXRecordDecl *TemplatedRecord = dyn_cast<CXXRecordDecl>(Templated)) {
790f4a2713aSLionel Sambuc     return TemplatedRecord;
791f4a2713aSLionel Sambuc   }
792f4a2713aSLionel Sambuc   // Now it can still be that we have an alias template.
793f4a2713aSLionel Sambuc   TypeAliasDecl *AliasDecl = dyn_cast<TypeAliasDecl>(Templated);
794f4a2713aSLionel Sambuc   assert(AliasDecl);
795f4a2713aSLionel Sambuc   return getAsCXXRecordDecl(AliasDecl->getUnderlyingType().getTypePtr());
796f4a2713aSLionel Sambuc }
797f4a2713aSLionel Sambuc 
798f4a2713aSLionel Sambuc // Returns true if the given class is directly or indirectly derived
799f4a2713aSLionel Sambuc // from a base type with the given name.  A class is not considered to be
800f4a2713aSLionel Sambuc // derived from itself.
classIsDerivedFrom(const CXXRecordDecl * Declaration,const Matcher<NamedDecl> & Base,BoundNodesTreeBuilder * Builder)801f4a2713aSLionel Sambuc bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
802f4a2713aSLionel Sambuc                                          const Matcher<NamedDecl> &Base,
803f4a2713aSLionel Sambuc                                          BoundNodesTreeBuilder *Builder) {
804f4a2713aSLionel Sambuc   if (!Declaration->hasDefinition())
805f4a2713aSLionel Sambuc     return false;
806*0a6a1f1dSLionel Sambuc   for (const auto &It : Declaration->bases()) {
807*0a6a1f1dSLionel Sambuc     const Type *TypeNode = It.getType().getTypePtr();
808f4a2713aSLionel Sambuc 
809f4a2713aSLionel Sambuc     if (typeHasMatchingAlias(TypeNode, Base, Builder))
810f4a2713aSLionel Sambuc       return true;
811f4a2713aSLionel Sambuc 
812f4a2713aSLionel Sambuc     CXXRecordDecl *ClassDecl = getAsCXXRecordDecl(TypeNode);
813*0a6a1f1dSLionel Sambuc     if (!ClassDecl)
814f4a2713aSLionel Sambuc       continue;
815f4a2713aSLionel Sambuc     if (ClassDecl == Declaration) {
816f4a2713aSLionel Sambuc       // This can happen for recursive template definitions; if the
817f4a2713aSLionel Sambuc       // current declaration did not match, we can safely return false.
818f4a2713aSLionel Sambuc       return false;
819f4a2713aSLionel Sambuc     }
820f4a2713aSLionel Sambuc     BoundNodesTreeBuilder Result(*Builder);
821f4a2713aSLionel Sambuc     if (Base.matches(*ClassDecl, this, &Result)) {
822*0a6a1f1dSLionel Sambuc       *Builder = std::move(Result);
823f4a2713aSLionel Sambuc       return true;
824f4a2713aSLionel Sambuc     }
825f4a2713aSLionel Sambuc     if (classIsDerivedFrom(ClassDecl, Base, Builder))
826f4a2713aSLionel Sambuc       return true;
827f4a2713aSLionel Sambuc   }
828f4a2713aSLionel Sambuc   return false;
829f4a2713aSLionel Sambuc }
830f4a2713aSLionel Sambuc 
TraverseDecl(Decl * DeclNode)831f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
832*0a6a1f1dSLionel Sambuc   if (!DeclNode) {
833f4a2713aSLionel Sambuc     return true;
834f4a2713aSLionel Sambuc   }
835f4a2713aSLionel Sambuc   match(*DeclNode);
836f4a2713aSLionel Sambuc   return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
837f4a2713aSLionel Sambuc }
838f4a2713aSLionel Sambuc 
TraverseStmt(Stmt * StmtNode)839f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) {
840*0a6a1f1dSLionel Sambuc   if (!StmtNode) {
841f4a2713aSLionel Sambuc     return true;
842f4a2713aSLionel Sambuc   }
843f4a2713aSLionel Sambuc   match(*StmtNode);
844f4a2713aSLionel Sambuc   return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode);
845f4a2713aSLionel Sambuc }
846f4a2713aSLionel Sambuc 
TraverseType(QualType TypeNode)847f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseType(QualType TypeNode) {
848f4a2713aSLionel Sambuc   match(TypeNode);
849f4a2713aSLionel Sambuc   return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
850f4a2713aSLionel Sambuc }
851f4a2713aSLionel Sambuc 
TraverseTypeLoc(TypeLoc TypeLocNode)852f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
853f4a2713aSLionel Sambuc   // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
854f4a2713aSLionel Sambuc   // We still want to find those types via matchers, so we match them here. Note
855f4a2713aSLionel Sambuc   // that the TypeLocs are structurally a shadow-hierarchy to the expressed
856f4a2713aSLionel Sambuc   // type, so we visit all involved parts of a compound type when matching on
857f4a2713aSLionel Sambuc   // each TypeLoc.
858f4a2713aSLionel Sambuc   match(TypeLocNode);
859f4a2713aSLionel Sambuc   match(TypeLocNode.getType());
860f4a2713aSLionel Sambuc   return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
861f4a2713aSLionel Sambuc }
862f4a2713aSLionel Sambuc 
TraverseNestedNameSpecifier(NestedNameSpecifier * NNS)863f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
864f4a2713aSLionel Sambuc   match(*NNS);
865f4a2713aSLionel Sambuc   return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
866f4a2713aSLionel Sambuc }
867f4a2713aSLionel Sambuc 
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)868f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
869f4a2713aSLionel Sambuc     NestedNameSpecifierLoc NNS) {
870f4a2713aSLionel Sambuc   match(NNS);
871f4a2713aSLionel Sambuc   // We only match the nested name specifier here (as opposed to traversing it)
872f4a2713aSLionel Sambuc   // because the traversal is already done in the parallel "Loc"-hierarchy.
873*0a6a1f1dSLionel Sambuc   if (NNS.hasQualifier())
874f4a2713aSLionel Sambuc     match(*NNS.getNestedNameSpecifier());
875f4a2713aSLionel Sambuc   return
876f4a2713aSLionel Sambuc       RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
877f4a2713aSLionel Sambuc }
878f4a2713aSLionel Sambuc 
879f4a2713aSLionel Sambuc class MatchASTConsumer : public ASTConsumer {
880f4a2713aSLionel Sambuc public:
MatchASTConsumer(MatchFinder * Finder,MatchFinder::ParsingDoneTestCallback * ParsingDone)881f4a2713aSLionel Sambuc   MatchASTConsumer(MatchFinder *Finder,
882f4a2713aSLionel Sambuc                    MatchFinder::ParsingDoneTestCallback *ParsingDone)
883f4a2713aSLionel Sambuc       : Finder(Finder), ParsingDone(ParsingDone) {}
884f4a2713aSLionel Sambuc 
885f4a2713aSLionel Sambuc private:
HandleTranslationUnit(ASTContext & Context)886*0a6a1f1dSLionel Sambuc   void HandleTranslationUnit(ASTContext &Context) override {
887*0a6a1f1dSLionel Sambuc     if (ParsingDone != nullptr) {
888f4a2713aSLionel Sambuc       ParsingDone->run();
889f4a2713aSLionel Sambuc     }
890f4a2713aSLionel Sambuc     Finder->matchAST(Context);
891f4a2713aSLionel Sambuc   }
892f4a2713aSLionel Sambuc 
893f4a2713aSLionel Sambuc   MatchFinder *Finder;
894f4a2713aSLionel Sambuc   MatchFinder::ParsingDoneTestCallback *ParsingDone;
895f4a2713aSLionel Sambuc };
896f4a2713aSLionel Sambuc 
897f4a2713aSLionel Sambuc } // end namespace
898f4a2713aSLionel Sambuc } // end namespace internal
899f4a2713aSLionel Sambuc 
MatchResult(const BoundNodes & Nodes,ASTContext * Context)900f4a2713aSLionel Sambuc MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes,
901f4a2713aSLionel Sambuc                                       ASTContext *Context)
902f4a2713aSLionel Sambuc   : Nodes(Nodes), Context(Context),
903f4a2713aSLionel Sambuc     SourceManager(&Context->getSourceManager()) {}
904f4a2713aSLionel Sambuc 
~MatchCallback()905f4a2713aSLionel Sambuc MatchFinder::MatchCallback::~MatchCallback() {}
~ParsingDoneTestCallback()906f4a2713aSLionel Sambuc MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
907f4a2713aSLionel Sambuc 
MatchFinder(MatchFinderOptions Options)908*0a6a1f1dSLionel Sambuc MatchFinder::MatchFinder(MatchFinderOptions Options)
909*0a6a1f1dSLionel Sambuc     : Options(std::move(Options)), ParsingDone(nullptr) {}
910f4a2713aSLionel Sambuc 
~MatchFinder()911f4a2713aSLionel Sambuc MatchFinder::~MatchFinder() {}
912f4a2713aSLionel Sambuc 
addMatcher(const DeclarationMatcher & NodeMatch,MatchCallback * Action)913f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
914f4a2713aSLionel Sambuc                              MatchCallback *Action) {
915*0a6a1f1dSLionel Sambuc   Matchers.DeclOrStmt.push_back(std::make_pair(NodeMatch, Action));
916*0a6a1f1dSLionel Sambuc   Matchers.AllCallbacks.push_back(Action);
917f4a2713aSLionel Sambuc }
918f4a2713aSLionel Sambuc 
addMatcher(const TypeMatcher & NodeMatch,MatchCallback * Action)919f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
920f4a2713aSLionel Sambuc                              MatchCallback *Action) {
921*0a6a1f1dSLionel Sambuc   Matchers.Type.push_back(std::make_pair(NodeMatch, Action));
922*0a6a1f1dSLionel Sambuc   Matchers.AllCallbacks.push_back(Action);
923f4a2713aSLionel Sambuc }
924f4a2713aSLionel Sambuc 
addMatcher(const StatementMatcher & NodeMatch,MatchCallback * Action)925f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
926f4a2713aSLionel Sambuc                              MatchCallback *Action) {
927*0a6a1f1dSLionel Sambuc   Matchers.DeclOrStmt.push_back(std::make_pair(NodeMatch, Action));
928*0a6a1f1dSLionel Sambuc   Matchers.AllCallbacks.push_back(Action);
929f4a2713aSLionel Sambuc }
930f4a2713aSLionel Sambuc 
addMatcher(const NestedNameSpecifierMatcher & NodeMatch,MatchCallback * Action)931f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
932f4a2713aSLionel Sambuc                              MatchCallback *Action) {
933*0a6a1f1dSLionel Sambuc   Matchers.NestedNameSpecifier.push_back(std::make_pair(NodeMatch, Action));
934*0a6a1f1dSLionel Sambuc   Matchers.AllCallbacks.push_back(Action);
935f4a2713aSLionel Sambuc }
936f4a2713aSLionel Sambuc 
addMatcher(const NestedNameSpecifierLocMatcher & NodeMatch,MatchCallback * Action)937f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
938f4a2713aSLionel Sambuc                              MatchCallback *Action) {
939*0a6a1f1dSLionel Sambuc   Matchers.NestedNameSpecifierLoc.push_back(std::make_pair(NodeMatch, Action));
940*0a6a1f1dSLionel Sambuc   Matchers.AllCallbacks.push_back(Action);
941f4a2713aSLionel Sambuc }
942f4a2713aSLionel Sambuc 
addMatcher(const TypeLocMatcher & NodeMatch,MatchCallback * Action)943f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
944f4a2713aSLionel Sambuc                              MatchCallback *Action) {
945*0a6a1f1dSLionel Sambuc   Matchers.TypeLoc.push_back(std::make_pair(NodeMatch, Action));
946*0a6a1f1dSLionel Sambuc   Matchers.AllCallbacks.push_back(Action);
947f4a2713aSLionel Sambuc }
948f4a2713aSLionel Sambuc 
addDynamicMatcher(const internal::DynTypedMatcher & NodeMatch,MatchCallback * Action)949f4a2713aSLionel Sambuc bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
950f4a2713aSLionel Sambuc                                     MatchCallback *Action) {
951f4a2713aSLionel Sambuc   if (NodeMatch.canConvertTo<Decl>()) {
952f4a2713aSLionel Sambuc     addMatcher(NodeMatch.convertTo<Decl>(), Action);
953f4a2713aSLionel Sambuc     return true;
954f4a2713aSLionel Sambuc   } else if (NodeMatch.canConvertTo<QualType>()) {
955f4a2713aSLionel Sambuc     addMatcher(NodeMatch.convertTo<QualType>(), Action);
956f4a2713aSLionel Sambuc     return true;
957f4a2713aSLionel Sambuc   } else if (NodeMatch.canConvertTo<Stmt>()) {
958f4a2713aSLionel Sambuc     addMatcher(NodeMatch.convertTo<Stmt>(), Action);
959f4a2713aSLionel Sambuc     return true;
960f4a2713aSLionel Sambuc   } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) {
961f4a2713aSLionel Sambuc     addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action);
962f4a2713aSLionel Sambuc     return true;
963f4a2713aSLionel Sambuc   } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) {
964f4a2713aSLionel Sambuc     addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action);
965f4a2713aSLionel Sambuc     return true;
966f4a2713aSLionel Sambuc   } else if (NodeMatch.canConvertTo<TypeLoc>()) {
967f4a2713aSLionel Sambuc     addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
968f4a2713aSLionel Sambuc     return true;
969f4a2713aSLionel Sambuc   }
970f4a2713aSLionel Sambuc   return false;
971f4a2713aSLionel Sambuc }
972f4a2713aSLionel Sambuc 
newASTConsumer()973*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
974*0a6a1f1dSLionel Sambuc   return llvm::make_unique<internal::MatchASTConsumer>(this, ParsingDone);
975f4a2713aSLionel Sambuc }
976f4a2713aSLionel Sambuc 
match(const clang::ast_type_traits::DynTypedNode & Node,ASTContext & Context)977f4a2713aSLionel Sambuc void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
978f4a2713aSLionel Sambuc                         ASTContext &Context) {
979*0a6a1f1dSLionel Sambuc   internal::MatchASTVisitor Visitor(&Matchers, Options);
980f4a2713aSLionel Sambuc   Visitor.set_active_ast_context(&Context);
981f4a2713aSLionel Sambuc   Visitor.match(Node);
982f4a2713aSLionel Sambuc }
983f4a2713aSLionel Sambuc 
matchAST(ASTContext & Context)984f4a2713aSLionel Sambuc void MatchFinder::matchAST(ASTContext &Context) {
985*0a6a1f1dSLionel Sambuc   internal::MatchASTVisitor Visitor(&Matchers, Options);
986f4a2713aSLionel Sambuc   Visitor.set_active_ast_context(&Context);
987f4a2713aSLionel Sambuc   Visitor.onStartOfTranslationUnit();
988f4a2713aSLionel Sambuc   Visitor.TraverseDecl(Context.getTranslationUnitDecl());
989f4a2713aSLionel Sambuc   Visitor.onEndOfTranslationUnit();
990f4a2713aSLionel Sambuc }
991f4a2713aSLionel Sambuc 
registerTestCallbackAfterParsing(MatchFinder::ParsingDoneTestCallback * NewParsingDone)992f4a2713aSLionel Sambuc void MatchFinder::registerTestCallbackAfterParsing(
993f4a2713aSLionel Sambuc     MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
994f4a2713aSLionel Sambuc   ParsingDone = NewParsingDone;
995f4a2713aSLionel Sambuc }
996f4a2713aSLionel Sambuc 
getID() const997*0a6a1f1dSLionel Sambuc StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
998*0a6a1f1dSLionel Sambuc 
999f4a2713aSLionel Sambuc } // end namespace ast_matchers
1000f4a2713aSLionel Sambuc } // end namespace clang
1001