blob: 1af2f09c3efc64a064dce6f4f99f2cf0cdea3f1a [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 Klimek4da21662012-07-06 05:48:52 +000032// We use memoization to avoid running the same matcher on the same
33// AST node twice. This pair is the key for looking up match
34// result. It consists of an ID of the MatcherInterface (for
35// identifying the matcher) and a pointer to the AST node.
Manuel Klimeka78d0d62012-09-05 12:12:07 +000036//
37// We currently only memoize on nodes whose pointers identify the
38// nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
39// For \c QualType and \c TypeLoc it is possible to implement
40// generation of keys for each type.
41// FIXME: Benchmark whether memoization of non-pointer typed nodes
42// provides enough benefit for the additional amount of code.
Manuel Klimek4da21662012-07-06 05:48:52 +000043typedef std::pair<uint64_t, const void*> UntypedMatchInput;
44
45// Used to store the result of a match and possibly bound nodes.
46struct MemoizedMatchResult {
47 bool ResultOfMatch;
48 BoundNodesTree Nodes;
49};
50
51// A RecursiveASTVisitor that traverses all children or all descendants of
52// a node.
53class MatchChildASTVisitor
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +000054 : public RecursiveASTVisitor<MatchChildASTVisitor> {
Manuel Klimek4da21662012-07-06 05:48:52 +000055public:
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +000056 typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
Manuel Klimek4da21662012-07-06 05:48:52 +000057
58 // Creates an AST visitor that matches 'matcher' on all children or
59 // descendants of a traversed node. max_depth is the maximum depth
60 // to traverse: use 1 for matching the children and INT_MAX for
61 // matching the descendants.
Manuel Klimeka78d0d62012-09-05 12:12:07 +000062 MatchChildASTVisitor(const DynTypedMatcher *Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +000063 ASTMatchFinder *Finder,
64 BoundNodesTreeBuilder *Builder,
65 int MaxDepth,
66 ASTMatchFinder::TraversalKind Traversal,
67 ASTMatchFinder::BindKind Bind)
Manuel Klimeka78d0d62012-09-05 12:12:07 +000068 : Matcher(Matcher),
Manuel Klimek4da21662012-07-06 05:48:52 +000069 Finder(Finder),
70 Builder(Builder),
Daniel Jaspera267cf62012-10-29 10:14:44 +000071 CurrentDepth(0),
Manuel Klimek4da21662012-07-06 05:48:52 +000072 MaxDepth(MaxDepth),
73 Traversal(Traversal),
74 Bind(Bind),
75 Matches(false) {}
76
77 // Returns true if a match is found in the subtree rooted at the
78 // given AST node. This is done via a set of mutually recursive
79 // functions. Here's how the recursion is done (the *wildcard can
80 // actually be Decl, Stmt, or Type):
81 //
82 // - Traverse(node) calls BaseTraverse(node) when it needs
83 // to visit the descendants of node.
84 // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
85 // Traverse*(c) for each child c of 'node'.
86 // - Traverse*(c) in turn calls Traverse(c), completing the
87 // recursion.
Manuel Klimeka78d0d62012-09-05 12:12:07 +000088 bool findMatch(const ast_type_traits::DynTypedNode &DynNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +000089 reset();
Manuel Klimeka78d0d62012-09-05 12:12:07 +000090 if (const Decl *D = DynNode.get<Decl>())
91 traverse(*D);
92 else if (const Stmt *S = DynNode.get<Stmt>())
93 traverse(*S);
Daniel Jasperd1ce3c12012-10-30 15:42:00 +000094 else if (const NestedNameSpecifier *NNS =
95 DynNode.get<NestedNameSpecifier>())
96 traverse(*NNS);
97 else if (const NestedNameSpecifierLoc *NNSLoc =
98 DynNode.get<NestedNameSpecifierLoc>())
99 traverse(*NNSLoc);
Daniel Jaspera267cf62012-10-29 10:14:44 +0000100 else if (const QualType *Q = DynNode.get<QualType>())
101 traverse(*Q);
102 else if (const TypeLoc *T = DynNode.get<TypeLoc>())
103 traverse(*T);
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000104 // FIXME: Add other base types after adding tests.
Manuel Klimek4da21662012-07-06 05:48:52 +0000105 return Matches;
106 }
107
108 // The following are overriding methods from the base visitor class.
109 // They are public only to allow CRTP to work. They are *not *part
110 // of the public API of this class.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000111 bool TraverseDecl(Decl *DeclNode) {
Daniel Jaspera267cf62012-10-29 10:14:44 +0000112 ScopedIncrement ScopedDepth(&CurrentDepth);
Manuel Klimek4da21662012-07-06 05:48:52 +0000113 return (DeclNode == NULL) || traverse(*DeclNode);
114 }
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000115 bool TraverseStmt(Stmt *StmtNode) {
Daniel Jaspera267cf62012-10-29 10:14:44 +0000116 ScopedIncrement ScopedDepth(&CurrentDepth);
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000117 const Stmt *StmtToTraverse = StmtNode;
Manuel Klimek4da21662012-07-06 05:48:52 +0000118 if (Traversal ==
119 ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) {
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000120 const Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000121 if (ExprNode != NULL) {
122 StmtToTraverse = ExprNode->IgnoreParenImpCasts();
123 }
124 }
125 return (StmtToTraverse == NULL) || traverse(*StmtToTraverse);
126 }
Daniel Jaspera267cf62012-10-29 10:14:44 +0000127 // We assume that the QualType and the contained type are on the same
128 // hierarchy level. Thus, we try to match either of them.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000129 bool TraverseType(QualType TypeNode) {
Daniel Jasperb55c67d2012-11-13 17:14:11 +0000130 if (TypeNode.isNull())
131 return true;
Daniel Jaspera267cf62012-10-29 10:14:44 +0000132 ScopedIncrement ScopedDepth(&CurrentDepth);
133 // Match the Type.
134 if (!match(*TypeNode))
135 return false;
136 // The QualType is matched inside traverse.
Manuel Klimek4da21662012-07-06 05:48:52 +0000137 return traverse(TypeNode);
138 }
Daniel Jaspera267cf62012-10-29 10:14:44 +0000139 // We assume that the TypeLoc, contained QualType and contained Type all are
140 // on the same hierarchy level. Thus, we try to match all of them.
141 bool TraverseTypeLoc(TypeLoc TypeLocNode) {
Daniel Jasperb55c67d2012-11-13 17:14:11 +0000142 if (TypeLocNode.isNull())
143 return true;
Daniel Jaspera267cf62012-10-29 10:14:44 +0000144 ScopedIncrement ScopedDepth(&CurrentDepth);
145 // Match the Type.
146 if (!match(*TypeLocNode.getType()))
147 return false;
148 // Match the QualType.
149 if (!match(TypeLocNode.getType()))
150 return false;
151 // The TypeLoc is matched inside traverse.
152 return traverse(TypeLocNode);
153 }
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000154 bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
155 ScopedIncrement ScopedDepth(&CurrentDepth);
156 return (NNS == NULL) || traverse(*NNS);
157 }
158 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
Daniel Jasperb55c67d2012-11-13 17:14:11 +0000159 if (!NNS)
160 return true;
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000161 ScopedIncrement ScopedDepth(&CurrentDepth);
162 if (!match(*NNS.getNestedNameSpecifier()))
163 return false;
Daniel Jasperb55c67d2012-11-13 17:14:11 +0000164 return traverse(NNS);
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000165 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000166
167 bool shouldVisitTemplateInstantiations() const { return true; }
168 bool shouldVisitImplicitCode() const { return true; }
Daniel Jasper278057f2012-11-15 03:29:05 +0000169 // Disables data recursion. We intercept Traverse* methods in the RAV, which
170 // are not triggered during data recursion.
171 bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
Manuel Klimek4da21662012-07-06 05:48:52 +0000172
173private:
174 // Used for updating the depth during traversal.
175 struct ScopedIncrement {
176 explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
177 ~ScopedIncrement() { --(*Depth); }
178
179 private:
180 int *Depth;
181 };
182
183 // Resets the state of this object.
184 void reset() {
185 Matches = false;
Daniel Jaspera267cf62012-10-29 10:14:44 +0000186 CurrentDepth = 0;
Manuel Klimek4da21662012-07-06 05:48:52 +0000187 }
188
189 // Forwards the call to the corresponding Traverse*() method in the
190 // base visitor class.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000191 bool baseTraverse(const Decl &DeclNode) {
192 return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
Manuel Klimek4da21662012-07-06 05:48:52 +0000193 }
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000194 bool baseTraverse(const Stmt &StmtNode) {
195 return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
Manuel Klimek4da21662012-07-06 05:48:52 +0000196 }
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000197 bool baseTraverse(QualType TypeNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000198 return VisitorBase::TraverseType(TypeNode);
199 }
Daniel Jaspera267cf62012-10-29 10:14:44 +0000200 bool baseTraverse(TypeLoc TypeLocNode) {
201 return VisitorBase::TraverseTypeLoc(TypeLocNode);
202 }
Daniel Jasperd1ce3c12012-10-30 15:42:00 +0000203 bool baseTraverse(const NestedNameSpecifier &NNS) {
204 return VisitorBase::TraverseNestedNameSpecifier(
205 const_cast<NestedNameSpecifier*>(&NNS));
206 }
207 bool baseTraverse(NestedNameSpecifierLoc NNS) {
208 return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
209 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000210
Daniel Jaspera267cf62012-10-29 10:14:44 +0000211 // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
212 // 0 < CurrentDepth <= MaxDepth.
213 //
214 // Returns 'true' if traversal should continue after this function
215 // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
Manuel Klimek4da21662012-07-06 05:48:52 +0000216 template <typename T>
Daniel Jaspera267cf62012-10-29 10:14:44 +0000217 bool match(const T &Node) {
218 if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
219 return true;
Manuel Klimek4da21662012-07-06 05:48:52 +0000220 }
221 if (Bind != ASTMatchFinder::BK_All) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000222 if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node),
223 Finder, Builder)) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000224 Matches = true;
225 return false; // Abort as soon as a match is found.
226 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000227 } else {
228 BoundNodesTreeBuilder RecursiveBuilder;
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000229 if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node),
230 Finder, &RecursiveBuilder)) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000231 // After the first match the matcher succeeds.
232 Matches = true;
233 Builder->addMatch(RecursiveBuilder.build());
234 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000235 }
Daniel Jaspera267cf62012-10-29 10:14:44 +0000236 return true;
237 }
238
239 // Traverses the subtree rooted at 'Node'; returns true if the
240 // traversal should continue after this function returns.
241 template <typename T>
242 bool traverse(const T &Node) {
243 TOOLING_COMPILE_ASSERT(IsBaseType<T>::value,
244 traverse_can_only_be_instantiated_with_base_type);
245 if (!match(Node))
246 return false;
247 return baseTraverse(Node);
Manuel Klimek4da21662012-07-06 05:48:52 +0000248 }
249
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000250 const DynTypedMatcher *const Matcher;
Manuel Klimek4da21662012-07-06 05:48:52 +0000251 ASTMatchFinder *const Finder;
252 BoundNodesTreeBuilder *const Builder;
253 int CurrentDepth;
254 const int MaxDepth;
255 const ASTMatchFinder::TraversalKind Traversal;
256 const ASTMatchFinder::BindKind Bind;
257 bool Matches;
258};
259
260// Controls the outermost traversal of the AST and allows to match multiple
261// matchers.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000262class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
Manuel Klimek4da21662012-07-06 05:48:52 +0000263 public ASTMatchFinder {
264public:
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000265 MatchASTVisitor(std::vector<std::pair<const internal::DynTypedMatcher*,
266 MatchCallback*> > *MatcherCallbackPairs)
267 : MatcherCallbackPairs(MatcherCallbackPairs),
Manuel Klimek4da21662012-07-06 05:48:52 +0000268 ActiveASTContext(NULL) {
269 }
270
Manuel Klimeke5793282012-11-02 01:31:03 +0000271 void onStartOfTranslationUnit() {
272 for (std::vector<std::pair<const internal::DynTypedMatcher*,
273 MatchCallback*> >::const_iterator
274 I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
275 I != E; ++I) {
276 I->second->onStartOfTranslationUnit();
277 }
278 }
279
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000280 void set_active_ast_context(ASTContext *NewActiveASTContext) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000281 ActiveASTContext = NewActiveASTContext;
282 }
283
284 // The following Visit*() and Traverse*() functions "override"
285 // methods in RecursiveASTVisitor.
286
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000287 bool VisitTypedefDecl(TypedefDecl *DeclNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000288 // When we see 'typedef A B', we add name 'B' to the set of names
289 // A's canonical type maps to. This is necessary for implementing
Daniel Jasper76dafa72012-09-07 12:48:17 +0000290 // isDerivedFrom(x) properly, where x can be the name of the base
Manuel Klimek4da21662012-07-06 05:48:52 +0000291 // class or any of its aliases.
292 //
293 // In general, the is-alias-of (as defined by typedefs) relation
294 // is tree-shaped, as you can typedef a type more than once. For
295 // example,
296 //
297 // typedef A B;
298 // typedef A C;
299 // typedef C D;
300 // typedef C E;
301 //
302 // gives you
303 //
304 // A
305 // |- B
306 // `- C
307 // |- D
308 // `- E
309 //
310 // It is wrong to assume that the relation is a chain. A correct
Daniel Jasper76dafa72012-09-07 12:48:17 +0000311 // implementation of isDerivedFrom() needs to recognize that B and
Manuel Klimek4da21662012-07-06 05:48:52 +0000312 // E are aliases, even though neither is a typedef of the other.
313 // Therefore, we cannot simply walk through one typedef chain to
314 // find out whether the type name matches.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000315 const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
316 const Type *CanonicalType = // root of the typedef tree
Manuel Klimek4da21662012-07-06 05:48:52 +0000317 ActiveASTContext->getCanonicalType(TypeNode);
Daniel Jasper20b802d2012-07-17 07:39:27 +0000318 TypeAliases[CanonicalType].insert(DeclNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000319 return true;
320 }
321
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000322 bool TraverseDecl(Decl *DeclNode);
323 bool TraverseStmt(Stmt *StmtNode);
324 bool TraverseType(QualType TypeNode);
325 bool TraverseTypeLoc(TypeLoc TypeNode);
Daniel Jaspera7564432012-09-13 13:11:25 +0000326 bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
327 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
Manuel Klimek4da21662012-07-06 05:48:52 +0000328
329 // Matches children or descendants of 'Node' with 'BaseMatcher'.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000330 bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node,
331 const DynTypedMatcher &Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000332 BoundNodesTreeBuilder *Builder, int MaxDepth,
333 TraversalKind Traversal, BindKind Bind) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000334 const UntypedMatchInput input(Matcher.getID(), Node.getMemoizationData());
Daniel Jaspera267cf62012-10-29 10:14:44 +0000335
336 // For AST-nodes that don't have an identity, we can't memoize.
337 if (!input.second)
338 return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal,
339 Bind);
340
Manuel Klimek4da21662012-07-06 05:48:52 +0000341 std::pair<MemoizationMap::iterator, bool> InsertResult
342 = ResultCache.insert(std::make_pair(input, MemoizedMatchResult()));
343 if (InsertResult.second) {
344 BoundNodesTreeBuilder DescendantBoundNodesBuilder;
345 InsertResult.first->second.ResultOfMatch =
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000346 matchesRecursively(Node, Matcher, &DescendantBoundNodesBuilder,
Manuel Klimek4da21662012-07-06 05:48:52 +0000347 MaxDepth, Traversal, Bind);
348 InsertResult.first->second.Nodes =
349 DescendantBoundNodesBuilder.build();
350 }
351 InsertResult.first->second.Nodes.copyTo(Builder);
352 return InsertResult.first->second.ResultOfMatch;
353 }
354
355 // Matches children or descendants of 'Node' with 'BaseMatcher'.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000356 bool matchesRecursively(const ast_type_traits::DynTypedNode &Node,
357 const DynTypedMatcher &Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000358 BoundNodesTreeBuilder *Builder, int MaxDepth,
359 TraversalKind Traversal, BindKind Bind) {
360 MatchChildASTVisitor Visitor(
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000361 &Matcher, this, Builder, MaxDepth, Traversal, Bind);
Manuel Klimek4da21662012-07-06 05:48:52 +0000362 return Visitor.findMatch(Node);
363 }
364
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000365 virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
Daniel Jasper20b802d2012-07-17 07:39:27 +0000366 const Matcher<NamedDecl> &Base,
367 BoundNodesTreeBuilder *Builder);
Manuel Klimek4da21662012-07-06 05:48:52 +0000368
Daniel Jasperc99a3ad2012-10-22 16:26:51 +0000369 // Implements ASTMatchFinder::matchesChildOf.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000370 virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
371 const DynTypedMatcher &Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000372 BoundNodesTreeBuilder *Builder,
373 TraversalKind Traversal,
374 BindKind Bind) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000375 return matchesRecursively(Node, Matcher, Builder, 1, Traversal,
Manuel Klimek4da21662012-07-06 05:48:52 +0000376 Bind);
377 }
Daniel Jasperc99a3ad2012-10-22 16:26:51 +0000378 // Implements ASTMatchFinder::matchesDescendantOf.
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000379 virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
380 const DynTypedMatcher &Matcher,
Manuel Klimek4da21662012-07-06 05:48:52 +0000381 BoundNodesTreeBuilder *Builder,
382 BindKind Bind) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000383 return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX,
Manuel Klimek4da21662012-07-06 05:48:52 +0000384 TK_AsIs, Bind);
385 }
Manuel Klimek579b1202012-09-07 09:26:10 +0000386 // Implements ASTMatchFinder::matchesAncestorOf.
387 virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
388 const DynTypedMatcher &Matcher,
Daniel Jasperc99a3ad2012-10-22 16:26:51 +0000389 BoundNodesTreeBuilder *Builder,
390 AncestorMatchMode MatchMode) {
Manuel Klimek30ace372012-12-06 14:42:48 +0000391 return matchesAncestorOfRecursively(Node, Matcher, Builder, MatchMode);
Manuel Klimek579b1202012-09-07 09:26:10 +0000392 }
Manuel Klimek4da21662012-07-06 05:48:52 +0000393
Manuel Klimek60969f52013-02-01 13:41:35 +0000394 // Matches all registered matchers on the given node and calls the
395 // result callback for every node that matches.
396 void match(const ast_type_traits::DynTypedNode& Node) {
397 for (std::vector<std::pair<const internal::DynTypedMatcher*,
398 MatchCallback*> >::const_iterator
399 I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
400 I != E; ++I) {
401 BoundNodesTreeBuilder Builder;
402 if (I->first->matches(Node, this, &Builder)) {
403 BoundNodesTree BoundNodes = Builder.build();
404 MatchVisitor Visitor(ActiveASTContext, I->second);
405 BoundNodes.visitMatches(&Visitor);
406 }
407 }
408 }
409
410 template <typename T> void match(const T &Node) {
411 match(ast_type_traits::DynTypedNode::create(Node));
412 }
413
Manuel Klimek7f2d4802012-11-30 13:45:19 +0000414 // Implements ASTMatchFinder::getASTContext.
415 virtual ASTContext &getASTContext() const { return *ActiveASTContext; }
416
Manuel Klimek4da21662012-07-06 05:48:52 +0000417 bool shouldVisitTemplateInstantiations() const { return true; }
418 bool shouldVisitImplicitCode() const { return true; }
Daniel Jasper278057f2012-11-15 03:29:05 +0000419 // Disables data recursion. We intercept Traverse* methods in the RAV, which
420 // are not triggered during data recursion.
421 bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
Manuel Klimek4da21662012-07-06 05:48:52 +0000422
423private:
Manuel Klimek30ace372012-12-06 14:42:48 +0000424 bool matchesAncestorOfRecursively(
425 const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher,
426 BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) {
427 if (Node.get<TranslationUnitDecl>() ==
428 ActiveASTContext->getTranslationUnitDecl())
429 return false;
430 assert(Node.getMemoizationData() &&
431 "Invariant broken: only nodes that support memoization may be "
432 "used in the parent map.");
Manuel Klimekff9a0102013-02-28 13:21:39 +0000433 ASTContext::ParentVector Parents = ActiveASTContext->getParents(Node);
434 if (Parents.empty()) {
Manuel Klimek30ace372012-12-06 14:42:48 +0000435 assert(false && "Found node that is not in the parent map.");
436 return false;
437 }
Manuel Klimekff9a0102013-02-28 13:21:39 +0000438 for (ASTContext::ParentVector::const_iterator AncestorI = Parents.begin(),
439 AncestorE = Parents.end();
Manuel Klimek30ace372012-12-06 14:42:48 +0000440 AncestorI != AncestorE; ++AncestorI) {
441 if (Matcher.matches(*AncestorI, this, Builder))
442 return true;
443 }
444 if (MatchMode == ASTMatchFinder::AMM_ParentOnly)
445 return false;
Manuel Klimekff9a0102013-02-28 13:21:39 +0000446 for (ASTContext::ParentVector::const_iterator AncestorI = Parents.begin(),
447 AncestorE = Parents.end();
Manuel Klimek30ace372012-12-06 14:42:48 +0000448 AncestorI != AncestorE; ++AncestorI) {
449 if (matchesAncestorOfRecursively(*AncestorI, Matcher, Builder, MatchMode))
450 return true;
451 }
452 return false;
453 }
454
455
Manuel Klimek4da21662012-07-06 05:48:52 +0000456 // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
457 // the aggregated bound nodes for each match.
458 class MatchVisitor : public BoundNodesTree::Visitor {
459 public:
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000460 MatchVisitor(ASTContext* Context,
Manuel Klimek4da21662012-07-06 05:48:52 +0000461 MatchFinder::MatchCallback* Callback)
462 : Context(Context),
463 Callback(Callback) {}
464
465 virtual void visitMatch(const BoundNodes& BoundNodesView) {
466 Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
467 }
468
469 private:
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000470 ASTContext* Context;
Manuel Klimek4da21662012-07-06 05:48:52 +0000471 MatchFinder::MatchCallback* Callback;
472 };
473
Daniel Jasper20b802d2012-07-17 07:39:27 +0000474 // Returns true if 'TypeNode' has an alias that matches the given matcher.
475 bool typeHasMatchingAlias(const Type *TypeNode,
476 const Matcher<NamedDecl> Matcher,
477 BoundNodesTreeBuilder *Builder) {
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000478 const Type *const CanonicalType =
Manuel Klimek4da21662012-07-06 05:48:52 +0000479 ActiveASTContext->getCanonicalType(TypeNode);
Daniel Jasper20b802d2012-07-17 07:39:27 +0000480 const std::set<const TypedefDecl*> &Aliases = TypeAliases[CanonicalType];
481 for (std::set<const TypedefDecl*>::const_iterator
482 It = Aliases.begin(), End = Aliases.end();
483 It != End; ++It) {
484 if (Matcher.matches(**It, this, Builder))
485 return true;
486 }
487 return false;
Manuel Klimek4da21662012-07-06 05:48:52 +0000488 }
489
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000490 std::vector<std::pair<const internal::DynTypedMatcher*,
491 MatchCallback*> > *const MatcherCallbackPairs;
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000492 ASTContext *ActiveASTContext;
Manuel Klimek4da21662012-07-06 05:48:52 +0000493
Daniel Jasper20b802d2012-07-17 07:39:27 +0000494 // Maps a canonical type to its TypedefDecls.
495 llvm::DenseMap<const Type*, std::set<const TypedefDecl*> > TypeAliases;
Manuel Klimek4da21662012-07-06 05:48:52 +0000496
497 // Maps (matcher, node) -> the match result for memoization.
498 typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult> MemoizationMap;
499 MemoizationMap ResultCache;
500};
501
502// Returns true if the given class is directly or indirectly derived
Daniel Jasper76dafa72012-09-07 12:48:17 +0000503// from a base type with the given name. A class is not considered to be
504// derived from itself.
Daniel Jasper20b802d2012-07-17 07:39:27 +0000505bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
506 const Matcher<NamedDecl> &Base,
507 BoundNodesTreeBuilder *Builder) {
Daniel Jasper20b802d2012-07-17 07:39:27 +0000508 if (!Declaration->hasDefinition())
Manuel Klimek4da21662012-07-06 05:48:52 +0000509 return false;
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000510 typedef CXXRecordDecl::base_class_const_iterator BaseIterator;
Manuel Klimek4da21662012-07-06 05:48:52 +0000511 for (BaseIterator It = Declaration->bases_begin(),
512 End = Declaration->bases_end(); It != End; ++It) {
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000513 const Type *TypeNode = It->getType().getTypePtr();
Manuel Klimek4da21662012-07-06 05:48:52 +0000514
Daniel Jasper20b802d2012-07-17 07:39:27 +0000515 if (typeHasMatchingAlias(TypeNode, Base, Builder))
Manuel Klimek4da21662012-07-06 05:48:52 +0000516 return true;
517
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000518 // Type::getAs<...>() drills through typedefs.
519 if (TypeNode->getAs<DependentNameType>() != NULL ||
Daniel Jasper08f0c532012-09-18 14:17:42 +0000520 TypeNode->getAs<DependentTemplateSpecializationType>() != NULL ||
Daniel Jasper20b802d2012-07-17 07:39:27 +0000521 TypeNode->getAs<TemplateTypeParmType>() != NULL)
Manuel Klimek4da21662012-07-06 05:48:52 +0000522 // Dependent names and template TypeNode parameters will be matched when
523 // the template is instantiated.
524 continue;
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000525 CXXRecordDecl *ClassDecl = NULL;
526 TemplateSpecializationType const *TemplateType =
527 TypeNode->getAs<TemplateSpecializationType>();
Manuel Klimek4da21662012-07-06 05:48:52 +0000528 if (TemplateType != NULL) {
Daniel Jasper20b802d2012-07-17 07:39:27 +0000529 if (TemplateType->getTemplateName().isDependent())
Manuel Klimek4da21662012-07-06 05:48:52 +0000530 // Dependent template specializations will be matched when the
531 // template is instantiated.
532 continue;
Daniel Jasper20b802d2012-07-17 07:39:27 +0000533
Manuel Klimek4da21662012-07-06 05:48:52 +0000534 // For template specialization types which are specializing a template
535 // declaration which is an explicit or partial specialization of another
536 // template declaration, getAsCXXRecordDecl() returns the corresponding
537 // ClassTemplateSpecializationDecl.
538 //
539 // For template specialization types which are specializing a template
540 // declaration which is neither an explicit nor partial specialization of
541 // another template declaration, getAsCXXRecordDecl() returns NULL and
542 // we get the CXXRecordDecl of the templated declaration.
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000543 CXXRecordDecl *SpecializationDecl =
Manuel Klimek4da21662012-07-06 05:48:52 +0000544 TemplateType->getAsCXXRecordDecl();
545 if (SpecializationDecl != NULL) {
546 ClassDecl = SpecializationDecl;
547 } else {
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000548 ClassDecl = dyn_cast<CXXRecordDecl>(
Manuel Klimek4da21662012-07-06 05:48:52 +0000549 TemplateType->getTemplateName()
550 .getAsTemplateDecl()->getTemplatedDecl());
551 }
552 } else {
553 ClassDecl = TypeNode->getAsCXXRecordDecl();
554 }
555 assert(ClassDecl != NULL);
Manuel Klimek987c2f52012-12-04 13:40:29 +0000556 if (ClassDecl == Declaration) {
557 // This can happen for recursive template definitions; if the
558 // current declaration did not match, we can safely return false.
559 assert(TemplateType);
560 return false;
561 }
Daniel Jasper76dafa72012-09-07 12:48:17 +0000562 if (Base.matches(*ClassDecl, this, Builder))
563 return true;
Daniel Jasper20b802d2012-07-17 07:39:27 +0000564 if (classIsDerivedFrom(ClassDecl, Base, Builder))
Manuel Klimek4da21662012-07-06 05:48:52 +0000565 return true;
Manuel Klimek4da21662012-07-06 05:48:52 +0000566 }
567 return false;
568}
569
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000570bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000571 if (DeclNode == NULL) {
572 return true;
573 }
574 match(*DeclNode);
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000575 return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000576}
577
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000578bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000579 if (StmtNode == NULL) {
580 return true;
581 }
582 match(*StmtNode);
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000583 return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000584}
585
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000586bool MatchASTVisitor::TraverseType(QualType TypeNode) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000587 match(TypeNode);
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000588 return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000589}
590
Daniel Jasperce620072012-10-17 08:52:59 +0000591bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
592 // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
593 // We still want to find those types via matchers, so we match them here. Note
594 // that the TypeLocs are structurally a shadow-hierarchy to the expressed
595 // type, so we visit all involved parts of a compound type when matching on
596 // each TypeLoc.
597 match(TypeLocNode);
598 match(TypeLocNode.getType());
599 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
Manuel Klimek4da21662012-07-06 05:48:52 +0000600}
601
Daniel Jaspera7564432012-09-13 13:11:25 +0000602bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
603 match(*NNS);
604 return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
605}
606
607bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
608 NestedNameSpecifierLoc NNS) {
609 match(NNS);
610 // We only match the nested name specifier here (as opposed to traversing it)
611 // because the traversal is already done in the parallel "Loc"-hierarchy.
612 match(*NNS.getNestedNameSpecifier());
613 return
614 RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
615}
616
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000617class MatchASTConsumer : public ASTConsumer {
Manuel Klimek4da21662012-07-06 05:48:52 +0000618public:
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000619 MatchASTConsumer(
620 std::vector<std::pair<const internal::DynTypedMatcher*,
621 MatchCallback*> > *MatcherCallbackPairs,
622 MatchFinder::ParsingDoneTestCallback *ParsingDone)
623 : Visitor(MatcherCallbackPairs),
624 ParsingDone(ParsingDone) {}
Manuel Klimek4da21662012-07-06 05:48:52 +0000625
626private:
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000627 virtual void HandleTranslationUnit(ASTContext &Context) {
Manuel Klimek4da21662012-07-06 05:48:52 +0000628 if (ParsingDone != NULL) {
629 ParsingDone->run();
630 }
631 Visitor.set_active_ast_context(&Context);
Manuel Klimeke5793282012-11-02 01:31:03 +0000632 Visitor.onStartOfTranslationUnit();
Manuel Klimek4da21662012-07-06 05:48:52 +0000633 Visitor.TraverseDecl(Context.getTranslationUnitDecl());
634 Visitor.set_active_ast_context(NULL);
635 }
636
637 MatchASTVisitor Visitor;
638 MatchFinder::ParsingDoneTestCallback *ParsingDone;
639};
640
641} // end namespace
642} // end namespace internal
643
644MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes,
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000645 ASTContext *Context)
Manuel Klimek4da21662012-07-06 05:48:52 +0000646 : Nodes(Nodes), Context(Context),
647 SourceManager(&Context->getSourceManager()) {}
648
649MatchFinder::MatchCallback::~MatchCallback() {}
650MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
651
652MatchFinder::MatchFinder() : ParsingDone(NULL) {}
653
654MatchFinder::~MatchFinder() {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000655 for (std::vector<std::pair<const internal::DynTypedMatcher*,
656 MatchCallback*> >::const_iterator
657 It = MatcherCallbackPairs.begin(), End = MatcherCallbackPairs.end();
Manuel Klimek4da21662012-07-06 05:48:52 +0000658 It != End; ++It) {
659 delete It->first;
660 }
661}
662
663void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
664 MatchCallback *Action) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000665 MatcherCallbackPairs.push_back(std::make_pair(
666 new internal::Matcher<Decl>(NodeMatch), Action));
Manuel Klimek4da21662012-07-06 05:48:52 +0000667}
668
669void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
670 MatchCallback *Action) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000671 MatcherCallbackPairs.push_back(std::make_pair(
672 new internal::Matcher<QualType>(NodeMatch), Action));
Manuel Klimek4da21662012-07-06 05:48:52 +0000673}
674
675void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
676 MatchCallback *Action) {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000677 MatcherCallbackPairs.push_back(std::make_pair(
678 new internal::Matcher<Stmt>(NodeMatch), Action));
Manuel Klimek4da21662012-07-06 05:48:52 +0000679}
680
Daniel Jaspera7564432012-09-13 13:11:25 +0000681void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
682 MatchCallback *Action) {
683 MatcherCallbackPairs.push_back(std::make_pair(
684 new NestedNameSpecifierMatcher(NodeMatch), Action));
685}
686
687void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
688 MatchCallback *Action) {
689 MatcherCallbackPairs.push_back(std::make_pair(
690 new NestedNameSpecifierLocMatcher(NodeMatch), Action));
691}
692
Daniel Jasperce620072012-10-17 08:52:59 +0000693void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
694 MatchCallback *Action) {
695 MatcherCallbackPairs.push_back(std::make_pair(
696 new TypeLocMatcher(NodeMatch), Action));
697}
698
Daniel Jaspere0e6b9e2012-07-10 20:20:19 +0000699ASTConsumer *MatchFinder::newASTConsumer() {
Manuel Klimeka78d0d62012-09-05 12:12:07 +0000700 return new internal::MatchASTConsumer(&MatcherCallbackPairs, ParsingDone);
Manuel Klimek4da21662012-07-06 05:48:52 +0000701}
702
Manuel Klimek60969f52013-02-01 13:41:35 +0000703void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
704 ASTContext &Context) {
Manuel Klimek3e2aa992012-10-24 14:47:44 +0000705 internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
706 Visitor.set_active_ast_context(&Context);
Manuel Klimek60969f52013-02-01 13:41:35 +0000707 Visitor.match(Node);
Manuel Klimek3e2aa992012-10-24 14:47:44 +0000708}
709
Manuel Klimek4da21662012-07-06 05:48:52 +0000710void MatchFinder::registerTestCallbackAfterParsing(
711 MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
712 ParsingDone = NewParsingDone;
713}
714
715} // end namespace ast_matchers
716} // end namespace clang