clang 24.0.0git
ASTMatchFinder.cpp
Go to the documentation of this file.
1//===--- ASTMatchFinder.cpp - Structural query framework ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implements an algorithm to efficiently search for matches on AST nodes.
10// Uses memoization to support recursive matches like HasDescendant.
11//
12// The general idea is to visit all AST nodes with a RecursiveASTVisitor,
13// calling the Matches(...) method of each matcher we are running on each
14// AST node. The matcher can recurse via the ASTMatchFinder interface.
15//
16//===----------------------------------------------------------------------===//
17
21#include "clang/AST/DeclCXX.h"
23#include "clang/Basic/Module.h"
24#include "llvm/ADT/DenseMap.h"
25#include "llvm/ADT/SmallPtrSet.h"
26#include "llvm/ADT/StringMap.h"
27#include "llvm/Support/PrettyStackTrace.h"
28#include "llvm/Support/Timer.h"
29#include <deque>
30#include <memory>
31#include <set>
32
33namespace clang {
34namespace ast_matchers {
35namespace internal {
36namespace {
37
38typedef MatchFinder::MatchCallback MatchCallback;
39
40// The maximum number of memoization entries to store.
41// 10k has been experimentally found to give a good trade-off
42// of performance vs. memory consumption by running matcher
43// that match on every statement over a very large codebase.
44//
45// FIXME: Do some performance optimization in general and
46// revisit this number; also, put up micro-benchmarks that we can
47// optimize this on.
48static const unsigned MaxMemoizationEntries = 10000;
49
50enum class MatchType {
51 Ancestors,
52
53 Descendants,
54 Child,
55};
56
57// We use memoization to avoid running the same matcher on the same
58// AST node twice. This struct is the key for looking up match
59// result. It consists of an ID of the MatcherInterface (for
60// identifying the matcher), a pointer to the AST node and the
61// bound nodes before the matcher was executed.
62//
63// We currently only memoize on nodes whose pointers identify the
64// nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
65// For \c QualType and \c TypeLoc it is possible to implement
66// generation of keys for each type.
67// FIXME: Benchmark whether memoization of non-pointer typed nodes
68// provides enough benefit for the additional amount of code.
69struct MatchKey {
70 DynTypedMatcher::MatcherIDType MatcherID;
71 DynTypedNode Node;
72 BoundNodesTreeBuilder BoundNodes;
73 TraversalKind Traversal = TK_AsIs;
74 MatchType Type;
75
76 bool operator<(const MatchKey &Other) const {
77 return std::tie(Traversal, Type, MatcherID, Node, BoundNodes) <
78 std::tie(Other.Traversal, Other.Type, Other.MatcherID, Other.Node,
79 Other.BoundNodes);
80 }
81};
82
83// Used to store the result of a match and possibly bound nodes.
84struct MemoizedMatchResult {
85 bool ResultOfMatch;
86 BoundNodesTreeBuilder Nodes;
87};
88
89// A RecursiveASTVisitor that traverses all children or all descendants of
90// a node.
91class MatchChildASTVisitor
92 : public RecursiveASTVisitor<MatchChildASTVisitor> {
93public:
94 typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
95
96 // Creates an AST visitor that matches 'matcher' on all children or
97 // descendants of a traversed node. max_depth is the maximum depth
98 // to traverse: use 1 for matching the children and INT_MAX for
99 // matching the descendants.
100 MatchChildASTVisitor(const DynTypedMatcher *Matcher, ASTMatchFinder *Finder,
101 BoundNodesTreeBuilder *Builder, int MaxDepth,
102 bool IgnoreImplicitChildren,
103 ASTMatchFinder::BindKind Bind)
104 : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0),
105 MaxDepth(MaxDepth), IgnoreImplicitChildren(IgnoreImplicitChildren),
106 Bind(Bind), Matches(false) {}
107
108 // Returns true if a match is found in the subtree rooted at the
109 // given AST node. This is done via a set of mutually recursive
110 // functions. Here's how the recursion is done (the *wildcard can
111 // actually be Decl, Stmt, or Type):
112 //
113 // - Traverse(node) calls BaseTraverse(node) when it needs
114 // to visit the descendants of node.
115 // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
116 // Traverse*(c) for each child c of 'node'.
117 // - Traverse*(c) in turn calls Traverse(c), completing the
118 // recursion.
119 bool findMatch(const DynTypedNode &DynNode) {
120 reset();
121 if (const Decl *D = DynNode.get<Decl>())
122 traverse(*D);
123 else if (const Stmt *S = DynNode.get<Stmt>())
124 traverse(*S);
125 else if (const NestedNameSpecifier *NNS =
126 DynNode.get<NestedNameSpecifier>())
127 traverse(*NNS);
128 else if (const NestedNameSpecifierLoc *NNSLoc =
129 DynNode.get<NestedNameSpecifierLoc>())
130 traverse(*NNSLoc);
131 else if (const QualType *Q = DynNode.get<QualType>())
132 traverse(*Q, /*TraverseQualifier=*/true);
133 else if (const TypeLoc *T = DynNode.get<TypeLoc>())
134 traverse(*T, /*TraverseQualifier=*/true);
135 else if (const auto *C = DynNode.get<CXXCtorInitializer>())
136 traverse(*C);
137 else if (const TemplateArgumentLoc *TALoc =
138 DynNode.get<TemplateArgumentLoc>())
139 traverse(*TALoc);
140 else if (const Attr *A = DynNode.get<Attr>())
141 traverse(*A);
142 // FIXME: Add other base types after adding tests.
143
144 // It's OK to always overwrite the bound nodes, as if there was
145 // no match in this recursive branch, the result set is empty
146 // anyway.
147 *Builder = ResultBindings;
148
149 return Matches;
150 }
151
152 // The following are overriding methods from the base visitor class.
153 // They are public only to allow CRTP to work. They are *not *part
154 // of the public API of this class.
155 bool TraverseDecl(Decl *DeclNode) {
156
157 if (DeclNode && DeclNode->isImplicit() &&
158 Finder->isTraversalIgnoringImplicitNodes())
159 return baseTraverse(*DeclNode);
160
161 ScopedIncrement ScopedDepth(&CurrentDepth);
162 return (DeclNode == nullptr) || traverse(*DeclNode);
163 }
164
165 Stmt *getStmtToTraverse(Stmt *StmtNode) {
166 Stmt *StmtToTraverse = StmtNode;
167 if (auto *ExprNode = dyn_cast_or_null<Expr>(StmtNode)) {
168 auto *LambdaNode = dyn_cast_or_null<LambdaExpr>(StmtNode);
169 if (LambdaNode && Finder->isTraversalIgnoringImplicitNodes())
170 StmtToTraverse = LambdaNode;
171 else
172 StmtToTraverse =
173 Finder->getASTContext().getParentMapContext().traverseIgnored(
174 ExprNode);
175 }
176 return StmtToTraverse;
177 }
178
179 bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) {
180 // If we need to keep track of the depth, we can't perform data recursion.
181 if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX))
182 Queue = nullptr;
183
184 ScopedIncrement ScopedDepth(&CurrentDepth);
185 Stmt *StmtToTraverse = getStmtToTraverse(StmtNode);
186 if (!StmtToTraverse)
187 return true;
188
189 if (IgnoreImplicitChildren && isa<CXXDefaultArgExpr>(StmtNode))
190 return true;
191
192 if (!match(*StmtToTraverse))
193 return false;
194 return VisitorBase::TraverseStmt(StmtToTraverse, Queue);
195 }
196 // We assume that the QualType and the contained type are on the same
197 // hierarchy level. Thus, we try to match either of them.
198 bool TraverseType(QualType TypeNode, bool TraverseQualifier = true) {
199 if (TypeNode.isNull())
200 return true;
201 ScopedIncrement ScopedDepth(&CurrentDepth);
202 // Match the Type.
203 if (!match(*TypeNode))
204 return false;
205 // The QualType is matched inside traverse.
206 return traverse(TypeNode, TraverseQualifier);
207 }
208 // We assume that the TypeLoc, contained QualType and contained Type all are
209 // on the same hierarchy level. Thus, we try to match all of them.
210 bool TraverseTypeLoc(TypeLoc TypeLocNode, bool TraverseQualifier = true) {
211 if (TypeLocNode.isNull())
212 return true;
213 ScopedIncrement ScopedDepth(&CurrentDepth);
214 // Match the Type.
215 if (!match(*TypeLocNode.getType()))
216 return false;
217 // Match the QualType.
218 if (!match(TypeLocNode.getType()))
219 return false;
220 // The TypeLoc is matched inside traverse.
221 return traverse(TypeLocNode, TraverseQualifier);
222 }
223 bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
224 ScopedIncrement ScopedDepth(&CurrentDepth);
225 return !NNS || traverse(NNS);
226 }
227 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
228 if (!NNS)
229 return true;
230 ScopedIncrement ScopedDepth(&CurrentDepth);
231 if (!match(NNS.getNestedNameSpecifier()))
232 return false;
233 return traverse(NNS);
234 }
235 bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
236 if (!CtorInit)
237 return true;
238 ScopedIncrement ScopedDepth(&CurrentDepth);
239 return traverse(*CtorInit);
240 }
241 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
242 ScopedIncrement ScopedDepth(&CurrentDepth);
243 return traverse(TAL);
244 }
245 bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) {
246 if (!Finder->isTraversalIgnoringImplicitNodes())
247 return VisitorBase::TraverseCXXForRangeStmt(Node);
248 if (!Node)
249 return true;
250 ScopedIncrement ScopedDepth(&CurrentDepth);
251 if (auto *Init = Node->getInit())
252 if (!traverse(*Init))
253 return false;
254 if (!match(*Node->getLoopVariable()))
255 return false;
256 if (match(*Node->getRangeInit()))
257 if (!VisitorBase::TraverseStmt(Node->getRangeInit()))
258 return false;
259 if (!match(*Node->getBody()))
260 return false;
261 return VisitorBase::TraverseStmt(Node->getBody());
262 }
263 bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *Node) {
264 if (!Finder->isTraversalIgnoringImplicitNodes())
265 return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node);
266 if (!Node)
267 return true;
268 ScopedIncrement ScopedDepth(&CurrentDepth);
269
270 return match(*Node->getLHS()) && match(*Node->getRHS());
271 }
272 bool TraverseAttr(Attr *A) {
273 if (A == nullptr ||
274 (A->isImplicit() &&
275 Finder->getASTContext().getParentMapContext().getTraversalKind() ==
277 return true;
278 ScopedIncrement ScopedDepth(&CurrentDepth);
279 return traverse(*A);
280 }
281 bool TraverseLambdaExpr(LambdaExpr *Node) {
282 if (!Finder->isTraversalIgnoringImplicitNodes())
283 return VisitorBase::TraverseLambdaExpr(Node);
284 if (!Node)
285 return true;
286 ScopedIncrement ScopedDepth(&CurrentDepth);
287
288 for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
289 const LambdaCapture *C = Node->capture_begin() + I;
290 if (!C->isExplicit())
291 continue;
292 if (Node->isInitCapture(C) && !match(*C->getCapturedVar()))
293 return false;
294 const Expr *CIE = Node->capture_init_begin()[I];
295 if (CIE != nullptr && !match(*CIE))
296 return false;
297 }
298
299 if (const auto *TPL = Node->getTemplateParameterList()) {
300 for (const auto *TP : *TPL) {
301 if (!match(*TP))
302 return false;
303 }
304 }
305
306 for (const auto *P : Node->getCallOperator()->parameters()) {
307 if (!match(*P))
308 return false;
309 }
310
311 if (!match(*Node->getBody()))
312 return false;
313
314 return VisitorBase::TraverseStmt(Node->getBody());
315 }
316
317 bool shouldVisitTemplateInstantiations() const { return true; }
318 bool shouldVisitImplicitCode() const { return !IgnoreImplicitChildren; }
319
320private:
321 // Used for updating the depth during traversal.
322 struct ScopedIncrement {
323 explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
324 ~ScopedIncrement() { --(*Depth); }
325
326 private:
327 int *Depth;
328 };
329
330 // Resets the state of this object.
331 void reset() {
332 Matches = false;
333 CurrentDepth = 0;
334 }
335
336 // Forwards the call to the corresponding Traverse*() method in the
337 // base visitor class.
338 bool baseTraverse(const Decl &DeclNode) {
339 return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
340 }
341 bool baseTraverse(const Stmt &StmtNode) {
342 return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
343 }
344 bool baseTraverse(QualType TypeNode, bool TraverseQualifier) {
345 return VisitorBase::TraverseType(TypeNode, TraverseQualifier);
346 }
347 bool baseTraverse(TypeLoc TypeLocNode, bool TraverseQualifier) {
348 return VisitorBase::TraverseTypeLoc(TypeLocNode, TraverseQualifier);
349 }
350 bool baseTraverse(NestedNameSpecifier NNS) {
352 }
353 bool baseTraverse(NestedNameSpecifierLoc NNS) {
355 }
356 bool baseTraverse(const CXXCtorInitializer &CtorInit) {
358 const_cast<CXXCtorInitializer *>(&CtorInit));
359 }
360 bool baseTraverse(TemplateArgumentLoc TAL) {
362 }
363 bool baseTraverse(const Attr &AttrNode) {
364 return VisitorBase::TraverseAttr(const_cast<Attr *>(&AttrNode));
365 }
366
367 // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
368 // 0 < CurrentDepth <= MaxDepth.
369 //
370 // Returns 'true' if traversal should continue after this function
371 // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
372 template <typename T>
373 bool match(const T &Node) {
374 if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
375 return true;
376 }
377 if (Bind != ASTMatchFinder::BK_All) {
378 BoundNodesTreeBuilder RecursiveBuilder(*Builder);
379 if (Matcher->matches(DynTypedNode::create(Node), Finder,
380 &RecursiveBuilder)) {
381 Matches = true;
382 ResultBindings.addMatch(RecursiveBuilder);
383 return false; // Abort as soon as a match is found.
384 }
385 } else {
386 BoundNodesTreeBuilder RecursiveBuilder(*Builder);
387 if (Matcher->matches(DynTypedNode::create(Node), Finder,
388 &RecursiveBuilder)) {
389 // After the first match the matcher succeeds.
390 Matches = true;
391 ResultBindings.addMatch(RecursiveBuilder);
392 }
393 }
394 return true;
395 }
396
397 // Traverses the subtree rooted at 'Node'; returns true if the
398 // traversal should continue after this function returns.
399 template <typename T, class... Args>
400 bool traverse(const T &Node, Args &&...args) {
401 static_assert(IsBaseType<T>::value,
402 "traverse can only be instantiated with base type");
403 if (!match(Node))
404 return false;
405 return baseTraverse(Node, std::forward<Args>(args)...);
406 }
407
408 const DynTypedMatcher *const Matcher;
409 ASTMatchFinder *const Finder;
410 BoundNodesTreeBuilder *const Builder;
411 BoundNodesTreeBuilder ResultBindings;
412 int CurrentDepth;
413 const int MaxDepth;
414 const bool IgnoreImplicitChildren;
415 const ASTMatchFinder::BindKind Bind;
416 bool Matches;
417};
418
419// Controls the outermost traversal of the AST and allows to match multiple
420// matchers.
421class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
422 public ASTMatchFinder {
423public:
424 MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
425 const MatchFinder::MatchFinderOptions &Options)
426 : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
427
428 ~MatchASTVisitor() override {
429 if (Options.CheckProfiling) {
430 Options.CheckProfiling->Records = std::move(TimeByBucket);
431 }
432 }
433
434 void onStartOfTranslationUnit() {
435 const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
436 TimeBucketRegion Timer;
437 for (MatchCallback *MC : Matchers->AllCallbacks) {
438 if (EnableCheckProfiling)
439 Timer.setBucket(&TimeByBucket[MC->getID()]);
440 MC->onStartOfTranslationUnit();
441 }
442 }
443
444 void onEndOfTranslationUnit() {
445 const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
446 TimeBucketRegion Timer;
447 for (MatchCallback *MC : Matchers->AllCallbacks) {
448 if (EnableCheckProfiling)
449 Timer.setBucket(&TimeByBucket[MC->getID()]);
450 MC->onEndOfTranslationUnit();
451 }
452 }
453
454 void set_active_ast_context(ASTContext *NewActiveASTContext) {
455 ActiveASTContext = NewActiveASTContext;
456 }
457
458 // The following Visit*() and Traverse*() functions "override"
459 // methods in RecursiveASTVisitor.
460
461 bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
462 // When we see 'typedef A B', we add name 'B' to the set of names
463 // A's canonical type maps to. This is necessary for implementing
464 // isDerivedFrom(x) properly, where x can be the name of the base
465 // class or any of its aliases.
466 //
467 // In general, the is-alias-of (as defined by typedefs) relation
468 // is tree-shaped, as you can typedef a type more than once. For
469 // example,
470 //
471 // typedef A B;
472 // typedef A C;
473 // typedef C D;
474 // typedef C E;
475 //
476 // gives you
477 //
478 // A
479 // |- B
480 // `- C
481 // |- D
482 // `- E
483 //
484 // It is wrong to assume that the relation is a chain. A correct
485 // implementation of isDerivedFrom() needs to recognize that B and
486 // E are aliases, even though neither is a typedef of the other.
487 // Therefore, we cannot simply walk through one typedef chain to
488 // find out whether the type name matches.
489 const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
490 const Type *CanonicalType = // root of the typedef tree
491 ActiveASTContext->getCanonicalType(TypeNode);
492 TypeAliases[CanonicalType].insert(DeclNode);
493 return true;
494 }
495
496 bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
497 const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface();
498 CompatibleAliases[InterfaceDecl].insert(CAD);
499 return true;
500 }
501
502 bool TraverseDecl(Decl *DeclNode);
503 bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
504 bool TraverseType(QualType TypeNode, bool TraverseQualifier = true);
505 bool TraverseTypeLoc(TypeLoc TypeNode, bool TraverseQualifier = true);
506 bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS);
507 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
508 bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
509 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
510 bool TraverseAttr(Attr *AttrNode);
511
512 bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
513 if (auto *RF = dyn_cast<CXXForRangeStmt>(S)) {
514 {
515 ASTNodeNotAsIsSourceScope RAII(this, true);
516 TraverseStmt(RF->getInit());
517 // Don't traverse under the loop variable
518 match(*RF->getLoopVariable());
519 TraverseStmt(RF->getRangeInit());
520 }
521 {
522 ASTNodeNotSpelledInSourceScope RAII(this, true);
523 for (auto *SubStmt : RF->children()) {
524 if (SubStmt != RF->getBody())
525 TraverseStmt(SubStmt);
526 }
527 }
528 TraverseStmt(RF->getBody());
529 return true;
530 } else if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
531 {
532 ASTNodeNotAsIsSourceScope RAII(this, true);
533 TraverseStmt(const_cast<Expr *>(RBO->getLHS()));
534 TraverseStmt(const_cast<Expr *>(RBO->getRHS()));
535 }
536 {
537 ASTNodeNotSpelledInSourceScope RAII(this, true);
538 for (auto *SubStmt : RBO->children()) {
539 TraverseStmt(SubStmt);
540 }
541 }
542 return true;
543 } else if (auto *LE = dyn_cast<LambdaExpr>(S)) {
544 for (auto I : llvm::zip(LE->captures(), LE->capture_inits())) {
545 auto C = std::get<0>(I);
546 ASTNodeNotSpelledInSourceScope RAII(
547 this, TraversingASTNodeNotSpelledInSource || !C.isExplicit());
548 TraverseLambdaCapture(LE, &C, std::get<1>(I));
549 }
550
551 {
552 ASTNodeNotSpelledInSourceScope RAII(this, true);
553 TraverseDecl(LE->getLambdaClass());
554 }
555 {
556 ASTNodeNotAsIsSourceScope RAII(this, true);
557
558 // We need to poke around to find the bits that might be explicitly
559 // written.
560 TypeLoc TL = LE->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
561 FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
562
563 if (auto *TPL = LE->getTemplateParameterList()) {
564 for (NamedDecl *D : *TPL) {
565 TraverseDecl(D);
566 }
567 if (Expr *RequiresClause = TPL->getRequiresClause()) {
568 TraverseStmt(RequiresClause);
569 }
570 }
571
572 if (LE->hasExplicitParameters()) {
573 // Visit parameters.
574 for (ParmVarDecl *Param : Proto.getParams())
575 TraverseDecl(Param);
576 }
577
578 const auto *T = Proto.getTypePtr();
579 for (const auto &E : T->exceptions())
580 TraverseType(E, /*TraverseQualifier=*/true);
581
582 if (Expr *NE = T->getNoexceptExpr())
583 TraverseStmt(NE, Queue);
584
585 if (LE->hasExplicitResultType())
586 TraverseTypeLoc(Proto.getReturnLoc(), /*TraverseQualifier=*/true);
587 TraverseStmt(
588 const_cast<Expr *>(LE->getTrailingRequiresClause().ConstraintExpr));
589 }
590
591 TraverseStmt(LE->getBody());
592 return true;
593 }
595 }
596
597 // Matches children or descendants of 'Node' with 'BaseMatcher'.
598 bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx,
599 const DynTypedMatcher &Matcher,
600 BoundNodesTreeBuilder *Builder, int MaxDepth,
601 BindKind Bind) {
602 // For AST-nodes that don't have an identity, we can't memoize.
603 if (!Node.getMemoizationData() || !Builder->isComparable())
604 return matchesRecursively(Node, Matcher, Builder, MaxDepth, Bind);
605
606 MatchKey Key;
607 Key.MatcherID = Matcher.getID();
608 Key.Node = Node;
609 // Note that we key on the bindings *before* the match.
610 Key.BoundNodes = *Builder;
611 Key.Traversal = Ctx.getParentMapContext().getTraversalKind();
612 // Memoize result even doing a single-level match, it might be expensive.
613 Key.Type = MaxDepth == 1 ? MatchType::Child : MatchType::Descendants;
614 MemoizationMap::iterator I = ResultCache.find(Key);
615 if (I != ResultCache.end()) {
616 *Builder = I->second.Nodes;
617 return I->second.ResultOfMatch;
618 }
619
620 MemoizedMatchResult Result;
621 Result.Nodes = *Builder;
622 Result.ResultOfMatch =
623 matchesRecursively(Node, Matcher, &Result.Nodes, MaxDepth, Bind);
624
625 MemoizedMatchResult &CachedResult = ResultCache[Key];
626 CachedResult = std::move(Result);
627
628 *Builder = CachedResult.Nodes;
629 return CachedResult.ResultOfMatch;
630 }
631
632 // Matches children or descendants of 'Node' with 'BaseMatcher'.
633 bool matchesRecursively(const DynTypedNode &Node,
634 const DynTypedMatcher &Matcher,
635 BoundNodesTreeBuilder *Builder, int MaxDepth,
636 BindKind Bind) {
637 bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
638 TraversingASTChildrenNotSpelledInSource;
639
640 bool IgnoreImplicitChildren = false;
641
642 if (isTraversalIgnoringImplicitNodes()) {
643 IgnoreImplicitChildren = true;
644 }
645
646 ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
647
648 MatchChildASTVisitor Visitor(&Matcher, this, Builder, MaxDepth,
649 IgnoreImplicitChildren, Bind);
650 return Visitor.findMatch(Node);
651 }
652
653 bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
654 const Matcher<NamedDecl> &Base,
655 BoundNodesTreeBuilder *Builder,
656 bool Directly) override;
657
658private:
659 bool
660 classIsDerivedFromImpl(const CXXRecordDecl *Declaration,
661 const Matcher<NamedDecl> &Base,
662 BoundNodesTreeBuilder *Builder, bool Directly,
663 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &Visited);
664
665public:
666 bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
667 const Matcher<NamedDecl> &Base,
668 BoundNodesTreeBuilder *Builder,
669 bool Directly) override;
670
671public:
672 // Implements ASTMatchFinder::matchesChildOf.
673 bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
674 const DynTypedMatcher &Matcher,
675 BoundNodesTreeBuilder *Builder, BindKind Bind) override {
676 if (ResultCache.size() > MaxMemoizationEntries)
677 ResultCache.clear();
678 return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, Bind);
679 }
680 // Implements ASTMatchFinder::matchesDescendantOf.
681 bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
682 const DynTypedMatcher &Matcher,
683 BoundNodesTreeBuilder *Builder,
684 BindKind Bind) override {
685 if (ResultCache.size() > MaxMemoizationEntries)
686 ResultCache.clear();
687 return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, INT_MAX,
688 Bind);
689 }
690 // Implements ASTMatchFinder::matchesAncestorOf.
691 bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
692 const DynTypedMatcher &Matcher,
693 BoundNodesTreeBuilder *Builder,
694 AncestorMatchMode MatchMode) override {
695 // Reset the cache outside of the recursive call to make sure we
696 // don't invalidate any iterators.
697 if (ResultCache.size() > MaxMemoizationEntries)
698 ResultCache.clear();
699 if (MatchMode == AncestorMatchMode::AMM_ParentOnly)
700 return matchesParentOf(Node, Matcher, Builder);
701 return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
702 }
703
704 // Matches all registered matchers on the given node and calls the
705 // result callback for every node that matches.
706 void match(const DynTypedNode &Node) {
707 // FIXME: Improve this with a switch or a visitor pattern.
708 if (auto *N = Node.get<Decl>()) {
709 match(*N);
710 } else if (auto *N = Node.get<Stmt>()) {
711 match(*N);
712 } else if (auto *N = Node.get<Type>()) {
713 match(*N);
714 } else if (auto *N = Node.get<QualType>()) {
715 match(*N);
716 } else if (auto *N = Node.get<NestedNameSpecifier>()) {
717 match(*N);
718 } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
719 match(*N);
720 } else if (auto *N = Node.get<TypeLoc>()) {
721 match(*N);
722 } else if (auto *N = Node.get<CXXCtorInitializer>()) {
723 match(*N);
724 } else if (auto *N = Node.get<TemplateArgumentLoc>()) {
725 match(*N);
726 } else if (auto *N = Node.get<Attr>()) {
727 match(*N);
728 }
729 }
730
731 template <typename T> void match(const T &Node) {
732 matchDispatch(&Node);
733 }
734
735 // Implements ASTMatchFinder::getASTContext.
736 ASTContext &getASTContext() const override { return *ActiveASTContext; }
737
738 bool shouldVisitTemplateInstantiations() const { return true; }
739 bool shouldVisitImplicitCode() const { return true; }
740
741 // We visit the lambda body explicitly, so instruct the RAV
742 // to not visit it on our behalf too.
743 bool shouldVisitLambdaBody() const { return false; }
744
745 bool IsMatchingInASTNodeNotSpelledInSource() const override {
746 return TraversingASTNodeNotSpelledInSource;
747 }
748 bool isMatchingChildrenNotSpelledInSource() const override {
749 return TraversingASTChildrenNotSpelledInSource;
750 }
751 void setMatchingChildrenNotSpelledInSource(bool Set) override {
752 TraversingASTChildrenNotSpelledInSource = Set;
753 }
754
755 bool IsMatchingInASTNodeNotAsIs() const override {
756 return TraversingASTNodeNotAsIs;
757 }
758
759 bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
760 ASTNodeNotSpelledInSourceScope RAII(this, true);
761 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
762 D);
763 }
764
765 bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
766 ASTNodeNotSpelledInSourceScope RAII(this, true);
767 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
768 D);
769 }
770
771 bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
772 ASTNodeNotSpelledInSourceScope RAII(this, true);
773 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
774 D);
775 }
776
777private:
778 bool TraversingASTNodeNotSpelledInSource = false;
779 bool TraversingASTNodeNotAsIs = false;
780 bool TraversingASTChildrenNotSpelledInSource = false;
781
782 class CurMatchData {
783// We don't have enough free low bits in 32bit builds to discriminate 8 pointer
784// types in PointerUnion. so split the union in 2 using a free bit from the
785// callback pointer.
786#define CMD_TYPES_0 \
787 const QualType *, const TypeLoc *, const NestedNameSpecifier *, \
788 const NestedNameSpecifierLoc *
789#define CMD_TYPES_1 \
790 const CXXCtorInitializer *, const TemplateArgumentLoc *, const Attr *, \
791 const DynTypedNode *
792
793#define IMPL(Index) \
794 template <typename NodeType> \
795 std::enable_if_t< \
796 llvm::is_one_of<const NodeType *, CMD_TYPES_##Index>::value> \
797 SetCallbackAndRawNode(const MatchCallback *CB, const NodeType &N) { \
798 assertEmpty(); \
799 Callback.setPointerAndInt(CB, Index); \
800 Node##Index = &N; \
801 } \
802 \
803 template <typename T> \
804 std::enable_if_t<llvm::is_one_of<const T *, CMD_TYPES_##Index>::value, \
805 const T *> \
806 getNode() const { \
807 assertHoldsState(); \
808 return Callback.getInt() == (Index) ? dyn_cast<const T *>(Node##Index) \
809 : nullptr; \
810 }
811
812 public:
813 CurMatchData() : Node0(nullptr) {}
814
815 IMPL(0)
816 IMPL(1)
817
818 const MatchCallback *getCallback() const { return Callback.getPointer(); }
819
820 void SetBoundNodes(const BoundNodes &BN) {
821 assertHoldsState();
822 BNodes = &BN;
823 }
824
825 void clearBoundNodes() {
826 assertHoldsState();
827 BNodes = nullptr;
828 }
829
830 const BoundNodes *getBoundNodes() const {
831 assertHoldsState();
832 return BNodes;
833 }
834
835 void reset() {
836 assertHoldsState();
837 Callback.setPointerAndInt(nullptr, 0);
838 Node0 = nullptr;
839 }
840
841 private:
842 void assertHoldsState() const {
843 assert(Callback.getPointer() != nullptr && !Node0.isNull());
844 }
845
846 void assertEmpty() const {
847 assert(Callback.getPointer() == nullptr && Node0.isNull() &&
848 BNodes == nullptr);
849 }
850
851 llvm::PointerIntPair<const MatchCallback *, 1> Callback;
852 union {
853 llvm::PointerUnion<CMD_TYPES_0> Node0;
854 llvm::PointerUnion<CMD_TYPES_1> Node1;
855 };
856 const BoundNodes *BNodes = nullptr;
857
858#undef CMD_TYPES_0
859#undef CMD_TYPES_1
860#undef IMPL
861 } CurMatchState;
862
863 struct CurMatchRAII {
864 template <typename NodeType>
865 CurMatchRAII(MatchASTVisitor &MV, const MatchCallback *CB,
866 const NodeType &NT)
867 : MV(MV) {
868 MV.CurMatchState.SetCallbackAndRawNode(CB, NT);
869 }
870
871 ~CurMatchRAII() { MV.CurMatchState.reset(); }
872
873 private:
874 MatchASTVisitor &MV;
875 };
876
877public:
878 class TraceReporter : llvm::PrettyStackTraceEntry {
879 static void dumpNode(const ASTContext &Ctx, const DynTypedNode &Node,
880 raw_ostream &OS) {
881 if (const auto *D = Node.get<Decl>()) {
882 OS << D->getDeclKindName() << "Decl ";
883 if (const auto *ND = dyn_cast<NamedDecl>(D)) {
884 ND->printQualifiedName(OS);
885 OS << " : ";
886 } else
887 OS << ": ";
888 D->getSourceRange().print(OS, Ctx.getSourceManager());
889 } else if (const auto *S = Node.get<Stmt>()) {
890 OS << S->getStmtClassName() << " : ";
891 S->getSourceRange().print(OS, Ctx.getSourceManager());
892 } else if (const auto *T = Node.get<Type>()) {
893 OS << T->getTypeClassName() << "Type : ";
894 QualType(T, 0).print(OS, Ctx.getPrintingPolicy());
895 } else if (const auto *QT = Node.get<QualType>()) {
896 OS << "QualType : ";
897 QT->print(OS, Ctx.getPrintingPolicy());
898 } else {
899 OS << Node.getNodeKind().asStringRef() << " : ";
900 Node.getSourceRange().print(OS, Ctx.getSourceManager());
901 }
902 }
903
904 static void dumpNodeFromState(const ASTContext &Ctx,
905 const CurMatchData &State, raw_ostream &OS) {
906 if (const DynTypedNode *MatchNode = State.getNode<DynTypedNode>()) {
907 dumpNode(Ctx, *MatchNode, OS);
908 } else if (const auto *QT = State.getNode<QualType>()) {
909 dumpNode(Ctx, DynTypedNode::create(*QT), OS);
910 } else if (const auto *TL = State.getNode<TypeLoc>()) {
911 dumpNode(Ctx, DynTypedNode::create(*TL), OS);
912 } else if (const auto *NNS = State.getNode<NestedNameSpecifier>()) {
913 dumpNode(Ctx, DynTypedNode::create(*NNS), OS);
914 } else if (const auto *NNSL = State.getNode<NestedNameSpecifierLoc>()) {
915 dumpNode(Ctx, DynTypedNode::create(*NNSL), OS);
916 } else if (const auto *CtorInit = State.getNode<CXXCtorInitializer>()) {
917 dumpNode(Ctx, DynTypedNode::create(*CtorInit), OS);
918 } else if (const auto *TAL = State.getNode<TemplateArgumentLoc>()) {
919 dumpNode(Ctx, DynTypedNode::create(*TAL), OS);
920 } else if (const auto *At = State.getNode<Attr>()) {
921 dumpNode(Ctx, DynTypedNode::create(*At), OS);
922 }
923 }
924
925 public:
926 TraceReporter(const MatchASTVisitor &MV) : MV(MV) {}
927 void print(raw_ostream &OS) const override {
928 const CurMatchData &State = MV.CurMatchState;
929 const MatchCallback *CB = State.getCallback();
930 if (!CB) {
931 OS << "ASTMatcher: Not currently matching\n";
932 return;
933 }
934
935 assert(MV.ActiveASTContext &&
936 "ActiveASTContext should be set if there is a matched callback");
937
938 ASTContext &Ctx = MV.getASTContext();
939
940 if (const BoundNodes *Nodes = State.getBoundNodes()) {
941 OS << "ASTMatcher: Processing '" << CB->getID() << "' against:\n\t";
942 dumpNodeFromState(Ctx, State, OS);
943 const BoundNodes::IDToNodeMap &Map = Nodes->getMap();
944 if (Map.empty()) {
945 OS << "\nNo bound nodes\n";
946 return;
947 }
948 OS << "\n--- Bound Nodes Begin ---\n";
949 for (const auto &Item : Map) {
950 OS << " " << Item.first << " - { ";
951 dumpNode(Ctx, Item.second, OS);
952 OS << " }\n";
953 }
954 OS << "--- Bound Nodes End ---\n";
955 } else {
956 OS << "ASTMatcher: Matching '" << CB->getID() << "' against:\n\t";
957 dumpNodeFromState(Ctx, State, OS);
958 OS << '\n';
959 }
960 }
961
962 private:
963 const MatchASTVisitor &MV;
964 };
965
966private:
967 struct ASTNodeNotSpelledInSourceScope {
968 ASTNodeNotSpelledInSourceScope(MatchASTVisitor *V, bool B)
969 : MV(V), MB(V->TraversingASTNodeNotSpelledInSource) {
970 V->TraversingASTNodeNotSpelledInSource = B;
971 }
972 ~ASTNodeNotSpelledInSourceScope() {
973 MV->TraversingASTNodeNotSpelledInSource = MB;
974 }
975
976 private:
977 MatchASTVisitor *MV;
978 bool MB;
979 };
980
981 struct ASTNodeNotAsIsSourceScope {
982 ASTNodeNotAsIsSourceScope(MatchASTVisitor *V, bool B)
983 : MV(V), MB(V->TraversingASTNodeNotAsIs) {
984 V->TraversingASTNodeNotAsIs = B;
985 }
986 ~ASTNodeNotAsIsSourceScope() { MV->TraversingASTNodeNotAsIs = MB; }
987
988 private:
989 MatchASTVisitor *MV;
990 bool MB;
991 };
992
993 class TimeBucketRegion {
994 public:
995 TimeBucketRegion() = default;
996 ~TimeBucketRegion() { setBucket(nullptr); }
997
998 /// Start timing for \p NewBucket.
999 ///
1000 /// If there was a bucket already set, it will finish the timing for that
1001 /// other bucket.
1002 /// \p NewBucket will be timed until the next call to \c setBucket() or
1003 /// until the \c TimeBucketRegion is destroyed.
1004 /// If \p NewBucket is the same as the currently timed bucket, this call
1005 /// does nothing.
1006 void setBucket(llvm::TimeRecord *NewBucket) {
1007 if (Bucket != NewBucket) {
1008 auto Now = llvm::TimeRecord::getCurrentTime(true);
1009 if (Bucket)
1010 *Bucket += Now;
1011 if (NewBucket)
1012 *NewBucket -= Now;
1013 Bucket = NewBucket;
1014 }
1015 }
1016
1017 private:
1018 llvm::TimeRecord *Bucket = nullptr;
1019 };
1020
1021 /// Runs all the \p Matchers on \p Node.
1022 ///
1023 /// Used by \c matchDispatch() below.
1024 template <typename T, typename MC>
1025 void matchWithoutFilter(const T &Node, const MC &Matchers) {
1026 const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
1027 TimeBucketRegion Timer;
1028 for (const auto &MP : Matchers) {
1029 if (EnableCheckProfiling)
1030 Timer.setBucket(&TimeByBucket[MP.second->getID()]);
1031 BoundNodesTreeBuilder Builder;
1032 CurMatchRAII RAII(*this, MP.second, Node);
1033 if (MP.first.matches(Node, this, &Builder)) {
1034 MatchVisitor Visitor(*this, ActiveASTContext, MP.second);
1035 Builder.visitMatches(&Visitor);
1036 }
1037 }
1038 }
1039
1040 void matchWithFilter(const DynTypedNode &DynNode) {
1041 auto Kind = DynNode.getNodeKind();
1042 auto it = MatcherFiltersMap.find(Kind);
1043 const auto &Filter =
1044 it != MatcherFiltersMap.end() ? it->second : getFilterForKind(Kind);
1045
1046 if (Filter.empty())
1047 return;
1048
1049 const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
1050 TimeBucketRegion Timer;
1051 auto &Matchers = this->Matchers->DeclOrStmt;
1052 // traverseIgnored() only ever replaces expressions.
1053 const bool IsExpr = DynNode.get<Expr>() != nullptr;
1054 for (unsigned short I : Filter) {
1055 auto &MP = Matchers[I];
1056 if (EnableCheckProfiling)
1057 Timer.setBucket(&TimeByBucket[MP.second->getID()]);
1058 BoundNodesTreeBuilder Builder;
1059
1060 if (IsExpr) {
1061 TraversalKindScope RAII(getASTContext(), MP.first.getTraversalKind());
1062 if (getASTContext().getParentMapContext().traverseIgnored(DynNode) !=
1063 DynNode)
1064 continue;
1065 }
1066
1067 CurMatchRAII RAII(*this, MP.second, DynNode);
1068 if (MP.first.matches(DynNode, this, &Builder)) {
1069 MatchVisitor Visitor(*this, ActiveASTContext, MP.second);
1070 Builder.visitMatches(&Visitor);
1071 }
1072 }
1073 }
1074
1075 const std::vector<unsigned short> &getFilterForKind(ASTNodeKind Kind) {
1076 auto &Filter = MatcherFiltersMap[Kind];
1077 auto &Matchers = this->Matchers->DeclOrStmt;
1078 assert((Matchers.size() < USHRT_MAX) && "Too many matchers.");
1079 for (unsigned I = 0, E = Matchers.size(); I != E; ++I) {
1080 if (Matchers[I].first.canMatchNodesOfKind(Kind)) {
1081 Filter.push_back(I);
1082 }
1083 }
1084 return Filter;
1085 }
1086
1087 /// @{
1088 /// Overloads to pair the different node types to their matchers.
1089 void matchDispatch(const Decl *Node) {
1090 return matchWithFilter(DynTypedNode::create(*Node));
1091 }
1092 void matchDispatch(const Stmt *Node) {
1093 return matchWithFilter(DynTypedNode::create(*Node));
1094 }
1095
1096 void matchDispatch(const Type *Node) {
1097 matchWithoutFilter(QualType(Node, 0), Matchers->Type);
1098 }
1099 void matchDispatch(const TypeLoc *Node) {
1100 matchWithoutFilter(*Node, Matchers->TypeLoc);
1101 }
1102 void matchDispatch(const QualType *Node) {
1103 matchWithoutFilter(*Node, Matchers->Type);
1104 }
1105 void matchDispatch(const NestedNameSpecifier *Node) {
1106 matchWithoutFilter(*Node, Matchers->NestedNameSpecifier);
1107 }
1108 void matchDispatch(const NestedNameSpecifierLoc *Node) {
1109 matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
1110 }
1111 void matchDispatch(const CXXCtorInitializer *Node) {
1112 matchWithoutFilter(*Node, Matchers->CtorInit);
1113 }
1114 void matchDispatch(const TemplateArgumentLoc *Node) {
1115 matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc);
1116 }
1117 void matchDispatch(const Attr *Node) {
1118 matchWithoutFilter(*Node, Matchers->Attr);
1119 }
1120 void matchDispatch(const void *) { /* Do nothing. */ }
1121 /// @}
1122
1123 // Returns whether a direct parent of \p Node matches \p Matcher.
1124 // Unlike matchesAnyAncestorOf there's no memoization: it doesn't save much.
1125 bool matchesParentOf(const DynTypedNode &Node, const DynTypedMatcher &Matcher,
1126 BoundNodesTreeBuilder *Builder) {
1127 for (const auto &Parent : ActiveASTContext->getParents(Node)) {
1128 BoundNodesTreeBuilder BuilderCopy = *Builder;
1129 if (Matcher.matches(Parent, this, &BuilderCopy)) {
1130 *Builder = std::move(BuilderCopy);
1131 return true;
1132 }
1133 }
1134 return false;
1135 }
1136
1137 // Returns whether an ancestor of \p Node matches \p Matcher.
1138 //
1139 // The order of matching (which can lead to different nodes being bound in
1140 // case there are multiple matches) is breadth first search.
1141 //
1142 // To allow memoization in the very common case of having deeply nested
1143 // expressions inside a template function, we first walk up the AST, memoizing
1144 // the result of the match along the way, as long as there is only a single
1145 // parent.
1146 //
1147 // Once there are multiple parents, the breadth first search order does not
1148 // allow simple memoization on the ancestors. Thus, we only memoize as long
1149 // as there is a single parent.
1150 //
1151 // We avoid a recursive implementation to prevent excessive stack use on
1152 // very deep ASTs (similarly to RecursiveASTVisitor's data recursion).
1153 bool matchesAnyAncestorOf(DynTypedNode Node, ASTContext &Ctx,
1154 const DynTypedMatcher &Matcher,
1155 BoundNodesTreeBuilder *Builder) {
1156
1157 // Memoization keys that can be updated with the result.
1158 // These are the memoizable nodes in the chain of unique parents, which
1159 // terminates when a node has multiple parents, or matches, or is the root.
1160 std::vector<MatchKey> Keys;
1161 // When returning, update the memoization cache.
1162 auto Finish = [&](bool Matched) {
1163 for (const auto &Key : Keys) {
1164 MemoizedMatchResult &CachedResult = ResultCache[Key];
1165 CachedResult.ResultOfMatch = Matched;
1166 CachedResult.Nodes = *Builder;
1167 }
1168 return Matched;
1169 };
1170
1171 // Loop while there's a single parent and we want to attempt memoization.
1172 DynTypedNodeList Parents{ArrayRef<DynTypedNode>()}; // after loop: size != 1
1173 for (;;) {
1174 // A cache key only makes sense if memoization is possible.
1175 if (Builder->isComparable()) {
1176 Keys.emplace_back();
1177 Keys.back().MatcherID = Matcher.getID();
1178 Keys.back().Node = Node;
1179 Keys.back().BoundNodes = *Builder;
1180 Keys.back().Traversal = Ctx.getParentMapContext().getTraversalKind();
1181 Keys.back().Type = MatchType::Ancestors;
1182
1183 // Check the cache.
1184 MemoizationMap::iterator I = ResultCache.find(Keys.back());
1185 if (I != ResultCache.end()) {
1186 Keys.pop_back(); // Don't populate the cache for the matching node!
1187 *Builder = I->second.Nodes;
1188 return Finish(I->second.ResultOfMatch);
1189 }
1190 }
1191
1192 Parents = ActiveASTContext->getParents(Node);
1193 // Either no parents or multiple parents: leave chain+memoize mode and
1194 // enter bfs+forgetful mode.
1195 if (Parents.size() != 1)
1196 break;
1197
1198 // Check the next parent.
1199 Node = *Parents.begin();
1200 BoundNodesTreeBuilder BuilderCopy = *Builder;
1201 if (Matcher.matches(Node, this, &BuilderCopy)) {
1202 *Builder = std::move(BuilderCopy);
1203 return Finish(true);
1204 }
1205 }
1206 // We reached the end of the chain.
1207
1208 if (Parents.empty()) {
1209 // Nodes may have no parents if:
1210 // a) the node is the TranslationUnitDecl
1211 // b) we have a limited traversal scope that excludes the parent edges
1212 // c) there is a bug in the AST, and the node is not reachable
1213 // Usually the traversal scope is the whole AST, which precludes b.
1214 // Bugs are common enough that it's worthwhile asserting when we can.
1215#ifndef NDEBUG
1216 if (!Node.get<TranslationUnitDecl>() &&
1217 /* Traversal scope is full AST if any of the bounds are the TU */
1218 llvm::any_of(ActiveASTContext->getTraversalScope(), [](Decl *D) {
1219 return D->getKind() == Decl::TranslationUnit;
1220 })) {
1221 llvm::errs() << "Tried to match orphan node:\n";
1222 Node.dump(llvm::errs(), *ActiveASTContext);
1223 llvm_unreachable("Parent map should be complete!");
1224 }
1225#endif
1226 } else {
1227 assert(Parents.size() > 1);
1228 // BFS starting from the parents not yet considered.
1229 // Memoization of newly visited nodes is not possible (but we still update
1230 // results for the elements in the chain we found above).
1231 std::deque<DynTypedNode> Queue(Parents.begin(), Parents.end());
1232 llvm::DenseSet<const void *> Visited;
1233 while (!Queue.empty()) {
1234 BoundNodesTreeBuilder BuilderCopy = *Builder;
1235 if (Matcher.matches(Queue.front(), this, &BuilderCopy)) {
1236 *Builder = std::move(BuilderCopy);
1237 return Finish(true);
1238 }
1239 for (const auto &Parent : ActiveASTContext->getParents(Queue.front())) {
1240 // Make sure we do not visit the same node twice.
1241 // Otherwise, we'll visit the common ancestors as often as there
1242 // are splits on the way down.
1243 if (Visited.insert(Parent.getMemoizationData()).second)
1244 Queue.push_back(Parent);
1245 }
1246 Queue.pop_front();
1247 }
1248 }
1249 return Finish(false);
1250 }
1251
1252 // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
1253 // the aggregated bound nodes for each match.
1254 class MatchVisitor : public BoundNodesTreeBuilder::Visitor {
1255 struct CurBoundScope {
1256 CurBoundScope(MatchASTVisitor::CurMatchData &State, const BoundNodes &BN)
1257 : State(State) {
1258 State.SetBoundNodes(BN);
1259 }
1260
1261 ~CurBoundScope() { State.clearBoundNodes(); }
1262
1263 private:
1264 MatchASTVisitor::CurMatchData &State;
1265 };
1266
1267 public:
1268 MatchVisitor(MatchASTVisitor &MV, ASTContext *Context,
1269 MatchFinder::MatchCallback *Callback)
1270 : State(MV.CurMatchState), Context(Context), Callback(Callback) {}
1271
1272 void visitMatch(const BoundNodes& BoundNodesView) override {
1273 TraversalKindScope RAII(*Context, Callback->getCheckTraversalKind());
1274 CurBoundScope RAII2(State, BoundNodesView);
1275 Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
1276 }
1277
1278 private:
1279 MatchASTVisitor::CurMatchData &State;
1280 ASTContext* Context;
1281 MatchFinder::MatchCallback* Callback;
1282 };
1283
1284 // Returns true if 'TypeNode' has an alias that matches the given matcher.
1285 bool typeHasMatchingAlias(const Type *TypeNode,
1286 const Matcher<NamedDecl> &Matcher,
1287 BoundNodesTreeBuilder *Builder) {
1288 const Type *const CanonicalType =
1289 ActiveASTContext->getCanonicalType(TypeNode);
1290 auto Aliases = TypeAliases.find(CanonicalType);
1291 if (Aliases == TypeAliases.end())
1292 return false;
1293
1294 auto matches = [&](const TypedefNameDecl *Alias) {
1295 BoundNodesTreeBuilder Result(*Builder);
1296 if (Matcher.matches(*Alias, this, &Result)) {
1297 *Builder = std::move(Result);
1298 return true;
1299 }
1300 return false;
1301 };
1302
1303 if (const auto *T = TypeNode->getAs<TypedefType>()) {
1304 const auto *TD = T->getDecl()->getCanonicalDecl();
1305
1306 // Prioritize exact matches.
1307 SmallVector<const TypedefNameDecl *, 8> NonExactMatches;
1308 for (const TypedefNameDecl *Alias : Aliases->second) {
1309 if (!declaresSameEntity(TD, Alias)) {
1310 NonExactMatches.push_back(Alias);
1311 continue;
1312 }
1313 if (matches(Alias))
1314 return true;
1315 }
1316
1317 for (const TypedefNameDecl *Alias : NonExactMatches) {
1318 BoundNodesTreeBuilder Result(*Builder);
1319 if (Matcher.matches(*Alias, this, &Result)) {
1320 *Builder = std::move(Result);
1321 return true;
1322 }
1323 }
1324 return false;
1325 }
1326
1327 for (const TypedefNameDecl *Alias : Aliases->second)
1328 if (matches(Alias))
1329 return true;
1330 return false;
1331 }
1332
1333 bool
1334 objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl *InterfaceDecl,
1335 const Matcher<NamedDecl> &Matcher,
1336 BoundNodesTreeBuilder *Builder) {
1337 auto Aliases = CompatibleAliases.find(InterfaceDecl);
1338 if (Aliases == CompatibleAliases.end())
1339 return false;
1340 for (const ObjCCompatibleAliasDecl *Alias : Aliases->second) {
1341 BoundNodesTreeBuilder Result(*Builder);
1342 if (Matcher.matches(*Alias, this, &Result)) {
1343 *Builder = std::move(Result);
1344 return true;
1345 }
1346 }
1347 return false;
1348 }
1349
1350 template <typename T> static SourceLocation getNodeLocation(const T &Node) {
1351 return Node.getBeginLoc();
1352 }
1353
1354 static SourceLocation getNodeLocation(const CXXCtorInitializer &Node) {
1355 return Node.getSourceLocation();
1356 }
1357
1358 static SourceLocation getNodeLocation(const TemplateArgumentLoc &Node) {
1359 return Node.getLocation();
1360 }
1361
1362 static SourceLocation getNodeLocation(const Attr &Node) {
1363 return Node.getLocation();
1364 }
1365
1366 bool isInSystemHeader(SourceLocation Loc) {
1367 const SourceManager &SM = getASTContext().getSourceManager();
1368 return SM.isInSystemHeader(Loc);
1369 }
1370
1371 template <typename T> bool shouldSkipNode(T &Node) {
1372 if (Options.IgnoreSystemHeaders && isInSystemHeader(getNodeLocation(Node)))
1373 return true;
1374 return false;
1375 }
1376
1377 template <typename T> bool shouldSkipNode(T *Node) {
1378 return (Node == nullptr) || shouldSkipNode(*Node);
1379 }
1380
1381 bool shouldSkipNode(QualType &) { return false; }
1382
1383 bool shouldSkipNode(NestedNameSpecifier &) { return false; }
1384
1385 /// Bucket to record map.
1386 ///
1387 /// Used to get the appropriate bucket for each matcher.
1388 llvm::StringMap<llvm::TimeRecord> TimeByBucket;
1389
1390 const MatchFinder::MatchersByType *Matchers;
1391
1392 /// Filtered list of matcher indices for each matcher kind.
1393 ///
1394 /// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
1395 /// kind (and derived kinds) so it is a waste to try every matcher on every
1396 /// node.
1397 /// We precalculate a list of matchers that pass the toplevel restrict check.
1398 llvm::DenseMap<ASTNodeKind, std::vector<unsigned short>> MatcherFiltersMap;
1399
1400 const MatchFinder::MatchFinderOptions &Options;
1401 ASTContext *ActiveASTContext;
1402
1403 // Maps a canonical type to its TypedefDecls.
1404 llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
1405
1406 // Maps an Objective-C interface to its ObjCCompatibleAliasDecls.
1407 llvm::DenseMap<const ObjCInterfaceDecl *,
1408 llvm::SmallPtrSet<const ObjCCompatibleAliasDecl *, 2>>
1409 CompatibleAliases;
1410
1411 // Maps (matcher, node) -> the match result for memoization.
1412 typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
1413 MemoizationMap ResultCache;
1414};
1415
1416static CXXRecordDecl *
1417getAsCXXRecordDeclOrPrimaryTemplate(const Type *TypeNode) {
1418 if (auto *RD = TypeNode->getAsCXXRecordDecl())
1419 return RD;
1420
1421 // Find the innermost TemplateSpecializationType that isn't an alias template.
1422 auto *TemplateType = TypeNode->getAs<TemplateSpecializationType>();
1423 while (TemplateType && TemplateType->isTypeAlias())
1424 TemplateType =
1425 TemplateType->getAliasedType()->getAs<TemplateSpecializationType>();
1426
1427 // If this is the name of a (dependent) template specialization, use the
1428 // definition of the template, even though it might be specialized later.
1429 if (TemplateType)
1430 if (auto *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(
1431 TemplateType->getTemplateName().getAsTemplateDecl()))
1432 return ClassTemplate->getTemplatedDecl();
1433
1434 return nullptr;
1435}
1436
1437// Returns true if the given C++ class is directly or indirectly derived
1438// from a base type with the given name. A class is not considered to be
1439// derived from itself.
1440bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
1441 const Matcher<NamedDecl> &Base,
1442 BoundNodesTreeBuilder *Builder,
1443 bool Directly) {
1444 llvm::SmallPtrSet<const CXXRecordDecl *, 8> Visited;
1445 return classIsDerivedFromImpl(Declaration, Base, Builder, Directly, Visited);
1446}
1447
1448bool MatchASTVisitor::classIsDerivedFromImpl(
1449 const CXXRecordDecl *Declaration, const Matcher<NamedDecl> &Base,
1450 BoundNodesTreeBuilder *Builder, bool Directly,
1451 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &Visited) {
1452 if (!Declaration->hasDefinition())
1453 return false;
1454 if (!Visited.insert(Declaration).second)
1455 return false;
1456 for (const auto &It : Declaration->bases()) {
1457 const Type *TypeNode = It.getType().getTypePtr();
1458
1459 if (typeHasMatchingAlias(TypeNode, Base, Builder))
1460 return true;
1461
1462 // FIXME: Going to the primary template here isn't really correct, but
1463 // unfortunately we accept a Decl matcher for the base class not a Type
1464 // matcher, so it's the best thing we can do with our current interface.
1465 CXXRecordDecl *ClassDecl = getAsCXXRecordDeclOrPrimaryTemplate(TypeNode);
1466 if (!ClassDecl)
1467 continue;
1468 if (ClassDecl == Declaration) {
1469 // This can happen for recursive template definitions.
1470 continue;
1471 }
1472 BoundNodesTreeBuilder Result(*Builder);
1473 if (Base.matches(*ClassDecl, this, &Result)) {
1474 *Builder = std::move(Result);
1475 return true;
1476 }
1477 if (!Directly &&
1478 classIsDerivedFromImpl(ClassDecl, Base, Builder, Directly, Visited))
1479 return true;
1480 }
1481 return false;
1482}
1483
1484// Returns true if the given Objective-C class is directly or indirectly
1485// derived from a matching base class. A class is not considered to be derived
1486// from itself.
1487bool MatchASTVisitor::objcClassIsDerivedFrom(
1488 const ObjCInterfaceDecl *Declaration, const Matcher<NamedDecl> &Base,
1489 BoundNodesTreeBuilder *Builder, bool Directly) {
1490 // Check if any of the superclasses of the class match.
1491 for (const ObjCInterfaceDecl *ClassDecl = Declaration->getSuperClass();
1492 ClassDecl != nullptr; ClassDecl = ClassDecl->getSuperClass()) {
1493 // Check if there are any matching compatibility aliases.
1494 if (objcClassHasMatchingCompatibilityAlias(ClassDecl, Base, Builder))
1495 return true;
1496
1497 // Check if there are any matching type aliases.
1498 const Type *TypeNode = ClassDecl->getTypeForDecl();
1499 if (typeHasMatchingAlias(TypeNode, Base, Builder))
1500 return true;
1501
1502 if (Base.matches(*ClassDecl, this, Builder))
1503 return true;
1504
1505 // Not `return false` as a temporary workaround for PR43879.
1506 if (Directly)
1507 break;
1508 }
1509
1510 return false;
1511}
1512
1513bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
1514 if (shouldSkipNode(DeclNode))
1515 return true;
1516
1517 if (Options.SkipDeclsInModules && DeclNode->isInAnotherModuleUnit())
1518 return true;
1519
1520 bool ScopedTraversal =
1521 TraversingASTNodeNotSpelledInSource || DeclNode->isImplicit();
1522 bool ScopedChildren = TraversingASTChildrenNotSpelledInSource;
1523
1524 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DeclNode)) {
1525 auto SK = CTSD->getSpecializationKind();
1526 if (SK == TSK_ExplicitInstantiationDeclaration ||
1527 SK == TSK_ExplicitInstantiationDefinition)
1528 ScopedChildren = true;
1529 } else if (const auto *FD = dyn_cast<FunctionDecl>(DeclNode)) {
1530 if (FD->isDefaulted())
1531 ScopedChildren = true;
1532 if (FD->isTemplateInstantiation())
1533 ScopedTraversal = true;
1534 } else if (isa<BindingDecl>(DeclNode)) {
1535 ScopedChildren = true;
1536 }
1537
1538 ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
1539 ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren);
1540
1541 match(*DeclNode);
1542 return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
1543}
1544
1545bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
1546 if (shouldSkipNode(StmtNode))
1547 return true;
1548
1549 bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
1550 TraversingASTChildrenNotSpelledInSource;
1551
1552 ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
1553 match(*StmtNode);
1554 return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode, Queue);
1555}
1556
1557bool MatchASTVisitor::TraverseType(QualType TypeNode, bool TraverseQualifier) {
1558 if (shouldSkipNode(TypeNode))
1559 return true;
1560
1561 match(TypeNode);
1562 return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode,
1563 TraverseQualifier);
1564}
1565
1566bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode,
1567 bool TraverseQualifier) {
1568 if (shouldSkipNode(TypeLocNode))
1569 return true;
1570 // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
1571 // We still want to find those types via matchers, so we match them here. Note
1572 // that the TypeLocs are structurally a shadow-hierarchy to the expressed
1573 // type, so we visit all involved parts of a compound type when matching on
1574 // each TypeLoc.
1575 match(TypeLocNode);
1576 match(TypeLocNode.getType());
1577 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(
1578 TypeLocNode, TraverseQualifier);
1579}
1580
1581bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
1582 if (shouldSkipNode(NNS))
1583 return true;
1584
1585 match(NNS);
1586 return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
1587}
1588
1589bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
1590 NestedNameSpecifierLoc NNS) {
1591 if (!NNS)
1592 return true;
1593
1594 if (shouldSkipNode(NNS))
1595 return true;
1596
1597 match(NNS);
1598
1599 // We only match the nested name specifier here (as opposed to traversing it)
1600 // because the traversal is already done in the parallel "Loc"-hierarchy.
1601 if (NNS.hasQualifier())
1602 match(NNS.getNestedNameSpecifier());
1603 return
1604 RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
1605}
1606
1607bool MatchASTVisitor::TraverseConstructorInitializer(
1608 CXXCtorInitializer *CtorInit) {
1609 if (shouldSkipNode(CtorInit))
1610 return true;
1611
1612 bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
1613 TraversingASTChildrenNotSpelledInSource;
1614
1615 if (!CtorInit->isWritten())
1616 ScopedTraversal = true;
1617
1618 ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
1619
1620 match(*CtorInit);
1621
1622 return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
1623 CtorInit);
1624}
1625
1626bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
1627 if (shouldSkipNode(Loc))
1628 return true;
1629
1630 match(Loc);
1631 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
1632}
1633
1634bool MatchASTVisitor::TraverseAttr(Attr *AttrNode) {
1635 if (shouldSkipNode(AttrNode))
1636 return true;
1637
1638 match(*AttrNode);
1639 return RecursiveASTVisitor<MatchASTVisitor>::TraverseAttr(AttrNode);
1640}
1641
1642class MatchASTConsumer : public ASTConsumer {
1643public:
1644 MatchASTConsumer(MatchFinder *Finder,
1645 MatchFinder::ParsingDoneTestCallback *ParsingDone)
1646 : Finder(Finder), ParsingDone(ParsingDone) {}
1647
1648private:
1649 void HandleTranslationUnit(ASTContext &Context) override {
1650 if (ParsingDone != nullptr) {
1651 ParsingDone->run();
1652 }
1653 Finder->matchAST(Context);
1654 }
1655
1656 MatchFinder *Finder;
1657 MatchFinder::ParsingDoneTestCallback *ParsingDone;
1658};
1659
1660} // end namespace
1661} // end namespace internal
1662
1663template <typename T>
1664static internal::Matcher<T>
1665adjustTraversalKind(const internal::Matcher<T> &NodeMatch,
1667 if (Action)
1668 if (std::optional<TraversalKind> TK = Action->getCheckTraversalKind())
1669 return traverse(*TK, NodeMatch);
1670 return NodeMatch;
1671}
1672
1677
1680
1682 : Options(std::move(Options)), ParsingDone(nullptr) {}
1683
1685
1687 MatchCallback *Action) {
1688 Matchers.DeclOrStmt.emplace_back(adjustTraversalKind(NodeMatch, Action),
1689 Action);
1690 Matchers.AllCallbacks.insert(Action);
1691}
1692
1694 MatchCallback *Action) {
1695 Matchers.Type.emplace_back(adjustTraversalKind(NodeMatch, Action), Action);
1696 Matchers.AllCallbacks.insert(Action);
1697}
1698
1700 MatchCallback *Action) {
1701 Matchers.DeclOrStmt.emplace_back(adjustTraversalKind(NodeMatch, Action),
1702 Action);
1703 Matchers.AllCallbacks.insert(Action);
1704}
1705
1707 MatchCallback *Action) {
1708 Matchers.NestedNameSpecifier.emplace_back(
1709 adjustTraversalKind(NodeMatch, Action), Action);
1710 Matchers.AllCallbacks.insert(Action);
1711}
1712
1714 MatchCallback *Action) {
1715 Matchers.NestedNameSpecifierLoc.emplace_back(
1716 adjustTraversalKind(NodeMatch, Action), Action);
1717 Matchers.AllCallbacks.insert(Action);
1718}
1719
1721 MatchCallback *Action) {
1722 Matchers.TypeLoc.emplace_back(adjustTraversalKind(NodeMatch, Action), Action);
1723 Matchers.AllCallbacks.insert(Action);
1724}
1725
1727 MatchCallback *Action) {
1728 Matchers.CtorInit.emplace_back(adjustTraversalKind(NodeMatch, Action),
1729 Action);
1730 Matchers.AllCallbacks.insert(Action);
1731}
1732
1734 MatchCallback *Action) {
1735 Matchers.TemplateArgumentLoc.emplace_back(
1736 adjustTraversalKind(NodeMatch, Action), Action);
1737 Matchers.AllCallbacks.insert(Action);
1738}
1739
1741 MatchCallback *Action) {
1742 Matchers.Attr.emplace_back(adjustTraversalKind(AttrMatch, Action), Action);
1743 Matchers.AllCallbacks.insert(Action);
1744}
1745
1746bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
1747 MatchCallback *Action) {
1748 if (NodeMatch.canConvertTo<Decl>()) {
1749 addMatcher(NodeMatch.convertTo<Decl>(), Action);
1750 return true;
1751 } else if (NodeMatch.canConvertTo<QualType>()) {
1752 addMatcher(NodeMatch.convertTo<QualType>(), Action);
1753 return true;
1754 } else if (NodeMatch.canConvertTo<Stmt>()) {
1755 addMatcher(NodeMatch.convertTo<Stmt>(), Action);
1756 return true;
1757 } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) {
1758 addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action);
1759 return true;
1760 } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) {
1761 addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action);
1762 return true;
1763 } else if (NodeMatch.canConvertTo<TypeLoc>()) {
1764 addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
1765 return true;
1766 } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
1767 addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
1768 return true;
1769 } else if (NodeMatch.canConvertTo<TemplateArgumentLoc>()) {
1770 addMatcher(NodeMatch.convertTo<TemplateArgumentLoc>(), Action);
1771 return true;
1772 } else if (NodeMatch.canConvertTo<Attr>()) {
1773 addMatcher(NodeMatch.convertTo<Attr>(), Action);
1774 return true;
1775 }
1776 return false;
1777}
1778
1779std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
1780 return std::make_unique<internal::MatchASTConsumer>(this, ParsingDone);
1781}
1782
1784 internal::MatchASTVisitor Visitor(&Matchers, Options);
1785 Visitor.set_active_ast_context(&Context);
1786 Visitor.match(Node);
1787}
1788
1790 internal::MatchASTVisitor Visitor(&Matchers, Options);
1791 internal::MatchASTVisitor::TraceReporter StackTrace(Visitor);
1792 Visitor.set_active_ast_context(&Context);
1793 Visitor.onStartOfTranslationUnit();
1794 Visitor.TraverseAST(Context);
1795 Visitor.onEndOfTranslationUnit();
1796}
1797
1799 MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
1800 ParsingDone = NewParsingDone;
1801}
1802
1803StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
1804
1805std::optional<TraversalKind>
1807 return std::nullopt;
1808}
1809
1810} // end namespace ast_matchers
1811} // end namespace clang
Defines the clang::ASTContext interface.
#define V(N, I)
#define IMPL(Index)
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Result
Implement __builtin_bit_cast and related operations.
static void print(llvm::raw_ostream &OS, const T &V, const Context &Ctx, QualType Ty)
Defines the clang::Module class, which describes a module in the source code.
SourceManager & getSourceManager()
Definition ASTContext.h:917
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const clang::PrintingPolicy & getPrintingPolicy() const
Definition ASTContext.h:909
ParentMapContext & getParentMapContext()
Returns the dynamic AST node parent map context.
Definition ASTContext.h:882
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
Attr - This represents one attribute.
Definition Attr.h:46
Represents a C++ base or member initializer.
Definition DeclCXX.h:2407
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
A dynamically typed AST node container.
static DynTypedNode create(const T &Node)
Creates a DynTypedNode from Node.
Expr * getNoexceptExpr() const
Return the expression inside noexcept(expression), or a null pointer if there is none (because the ex...
Definition TypeBase.h:5781
ArrayRef< QualType > exceptions() const
Definition TypeBase.h:5870
A C++ nested-name-specifier augmented with source location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
A (possibly-)qualified type.
Definition TypeBase.h:938
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS)
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc)
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)
bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier=true)
bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue)
bool TraverseType(QualType T, bool TraverseQualifier=true)
bool TraverseConstructorInitializer(CXXCtorInitializer *Init)
Stmt - This represents one statement.
Definition Stmt.h:85
Location wrapper for a TemplateArgument.
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
const char * getTypeClassName() const
Definition Type.cpp:3612
Maps string IDs to AST nodes matched by parts of a matcher.
internal::BoundNodesMap::IDToNodeMap IDToNodeMap
Type of mapping from binding identifiers to bound nodes.
Called when the Match registered for it was successfully found in the AST.
virtual std::optional< TraversalKind > getCheckTraversalKind() const
TraversalKind to use while matching and processing the result nodes.
virtual StringRef getID() const
An id used to group the matchers.
Called when parsing is finished. Intended for testing only.
MatchFinder(MatchFinderOptions Options=MatchFinderOptions())
bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
void addMatcher(const DeclarationMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
void match(const T &Node, ASTContext &Context)
Calls the registered callbacks on all matches on the given Node.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone)
Registers a callback to notify the end of parsing.
std::unique_ptr< clang::ASTConsumer > newASTConsumer()
Creates a clang ASTConsumer that finds all matches.
void matchAST(ASTContext &Context)
Finds all matches in the given AST.
#define USHRT_MAX
Definition limits.h:62
#define INT_MAX
Definition limits.h:50
internal::Matcher< QualType > TypeMatcher
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< Attr > AttrMatcher
internal::Matcher< CXXCtorInitializer > CXXCtorInitializerMatcher
internal::Matcher< Stmt > StatementMatcher
internal::Matcher< TemplateArgumentLoc > TemplateArgumentLocMatcher
internal::Matcher< NestedNameSpecifierLoc > NestedNameSpecifierLocMatcher
static internal::Matcher< T > adjustTraversalKind(const internal::Matcher< T > &NodeMatch, MatchFinder::MatchCallback *Action)
internal::Matcher< T > traverse(TraversalKind TK, const internal::Matcher< T > &InnerMatcher)
Causes all nested matchers to be matched with the specified traversal kind.
internal::Matcher< NestedNameSpecifier > NestedNameSpecifierMatcher
internal::Matcher< TypeLoc > TypeLocMatcher
DynTypedNode DynTypedNode
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1527
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
bool matches(const til::SExpr *E1, const til::SExpr *E2)
llvm::cl::opt< std::string > Filter
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Bind
'bind' clause, allowed on routine constructs.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
TraversalKind
Defines how we descend a level in the AST when we pass through expressions.
@ TK_AsIs
Will traverse all child nodes.
@ TK_IgnoreUnlessSpelledInSource
Ignore AST nodes not written in the source.
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
Definition DeclBase.h:1305
@ Other
Other implicit parameter.
Definition Decl.h:1775
#define false
Definition stdbool.h:26
MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context)
const BoundNodes Nodes
Contains the nodes bound on the current match.
clang::ASTContext *const Context
Utilities for interpreting the matched AST structures.