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