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