blob: c13cf4a277f3cfe096c3c188c55cf99c866fe588 [file] [log] [blame]
Manuel Klimek4da21662012-07-06 05:48:52 +00001//===--- ASTMatchFinder.cpp - Structural query framework ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implements an algorithm to efficiently search for matches on AST nodes.
11// Uses memoization to support recursive matches like HasDescendant.
12//
13// The general idea is to visit all AST nodes with a RecursiveASTVisitor,
14// calling the Matches(...) method of each matcher we are running on each
15// AST node. The matcher can recurse via the ASTMatchFinder interface.
16//
17//===----------------------------------------------------------------------===//
18
19#include "clang/ASTMatchers/ASTMatchFinder.h"
20#include "clang/AST/ASTConsumer.h"
21#include "clang/AST/ASTContext.h"
22#include "clang/AST/RecursiveASTVisitor.h"
23#include <set>
24
25namespace clang {
26namespace ast_matchers {
27namespace internal {
28namespace {
29
Manuel Klimeka78d0d62012-09-05 12:12:07 +000030typedef MatchFinder::MatchCallback MatchCallback;
31
Manuel Klimek579b1202012-09-07 09:26:10 +000032/// \brief A \c RecursiveASTVisitor that builds a map from nodes to their
33/// parents as defined by the \c RecursiveASTVisitor.
34///
35/// Note that the relationship described here is purely in terms of AST
36/// traversal - there are other relationships (for example declaration context)
37/// in the AST that are better modeled by special matchers.
38///
39/// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
40class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> {
41public:
42 /// \brief Maps from a node to its parent.
43 typedef llvm::DenseMap<const void*, ast_type_traits::DynTypedNode> ParentMap;
44
45 /// \brief Builds and returns the translation unit's parent map.
46 ///
47 /// The caller takes ownership of the returned \c ParentMap.
48 static ParentMap *buildMap(TranslationUnitDecl &TU) {
49 ParentMapASTVisitor Visitor(new ParentMap);
50 Visitor.TraverseDecl(&TU);
51 return Visitor.Parents;
52 }
53
54private:
55 typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase;
56
57 ParentMapASTVisitor(ParentMap *Parents) : Parents(Parents) {}
58
59 bool shouldVisitTemplateInstantiations() const { return true; }
60 bool shouldVisitImplicitCode() const { return true; }
Daniel Jasper278057f2012-11-15 03:29:05 +000061 // Disables data recursion. We intercept Traverse* methods in the RAV, which
62 // are not triggered during data recursion.
63 bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
Manuel Klimek579b1202012-09-07 09:26:10 +000064
65 template <typename T>
66 bool TraverseNode(T *Node, bool (VisitorBase::*traverse)(T*)) {
67 if (Node == NULL)
68 return true;
69 if (ParentStack.size() > 0)
70 (*Parents)[Node] = ParentStack.back();
71 ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node));
72 bool Result = (this->*traverse)(Node);
73 ParentStack.pop_back();
74 return Result;
75 }
76
77 bool TraverseDecl(Decl *DeclNode) {
78 return TraverseNode(DeclNode, &VisitorBase::TraverseDecl);
79 }
80
81 bool TraverseStmt(Stmt *StmtNode) {
82 return TraverseNode(StmtNode, &VisitorBase::TraverseStmt);
83 }
84
85 ParentMap *Parents;
86 llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack;
87
88 friend class RecursiveASTVisitor<ParentMapASTVisitor>;
89};
90
Manuel Klimek4da21662012-07-06 05:48:52 +000091// We use memoization to avoid running the same matcher on the same
92// AST node twice. This pair is the key for looking up match
93// result. It consists of an ID of the MatcherInterface (for
94// identifying the matcher) and a pointer to the AST node.
Manuel Klimeka78d0d62012-09-05 12:12:07 +000095//
96// We currently only memoize on nodes whose pointers identify the
97// nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
98// For \c QualType and \c TypeLoc it is possible to implement
99// generation of keys for each type.
100// FIXME: Benchmark whether memoization of non-pointer typed nodes
101// provides enough benefit for the additional amount of code.
Manuel Klimek4da21662012-07-06 05:48:52 +0000102typedef std::pair<uint64_t, const void*> UntypedMatchInput;
103
104// Used to store the result of a match and possibly bound nodes.
105struct MemoizedMatchResult {
106 bool ResultOfMatch;
107 BoundNodesTree Nodes;
108};
109
110// A RecursiveASTVisitor that traverses all children or all descendants of
111// a node.
112class MatchChildASTVisitor
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000113 : public RecursiveASTVisitor<MatchChildASTVisitor> {
Manuel Klimek4da21662012-07-06 05:48:52 +0000114public:
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000115 typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
Manuel Klimek4da21662012-07-06 05:48:52 +0000116
117 // Creates an AST visitor that matches 'matcher' on all children or
118 // descendants of a traversed node. max_depth is the maximum depth
119 // to traverse: use 1 for matching the children and INT_MAX for
120 // matching the descendants.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000121 MatchChildASTVisitor(const DynTypedMatcher *Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000122 ASTMatchFinder *Finder,
123 BoundNodesTreeBuilder *Builder,
124 int MaxDepth,
125 ASTMatchFinder::TraversalKind Traversal,
126 ASTMatchFinder::BindKind Bind)
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000127 : Matcher(Matcher),
Manuel Klimek4da21662012-07-06 05:48:52 +0000128 Finder(Finder),
129 Builder(Builder),
Daniel Jaspera267cf62012-10-29 10:14:44 +0000130 CurrentDepth(0),
Manuel Klimek4da21662012-07-06 05:48:52 +0000131 MaxDepth(MaxDepth),
132 Traversal(Traversal),
133 Bind(Bind),
134 Matches(false) {}
135
136 // Returns true if a match is found in the subtree rooted at the
137 // given AST node. This is done via a set of mutually recursive
138 // functions. Here's how the recursion is done (the *wildcard can
139 // actually be Decl, Stmt, or Type):
140 //
141 // - Traverse(node) calls BaseTraverse(node) when it needs
142 // to visit the descendants of node.
143 // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
144 // Traverse*(c) for each child c of 'node'.
145 // - Traverse*(c) in turn calls Traverse(c), completing the
146 // recursion.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000147 bool findMatch(const ast_type_traits::DynTypedNode &DynNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000148 reset();
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000149 if (const Decl *D = DynNode.get<Decl>())
150 traverse(*D);
151 else if (const Stmt *S = DynNode.get<Stmt>())
152 traverse(*S);
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000153 else if (const NestedNameSpecifier *NNS =
154 DynNode.get<NestedNameSpecifier>())
155 traverse(*NNS);
156 else if (const NestedNameSpecifierLoc *NNSLoc =
157 DynNode.get<NestedNameSpecifierLoc>())
158 traverse(*NNSLoc);
Daniel Jaspera267cf62012-10-29 10:14:44 +0000159 else if (const QualType *Q = DynNode.get<QualType>())
160 traverse(*Q);
161 else if (const TypeLoc *T = DynNode.get<TypeLoc>())
162 traverse(*T);
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000163 // FIXME: Add other base types after adding tests.
Manuel Klimek4da21662012-07-06 05:48:52 +0000164 return Matches;
165 }
166
167 // The following are overriding methods from the base visitor class.
168 // They are public only to allow CRTP to work. They are *not *part
169 // of the public API of this class.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000170 bool TraverseDecl(Decl *DeclNode) {
Daniel Jaspera267cf62012-10-29 10:14:44 +0000171 ScopedIncrement ScopedDepth(&CurrentDepth);
Manuel Klimek4da21662012-07-06 05:48:52 +0000172 return (DeclNode == NULL) || traverse(*DeclNode);
173 }
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000174 bool TraverseStmt(Stmt *StmtNode) {
Daniel Jaspera267cf62012-10-29 10:14:44 +0000175 ScopedIncrement ScopedDepth(&CurrentDepth);
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000176 const Stmt *StmtToTraverse = StmtNode;
Manuel Klimek4da21662012-07-06 05:48:52 +0000177 if (Traversal ==
178 ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) {
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000179 const Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000180 if (ExprNode != NULL) {
181 StmtToTraverse = ExprNode->IgnoreParenImpCasts();
182 }
183 }
184 return (StmtToTraverse == NULL) || traverse(*StmtToTraverse);
185 }
Daniel Jaspera267cf62012-10-29 10:14:44 +0000186 // We assume that the QualType and the contained type are on the same
187 // hierarchy level. Thus, we try to match either of them.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000188 bool TraverseType(QualType TypeNode) {
Daniel Jasperb55c67d2012-11-13 17:14:11 +0000189 if (TypeNode.isNull())
190 return true;
Daniel Jaspera267cf62012-10-29 10:14:44 +0000191 ScopedIncrement ScopedDepth(&CurrentDepth);
192 // Match the Type.
193 if (!match(*TypeNode))
194 return false;
195 // The QualType is matched inside traverse.
Manuel Klimek4da21662012-07-06 05:48:52 +0000196 return traverse(TypeNode);
197 }
Daniel Jaspera267cf62012-10-29 10:14:44 +0000198 // We assume that the TypeLoc, contained QualType and contained Type all are
199 // on the same hierarchy level. Thus, we try to match all of them.
200 bool TraverseTypeLoc(TypeLoc TypeLocNode) {
Daniel Jasperb55c67d2012-11-13 17:14:11 +0000201 if (TypeLocNode.isNull())
202 return true;
Daniel Jaspera267cf62012-10-29 10:14:44 +0000203 ScopedIncrement ScopedDepth(&CurrentDepth);
204 // Match the Type.
205 if (!match(*TypeLocNode.getType()))
206 return false;
207 // Match the QualType.
208 if (!match(TypeLocNode.getType()))
209 return false;
210 // The TypeLoc is matched inside traverse.
211 return traverse(TypeLocNode);
212 }
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000213 bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
214 ScopedIncrement ScopedDepth(&CurrentDepth);
215 return (NNS == NULL) || traverse(*NNS);
216 }
217 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
Daniel Jasperb55c67d2012-11-13 17:14:11 +0000218 if (!NNS)
219 return true;
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000220 ScopedIncrement ScopedDepth(&CurrentDepth);
221 if (!match(*NNS.getNestedNameSpecifier()))
222 return false;
Daniel Jasperb55c67d2012-11-13 17:14:11 +0000223 return traverse(NNS);
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000224 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000225
226 bool shouldVisitTemplateInstantiations() const { return true; }
227 bool shouldVisitImplicitCode() const { return true; }
Daniel Jasper278057f2012-11-15 03:29:05 +0000228 // Disables data recursion. We intercept Traverse* methods in the RAV, which
229 // are not triggered during data recursion.
230 bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
Manuel Klimek4da21662012-07-06 05:48:52 +0000231
232private:
233 // Used for updating the depth during traversal.
234 struct ScopedIncrement {
235 explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
236 ~ScopedIncrement() { --(*Depth); }
237
238 private:
239 int *Depth;
240 };
241
242 // Resets the state of this object.
243 void reset() {
244 Matches = false;
Daniel Jaspera267cf62012-10-29 10:14:44 +0000245 CurrentDepth = 0;
Manuel Klimek4da21662012-07-06 05:48:52 +0000246 }
247
248 // Forwards the call to the corresponding Traverse*() method in the
249 // base visitor class.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000250 bool baseTraverse(const Decl &DeclNode) {
251 return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
Manuel Klimek4da21662012-07-06 05:48:52 +0000252 }
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000253 bool baseTraverse(const Stmt &StmtNode) {
254 return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
Manuel Klimek4da21662012-07-06 05:48:52 +0000255 }
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000256 bool baseTraverse(QualType TypeNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000257 return VisitorBase::TraverseType(TypeNode);
258 }
Daniel Jaspera267cf62012-10-29 10:14:44 +0000259 bool baseTraverse(TypeLoc TypeLocNode) {
260 return VisitorBase::TraverseTypeLoc(TypeLocNode);
261 }
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000262 bool baseTraverse(const NestedNameSpecifier &NNS) {
263 return VisitorBase::TraverseNestedNameSpecifier(
264 const_cast<NestedNameSpecifier*>(&NNS));
265 }
266 bool baseTraverse(NestedNameSpecifierLoc NNS) {
267 return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
268 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000269
Daniel Jaspera267cf62012-10-29 10:14:44 +0000270 // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
271 // 0 < CurrentDepth <= MaxDepth.
272 //
273 // Returns 'true' if traversal should continue after this function
274 // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
Manuel Klimek4da21662012-07-06 05:48:52 +0000275 template <typename T>
Daniel Jaspera267cf62012-10-29 10:14:44 +0000276 bool match(const T &Node) {
277 if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
278 return true;
Manuel Klimek4da21662012-07-06 05:48:52 +0000279 }
280 if (Bind != ASTMatchFinder::BK_All) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000281 if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node),
282 Finder, Builder)) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000283 Matches = true;
284 return false; // Abort as soon as a match is found.
285 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000286 } else {
287 BoundNodesTreeBuilder RecursiveBuilder;
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000288 if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node),
289 Finder, &RecursiveBuilder)) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000290 // After the first match the matcher succeeds.
291 Matches = true;
292 Builder->addMatch(RecursiveBuilder.build());
293 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000294 }
Daniel Jaspera267cf62012-10-29 10:14:44 +0000295 return true;
296 }
297
298 // Traverses the subtree rooted at 'Node'; returns true if the
299 // traversal should continue after this function returns.
300 template <typename T>
301 bool traverse(const T &Node) {
302 TOOLING_COMPILE_ASSERT(IsBaseType<T>::value,
303 traverse_can_only_be_instantiated_with_base_type);
304 if (!match(Node))
305 return false;
306 return baseTraverse(Node);
Manuel Klimek4da21662012-07-06 05:48:52 +0000307 }
308
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000309 const DynTypedMatcher *const Matcher;
Manuel Klimek4da21662012-07-06 05:48:52 +0000310 ASTMatchFinder *const Finder;
311 BoundNodesTreeBuilder *const Builder;
312 int CurrentDepth;
313 const int MaxDepth;
314 const ASTMatchFinder::TraversalKind Traversal;
315 const ASTMatchFinder::BindKind Bind;
316 bool Matches;
317};
318
319// Controls the outermost traversal of the AST and allows to match multiple
320// matchers.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000321class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
Manuel Klimek4da21662012-07-06 05:48:52 +0000322 public ASTMatchFinder {
323public:
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000324 MatchASTVisitor(std::vector<std::pair<const internal::DynTypedMatcher*,
325 MatchCallback*> > *MatcherCallbackPairs)
326 : MatcherCallbackPairs(MatcherCallbackPairs),
Manuel Klimek4da21662012-07-06 05:48:52 +0000327 ActiveASTContext(NULL) {
328 }
329
Manuel Klimeke5793282012-11-02 01:31:03 +0000330 void onStartOfTranslationUnit() {
331 for (std::vector<std::pair<const internal::DynTypedMatcher*,
332 MatchCallback*> >::const_iterator
333 I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
334 I != E; ++I) {
335 I->second->onStartOfTranslationUnit();
336 }
337 }
338
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000339 void set_active_ast_context(ASTContext *NewActiveASTContext) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000340 ActiveASTContext = NewActiveASTContext;
341 }
342
343 // The following Visit*() and Traverse*() functions "override"
344 // methods in RecursiveASTVisitor.
345
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000346 bool VisitTypedefDecl(TypedefDecl *DeclNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000347 // When we see 'typedef A B', we add name 'B' to the set of names
348 // A's canonical type maps to. This is necessary for implementing
Daniel Jasper76dafa72012-09-07 12:48:17 +0000349 // isDerivedFrom(x) properly, where x can be the name of the base
Manuel Klimek4da21662012-07-06 05:48:52 +0000350 // class or any of its aliases.
351 //
352 // In general, the is-alias-of (as defined by typedefs) relation
353 // is tree-shaped, as you can typedef a type more than once. For
354 // example,
355 //
356 // typedef A B;
357 // typedef A C;
358 // typedef C D;
359 // typedef C E;
360 //
361 // gives you
362 //
363 // A
364 // |- B
365 // `- C
366 // |- D
367 // `- E
368 //
369 // It is wrong to assume that the relation is a chain. A correct
Daniel Jasper76dafa72012-09-07 12:48:17 +0000370 // implementation of isDerivedFrom() needs to recognize that B and
Manuel Klimek4da21662012-07-06 05:48:52 +0000371 // E are aliases, even though neither is a typedef of the other.
372 // Therefore, we cannot simply walk through one typedef chain to
373 // find out whether the type name matches.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000374 const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
375 const Type *CanonicalType = // root of the typedef tree
Manuel Klimek4da21662012-07-06 05:48:52 +0000376 ActiveASTContext->getCanonicalType(TypeNode);
Daniel Jasper20b802d2012-07-17 07:39:27 +0000377 TypeAliases[CanonicalType].insert(DeclNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000378 return true;
379 }
380
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000381 bool TraverseDecl(Decl *DeclNode);
382 bool TraverseStmt(Stmt *StmtNode);
383 bool TraverseType(QualType TypeNode);
384 bool TraverseTypeLoc(TypeLoc TypeNode);
Daniel Jaspera7564432012-09-13 13:11:25 +0000385 bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
386 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
Manuel Klimek4da21662012-07-06 05:48:52 +0000387
388 // Matches children or descendants of 'Node' with 'BaseMatcher'.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000389 bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node,
390 const DynTypedMatcher &Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000391 BoundNodesTreeBuilder *Builder, int MaxDepth,
392 TraversalKind Traversal, BindKind Bind) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000393 const UntypedMatchInput input(Matcher.getID(), Node.getMemoizationData());
Daniel Jaspera267cf62012-10-29 10:14:44 +0000394
395 // For AST-nodes that don't have an identity, we can't memoize.
396 if (!input.second)
397 return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal,
398 Bind);
399
Manuel Klimek4da21662012-07-06 05:48:52 +0000400 std::pair<MemoizationMap::iterator, bool> InsertResult
401 = ResultCache.insert(std::make_pair(input, MemoizedMatchResult()));
402 if (InsertResult.second) {
403 BoundNodesTreeBuilder DescendantBoundNodesBuilder;
404 InsertResult.first->second.ResultOfMatch =
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000405 matchesRecursively(Node, Matcher, &DescendantBoundNodesBuilder,
Manuel Klimek4da21662012-07-06 05:48:52 +0000406 MaxDepth, Traversal, Bind);
407 InsertResult.first->second.Nodes =
408 DescendantBoundNodesBuilder.build();
409 }
410 InsertResult.first->second.Nodes.copyTo(Builder);
411 return InsertResult.first->second.ResultOfMatch;
412 }
413
414 // Matches children or descendants of 'Node' with 'BaseMatcher'.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000415 bool matchesRecursively(const ast_type_traits::DynTypedNode &Node,
416 const DynTypedMatcher &Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000417 BoundNodesTreeBuilder *Builder, int MaxDepth,
418 TraversalKind Traversal, BindKind Bind) {
419 MatchChildASTVisitor Visitor(
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000420 &Matcher, this, Builder, MaxDepth, Traversal, Bind);
Manuel Klimek4da21662012-07-06 05:48:52 +0000421 return Visitor.findMatch(Node);
422 }
423
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000424 virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
Daniel Jasper20b802d2012-07-17 07:39:27 +0000425 const Matcher<NamedDecl> &Base,
426 BoundNodesTreeBuilder *Builder);
Manuel Klimek4da21662012-07-06 05:48:52 +0000427
Daniel Jasperc99a3ad2012-10-22 16:26:51 +0000428 // Implements ASTMatchFinder::matchesChildOf.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000429 virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
430 const DynTypedMatcher &Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000431 BoundNodesTreeBuilder *Builder,
432 TraversalKind Traversal,
433 BindKind Bind) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000434 return matchesRecursively(Node, Matcher, Builder, 1, Traversal,
Manuel Klimek4da21662012-07-06 05:48:52 +0000435 Bind);
436 }
Daniel Jasperc99a3ad2012-10-22 16:26:51 +0000437 // Implements ASTMatchFinder::matchesDescendantOf.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000438 virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
439 const DynTypedMatcher &Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000440 BoundNodesTreeBuilder *Builder,
441 BindKind Bind) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000442 return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX,
Manuel Klimek4da21662012-07-06 05:48:52 +0000443 TK_AsIs, Bind);
444 }
Manuel Klimek579b1202012-09-07 09:26:10 +0000445 // Implements ASTMatchFinder::matchesAncestorOf.
446 virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
447 const DynTypedMatcher &Matcher,
Daniel Jasperc99a3ad2012-10-22 16:26:51 +0000448 BoundNodesTreeBuilder *Builder,
449 AncestorMatchMode MatchMode) {
Manuel Klimek579b1202012-09-07 09:26:10 +0000450 if (!Parents) {
451 // We always need to run over the whole translation unit, as
452 // \c hasAncestor can escape any subtree.
453 Parents.reset(ParentMapASTVisitor::buildMap(
454 *ActiveASTContext->getTranslationUnitDecl()));
455 }
456 ast_type_traits::DynTypedNode Ancestor = Node;
457 while (Ancestor.get<TranslationUnitDecl>() !=
458 ActiveASTContext->getTranslationUnitDecl()) {
459 assert(Ancestor.getMemoizationData() &&
460 "Invariant broken: only nodes that support memoization may be "
461 "used in the parent map.");
462 ParentMapASTVisitor::ParentMap::const_iterator I =
463 Parents->find(Ancestor.getMemoizationData());
464 if (I == Parents->end()) {
465 assert(false &&
466 "Found node that is not in the parent map.");
467 return false;
468 }
469 Ancestor = I->second;
470 if (Matcher.matches(Ancestor, this, Builder))
471 return true;
Daniel Jasperc99a3ad2012-10-22 16:26:51 +0000472 if (MatchMode == ASTMatchFinder::AMM_ParentOnly)
473 return false;
Manuel Klimek579b1202012-09-07 09:26:10 +0000474 }
475 return false;
476 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000477
Manuel Klimek7f2d4802012-11-30 13:45:19 +0000478 // Implements ASTMatchFinder::getASTContext.
479 virtual ASTContext &getASTContext() const { return *ActiveASTContext; }
480
Manuel Klimek4da21662012-07-06 05:48:52 +0000481 bool shouldVisitTemplateInstantiations() const { return true; }
482 bool shouldVisitImplicitCode() const { return true; }
Daniel Jasper278057f2012-11-15 03:29:05 +0000483 // Disables data recursion. We intercept Traverse* methods in the RAV, which
484 // are not triggered during data recursion.
485 bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
Manuel Klimek4da21662012-07-06 05:48:52 +0000486
487private:
488 // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
489 // the aggregated bound nodes for each match.
490 class MatchVisitor : public BoundNodesTree::Visitor {
491 public:
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000492 MatchVisitor(ASTContext* Context,
Manuel Klimek4da21662012-07-06 05:48:52 +0000493 MatchFinder::MatchCallback* Callback)
494 : Context(Context),
495 Callback(Callback) {}
496
497 virtual void visitMatch(const BoundNodes& BoundNodesView) {
498 Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
499 }
500
501 private:
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000502 ASTContext* Context;
Manuel Klimek4da21662012-07-06 05:48:52 +0000503 MatchFinder::MatchCallback* Callback;
504 };
505
Daniel Jasper20b802d2012-07-17 07:39:27 +0000506 // Returns true if 'TypeNode' has an alias that matches the given matcher.
507 bool typeHasMatchingAlias(const Type *TypeNode,
508 const Matcher<NamedDecl> Matcher,
509 BoundNodesTreeBuilder *Builder) {
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000510 const Type *const CanonicalType =
Manuel Klimek4da21662012-07-06 05:48:52 +0000511 ActiveASTContext->getCanonicalType(TypeNode);
Daniel Jasper20b802d2012-07-17 07:39:27 +0000512 const std::set<const TypedefDecl*> &Aliases = TypeAliases[CanonicalType];
513 for (std::set<const TypedefDecl*>::const_iterator
514 It = Aliases.begin(), End = Aliases.end();
515 It != End; ++It) {
516 if (Matcher.matches(**It, this, Builder))
517 return true;
518 }
519 return false;
Manuel Klimek4da21662012-07-06 05:48:52 +0000520 }
521
522 // Matches all registered matchers on the given node and calls the
523 // result callback for every node that matches.
524 template <typename T>
525 void match(const T &node) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000526 for (std::vector<std::pair<const internal::DynTypedMatcher*,
527 MatchCallback*> >::const_iterator
528 I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
529 I != E; ++I) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000530 BoundNodesTreeBuilder Builder;
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000531 if (I->first->matches(ast_type_traits::DynTypedNode::create(node),
532 this, &Builder)) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000533 BoundNodesTree BoundNodes = Builder.build();
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000534 MatchVisitor Visitor(ActiveASTContext, I->second);
Manuel Klimek4da21662012-07-06 05:48:52 +0000535 BoundNodes.visitMatches(&Visitor);
536 }
537 }
538 }
539
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000540 std::vector<std::pair<const internal::DynTypedMatcher*,
541 MatchCallback*> > *const MatcherCallbackPairs;
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000542 ASTContext *ActiveASTContext;
Manuel Klimek4da21662012-07-06 05:48:52 +0000543
Daniel Jasper20b802d2012-07-17 07:39:27 +0000544 // Maps a canonical type to its TypedefDecls.
545 llvm::DenseMap<const Type*, std::set<const TypedefDecl*> > TypeAliases;
Manuel Klimek4da21662012-07-06 05:48:52 +0000546
547 // Maps (matcher, node) -> the match result for memoization.
548 typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult> MemoizationMap;
549 MemoizationMap ResultCache;
Manuel Klimek579b1202012-09-07 09:26:10 +0000550
551 llvm::OwningPtr<ParentMapASTVisitor::ParentMap> Parents;
Manuel Klimek4da21662012-07-06 05:48:52 +0000552};
553
554// Returns true if the given class is directly or indirectly derived
Daniel Jasper76dafa72012-09-07 12:48:17 +0000555// from a base type with the given name. A class is not considered to be
556// derived from itself.
Daniel Jasper20b802d2012-07-17 07:39:27 +0000557bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
558 const Matcher<NamedDecl> &Base,
559 BoundNodesTreeBuilder *Builder) {
Daniel Jasper20b802d2012-07-17 07:39:27 +0000560 if (!Declaration->hasDefinition())
Manuel Klimek4da21662012-07-06 05:48:52 +0000561 return false;
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000562 typedef CXXRecordDecl::base_class_const_iterator BaseIterator;
Manuel Klimek4da21662012-07-06 05:48:52 +0000563 for (BaseIterator It = Declaration->bases_begin(),
564 End = Declaration->bases_end(); It != End; ++It) {
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000565 const Type *TypeNode = It->getType().getTypePtr();
Manuel Klimek4da21662012-07-06 05:48:52 +0000566
Daniel Jasper20b802d2012-07-17 07:39:27 +0000567 if (typeHasMatchingAlias(TypeNode, Base, Builder))
Manuel Klimek4da21662012-07-06 05:48:52 +0000568 return true;
569
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000570 // Type::getAs<...>() drills through typedefs.
571 if (TypeNode->getAs<DependentNameType>() != NULL ||
Daniel Jasper08f0c532012-09-18 14:17:42 +0000572 TypeNode->getAs<DependentTemplateSpecializationType>() != NULL ||
Daniel Jasper20b802d2012-07-17 07:39:27 +0000573 TypeNode->getAs<TemplateTypeParmType>() != NULL)
Manuel Klimek4da21662012-07-06 05:48:52 +0000574 // Dependent names and template TypeNode parameters will be matched when
575 // the template is instantiated.
576 continue;
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000577 CXXRecordDecl *ClassDecl = NULL;
578 TemplateSpecializationType const *TemplateType =
579 TypeNode->getAs<TemplateSpecializationType>();
Manuel Klimek4da21662012-07-06 05:48:52 +0000580 if (TemplateType != NULL) {
Daniel Jasper20b802d2012-07-17 07:39:27 +0000581 if (TemplateType->getTemplateName().isDependent())
Manuel Klimek4da21662012-07-06 05:48:52 +0000582 // Dependent template specializations will be matched when the
583 // template is instantiated.
584 continue;
Daniel Jasper20b802d2012-07-17 07:39:27 +0000585
Manuel Klimek4da21662012-07-06 05:48:52 +0000586 // For template specialization types which are specializing a template
587 // declaration which is an explicit or partial specialization of another
588 // template declaration, getAsCXXRecordDecl() returns the corresponding
589 // ClassTemplateSpecializationDecl.
590 //
591 // For template specialization types which are specializing a template
592 // declaration which is neither an explicit nor partial specialization of
593 // another template declaration, getAsCXXRecordDecl() returns NULL and
594 // we get the CXXRecordDecl of the templated declaration.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000595 CXXRecordDecl *SpecializationDecl =
Manuel Klimek4da21662012-07-06 05:48:52 +0000596 TemplateType->getAsCXXRecordDecl();
597 if (SpecializationDecl != NULL) {
598 ClassDecl = SpecializationDecl;
599 } else {
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000600 ClassDecl = llvm::dyn_cast<CXXRecordDecl>(
Manuel Klimek4da21662012-07-06 05:48:52 +0000601 TemplateType->getTemplateName()
602 .getAsTemplateDecl()->getTemplatedDecl());
603 }
604 } else {
605 ClassDecl = TypeNode->getAsCXXRecordDecl();
606 }
607 assert(ClassDecl != NULL);
608 assert(ClassDecl != Declaration);
Daniel Jasper76dafa72012-09-07 12:48:17 +0000609 if (Base.matches(*ClassDecl, this, Builder))
610 return true;
Daniel Jasper20b802d2012-07-17 07:39:27 +0000611 if (classIsDerivedFrom(ClassDecl, Base, Builder))
Manuel Klimek4da21662012-07-06 05:48:52 +0000612 return true;
Manuel Klimek4da21662012-07-06 05:48:52 +0000613 }
614 return false;
615}
616
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000617bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000618 if (DeclNode == NULL) {
619 return true;
620 }
621 match(*DeclNode);
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000622 return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000623}
624
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000625bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000626 if (StmtNode == NULL) {
627 return true;
628 }
629 match(*StmtNode);
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000630 return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000631}
632
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000633bool MatchASTVisitor::TraverseType(QualType TypeNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000634 match(TypeNode);
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000635 return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000636}
637
Daniel Jasperce620072012-10-17 08:52:59 +0000638bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
639 // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
640 // We still want to find those types via matchers, so we match them here. Note
641 // that the TypeLocs are structurally a shadow-hierarchy to the expressed
642 // type, so we visit all involved parts of a compound type when matching on
643 // each TypeLoc.
644 match(TypeLocNode);
645 match(TypeLocNode.getType());
646 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000647}
648
Daniel Jaspera7564432012-09-13 13:11:25 +0000649bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
650 match(*NNS);
651 return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
652}
653
654bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
655 NestedNameSpecifierLoc NNS) {
656 match(NNS);
657 // We only match the nested name specifier here (as opposed to traversing it)
658 // because the traversal is already done in the parallel "Loc"-hierarchy.
659 match(*NNS.getNestedNameSpecifier());
660 return
661 RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
662}
663
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000664class MatchASTConsumer : public ASTConsumer {
Manuel Klimek4da21662012-07-06 05:48:52 +0000665public:
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000666 MatchASTConsumer(
667 std::vector<std::pair<const internal::DynTypedMatcher*,
668 MatchCallback*> > *MatcherCallbackPairs,
669 MatchFinder::ParsingDoneTestCallback *ParsingDone)
670 : Visitor(MatcherCallbackPairs),
671 ParsingDone(ParsingDone) {}
Manuel Klimek4da21662012-07-06 05:48:52 +0000672
673private:
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000674 virtual void HandleTranslationUnit(ASTContext &Context) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000675 if (ParsingDone != NULL) {
676 ParsingDone->run();
677 }
678 Visitor.set_active_ast_context(&Context);
Manuel Klimeke5793282012-11-02 01:31:03 +0000679 Visitor.onStartOfTranslationUnit();
Manuel Klimek4da21662012-07-06 05:48:52 +0000680 Visitor.TraverseDecl(Context.getTranslationUnitDecl());
681 Visitor.set_active_ast_context(NULL);
682 }
683
684 MatchASTVisitor Visitor;
685 MatchFinder::ParsingDoneTestCallback *ParsingDone;
686};
687
688} // end namespace
689} // end namespace internal
690
691MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes,
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000692 ASTContext *Context)
Manuel Klimek4da21662012-07-06 05:48:52 +0000693 : Nodes(Nodes), Context(Context),
694 SourceManager(&Context->getSourceManager()) {}
695
696MatchFinder::MatchCallback::~MatchCallback() {}
697MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
698
699MatchFinder::MatchFinder() : ParsingDone(NULL) {}
700
701MatchFinder::~MatchFinder() {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000702 for (std::vector<std::pair<const internal::DynTypedMatcher*,
703 MatchCallback*> >::const_iterator
704 It = MatcherCallbackPairs.begin(), End = MatcherCallbackPairs.end();
Manuel Klimek4da21662012-07-06 05:48:52 +0000705 It != End; ++It) {
706 delete It->first;
707 }
708}
709
710void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
711 MatchCallback *Action) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000712 MatcherCallbackPairs.push_back(std::make_pair(
713 new internal::Matcher<Decl>(NodeMatch), Action));
Manuel Klimek4da21662012-07-06 05:48:52 +0000714}
715
716void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
717 MatchCallback *Action) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000718 MatcherCallbackPairs.push_back(std::make_pair(
719 new internal::Matcher<QualType>(NodeMatch), Action));
Manuel Klimek4da21662012-07-06 05:48:52 +0000720}
721
722void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
723 MatchCallback *Action) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000724 MatcherCallbackPairs.push_back(std::make_pair(
725 new internal::Matcher<Stmt>(NodeMatch), Action));
Manuel Klimek4da21662012-07-06 05:48:52 +0000726}
727
Daniel Jaspera7564432012-09-13 13:11:25 +0000728void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
729 MatchCallback *Action) {
730 MatcherCallbackPairs.push_back(std::make_pair(
731 new NestedNameSpecifierMatcher(NodeMatch), Action));
732}
733
734void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
735 MatchCallback *Action) {
736 MatcherCallbackPairs.push_back(std::make_pair(
737 new NestedNameSpecifierLocMatcher(NodeMatch), Action));
738}
739
Daniel Jasperce620072012-10-17 08:52:59 +0000740void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
741 MatchCallback *Action) {
742 MatcherCallbackPairs.push_back(std::make_pair(
743 new TypeLocMatcher(NodeMatch), Action));
744}
745
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000746ASTConsumer *MatchFinder::newASTConsumer() {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000747 return new internal::MatchASTConsumer(&MatcherCallbackPairs, ParsingDone);
Manuel Klimek4da21662012-07-06 05:48:52 +0000748}
749
Manuel Klimek3e2aa992012-10-24 14:47:44 +0000750void MatchFinder::findAll(const Decl &Node, ASTContext &Context) {
751 internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
752 Visitor.set_active_ast_context(&Context);
753 Visitor.TraverseDecl(const_cast<Decl*>(&Node));
754}
755
756void MatchFinder::findAll(const Stmt &Node, ASTContext &Context) {
757 internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
758 Visitor.set_active_ast_context(&Context);
759 Visitor.TraverseStmt(const_cast<Stmt*>(&Node));
760}
761
Manuel Klimek4da21662012-07-06 05:48:52 +0000762void MatchFinder::registerTestCallbackAfterParsing(
763 MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
764 ParsingDone = NewParsingDone;
765}
766
767} // end namespace ast_matchers
768} // end namespace clang