1 //===--- ASTMatchFinder.cpp - Structural query framework ------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Implements an algorithm to efficiently search for matches on AST nodes.
10 // Uses memoization to support recursive matches like HasDescendant.
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.
16 //===----------------------------------------------------------------------===//
18 #include "clang/ASTMatchers/ASTMatchFinder.h"
19 #include "clang/AST/ASTConsumer.h"
20 #include "clang/AST/ASTContext.h"
21 #include "clang/AST/DeclCXX.h"
22 #include "clang/AST/RecursiveASTVisitor.h"
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/SmallPtrSet.h"
25 #include "llvm/ADT/StringMap.h"
26 #include "llvm/Support/PrettyStackTrace.h"
27 #include "llvm/Support/Timer.h"
33 namespace ast_matchers
{
37 typedef MatchFinder::MatchCallback MatchCallback
;
39 // The maximum number of memoization entries to store.
40 // 10k has been experimentally found to give a good trade-off
41 // of performance vs. memory consumption by running matcher
42 // that match on every statement over a very large codebase.
44 // FIXME: Do some performance optimization in general and
45 // revisit this number; also, put up micro-benchmarks that we can
47 static const unsigned MaxMemoizationEntries
= 10000;
49 enum class MatchType
{
56 // We use memoization to avoid running the same matcher on the same
57 // AST node twice. This struct is the key for looking up match
58 // result. It consists of an ID of the MatcherInterface (for
59 // identifying the matcher), a pointer to the AST node and the
60 // bound nodes before the matcher was executed.
62 // We currently only memoize on nodes whose pointers identify the
63 // nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
64 // For \c QualType and \c TypeLoc it is possible to implement
65 // generation of keys for each type.
66 // FIXME: Benchmark whether memoization of non-pointer typed nodes
67 // provides enough benefit for the additional amount of code.
69 DynTypedMatcher::MatcherIDType MatcherID
;
71 BoundNodesTreeBuilder BoundNodes
;
72 TraversalKind Traversal
= TK_AsIs
;
75 bool operator<(const MatchKey
&Other
) const {
76 return std::tie(Traversal
, Type
, MatcherID
, Node
, BoundNodes
) <
77 std::tie(Other
.Traversal
, Other
.Type
, Other
.MatcherID
, Other
.Node
,
82 // Used to store the result of a match and possibly bound nodes.
83 struct MemoizedMatchResult
{
85 BoundNodesTreeBuilder Nodes
;
88 // A RecursiveASTVisitor that traverses all children or all descendants of
90 class MatchChildASTVisitor
91 : public RecursiveASTVisitor
<MatchChildASTVisitor
> {
93 typedef RecursiveASTVisitor
<MatchChildASTVisitor
> VisitorBase
;
95 // Creates an AST visitor that matches 'matcher' on all children or
96 // descendants of a traversed node. max_depth is the maximum depth
97 // to traverse: use 1 for matching the children and INT_MAX for
98 // matching the descendants.
99 MatchChildASTVisitor(const DynTypedMatcher
*Matcher
, ASTMatchFinder
*Finder
,
100 BoundNodesTreeBuilder
*Builder
, int MaxDepth
,
101 bool IgnoreImplicitChildren
,
102 ASTMatchFinder::BindKind Bind
)
103 : Matcher(Matcher
), Finder(Finder
), Builder(Builder
), CurrentDepth(0),
104 MaxDepth(MaxDepth
), IgnoreImplicitChildren(IgnoreImplicitChildren
),
105 Bind(Bind
), Matches(false) {}
107 // Returns true if a match is found in the subtree rooted at the
108 // given AST node. This is done via a set of mutually recursive
109 // functions. Here's how the recursion is done (the *wildcard can
110 // actually be Decl, Stmt, or Type):
112 // - Traverse(node) calls BaseTraverse(node) when it needs
113 // to visit the descendants of node.
114 // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
115 // Traverse*(c) for each child c of 'node'.
116 // - Traverse*(c) in turn calls Traverse(c), completing the
118 bool findMatch(const DynTypedNode
&DynNode
) {
120 if (const Decl
*D
= DynNode
.get
<Decl
>())
122 else if (const Stmt
*S
= DynNode
.get
<Stmt
>())
124 else if (const NestedNameSpecifier
*NNS
=
125 DynNode
.get
<NestedNameSpecifier
>())
127 else if (const NestedNameSpecifierLoc
*NNSLoc
=
128 DynNode
.get
<NestedNameSpecifierLoc
>())
130 else if (const QualType
*Q
= DynNode
.get
<QualType
>())
132 else if (const TypeLoc
*T
= DynNode
.get
<TypeLoc
>())
134 else if (const auto *C
= DynNode
.get
<CXXCtorInitializer
>())
136 else if (const TemplateArgumentLoc
*TALoc
=
137 DynNode
.get
<TemplateArgumentLoc
>())
139 else if (const Attr
*A
= DynNode
.get
<Attr
>())
141 // FIXME: Add other base types after adding tests.
143 // It's OK to always overwrite the bound nodes, as if there was
144 // no match in this recursive branch, the result set is empty
146 *Builder
= ResultBindings
;
151 // The following are overriding methods from the base visitor class.
152 // They are public only to allow CRTP to work. They are *not *part
153 // of the public API of this class.
154 bool TraverseDecl(Decl
*DeclNode
) {
156 if (DeclNode
&& DeclNode
->isImplicit() &&
157 Finder
->isTraversalIgnoringImplicitNodes())
158 return baseTraverse(*DeclNode
);
160 ScopedIncrement
ScopedDepth(&CurrentDepth
);
161 return (DeclNode
== nullptr) || traverse(*DeclNode
);
164 Stmt
*getStmtToTraverse(Stmt
*StmtNode
) {
165 Stmt
*StmtToTraverse
= StmtNode
;
166 if (auto *ExprNode
= dyn_cast_or_null
<Expr
>(StmtNode
)) {
167 auto *LambdaNode
= dyn_cast_or_null
<LambdaExpr
>(StmtNode
);
168 if (LambdaNode
&& Finder
->isTraversalIgnoringImplicitNodes())
169 StmtToTraverse
= LambdaNode
;
172 Finder
->getASTContext().getParentMapContext().traverseIgnored(
175 return StmtToTraverse
;
178 bool TraverseStmt(Stmt
*StmtNode
, DataRecursionQueue
*Queue
= nullptr) {
179 // If we need to keep track of the depth, we can't perform data recursion.
180 if (CurrentDepth
== 0 || (CurrentDepth
<= MaxDepth
&& MaxDepth
< INT_MAX
))
183 ScopedIncrement
ScopedDepth(&CurrentDepth
);
184 Stmt
*StmtToTraverse
= getStmtToTraverse(StmtNode
);
188 if (IgnoreImplicitChildren
&& isa
<CXXDefaultArgExpr
>(StmtNode
))
191 if (!match(*StmtToTraverse
))
193 return VisitorBase::TraverseStmt(StmtToTraverse
, Queue
);
195 // We assume that the QualType and the contained type are on the same
196 // hierarchy level. Thus, we try to match either of them.
197 bool TraverseType(QualType TypeNode
) {
198 if (TypeNode
.isNull())
200 ScopedIncrement
ScopedDepth(&CurrentDepth
);
202 if (!match(*TypeNode
))
204 // The QualType is matched inside traverse.
205 return traverse(TypeNode
);
207 // We assume that the TypeLoc, contained QualType and contained Type all are
208 // on the same hierarchy level. Thus, we try to match all of them.
209 bool TraverseTypeLoc(TypeLoc TypeLocNode
) {
210 if (TypeLocNode
.isNull())
212 ScopedIncrement
ScopedDepth(&CurrentDepth
);
214 if (!match(*TypeLocNode
.getType()))
216 // Match the QualType.
217 if (!match(TypeLocNode
.getType()))
219 // The TypeLoc is matched inside traverse.
220 return traverse(TypeLocNode
);
222 bool TraverseNestedNameSpecifier(NestedNameSpecifier
*NNS
) {
223 ScopedIncrement
ScopedDepth(&CurrentDepth
);
224 return (NNS
== nullptr) || traverse(*NNS
);
226 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS
) {
229 ScopedIncrement
ScopedDepth(&CurrentDepth
);
230 if (!match(*NNS
.getNestedNameSpecifier()))
232 return traverse(NNS
);
234 bool TraverseConstructorInitializer(CXXCtorInitializer
*CtorInit
) {
237 ScopedIncrement
ScopedDepth(&CurrentDepth
);
238 return traverse(*CtorInit
);
240 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL
) {
241 ScopedIncrement
ScopedDepth(&CurrentDepth
);
242 return traverse(TAL
);
244 bool TraverseCXXForRangeStmt(CXXForRangeStmt
*Node
) {
245 if (!Finder
->isTraversalIgnoringImplicitNodes())
246 return VisitorBase::TraverseCXXForRangeStmt(Node
);
249 ScopedIncrement
ScopedDepth(&CurrentDepth
);
250 if (auto *Init
= Node
->getInit())
251 if (!traverse(*Init
))
253 if (!match(*Node
->getLoopVariable()))
255 if (match(*Node
->getRangeInit()))
256 if (!VisitorBase::TraverseStmt(Node
->getRangeInit()))
258 if (!match(*Node
->getBody()))
260 return VisitorBase::TraverseStmt(Node
->getBody());
262 bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator
*Node
) {
263 if (!Finder
->isTraversalIgnoringImplicitNodes())
264 return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node
);
267 ScopedIncrement
ScopedDepth(&CurrentDepth
);
269 return match(*Node
->getLHS()) && match(*Node
->getRHS());
271 bool TraverseAttr(Attr
*A
) {
274 Finder
->getASTContext().getParentMapContext().getTraversalKind() ==
275 TK_IgnoreUnlessSpelledInSource
))
277 ScopedIncrement
ScopedDepth(&CurrentDepth
);
280 bool TraverseLambdaExpr(LambdaExpr
*Node
) {
281 if (!Finder
->isTraversalIgnoringImplicitNodes())
282 return VisitorBase::TraverseLambdaExpr(Node
);
285 ScopedIncrement
ScopedDepth(&CurrentDepth
);
287 for (unsigned I
= 0, N
= Node
->capture_size(); I
!= N
; ++I
) {
288 const LambdaCapture
*C
= Node
->capture_begin() + I
;
289 if (!C
->isExplicit())
291 if (Node
->isInitCapture(C
) && !match(*C
->getCapturedVar()))
293 const Expr
*CIE
= Node
->capture_init_begin()[I
];
294 if (CIE
!= nullptr && !match(*CIE
))
298 if (const auto *TPL
= Node
->getTemplateParameterList()) {
299 for (const auto *TP
: *TPL
) {
305 for (const auto *P
: Node
->getCallOperator()->parameters()) {
310 if (!match(*Node
->getBody()))
313 return VisitorBase::TraverseStmt(Node
->getBody());
316 bool shouldVisitTemplateInstantiations() const { return true; }
317 bool shouldVisitImplicitCode() const { return !IgnoreImplicitChildren
; }
320 // Used for updating the depth during traversal.
321 struct ScopedIncrement
{
322 explicit ScopedIncrement(int *Depth
) : Depth(Depth
) { ++(*Depth
); }
323 ~ScopedIncrement() { --(*Depth
); }
329 // Resets the state of this object.
335 // Forwards the call to the corresponding Traverse*() method in the
336 // base visitor class.
337 bool baseTraverse(const Decl
&DeclNode
) {
338 return VisitorBase::TraverseDecl(const_cast<Decl
*>(&DeclNode
));
340 bool baseTraverse(const Stmt
&StmtNode
) {
341 return VisitorBase::TraverseStmt(const_cast<Stmt
*>(&StmtNode
));
343 bool baseTraverse(QualType TypeNode
) {
344 return VisitorBase::TraverseType(TypeNode
);
346 bool baseTraverse(TypeLoc TypeLocNode
) {
347 return VisitorBase::TraverseTypeLoc(TypeLocNode
);
349 bool baseTraverse(const NestedNameSpecifier
&NNS
) {
350 return VisitorBase::TraverseNestedNameSpecifier(
351 const_cast<NestedNameSpecifier
*>(&NNS
));
353 bool baseTraverse(NestedNameSpecifierLoc NNS
) {
354 return VisitorBase::TraverseNestedNameSpecifierLoc(NNS
);
356 bool baseTraverse(const CXXCtorInitializer
&CtorInit
) {
357 return VisitorBase::TraverseConstructorInitializer(
358 const_cast<CXXCtorInitializer
*>(&CtorInit
));
360 bool baseTraverse(TemplateArgumentLoc TAL
) {
361 return VisitorBase::TraverseTemplateArgumentLoc(TAL
);
363 bool baseTraverse(const Attr
&AttrNode
) {
364 return VisitorBase::TraverseAttr(const_cast<Attr
*>(&AttrNode
));
367 // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
368 // 0 < CurrentDepth <= MaxDepth.
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
) {
377 if (Bind
!= ASTMatchFinder::BK_All
) {
378 BoundNodesTreeBuilder
RecursiveBuilder(*Builder
);
379 if (Matcher
->matches(DynTypedNode::create(Node
), Finder
,
380 &RecursiveBuilder
)) {
382 ResultBindings
.addMatch(RecursiveBuilder
);
383 return false; // Abort as soon as a match is found.
386 BoundNodesTreeBuilder
RecursiveBuilder(*Builder
);
387 if (Matcher
->matches(DynTypedNode::create(Node
), Finder
,
388 &RecursiveBuilder
)) {
389 // After the first match the matcher succeeds.
391 ResultBindings
.addMatch(RecursiveBuilder
);
397 // Traverses the subtree rooted at 'Node'; returns true if the
398 // traversal should continue after this function returns.
399 template <typename T
>
400 bool traverse(const T
&Node
) {
401 static_assert(IsBaseType
<T
>::value
,
402 "traverse can only be instantiated with base type");
405 return baseTraverse(Node
);
408 const DynTypedMatcher
*const Matcher
;
409 ASTMatchFinder
*const Finder
;
410 BoundNodesTreeBuilder
*const Builder
;
411 BoundNodesTreeBuilder ResultBindings
;
414 const bool IgnoreImplicitChildren
;
415 const ASTMatchFinder::BindKind Bind
;
419 // Controls the outermost traversal of the AST and allows to match multiple
421 class MatchASTVisitor
: public RecursiveASTVisitor
<MatchASTVisitor
>,
422 public ASTMatchFinder
{
424 MatchASTVisitor(const MatchFinder::MatchersByType
*Matchers
,
425 const MatchFinder::MatchFinderOptions
&Options
)
426 : Matchers(Matchers
), Options(Options
), ActiveASTContext(nullptr) {}
428 ~MatchASTVisitor() override
{
429 if (Options
.CheckProfiling
) {
430 Options
.CheckProfiling
->Records
= std::move(TimeByBucket
);
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();
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();
454 void set_active_ast_context(ASTContext
*NewActiveASTContext
) {
455 ActiveASTContext
= NewActiveASTContext
;
458 // The following Visit*() and Traverse*() functions "override"
459 // methods in RecursiveASTVisitor.
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.
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
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
);
496 bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl
*CAD
) {
497 const ObjCInterfaceDecl
*InterfaceDecl
= CAD
->getClassInterface();
498 CompatibleAliases
[InterfaceDecl
].insert(CAD
);
502 bool TraverseDecl(Decl
*DeclNode
);
503 bool TraverseStmt(Stmt
*StmtNode
, DataRecursionQueue
*Queue
= nullptr);
504 bool TraverseType(QualType TypeNode
);
505 bool TraverseTypeLoc(TypeLoc TypeNode
);
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
);
512 bool dataTraverseNode(Stmt
*S
, DataRecursionQueue
*Queue
) {
513 if (auto *RF
= dyn_cast
<CXXForRangeStmt
>(S
)) {
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());
522 ASTNodeNotSpelledInSourceScope
RAII(this, true);
523 for (auto *SubStmt
: RF
->children()) {
524 if (SubStmt
!= RF
->getBody())
525 TraverseStmt(SubStmt
);
528 TraverseStmt(RF
->getBody());
530 } else if (auto *RBO
= dyn_cast
<CXXRewrittenBinaryOperator
>(S
)) {
532 ASTNodeNotAsIsSourceScope
RAII(this, true);
533 TraverseStmt(const_cast<Expr
*>(RBO
->getLHS()));
534 TraverseStmt(const_cast<Expr
*>(RBO
->getRHS()));
537 ASTNodeNotSpelledInSourceScope
RAII(this, true);
538 for (auto *SubStmt
: RBO
->children()) {
539 TraverseStmt(SubStmt
);
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
));
552 ASTNodeNotSpelledInSourceScope
RAII(this, true);
553 TraverseDecl(LE
->getLambdaClass());
556 ASTNodeNotAsIsSourceScope
RAII(this, true);
558 // We need to poke around to find the bits that might be explicitly
560 TypeLoc TL
= LE
->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
561 FunctionProtoTypeLoc Proto
= TL
.getAsAdjusted
<FunctionProtoTypeLoc
>();
563 if (auto *TPL
= LE
->getTemplateParameterList()) {
564 for (NamedDecl
*D
: *TPL
) {
567 if (Expr
*RequiresClause
= TPL
->getRequiresClause()) {
568 TraverseStmt(RequiresClause
);
572 if (LE
->hasExplicitParameters()) {
574 for (ParmVarDecl
*Param
: Proto
.getParams())
578 const auto *T
= Proto
.getTypePtr();
579 for (const auto &E
: T
->exceptions())
582 if (Expr
*NE
= T
->getNoexceptExpr())
583 TraverseStmt(NE
, Queue
);
585 if (LE
->hasExplicitResultType())
586 TraverseTypeLoc(Proto
.getReturnLoc());
587 TraverseStmt(LE
->getTrailingRequiresClause());
590 TraverseStmt(LE
->getBody());
593 return RecursiveASTVisitor
<MatchASTVisitor
>::dataTraverseNode(S
, Queue
);
596 // Matches children or descendants of 'Node' with 'BaseMatcher'.
597 bool memoizedMatchesRecursively(const DynTypedNode
&Node
, ASTContext
&Ctx
,
598 const DynTypedMatcher
&Matcher
,
599 BoundNodesTreeBuilder
*Builder
, int MaxDepth
,
601 // For AST-nodes that don't have an identity, we can't memoize.
602 if (!Node
.getMemoizationData() || !Builder
->isComparable())
603 return matchesRecursively(Node
, Matcher
, Builder
, MaxDepth
, Bind
);
606 Key
.MatcherID
= Matcher
.getID();
608 // Note that we key on the bindings *before* the match.
609 Key
.BoundNodes
= *Builder
;
610 Key
.Traversal
= Ctx
.getParentMapContext().getTraversalKind();
611 // Memoize result even doing a single-level match, it might be expensive.
612 Key
.Type
= MaxDepth
== 1 ? MatchType::Child
: MatchType::Descendants
;
613 MemoizationMap::iterator I
= ResultCache
.find(Key
);
614 if (I
!= ResultCache
.end()) {
615 *Builder
= I
->second
.Nodes
;
616 return I
->second
.ResultOfMatch
;
619 MemoizedMatchResult Result
;
620 Result
.Nodes
= *Builder
;
621 Result
.ResultOfMatch
=
622 matchesRecursively(Node
, Matcher
, &Result
.Nodes
, MaxDepth
, Bind
);
624 MemoizedMatchResult
&CachedResult
= ResultCache
[Key
];
625 CachedResult
= std::move(Result
);
627 *Builder
= CachedResult
.Nodes
;
628 return CachedResult
.ResultOfMatch
;
631 // Matches children or descendants of 'Node' with 'BaseMatcher'.
632 bool matchesRecursively(const DynTypedNode
&Node
,
633 const DynTypedMatcher
&Matcher
,
634 BoundNodesTreeBuilder
*Builder
, int MaxDepth
,
636 bool ScopedTraversal
= TraversingASTNodeNotSpelledInSource
||
637 TraversingASTChildrenNotSpelledInSource
;
639 bool IgnoreImplicitChildren
= false;
641 if (isTraversalIgnoringImplicitNodes()) {
642 IgnoreImplicitChildren
= true;
645 ASTNodeNotSpelledInSourceScope
RAII(this, ScopedTraversal
);
647 MatchChildASTVisitor
Visitor(&Matcher
, this, Builder
, MaxDepth
,
648 IgnoreImplicitChildren
, Bind
);
649 return Visitor
.findMatch(Node
);
652 bool classIsDerivedFrom(const CXXRecordDecl
*Declaration
,
653 const Matcher
<NamedDecl
> &Base
,
654 BoundNodesTreeBuilder
*Builder
,
655 bool Directly
) override
;
659 classIsDerivedFromImpl(const CXXRecordDecl
*Declaration
,
660 const Matcher
<NamedDecl
> &Base
,
661 BoundNodesTreeBuilder
*Builder
, bool Directly
,
662 llvm::SmallPtrSetImpl
<const CXXRecordDecl
*> &Visited
);
665 bool objcClassIsDerivedFrom(const ObjCInterfaceDecl
*Declaration
,
666 const Matcher
<NamedDecl
> &Base
,
667 BoundNodesTreeBuilder
*Builder
,
668 bool Directly
) override
;
671 // Implements ASTMatchFinder::matchesChildOf.
672 bool matchesChildOf(const DynTypedNode
&Node
, ASTContext
&Ctx
,
673 const DynTypedMatcher
&Matcher
,
674 BoundNodesTreeBuilder
*Builder
, BindKind Bind
) override
{
675 if (ResultCache
.size() > MaxMemoizationEntries
)
677 return memoizedMatchesRecursively(Node
, Ctx
, Matcher
, Builder
, 1, Bind
);
679 // Implements ASTMatchFinder::matchesDescendantOf.
680 bool matchesDescendantOf(const DynTypedNode
&Node
, ASTContext
&Ctx
,
681 const DynTypedMatcher
&Matcher
,
682 BoundNodesTreeBuilder
*Builder
,
683 BindKind Bind
) override
{
684 if (ResultCache
.size() > MaxMemoizationEntries
)
686 return memoizedMatchesRecursively(Node
, Ctx
, Matcher
, Builder
, INT_MAX
,
689 // Implements ASTMatchFinder::matchesAncestorOf.
690 bool matchesAncestorOf(const DynTypedNode
&Node
, ASTContext
&Ctx
,
691 const DynTypedMatcher
&Matcher
,
692 BoundNodesTreeBuilder
*Builder
,
693 AncestorMatchMode MatchMode
) override
{
694 // Reset the cache outside of the recursive call to make sure we
695 // don't invalidate any iterators.
696 if (ResultCache
.size() > MaxMemoizationEntries
)
698 if (MatchMode
== AncestorMatchMode::AMM_ParentOnly
)
699 return matchesParentOf(Node
, Matcher
, Builder
);
700 return matchesAnyAncestorOf(Node
, Ctx
, Matcher
, Builder
);
703 // Matches all registered matchers on the given node and calls the
704 // result callback for every node that matches.
705 void match(const DynTypedNode
&Node
) {
706 // FIXME: Improve this with a switch or a visitor pattern.
707 if (auto *N
= Node
.get
<Decl
>()) {
709 } else if (auto *N
= Node
.get
<Stmt
>()) {
711 } else if (auto *N
= Node
.get
<Type
>()) {
713 } else if (auto *N
= Node
.get
<QualType
>()) {
715 } else if (auto *N
= Node
.get
<NestedNameSpecifier
>()) {
717 } else if (auto *N
= Node
.get
<NestedNameSpecifierLoc
>()) {
719 } else if (auto *N
= Node
.get
<TypeLoc
>()) {
721 } else if (auto *N
= Node
.get
<CXXCtorInitializer
>()) {
723 } else if (auto *N
= Node
.get
<TemplateArgumentLoc
>()) {
725 } else if (auto *N
= Node
.get
<Attr
>()) {
730 template <typename T
> void match(const T
&Node
) {
731 matchDispatch(&Node
);
734 // Implements ASTMatchFinder::getASTContext.
735 ASTContext
&getASTContext() const override
{ return *ActiveASTContext
; }
737 bool shouldVisitTemplateInstantiations() const { return true; }
738 bool shouldVisitImplicitCode() const { return true; }
740 // We visit the lambda body explicitly, so instruct the RAV
741 // to not visit it on our behalf too.
742 bool shouldVisitLambdaBody() const { return false; }
744 bool IsMatchingInASTNodeNotSpelledInSource() const override
{
745 return TraversingASTNodeNotSpelledInSource
;
747 bool isMatchingChildrenNotSpelledInSource() const override
{
748 return TraversingASTChildrenNotSpelledInSource
;
750 void setMatchingChildrenNotSpelledInSource(bool Set
) override
{
751 TraversingASTChildrenNotSpelledInSource
= Set
;
754 bool IsMatchingInASTNodeNotAsIs() const override
{
755 return TraversingASTNodeNotAsIs
;
758 bool TraverseTemplateInstantiations(ClassTemplateDecl
*D
) {
759 ASTNodeNotSpelledInSourceScope
RAII(this, true);
760 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTemplateInstantiations(
764 bool TraverseTemplateInstantiations(VarTemplateDecl
*D
) {
765 ASTNodeNotSpelledInSourceScope
RAII(this, true);
766 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTemplateInstantiations(
770 bool TraverseTemplateInstantiations(FunctionTemplateDecl
*D
) {
771 ASTNodeNotSpelledInSourceScope
RAII(this, true);
772 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTemplateInstantiations(
777 bool TraversingASTNodeNotSpelledInSource
= false;
778 bool TraversingASTNodeNotAsIs
= false;
779 bool TraversingASTChildrenNotSpelledInSource
= false;
782 // We don't have enough free low bits in 32bit builds to discriminate 8 pointer
783 // types in PointerUnion. so split the union in 2 using a free bit from the
785 #define CMD_TYPES_0 \
786 const QualType *, const TypeLoc *, const NestedNameSpecifier *, \
787 const NestedNameSpecifierLoc *
788 #define CMD_TYPES_1 \
789 const CXXCtorInitializer *, const TemplateArgumentLoc *, const Attr *, \
792 #define IMPL(Index) \
793 template <typename NodeType> \
795 llvm::is_one_of<const NodeType *, CMD_TYPES_##Index>::value> \
796 SetCallbackAndRawNode(const MatchCallback *CB, const NodeType &N) { \
798 Callback.setPointerAndInt(CB, Index); \
802 template <typename T> \
803 std::enable_if_t<llvm::is_one_of<const T *, CMD_TYPES_##Index>::value, \
806 assertHoldsState(); \
807 return Callback.getInt() == (Index) ? Node##Index.dyn_cast<const T *>() \
812 CurMatchData() : Node0(nullptr) {}
817 const MatchCallback
*getCallback() const { return Callback
.getPointer(); }
819 void SetBoundNodes(const BoundNodes
&BN
) {
824 void clearBoundNodes() {
829 const BoundNodes
*getBoundNodes() const {
836 Callback
.setPointerAndInt(nullptr, 0);
841 void assertHoldsState() const {
842 assert(Callback
.getPointer() != nullptr && !Node0
.isNull());
845 void assertEmpty() const {
846 assert(Callback
.getPointer() == nullptr && Node0
.isNull() &&
850 llvm::PointerIntPair
<const MatchCallback
*, 1> Callback
;
852 llvm::PointerUnion
<CMD_TYPES_0
> Node0
;
853 llvm::PointerUnion
<CMD_TYPES_1
> Node1
;
855 const BoundNodes
*BNodes
= nullptr;
862 struct CurMatchRAII
{
863 template <typename NodeType
>
864 CurMatchRAII(MatchASTVisitor
&MV
, const MatchCallback
*CB
,
867 MV
.CurMatchState
.SetCallbackAndRawNode(CB
, NT
);
870 ~CurMatchRAII() { MV
.CurMatchState
.reset(); }
877 class TraceReporter
: llvm::PrettyStackTraceEntry
{
878 static void dumpNode(const ASTContext
&Ctx
, const DynTypedNode
&Node
,
880 if (const auto *D
= Node
.get
<Decl
>()) {
881 OS
<< D
->getDeclKindName() << "Decl ";
882 if (const auto *ND
= dyn_cast
<NamedDecl
>(D
)) {
883 ND
->printQualifiedName(OS
);
887 D
->getSourceRange().print(OS
, Ctx
.getSourceManager());
888 } else if (const auto *S
= Node
.get
<Stmt
>()) {
889 OS
<< S
->getStmtClassName() << " : ";
890 S
->getSourceRange().print(OS
, Ctx
.getSourceManager());
891 } else if (const auto *T
= Node
.get
<Type
>()) {
892 OS
<< T
->getTypeClassName() << "Type : ";
893 QualType(T
, 0).print(OS
, Ctx
.getPrintingPolicy());
894 } else if (const auto *QT
= Node
.get
<QualType
>()) {
896 QT
->print(OS
, Ctx
.getPrintingPolicy());
898 OS
<< Node
.getNodeKind().asStringRef() << " : ";
899 Node
.getSourceRange().print(OS
, Ctx
.getSourceManager());
903 static void dumpNodeFromState(const ASTContext
&Ctx
,
904 const CurMatchData
&State
, raw_ostream
&OS
) {
905 if (const DynTypedNode
*MatchNode
= State
.getNode
<DynTypedNode
>()) {
906 dumpNode(Ctx
, *MatchNode
, OS
);
907 } else if (const auto *QT
= State
.getNode
<QualType
>()) {
908 dumpNode(Ctx
, DynTypedNode::create(*QT
), OS
);
909 } else if (const auto *TL
= State
.getNode
<TypeLoc
>()) {
910 dumpNode(Ctx
, DynTypedNode::create(*TL
), OS
);
911 } else if (const auto *NNS
= State
.getNode
<NestedNameSpecifier
>()) {
912 dumpNode(Ctx
, DynTypedNode::create(*NNS
), OS
);
913 } else if (const auto *NNSL
= State
.getNode
<NestedNameSpecifierLoc
>()) {
914 dumpNode(Ctx
, DynTypedNode::create(*NNSL
), OS
);
915 } else if (const auto *CtorInit
= State
.getNode
<CXXCtorInitializer
>()) {
916 dumpNode(Ctx
, DynTypedNode::create(*CtorInit
), OS
);
917 } else if (const auto *TAL
= State
.getNode
<TemplateArgumentLoc
>()) {
918 dumpNode(Ctx
, DynTypedNode::create(*TAL
), OS
);
919 } else if (const auto *At
= State
.getNode
<Attr
>()) {
920 dumpNode(Ctx
, DynTypedNode::create(*At
), OS
);
925 TraceReporter(const MatchASTVisitor
&MV
) : MV(MV
) {}
926 void print(raw_ostream
&OS
) const override
{
927 const CurMatchData
&State
= MV
.CurMatchState
;
928 const MatchCallback
*CB
= State
.getCallback();
930 OS
<< "ASTMatcher: Not currently matching\n";
934 assert(MV
.ActiveASTContext
&&
935 "ActiveASTContext should be set if there is a matched callback");
937 ASTContext
&Ctx
= MV
.getASTContext();
939 if (const BoundNodes
*Nodes
= State
.getBoundNodes()) {
940 OS
<< "ASTMatcher: Processing '" << CB
->getID() << "' against:\n\t";
941 dumpNodeFromState(Ctx
, State
, OS
);
942 const BoundNodes::IDToNodeMap
&Map
= Nodes
->getMap();
944 OS
<< "\nNo bound nodes\n";
947 OS
<< "\n--- Bound Nodes Begin ---\n";
948 for (const auto &Item
: Map
) {
949 OS
<< " " << Item
.first
<< " - { ";
950 dumpNode(Ctx
, Item
.second
, OS
);
953 OS
<< "--- Bound Nodes End ---\n";
955 OS
<< "ASTMatcher: Matching '" << CB
->getID() << "' against:\n\t";
956 dumpNodeFromState(Ctx
, State
, OS
);
962 const MatchASTVisitor
&MV
;
966 struct ASTNodeNotSpelledInSourceScope
{
967 ASTNodeNotSpelledInSourceScope(MatchASTVisitor
*V
, bool B
)
968 : MV(V
), MB(V
->TraversingASTNodeNotSpelledInSource
) {
969 V
->TraversingASTNodeNotSpelledInSource
= B
;
971 ~ASTNodeNotSpelledInSourceScope() {
972 MV
->TraversingASTNodeNotSpelledInSource
= MB
;
980 struct ASTNodeNotAsIsSourceScope
{
981 ASTNodeNotAsIsSourceScope(MatchASTVisitor
*V
, bool B
)
982 : MV(V
), MB(V
->TraversingASTNodeNotAsIs
) {
983 V
->TraversingASTNodeNotAsIs
= B
;
985 ~ASTNodeNotAsIsSourceScope() { MV
->TraversingASTNodeNotAsIs
= MB
; }
992 class TimeBucketRegion
{
994 TimeBucketRegion() = default;
995 ~TimeBucketRegion() { setBucket(nullptr); }
997 /// Start timing for \p NewBucket.
999 /// If there was a bucket already set, it will finish the timing for that
1001 /// \p NewBucket will be timed until the next call to \c setBucket() or
1002 /// until the \c TimeBucketRegion is destroyed.
1003 /// If \p NewBucket is the same as the currently timed bucket, this call
1005 void setBucket(llvm::TimeRecord
*NewBucket
) {
1006 if (Bucket
!= NewBucket
) {
1007 auto Now
= llvm::TimeRecord::getCurrentTime(true);
1017 llvm::TimeRecord
*Bucket
= nullptr;
1020 /// Runs all the \p Matchers on \p Node.
1022 /// Used by \c matchDispatch() below.
1023 template <typename T
, typename MC
>
1024 void matchWithoutFilter(const T
&Node
, const MC
&Matchers
) {
1025 const bool EnableCheckProfiling
= Options
.CheckProfiling
.has_value();
1026 TimeBucketRegion Timer
;
1027 for (const auto &MP
: Matchers
) {
1028 if (EnableCheckProfiling
)
1029 Timer
.setBucket(&TimeByBucket
[MP
.second
->getID()]);
1030 BoundNodesTreeBuilder Builder
;
1031 CurMatchRAII
RAII(*this, MP
.second
, Node
);
1032 if (MP
.first
.matches(Node
, this, &Builder
)) {
1033 MatchVisitor
Visitor(*this, ActiveASTContext
, MP
.second
);
1034 Builder
.visitMatches(&Visitor
);
1039 void matchWithFilter(const DynTypedNode
&DynNode
) {
1040 auto Kind
= DynNode
.getNodeKind();
1041 auto it
= MatcherFiltersMap
.find(Kind
);
1042 const auto &Filter
=
1043 it
!= MatcherFiltersMap
.end() ? it
->second
: getFilterForKind(Kind
);
1048 const bool EnableCheckProfiling
= Options
.CheckProfiling
.has_value();
1049 TimeBucketRegion Timer
;
1050 auto &Matchers
= this->Matchers
->DeclOrStmt
;
1051 for (unsigned short I
: Filter
) {
1052 auto &MP
= Matchers
[I
];
1053 if (EnableCheckProfiling
)
1054 Timer
.setBucket(&TimeByBucket
[MP
.second
->getID()]);
1055 BoundNodesTreeBuilder Builder
;
1058 TraversalKindScope
RAII(getASTContext(), MP
.first
.getTraversalKind());
1059 if (getASTContext().getParentMapContext().traverseIgnored(DynNode
) !=
1064 CurMatchRAII
RAII(*this, MP
.second
, DynNode
);
1065 if (MP
.first
.matches(DynNode
, this, &Builder
)) {
1066 MatchVisitor
Visitor(*this, ActiveASTContext
, MP
.second
);
1067 Builder
.visitMatches(&Visitor
);
1072 const std::vector
<unsigned short> &getFilterForKind(ASTNodeKind Kind
) {
1073 auto &Filter
= MatcherFiltersMap
[Kind
];
1074 auto &Matchers
= this->Matchers
->DeclOrStmt
;
1075 assert((Matchers
.size() < USHRT_MAX
) && "Too many matchers.");
1076 for (unsigned I
= 0, E
= Matchers
.size(); I
!= E
; ++I
) {
1077 if (Matchers
[I
].first
.canMatchNodesOfKind(Kind
)) {
1078 Filter
.push_back(I
);
1085 /// Overloads to pair the different node types to their matchers.
1086 void matchDispatch(const Decl
*Node
) {
1087 return matchWithFilter(DynTypedNode::create(*Node
));
1089 void matchDispatch(const Stmt
*Node
) {
1090 return matchWithFilter(DynTypedNode::create(*Node
));
1093 void matchDispatch(const Type
*Node
) {
1094 matchWithoutFilter(QualType(Node
, 0), Matchers
->Type
);
1096 void matchDispatch(const TypeLoc
*Node
) {
1097 matchWithoutFilter(*Node
, Matchers
->TypeLoc
);
1099 void matchDispatch(const QualType
*Node
) {
1100 matchWithoutFilter(*Node
, Matchers
->Type
);
1102 void matchDispatch(const NestedNameSpecifier
*Node
) {
1103 matchWithoutFilter(*Node
, Matchers
->NestedNameSpecifier
);
1105 void matchDispatch(const NestedNameSpecifierLoc
*Node
) {
1106 matchWithoutFilter(*Node
, Matchers
->NestedNameSpecifierLoc
);
1108 void matchDispatch(const CXXCtorInitializer
*Node
) {
1109 matchWithoutFilter(*Node
, Matchers
->CtorInit
);
1111 void matchDispatch(const TemplateArgumentLoc
*Node
) {
1112 matchWithoutFilter(*Node
, Matchers
->TemplateArgumentLoc
);
1114 void matchDispatch(const Attr
*Node
) {
1115 matchWithoutFilter(*Node
, Matchers
->Attr
);
1117 void matchDispatch(const void *) { /* Do nothing. */ }
1120 // Returns whether a direct parent of \p Node matches \p Matcher.
1121 // Unlike matchesAnyAncestorOf there's no memoization: it doesn't save much.
1122 bool matchesParentOf(const DynTypedNode
&Node
, const DynTypedMatcher
&Matcher
,
1123 BoundNodesTreeBuilder
*Builder
) {
1124 for (const auto &Parent
: ActiveASTContext
->getParents(Node
)) {
1125 BoundNodesTreeBuilder BuilderCopy
= *Builder
;
1126 if (Matcher
.matches(Parent
, this, &BuilderCopy
)) {
1127 *Builder
= std::move(BuilderCopy
);
1134 // Returns whether an ancestor of \p Node matches \p Matcher.
1136 // The order of matching (which can lead to different nodes being bound in
1137 // case there are multiple matches) is breadth first search.
1139 // To allow memoization in the very common case of having deeply nested
1140 // expressions inside a template function, we first walk up the AST, memoizing
1141 // the result of the match along the way, as long as there is only a single
1144 // Once there are multiple parents, the breadth first search order does not
1145 // allow simple memoization on the ancestors. Thus, we only memoize as long
1146 // as there is a single parent.
1148 // We avoid a recursive implementation to prevent excessive stack use on
1149 // very deep ASTs (similarly to RecursiveASTVisitor's data recursion).
1150 bool matchesAnyAncestorOf(DynTypedNode Node
, ASTContext
&Ctx
,
1151 const DynTypedMatcher
&Matcher
,
1152 BoundNodesTreeBuilder
*Builder
) {
1154 // Memoization keys that can be updated with the result.
1155 // These are the memoizable nodes in the chain of unique parents, which
1156 // terminates when a node has multiple parents, or matches, or is the root.
1157 std::vector
<MatchKey
> Keys
;
1158 // When returning, update the memoization cache.
1159 auto Finish
= [&](bool Matched
) {
1160 for (const auto &Key
: Keys
) {
1161 MemoizedMatchResult
&CachedResult
= ResultCache
[Key
];
1162 CachedResult
.ResultOfMatch
= Matched
;
1163 CachedResult
.Nodes
= *Builder
;
1168 // Loop while there's a single parent and we want to attempt memoization.
1169 DynTypedNodeList Parents
{ArrayRef
<DynTypedNode
>()}; // after loop: size != 1
1171 // A cache key only makes sense if memoization is possible.
1172 if (Builder
->isComparable()) {
1173 Keys
.emplace_back();
1174 Keys
.back().MatcherID
= Matcher
.getID();
1175 Keys
.back().Node
= Node
;
1176 Keys
.back().BoundNodes
= *Builder
;
1177 Keys
.back().Traversal
= Ctx
.getParentMapContext().getTraversalKind();
1178 Keys
.back().Type
= MatchType::Ancestors
;
1181 MemoizationMap::iterator I
= ResultCache
.find(Keys
.back());
1182 if (I
!= ResultCache
.end()) {
1183 Keys
.pop_back(); // Don't populate the cache for the matching node!
1184 *Builder
= I
->second
.Nodes
;
1185 return Finish(I
->second
.ResultOfMatch
);
1189 Parents
= ActiveASTContext
->getParents(Node
);
1190 // Either no parents or multiple parents: leave chain+memoize mode and
1191 // enter bfs+forgetful mode.
1192 if (Parents
.size() != 1)
1195 // Check the next parent.
1196 Node
= *Parents
.begin();
1197 BoundNodesTreeBuilder BuilderCopy
= *Builder
;
1198 if (Matcher
.matches(Node
, this, &BuilderCopy
)) {
1199 *Builder
= std::move(BuilderCopy
);
1200 return Finish(true);
1203 // We reached the end of the chain.
1205 if (Parents
.empty()) {
1206 // Nodes may have no parents if:
1207 // a) the node is the TranslationUnitDecl
1208 // b) we have a limited traversal scope that excludes the parent edges
1209 // c) there is a bug in the AST, and the node is not reachable
1210 // Usually the traversal scope is the whole AST, which precludes b.
1211 // Bugs are common enough that it's worthwhile asserting when we can.
1213 if (!Node
.get
<TranslationUnitDecl
>() &&
1214 /* Traversal scope is full AST if any of the bounds are the TU */
1215 llvm::any_of(ActiveASTContext
->getTraversalScope(), [](Decl
*D
) {
1216 return D
->getKind() == Decl::TranslationUnit
;
1218 llvm::errs() << "Tried to match orphan node:\n";
1219 Node
.dump(llvm::errs(), *ActiveASTContext
);
1220 llvm_unreachable("Parent map should be complete!");
1224 assert(Parents
.size() > 1);
1225 // BFS starting from the parents not yet considered.
1226 // Memoization of newly visited nodes is not possible (but we still update
1227 // results for the elements in the chain we found above).
1228 std::deque
<DynTypedNode
> Queue(Parents
.begin(), Parents
.end());
1229 llvm::DenseSet
<const void *> Visited
;
1230 while (!Queue
.empty()) {
1231 BoundNodesTreeBuilder BuilderCopy
= *Builder
;
1232 if (Matcher
.matches(Queue
.front(), this, &BuilderCopy
)) {
1233 *Builder
= std::move(BuilderCopy
);
1234 return Finish(true);
1236 for (const auto &Parent
: ActiveASTContext
->getParents(Queue
.front())) {
1237 // Make sure we do not visit the same node twice.
1238 // Otherwise, we'll visit the common ancestors as often as there
1239 // are splits on the way down.
1240 if (Visited
.insert(Parent
.getMemoizationData()).second
)
1241 Queue
.push_back(Parent
);
1246 return Finish(false);
1249 // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
1250 // the aggregated bound nodes for each match.
1251 class MatchVisitor
: public BoundNodesTreeBuilder::Visitor
{
1252 struct CurBoundScope
{
1253 CurBoundScope(MatchASTVisitor::CurMatchData
&State
, const BoundNodes
&BN
)
1255 State
.SetBoundNodes(BN
);
1258 ~CurBoundScope() { State
.clearBoundNodes(); }
1261 MatchASTVisitor::CurMatchData
&State
;
1265 MatchVisitor(MatchASTVisitor
&MV
, ASTContext
*Context
,
1266 MatchFinder::MatchCallback
*Callback
)
1267 : State(MV
.CurMatchState
), Context(Context
), Callback(Callback
) {}
1269 void visitMatch(const BoundNodes
& BoundNodesView
) override
{
1270 TraversalKindScope
RAII(*Context
, Callback
->getCheckTraversalKind());
1271 CurBoundScope
RAII2(State
, BoundNodesView
);
1272 Callback
->run(MatchFinder::MatchResult(BoundNodesView
, Context
));
1276 MatchASTVisitor::CurMatchData
&State
;
1277 ASTContext
* Context
;
1278 MatchFinder::MatchCallback
* Callback
;
1281 // Returns true if 'TypeNode' has an alias that matches the given matcher.
1282 bool typeHasMatchingAlias(const Type
*TypeNode
,
1283 const Matcher
<NamedDecl
> &Matcher
,
1284 BoundNodesTreeBuilder
*Builder
) {
1285 const Type
*const CanonicalType
=
1286 ActiveASTContext
->getCanonicalType(TypeNode
);
1287 auto Aliases
= TypeAliases
.find(CanonicalType
);
1288 if (Aliases
== TypeAliases
.end())
1290 for (const TypedefNameDecl
*Alias
: Aliases
->second
) {
1291 BoundNodesTreeBuilder
Result(*Builder
);
1292 if (Matcher
.matches(*Alias
, this, &Result
)) {
1293 *Builder
= std::move(Result
);
1301 objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl
*InterfaceDecl
,
1302 const Matcher
<NamedDecl
> &Matcher
,
1303 BoundNodesTreeBuilder
*Builder
) {
1304 auto Aliases
= CompatibleAliases
.find(InterfaceDecl
);
1305 if (Aliases
== CompatibleAliases
.end())
1307 for (const ObjCCompatibleAliasDecl
*Alias
: Aliases
->second
) {
1308 BoundNodesTreeBuilder
Result(*Builder
);
1309 if (Matcher
.matches(*Alias
, this, &Result
)) {
1310 *Builder
= std::move(Result
);
1317 /// Bucket to record map.
1319 /// Used to get the appropriate bucket for each matcher.
1320 llvm::StringMap
<llvm::TimeRecord
> TimeByBucket
;
1322 const MatchFinder::MatchersByType
*Matchers
;
1324 /// Filtered list of matcher indices for each matcher kind.
1326 /// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
1327 /// kind (and derived kinds) so it is a waste to try every matcher on every
1329 /// We precalculate a list of matchers that pass the toplevel restrict check.
1330 llvm::DenseMap
<ASTNodeKind
, std::vector
<unsigned short>> MatcherFiltersMap
;
1332 const MatchFinder::MatchFinderOptions
&Options
;
1333 ASTContext
*ActiveASTContext
;
1335 // Maps a canonical type to its TypedefDecls.
1336 llvm::DenseMap
<const Type
*, std::set
<const TypedefNameDecl
*> > TypeAliases
;
1338 // Maps an Objective-C interface to its ObjCCompatibleAliasDecls.
1339 llvm::DenseMap
<const ObjCInterfaceDecl
*,
1340 llvm::SmallPtrSet
<const ObjCCompatibleAliasDecl
*, 2>>
1343 // Maps (matcher, node) -> the match result for memoization.
1344 typedef std::map
<MatchKey
, MemoizedMatchResult
> MemoizationMap
;
1345 MemoizationMap ResultCache
;
1348 static CXXRecordDecl
*
1349 getAsCXXRecordDeclOrPrimaryTemplate(const Type
*TypeNode
) {
1350 if (auto *RD
= TypeNode
->getAsCXXRecordDecl())
1353 // Find the innermost TemplateSpecializationType that isn't an alias template.
1354 auto *TemplateType
= TypeNode
->getAs
<TemplateSpecializationType
>();
1355 while (TemplateType
&& TemplateType
->isTypeAlias())
1357 TemplateType
->getAliasedType()->getAs
<TemplateSpecializationType
>();
1359 // If this is the name of a (dependent) template specialization, use the
1360 // definition of the template, even though it might be specialized later.
1362 if (auto *ClassTemplate
= dyn_cast_or_null
<ClassTemplateDecl
>(
1363 TemplateType
->getTemplateName().getAsTemplateDecl()))
1364 return ClassTemplate
->getTemplatedDecl();
1369 // Returns true if the given C++ class is directly or indirectly derived
1370 // from a base type with the given name. A class is not considered to be
1371 // derived from itself.
1372 bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl
*Declaration
,
1373 const Matcher
<NamedDecl
> &Base
,
1374 BoundNodesTreeBuilder
*Builder
,
1376 llvm::SmallPtrSet
<const CXXRecordDecl
*, 8> Visited
;
1377 return classIsDerivedFromImpl(Declaration
, Base
, Builder
, Directly
, Visited
);
1380 bool MatchASTVisitor::classIsDerivedFromImpl(
1381 const CXXRecordDecl
*Declaration
, const Matcher
<NamedDecl
> &Base
,
1382 BoundNodesTreeBuilder
*Builder
, bool Directly
,
1383 llvm::SmallPtrSetImpl
<const CXXRecordDecl
*> &Visited
) {
1384 if (!Declaration
->hasDefinition())
1386 if (!Visited
.insert(Declaration
).second
)
1388 for (const auto &It
: Declaration
->bases()) {
1389 const Type
*TypeNode
= It
.getType().getTypePtr();
1391 if (typeHasMatchingAlias(TypeNode
, Base
, Builder
))
1394 // FIXME: Going to the primary template here isn't really correct, but
1395 // unfortunately we accept a Decl matcher for the base class not a Type
1396 // matcher, so it's the best thing we can do with our current interface.
1397 CXXRecordDecl
*ClassDecl
= getAsCXXRecordDeclOrPrimaryTemplate(TypeNode
);
1400 if (ClassDecl
== Declaration
) {
1401 // This can happen for recursive template definitions.
1404 BoundNodesTreeBuilder
Result(*Builder
);
1405 if (Base
.matches(*ClassDecl
, this, &Result
)) {
1406 *Builder
= std::move(Result
);
1410 classIsDerivedFromImpl(ClassDecl
, Base
, Builder
, Directly
, Visited
))
1416 // Returns true if the given Objective-C class is directly or indirectly
1417 // derived from a matching base class. A class is not considered to be derived
1419 bool MatchASTVisitor::objcClassIsDerivedFrom(
1420 const ObjCInterfaceDecl
*Declaration
, const Matcher
<NamedDecl
> &Base
,
1421 BoundNodesTreeBuilder
*Builder
, bool Directly
) {
1422 // Check if any of the superclasses of the class match.
1423 for (const ObjCInterfaceDecl
*ClassDecl
= Declaration
->getSuperClass();
1424 ClassDecl
!= nullptr; ClassDecl
= ClassDecl
->getSuperClass()) {
1425 // Check if there are any matching compatibility aliases.
1426 if (objcClassHasMatchingCompatibilityAlias(ClassDecl
, Base
, Builder
))
1429 // Check if there are any matching type aliases.
1430 const Type
*TypeNode
= ClassDecl
->getTypeForDecl();
1431 if (typeHasMatchingAlias(TypeNode
, Base
, Builder
))
1434 if (Base
.matches(*ClassDecl
, this, Builder
))
1437 // Not `return false` as a temporary workaround for PR43879.
1445 bool MatchASTVisitor::TraverseDecl(Decl
*DeclNode
) {
1450 bool ScopedTraversal
=
1451 TraversingASTNodeNotSpelledInSource
|| DeclNode
->isImplicit();
1452 bool ScopedChildren
= TraversingASTChildrenNotSpelledInSource
;
1454 if (const auto *CTSD
= dyn_cast
<ClassTemplateSpecializationDecl
>(DeclNode
)) {
1455 auto SK
= CTSD
->getSpecializationKind();
1456 if (SK
== TSK_ExplicitInstantiationDeclaration
||
1457 SK
== TSK_ExplicitInstantiationDefinition
)
1458 ScopedChildren
= true;
1459 } else if (const auto *FD
= dyn_cast
<FunctionDecl
>(DeclNode
)) {
1460 if (FD
->isDefaulted())
1461 ScopedChildren
= true;
1462 if (FD
->isTemplateInstantiation())
1463 ScopedTraversal
= true;
1464 } else if (isa
<BindingDecl
>(DeclNode
)) {
1465 ScopedChildren
= true;
1468 ASTNodeNotSpelledInSourceScope
RAII1(this, ScopedTraversal
);
1469 ASTChildrenNotSpelledInSourceScope
RAII2(this, ScopedChildren
);
1472 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseDecl(DeclNode
);
1475 bool MatchASTVisitor::TraverseStmt(Stmt
*StmtNode
, DataRecursionQueue
*Queue
) {
1479 bool ScopedTraversal
= TraversingASTNodeNotSpelledInSource
||
1480 TraversingASTChildrenNotSpelledInSource
;
1482 ASTNodeNotSpelledInSourceScope
RAII(this, ScopedTraversal
);
1484 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseStmt(StmtNode
, Queue
);
1487 bool MatchASTVisitor::TraverseType(QualType TypeNode
) {
1489 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseType(TypeNode
);
1492 bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode
) {
1493 // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
1494 // We still want to find those types via matchers, so we match them here. Note
1495 // that the TypeLocs are structurally a shadow-hierarchy to the expressed
1496 // type, so we visit all involved parts of a compound type when matching on
1499 match(TypeLocNode
.getType());
1500 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTypeLoc(TypeLocNode
);
1503 bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier
*NNS
) {
1505 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseNestedNameSpecifier(NNS
);
1508 bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
1509 NestedNameSpecifierLoc NNS
) {
1515 // We only match the nested name specifier here (as opposed to traversing it)
1516 // because the traversal is already done in the parallel "Loc"-hierarchy.
1517 if (NNS
.hasQualifier())
1518 match(*NNS
.getNestedNameSpecifier());
1520 RecursiveASTVisitor
<MatchASTVisitor
>::TraverseNestedNameSpecifierLoc(NNS
);
1523 bool MatchASTVisitor::TraverseConstructorInitializer(
1524 CXXCtorInitializer
*CtorInit
) {
1528 bool ScopedTraversal
= TraversingASTNodeNotSpelledInSource
||
1529 TraversingASTChildrenNotSpelledInSource
;
1531 if (!CtorInit
->isWritten())
1532 ScopedTraversal
= true;
1534 ASTNodeNotSpelledInSourceScope
RAII1(this, ScopedTraversal
);
1538 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseConstructorInitializer(
1542 bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc
) {
1544 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTemplateArgumentLoc(Loc
);
1547 bool MatchASTVisitor::TraverseAttr(Attr
*AttrNode
) {
1549 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseAttr(AttrNode
);
1552 class MatchASTConsumer
: public ASTConsumer
{
1554 MatchASTConsumer(MatchFinder
*Finder
,
1555 MatchFinder::ParsingDoneTestCallback
*ParsingDone
)
1556 : Finder(Finder
), ParsingDone(ParsingDone
) {}
1559 void HandleTranslationUnit(ASTContext
&Context
) override
{
1560 if (ParsingDone
!= nullptr) {
1563 Finder
->matchAST(Context
);
1566 MatchFinder
*Finder
;
1567 MatchFinder::ParsingDoneTestCallback
*ParsingDone
;
1571 } // end namespace internal
1573 MatchFinder::MatchResult::MatchResult(const BoundNodes
&Nodes
,
1574 ASTContext
*Context
)
1575 : Nodes(Nodes
), Context(Context
),
1576 SourceManager(&Context
->getSourceManager()) {}
1578 MatchFinder::MatchCallback::~MatchCallback() {}
1579 MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
1581 MatchFinder::MatchFinder(MatchFinderOptions Options
)
1582 : Options(std::move(Options
)), ParsingDone(nullptr) {}
1584 MatchFinder::~MatchFinder() {}
1586 void MatchFinder::addMatcher(const DeclarationMatcher
&NodeMatch
,
1587 MatchCallback
*Action
) {
1588 std::optional
<TraversalKind
> TK
;
1590 TK
= Action
->getCheckTraversalKind();
1592 Matchers
.DeclOrStmt
.emplace_back(traverse(*TK
, NodeMatch
), Action
);
1594 Matchers
.DeclOrStmt
.emplace_back(NodeMatch
, Action
);
1595 Matchers
.AllCallbacks
.insert(Action
);
1598 void MatchFinder::addMatcher(const TypeMatcher
&NodeMatch
,
1599 MatchCallback
*Action
) {
1600 Matchers
.Type
.emplace_back(NodeMatch
, Action
);
1601 Matchers
.AllCallbacks
.insert(Action
);
1604 void MatchFinder::addMatcher(const StatementMatcher
&NodeMatch
,
1605 MatchCallback
*Action
) {
1606 std::optional
<TraversalKind
> TK
;
1608 TK
= Action
->getCheckTraversalKind();
1610 Matchers
.DeclOrStmt
.emplace_back(traverse(*TK
, NodeMatch
), Action
);
1612 Matchers
.DeclOrStmt
.emplace_back(NodeMatch
, Action
);
1613 Matchers
.AllCallbacks
.insert(Action
);
1616 void MatchFinder::addMatcher(const NestedNameSpecifierMatcher
&NodeMatch
,
1617 MatchCallback
*Action
) {
1618 Matchers
.NestedNameSpecifier
.emplace_back(NodeMatch
, Action
);
1619 Matchers
.AllCallbacks
.insert(Action
);
1622 void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher
&NodeMatch
,
1623 MatchCallback
*Action
) {
1624 Matchers
.NestedNameSpecifierLoc
.emplace_back(NodeMatch
, Action
);
1625 Matchers
.AllCallbacks
.insert(Action
);
1628 void MatchFinder::addMatcher(const TypeLocMatcher
&NodeMatch
,
1629 MatchCallback
*Action
) {
1630 Matchers
.TypeLoc
.emplace_back(NodeMatch
, Action
);
1631 Matchers
.AllCallbacks
.insert(Action
);
1634 void MatchFinder::addMatcher(const CXXCtorInitializerMatcher
&NodeMatch
,
1635 MatchCallback
*Action
) {
1636 Matchers
.CtorInit
.emplace_back(NodeMatch
, Action
);
1637 Matchers
.AllCallbacks
.insert(Action
);
1640 void MatchFinder::addMatcher(const TemplateArgumentLocMatcher
&NodeMatch
,
1641 MatchCallback
*Action
) {
1642 Matchers
.TemplateArgumentLoc
.emplace_back(NodeMatch
, Action
);
1643 Matchers
.AllCallbacks
.insert(Action
);
1646 void MatchFinder::addMatcher(const AttrMatcher
&AttrMatch
,
1647 MatchCallback
*Action
) {
1648 Matchers
.Attr
.emplace_back(AttrMatch
, Action
);
1649 Matchers
.AllCallbacks
.insert(Action
);
1652 bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher
&NodeMatch
,
1653 MatchCallback
*Action
) {
1654 if (NodeMatch
.canConvertTo
<Decl
>()) {
1655 addMatcher(NodeMatch
.convertTo
<Decl
>(), Action
);
1657 } else if (NodeMatch
.canConvertTo
<QualType
>()) {
1658 addMatcher(NodeMatch
.convertTo
<QualType
>(), Action
);
1660 } else if (NodeMatch
.canConvertTo
<Stmt
>()) {
1661 addMatcher(NodeMatch
.convertTo
<Stmt
>(), Action
);
1663 } else if (NodeMatch
.canConvertTo
<NestedNameSpecifier
>()) {
1664 addMatcher(NodeMatch
.convertTo
<NestedNameSpecifier
>(), Action
);
1666 } else if (NodeMatch
.canConvertTo
<NestedNameSpecifierLoc
>()) {
1667 addMatcher(NodeMatch
.convertTo
<NestedNameSpecifierLoc
>(), Action
);
1669 } else if (NodeMatch
.canConvertTo
<TypeLoc
>()) {
1670 addMatcher(NodeMatch
.convertTo
<TypeLoc
>(), Action
);
1672 } else if (NodeMatch
.canConvertTo
<CXXCtorInitializer
>()) {
1673 addMatcher(NodeMatch
.convertTo
<CXXCtorInitializer
>(), Action
);
1675 } else if (NodeMatch
.canConvertTo
<TemplateArgumentLoc
>()) {
1676 addMatcher(NodeMatch
.convertTo
<TemplateArgumentLoc
>(), Action
);
1678 } else if (NodeMatch
.canConvertTo
<Attr
>()) {
1679 addMatcher(NodeMatch
.convertTo
<Attr
>(), Action
);
1685 std::unique_ptr
<ASTConsumer
> MatchFinder::newASTConsumer() {
1686 return std::make_unique
<internal::MatchASTConsumer
>(this, ParsingDone
);
1689 void MatchFinder::match(const clang::DynTypedNode
&Node
, ASTContext
&Context
) {
1690 internal::MatchASTVisitor
Visitor(&Matchers
, Options
);
1691 Visitor
.set_active_ast_context(&Context
);
1692 Visitor
.match(Node
);
1695 void MatchFinder::matchAST(ASTContext
&Context
) {
1696 internal::MatchASTVisitor
Visitor(&Matchers
, Options
);
1697 internal::MatchASTVisitor::TraceReporter
StackTrace(Visitor
);
1698 Visitor
.set_active_ast_context(&Context
);
1699 Visitor
.onStartOfTranslationUnit();
1700 Visitor
.TraverseAST(Context
);
1701 Visitor
.onEndOfTranslationUnit();
1704 void MatchFinder::registerTestCallbackAfterParsing(
1705 MatchFinder::ParsingDoneTestCallback
*NewParsingDone
) {
1706 ParsingDone
= NewParsingDone
;
1709 StringRef
MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
1711 std::optional
<TraversalKind
>
1712 MatchFinder::MatchCallback::getCheckTraversalKind() const {
1713 return std::nullopt
;
1716 } // end namespace ast_matchers
1717 } // end namespace clang