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/RecursiveASTVisitor.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/StringMap.h"
24 #include "llvm/Support/PrettyStackTrace.h"
25 #include "llvm/Support/Timer.h"
31 namespace ast_matchers
{
35 typedef MatchFinder::MatchCallback MatchCallback
;
37 // The maximum number of memoization entries to store.
38 // 10k has been experimentally found to give a good trade-off
39 // of performance vs. memory consumption by running matcher
40 // that match on every statement over a very large codebase.
42 // FIXME: Do some performance optimization in general and
43 // revisit this number; also, put up micro-benchmarks that we can
45 static const unsigned MaxMemoizationEntries
= 10000;
47 enum class MatchType
{
54 // We use memoization to avoid running the same matcher on the same
55 // AST node twice. This struct is the key for looking up match
56 // result. It consists of an ID of the MatcherInterface (for
57 // identifying the matcher), a pointer to the AST node and the
58 // bound nodes before the matcher was executed.
60 // We currently only memoize on nodes whose pointers identify the
61 // nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
62 // For \c QualType and \c TypeLoc it is possible to implement
63 // generation of keys for each type.
64 // FIXME: Benchmark whether memoization of non-pointer typed nodes
65 // provides enough benefit for the additional amount of code.
67 DynTypedMatcher::MatcherIDType MatcherID
;
69 BoundNodesTreeBuilder BoundNodes
;
70 TraversalKind Traversal
= TK_AsIs
;
73 bool operator<(const MatchKey
&Other
) const {
74 return std::tie(Traversal
, Type
, MatcherID
, Node
, BoundNodes
) <
75 std::tie(Other
.Traversal
, Other
.Type
, Other
.MatcherID
, Other
.Node
,
80 // Used to store the result of a match and possibly bound nodes.
81 struct MemoizedMatchResult
{
83 BoundNodesTreeBuilder Nodes
;
86 // A RecursiveASTVisitor that traverses all children or all descendants of
88 class MatchChildASTVisitor
89 : public RecursiveASTVisitor
<MatchChildASTVisitor
> {
91 typedef RecursiveASTVisitor
<MatchChildASTVisitor
> VisitorBase
;
93 // Creates an AST visitor that matches 'matcher' on all children or
94 // descendants of a traversed node. max_depth is the maximum depth
95 // to traverse: use 1 for matching the children and INT_MAX for
96 // matching the descendants.
97 MatchChildASTVisitor(const DynTypedMatcher
*Matcher
, ASTMatchFinder
*Finder
,
98 BoundNodesTreeBuilder
*Builder
, int MaxDepth
,
99 bool IgnoreImplicitChildren
,
100 ASTMatchFinder::BindKind Bind
)
101 : Matcher(Matcher
), Finder(Finder
), Builder(Builder
), CurrentDepth(0),
102 MaxDepth(MaxDepth
), IgnoreImplicitChildren(IgnoreImplicitChildren
),
103 Bind(Bind
), Matches(false) {}
105 // Returns true if a match is found in the subtree rooted at the
106 // given AST node. This is done via a set of mutually recursive
107 // functions. Here's how the recursion is done (the *wildcard can
108 // actually be Decl, Stmt, or Type):
110 // - Traverse(node) calls BaseTraverse(node) when it needs
111 // to visit the descendants of node.
112 // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
113 // Traverse*(c) for each child c of 'node'.
114 // - Traverse*(c) in turn calls Traverse(c), completing the
116 bool findMatch(const DynTypedNode
&DynNode
) {
118 if (const Decl
*D
= DynNode
.get
<Decl
>())
120 else if (const Stmt
*S
= DynNode
.get
<Stmt
>())
122 else if (const NestedNameSpecifier
*NNS
=
123 DynNode
.get
<NestedNameSpecifier
>())
125 else if (const NestedNameSpecifierLoc
*NNSLoc
=
126 DynNode
.get
<NestedNameSpecifierLoc
>())
128 else if (const QualType
*Q
= DynNode
.get
<QualType
>())
130 else if (const TypeLoc
*T
= DynNode
.get
<TypeLoc
>())
132 else if (const auto *C
= DynNode
.get
<CXXCtorInitializer
>())
134 else if (const TemplateArgumentLoc
*TALoc
=
135 DynNode
.get
<TemplateArgumentLoc
>())
137 else if (const Attr
*A
= DynNode
.get
<Attr
>())
139 // FIXME: Add other base types after adding tests.
141 // It's OK to always overwrite the bound nodes, as if there was
142 // no match in this recursive branch, the result set is empty
144 *Builder
= ResultBindings
;
149 // The following are overriding methods from the base visitor class.
150 // They are public only to allow CRTP to work. They are *not *part
151 // of the public API of this class.
152 bool TraverseDecl(Decl
*DeclNode
) {
154 if (DeclNode
&& DeclNode
->isImplicit() &&
155 Finder
->isTraversalIgnoringImplicitNodes())
156 return baseTraverse(*DeclNode
);
158 ScopedIncrement
ScopedDepth(&CurrentDepth
);
159 return (DeclNode
== nullptr) || traverse(*DeclNode
);
162 Stmt
*getStmtToTraverse(Stmt
*StmtNode
) {
163 Stmt
*StmtToTraverse
= StmtNode
;
164 if (auto *ExprNode
= dyn_cast_or_null
<Expr
>(StmtNode
)) {
165 auto *LambdaNode
= dyn_cast_or_null
<LambdaExpr
>(StmtNode
);
166 if (LambdaNode
&& Finder
->isTraversalIgnoringImplicitNodes())
167 StmtToTraverse
= LambdaNode
;
170 Finder
->getASTContext().getParentMapContext().traverseIgnored(
173 return StmtToTraverse
;
176 bool TraverseStmt(Stmt
*StmtNode
, DataRecursionQueue
*Queue
= nullptr) {
177 // If we need to keep track of the depth, we can't perform data recursion.
178 if (CurrentDepth
== 0 || (CurrentDepth
<= MaxDepth
&& MaxDepth
< INT_MAX
))
181 ScopedIncrement
ScopedDepth(&CurrentDepth
);
182 Stmt
*StmtToTraverse
= getStmtToTraverse(StmtNode
);
186 if (IgnoreImplicitChildren
&& isa
<CXXDefaultArgExpr
>(StmtNode
))
189 if (!match(*StmtToTraverse
))
191 return VisitorBase::TraverseStmt(StmtToTraverse
, Queue
);
193 // We assume that the QualType and the contained type are on the same
194 // hierarchy level. Thus, we try to match either of them.
195 bool TraverseType(QualType TypeNode
) {
196 if (TypeNode
.isNull())
198 ScopedIncrement
ScopedDepth(&CurrentDepth
);
200 if (!match(*TypeNode
))
202 // The QualType is matched inside traverse.
203 return traverse(TypeNode
);
205 // We assume that the TypeLoc, contained QualType and contained Type all are
206 // on the same hierarchy level. Thus, we try to match all of them.
207 bool TraverseTypeLoc(TypeLoc TypeLocNode
) {
208 if (TypeLocNode
.isNull())
210 ScopedIncrement
ScopedDepth(&CurrentDepth
);
212 if (!match(*TypeLocNode
.getType()))
214 // Match the QualType.
215 if (!match(TypeLocNode
.getType()))
217 // The TypeLoc is matched inside traverse.
218 return traverse(TypeLocNode
);
220 bool TraverseNestedNameSpecifier(NestedNameSpecifier
*NNS
) {
221 ScopedIncrement
ScopedDepth(&CurrentDepth
);
222 return (NNS
== nullptr) || traverse(*NNS
);
224 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS
) {
227 ScopedIncrement
ScopedDepth(&CurrentDepth
);
228 if (!match(*NNS
.getNestedNameSpecifier()))
230 return traverse(NNS
);
232 bool TraverseConstructorInitializer(CXXCtorInitializer
*CtorInit
) {
235 ScopedIncrement
ScopedDepth(&CurrentDepth
);
236 return traverse(*CtorInit
);
238 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL
) {
239 ScopedIncrement
ScopedDepth(&CurrentDepth
);
240 return traverse(TAL
);
242 bool TraverseCXXForRangeStmt(CXXForRangeStmt
*Node
) {
243 if (!Finder
->isTraversalIgnoringImplicitNodes())
244 return VisitorBase::TraverseCXXForRangeStmt(Node
);
247 ScopedIncrement
ScopedDepth(&CurrentDepth
);
248 if (auto *Init
= Node
->getInit())
249 if (!traverse(*Init
))
251 if (!match(*Node
->getLoopVariable()))
253 if (match(*Node
->getRangeInit()))
254 if (!VisitorBase::TraverseStmt(Node
->getRangeInit()))
256 if (!match(*Node
->getBody()))
258 return VisitorBase::TraverseStmt(Node
->getBody());
260 bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator
*Node
) {
261 if (!Finder
->isTraversalIgnoringImplicitNodes())
262 return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node
);
265 ScopedIncrement
ScopedDepth(&CurrentDepth
);
267 return match(*Node
->getLHS()) && match(*Node
->getRHS());
269 bool TraverseAttr(Attr
*A
) {
272 Finder
->getASTContext().getParentMapContext().getTraversalKind() ==
273 TK_IgnoreUnlessSpelledInSource
))
275 ScopedIncrement
ScopedDepth(&CurrentDepth
);
278 bool TraverseLambdaExpr(LambdaExpr
*Node
) {
279 if (!Finder
->isTraversalIgnoringImplicitNodes())
280 return VisitorBase::TraverseLambdaExpr(Node
);
283 ScopedIncrement
ScopedDepth(&CurrentDepth
);
285 for (unsigned I
= 0, N
= Node
->capture_size(); I
!= N
; ++I
) {
286 const auto *C
= Node
->capture_begin() + I
;
287 if (!C
->isExplicit())
289 if (Node
->isInitCapture(C
) && !match(*C
->getCapturedVar()))
291 if (!match(*Node
->capture_init_begin()[I
]))
295 if (const auto *TPL
= Node
->getTemplateParameterList()) {
296 for (const auto *TP
: *TPL
) {
302 for (const auto *P
: Node
->getCallOperator()->parameters()) {
307 if (!match(*Node
->getBody()))
310 return VisitorBase::TraverseStmt(Node
->getBody());
313 bool shouldVisitTemplateInstantiations() const { return true; }
314 bool shouldVisitImplicitCode() const { return !IgnoreImplicitChildren
; }
317 // Used for updating the depth during traversal.
318 struct ScopedIncrement
{
319 explicit ScopedIncrement(int *Depth
) : Depth(Depth
) { ++(*Depth
); }
320 ~ScopedIncrement() { --(*Depth
); }
326 // Resets the state of this object.
332 // Forwards the call to the corresponding Traverse*() method in the
333 // base visitor class.
334 bool baseTraverse(const Decl
&DeclNode
) {
335 return VisitorBase::TraverseDecl(const_cast<Decl
*>(&DeclNode
));
337 bool baseTraverse(const Stmt
&StmtNode
) {
338 return VisitorBase::TraverseStmt(const_cast<Stmt
*>(&StmtNode
));
340 bool baseTraverse(QualType TypeNode
) {
341 return VisitorBase::TraverseType(TypeNode
);
343 bool baseTraverse(TypeLoc TypeLocNode
) {
344 return VisitorBase::TraverseTypeLoc(TypeLocNode
);
346 bool baseTraverse(const NestedNameSpecifier
&NNS
) {
347 return VisitorBase::TraverseNestedNameSpecifier(
348 const_cast<NestedNameSpecifier
*>(&NNS
));
350 bool baseTraverse(NestedNameSpecifierLoc NNS
) {
351 return VisitorBase::TraverseNestedNameSpecifierLoc(NNS
);
353 bool baseTraverse(const CXXCtorInitializer
&CtorInit
) {
354 return VisitorBase::TraverseConstructorInitializer(
355 const_cast<CXXCtorInitializer
*>(&CtorInit
));
357 bool baseTraverse(TemplateArgumentLoc TAL
) {
358 return VisitorBase::TraverseTemplateArgumentLoc(TAL
);
360 bool baseTraverse(const Attr
&AttrNode
) {
361 return VisitorBase::TraverseAttr(const_cast<Attr
*>(&AttrNode
));
364 // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
365 // 0 < CurrentDepth <= MaxDepth.
367 // Returns 'true' if traversal should continue after this function
368 // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
369 template <typename T
>
370 bool match(const T
&Node
) {
371 if (CurrentDepth
== 0 || CurrentDepth
> MaxDepth
) {
374 if (Bind
!= ASTMatchFinder::BK_All
) {
375 BoundNodesTreeBuilder
RecursiveBuilder(*Builder
);
376 if (Matcher
->matches(DynTypedNode::create(Node
), Finder
,
377 &RecursiveBuilder
)) {
379 ResultBindings
.addMatch(RecursiveBuilder
);
380 return false; // Abort as soon as a match is found.
383 BoundNodesTreeBuilder
RecursiveBuilder(*Builder
);
384 if (Matcher
->matches(DynTypedNode::create(Node
), Finder
,
385 &RecursiveBuilder
)) {
386 // After the first match the matcher succeeds.
388 ResultBindings
.addMatch(RecursiveBuilder
);
394 // Traverses the subtree rooted at 'Node'; returns true if the
395 // traversal should continue after this function returns.
396 template <typename T
>
397 bool traverse(const T
&Node
) {
398 static_assert(IsBaseType
<T
>::value
,
399 "traverse can only be instantiated with base type");
402 return baseTraverse(Node
);
405 const DynTypedMatcher
*const Matcher
;
406 ASTMatchFinder
*const Finder
;
407 BoundNodesTreeBuilder
*const Builder
;
408 BoundNodesTreeBuilder ResultBindings
;
411 const bool IgnoreImplicitChildren
;
412 const ASTMatchFinder::BindKind Bind
;
416 // Controls the outermost traversal of the AST and allows to match multiple
418 class MatchASTVisitor
: public RecursiveASTVisitor
<MatchASTVisitor
>,
419 public ASTMatchFinder
{
421 MatchASTVisitor(const MatchFinder::MatchersByType
*Matchers
,
422 const MatchFinder::MatchFinderOptions
&Options
)
423 : Matchers(Matchers
), Options(Options
), ActiveASTContext(nullptr) {}
425 ~MatchASTVisitor() override
{
426 if (Options
.CheckProfiling
) {
427 Options
.CheckProfiling
->Records
= std::move(TimeByBucket
);
431 void onStartOfTranslationUnit() {
432 const bool EnableCheckProfiling
= Options
.CheckProfiling
.has_value();
433 TimeBucketRegion Timer
;
434 for (MatchCallback
*MC
: Matchers
->AllCallbacks
) {
435 if (EnableCheckProfiling
)
436 Timer
.setBucket(&TimeByBucket
[MC
->getID()]);
437 MC
->onStartOfTranslationUnit();
441 void onEndOfTranslationUnit() {
442 const bool EnableCheckProfiling
= Options
.CheckProfiling
.has_value();
443 TimeBucketRegion Timer
;
444 for (MatchCallback
*MC
: Matchers
->AllCallbacks
) {
445 if (EnableCheckProfiling
)
446 Timer
.setBucket(&TimeByBucket
[MC
->getID()]);
447 MC
->onEndOfTranslationUnit();
451 void set_active_ast_context(ASTContext
*NewActiveASTContext
) {
452 ActiveASTContext
= NewActiveASTContext
;
455 // The following Visit*() and Traverse*() functions "override"
456 // methods in RecursiveASTVisitor.
458 bool VisitTypedefNameDecl(TypedefNameDecl
*DeclNode
) {
459 // When we see 'typedef A B', we add name 'B' to the set of names
460 // A's canonical type maps to. This is necessary for implementing
461 // isDerivedFrom(x) properly, where x can be the name of the base
462 // class or any of its aliases.
464 // In general, the is-alias-of (as defined by typedefs) relation
465 // is tree-shaped, as you can typedef a type more than once. For
481 // It is wrong to assume that the relation is a chain. A correct
482 // implementation of isDerivedFrom() needs to recognize that B and
483 // E are aliases, even though neither is a typedef of the other.
484 // Therefore, we cannot simply walk through one typedef chain to
485 // find out whether the type name matches.
486 const Type
*TypeNode
= DeclNode
->getUnderlyingType().getTypePtr();
487 const Type
*CanonicalType
= // root of the typedef tree
488 ActiveASTContext
->getCanonicalType(TypeNode
);
489 TypeAliases
[CanonicalType
].insert(DeclNode
);
493 bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl
*CAD
) {
494 const ObjCInterfaceDecl
*InterfaceDecl
= CAD
->getClassInterface();
495 CompatibleAliases
[InterfaceDecl
].insert(CAD
);
499 bool TraverseDecl(Decl
*DeclNode
);
500 bool TraverseStmt(Stmt
*StmtNode
, DataRecursionQueue
*Queue
= nullptr);
501 bool TraverseType(QualType TypeNode
);
502 bool TraverseTypeLoc(TypeLoc TypeNode
);
503 bool TraverseNestedNameSpecifier(NestedNameSpecifier
*NNS
);
504 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS
);
505 bool TraverseConstructorInitializer(CXXCtorInitializer
*CtorInit
);
506 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL
);
507 bool TraverseAttr(Attr
*AttrNode
);
509 bool dataTraverseNode(Stmt
*S
, DataRecursionQueue
*Queue
) {
510 if (auto *RF
= dyn_cast
<CXXForRangeStmt
>(S
)) {
512 ASTNodeNotAsIsSourceScope
RAII(this, true);
513 TraverseStmt(RF
->getInit());
514 // Don't traverse under the loop variable
515 match(*RF
->getLoopVariable());
516 TraverseStmt(RF
->getRangeInit());
519 ASTNodeNotSpelledInSourceScope
RAII(this, true);
520 for (auto *SubStmt
: RF
->children()) {
521 if (SubStmt
!= RF
->getBody())
522 TraverseStmt(SubStmt
);
525 TraverseStmt(RF
->getBody());
527 } else if (auto *RBO
= dyn_cast
<CXXRewrittenBinaryOperator
>(S
)) {
529 ASTNodeNotAsIsSourceScope
RAII(this, true);
530 TraverseStmt(const_cast<Expr
*>(RBO
->getLHS()));
531 TraverseStmt(const_cast<Expr
*>(RBO
->getRHS()));
534 ASTNodeNotSpelledInSourceScope
RAII(this, true);
535 for (auto *SubStmt
: RBO
->children()) {
536 TraverseStmt(SubStmt
);
540 } else if (auto *LE
= dyn_cast
<LambdaExpr
>(S
)) {
541 for (auto I
: llvm::zip(LE
->captures(), LE
->capture_inits())) {
542 auto C
= std::get
<0>(I
);
543 ASTNodeNotSpelledInSourceScope
RAII(
544 this, TraversingASTNodeNotSpelledInSource
|| !C
.isExplicit());
545 TraverseLambdaCapture(LE
, &C
, std::get
<1>(I
));
549 ASTNodeNotSpelledInSourceScope
RAII(this, true);
550 TraverseDecl(LE
->getLambdaClass());
553 ASTNodeNotAsIsSourceScope
RAII(this, true);
555 // We need to poke around to find the bits that might be explicitly
557 TypeLoc TL
= LE
->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
558 FunctionProtoTypeLoc Proto
= TL
.getAsAdjusted
<FunctionProtoTypeLoc
>();
560 if (auto *TPL
= LE
->getTemplateParameterList()) {
561 for (NamedDecl
*D
: *TPL
) {
564 if (Expr
*RequiresClause
= TPL
->getRequiresClause()) {
565 TraverseStmt(RequiresClause
);
569 if (LE
->hasExplicitParameters()) {
571 for (ParmVarDecl
*Param
: Proto
.getParams())
575 const auto *T
= Proto
.getTypePtr();
576 for (const auto &E
: T
->exceptions())
579 if (Expr
*NE
= T
->getNoexceptExpr())
580 TraverseStmt(NE
, Queue
);
582 if (LE
->hasExplicitResultType())
583 TraverseTypeLoc(Proto
.getReturnLoc());
584 TraverseStmt(LE
->getTrailingRequiresClause());
587 TraverseStmt(LE
->getBody());
590 return RecursiveASTVisitor
<MatchASTVisitor
>::dataTraverseNode(S
, Queue
);
593 // Matches children or descendants of 'Node' with 'BaseMatcher'.
594 bool memoizedMatchesRecursively(const DynTypedNode
&Node
, ASTContext
&Ctx
,
595 const DynTypedMatcher
&Matcher
,
596 BoundNodesTreeBuilder
*Builder
, int MaxDepth
,
598 // For AST-nodes that don't have an identity, we can't memoize.
599 if (!Node
.getMemoizationData() || !Builder
->isComparable())
600 return matchesRecursively(Node
, Matcher
, Builder
, MaxDepth
, Bind
);
603 Key
.MatcherID
= Matcher
.getID();
605 // Note that we key on the bindings *before* the match.
606 Key
.BoundNodes
= *Builder
;
607 Key
.Traversal
= Ctx
.getParentMapContext().getTraversalKind();
608 // Memoize result even doing a single-level match, it might be expensive.
609 Key
.Type
= MaxDepth
== 1 ? MatchType::Child
: MatchType::Descendants
;
610 MemoizationMap::iterator I
= ResultCache
.find(Key
);
611 if (I
!= ResultCache
.end()) {
612 *Builder
= I
->second
.Nodes
;
613 return I
->second
.ResultOfMatch
;
616 MemoizedMatchResult Result
;
617 Result
.Nodes
= *Builder
;
618 Result
.ResultOfMatch
=
619 matchesRecursively(Node
, Matcher
, &Result
.Nodes
, MaxDepth
, Bind
);
621 MemoizedMatchResult
&CachedResult
= ResultCache
[Key
];
622 CachedResult
= std::move(Result
);
624 *Builder
= CachedResult
.Nodes
;
625 return CachedResult
.ResultOfMatch
;
628 // Matches children or descendants of 'Node' with 'BaseMatcher'.
629 bool matchesRecursively(const DynTypedNode
&Node
,
630 const DynTypedMatcher
&Matcher
,
631 BoundNodesTreeBuilder
*Builder
, int MaxDepth
,
633 bool ScopedTraversal
= TraversingASTNodeNotSpelledInSource
||
634 TraversingASTChildrenNotSpelledInSource
;
636 bool IgnoreImplicitChildren
= false;
638 if (isTraversalIgnoringImplicitNodes()) {
639 IgnoreImplicitChildren
= true;
642 ASTNodeNotSpelledInSourceScope
RAII(this, ScopedTraversal
);
644 MatchChildASTVisitor
Visitor(&Matcher
, this, Builder
, MaxDepth
,
645 IgnoreImplicitChildren
, Bind
);
646 return Visitor
.findMatch(Node
);
649 bool classIsDerivedFrom(const CXXRecordDecl
*Declaration
,
650 const Matcher
<NamedDecl
> &Base
,
651 BoundNodesTreeBuilder
*Builder
,
652 bool Directly
) override
;
654 bool objcClassIsDerivedFrom(const ObjCInterfaceDecl
*Declaration
,
655 const Matcher
<NamedDecl
> &Base
,
656 BoundNodesTreeBuilder
*Builder
,
657 bool Directly
) override
;
659 // Implements ASTMatchFinder::matchesChildOf.
660 bool matchesChildOf(const DynTypedNode
&Node
, ASTContext
&Ctx
,
661 const DynTypedMatcher
&Matcher
,
662 BoundNodesTreeBuilder
*Builder
, BindKind Bind
) override
{
663 if (ResultCache
.size() > MaxMemoizationEntries
)
665 return memoizedMatchesRecursively(Node
, Ctx
, Matcher
, Builder
, 1, Bind
);
667 // Implements ASTMatchFinder::matchesDescendantOf.
668 bool matchesDescendantOf(const DynTypedNode
&Node
, ASTContext
&Ctx
,
669 const DynTypedMatcher
&Matcher
,
670 BoundNodesTreeBuilder
*Builder
,
671 BindKind Bind
) override
{
672 if (ResultCache
.size() > MaxMemoizationEntries
)
674 return memoizedMatchesRecursively(Node
, Ctx
, Matcher
, Builder
, INT_MAX
,
677 // Implements ASTMatchFinder::matchesAncestorOf.
678 bool matchesAncestorOf(const DynTypedNode
&Node
, ASTContext
&Ctx
,
679 const DynTypedMatcher
&Matcher
,
680 BoundNodesTreeBuilder
*Builder
,
681 AncestorMatchMode MatchMode
) override
{
682 // Reset the cache outside of the recursive call to make sure we
683 // don't invalidate any iterators.
684 if (ResultCache
.size() > MaxMemoizationEntries
)
686 if (MatchMode
== AncestorMatchMode::AMM_ParentOnly
)
687 return matchesParentOf(Node
, Matcher
, Builder
);
688 return matchesAnyAncestorOf(Node
, Ctx
, Matcher
, Builder
);
691 // Matches all registered matchers on the given node and calls the
692 // result callback for every node that matches.
693 void match(const DynTypedNode
&Node
) {
694 // FIXME: Improve this with a switch or a visitor pattern.
695 if (auto *N
= Node
.get
<Decl
>()) {
697 } else if (auto *N
= Node
.get
<Stmt
>()) {
699 } else if (auto *N
= Node
.get
<Type
>()) {
701 } else if (auto *N
= Node
.get
<QualType
>()) {
703 } else if (auto *N
= Node
.get
<NestedNameSpecifier
>()) {
705 } else if (auto *N
= Node
.get
<NestedNameSpecifierLoc
>()) {
707 } else if (auto *N
= Node
.get
<TypeLoc
>()) {
709 } else if (auto *N
= Node
.get
<CXXCtorInitializer
>()) {
711 } else if (auto *N
= Node
.get
<TemplateArgumentLoc
>()) {
713 } else if (auto *N
= Node
.get
<Attr
>()) {
718 template <typename T
> void match(const T
&Node
) {
719 matchDispatch(&Node
);
722 // Implements ASTMatchFinder::getASTContext.
723 ASTContext
&getASTContext() const override
{ return *ActiveASTContext
; }
725 bool shouldVisitTemplateInstantiations() const { return true; }
726 bool shouldVisitImplicitCode() const { return true; }
728 // We visit the lambda body explicitly, so instruct the RAV
729 // to not visit it on our behalf too.
730 bool shouldVisitLambdaBody() const { return false; }
732 bool IsMatchingInASTNodeNotSpelledInSource() const override
{
733 return TraversingASTNodeNotSpelledInSource
;
735 bool isMatchingChildrenNotSpelledInSource() const override
{
736 return TraversingASTChildrenNotSpelledInSource
;
738 void setMatchingChildrenNotSpelledInSource(bool Set
) override
{
739 TraversingASTChildrenNotSpelledInSource
= Set
;
742 bool IsMatchingInASTNodeNotAsIs() const override
{
743 return TraversingASTNodeNotAsIs
;
746 bool TraverseTemplateInstantiations(ClassTemplateDecl
*D
) {
747 ASTNodeNotSpelledInSourceScope
RAII(this, true);
748 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTemplateInstantiations(
752 bool TraverseTemplateInstantiations(VarTemplateDecl
*D
) {
753 ASTNodeNotSpelledInSourceScope
RAII(this, true);
754 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTemplateInstantiations(
758 bool TraverseTemplateInstantiations(FunctionTemplateDecl
*D
) {
759 ASTNodeNotSpelledInSourceScope
RAII(this, true);
760 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTemplateInstantiations(
765 bool TraversingASTNodeNotSpelledInSource
= false;
766 bool TraversingASTNodeNotAsIs
= false;
767 bool TraversingASTChildrenNotSpelledInSource
= false;
770 // We don't have enough free low bits in 32bit builds to discriminate 8 pointer
771 // types in PointerUnion. so split the union in 2 using a free bit from the
773 #define CMD_TYPES_0 \
774 const QualType *, const TypeLoc *, const NestedNameSpecifier *, \
775 const NestedNameSpecifierLoc *
776 #define CMD_TYPES_1 \
777 const CXXCtorInitializer *, const TemplateArgumentLoc *, const Attr *, \
780 #define IMPL(Index) \
781 template <typename NodeType> \
782 typename std::enable_if_t< \
783 llvm::is_one_of<const NodeType *, CMD_TYPES_##Index>::value> \
784 SetCallbackAndRawNode(const MatchCallback *CB, const NodeType &N) { \
786 Callback.setPointerAndInt(CB, Index); \
790 template <typename T> \
791 typename std::enable_if_t< \
792 llvm::is_one_of<const T *, CMD_TYPES_##Index>::value, const T *> \
794 assertHoldsState(); \
795 return Callback.getInt() == (Index) ? Node##Index.dyn_cast<const T *>() \
800 CurMatchData() : Node0(nullptr) {}
805 const MatchCallback
*getCallback() const { return Callback
.getPointer(); }
807 void SetBoundNodes(const BoundNodes
&BN
) {
812 void clearBoundNodes() {
817 const BoundNodes
*getBoundNodes() const {
824 Callback
.setPointerAndInt(nullptr, 0);
829 void assertHoldsState() const {
830 assert(Callback
.getPointer() != nullptr && !Node0
.isNull());
833 void assertEmpty() const {
834 assert(Callback
.getPointer() == nullptr && Node0
.isNull() &&
838 llvm::PointerIntPair
<const MatchCallback
*, 1> Callback
;
840 llvm::PointerUnion
<CMD_TYPES_0
> Node0
;
841 llvm::PointerUnion
<CMD_TYPES_1
> Node1
;
843 const BoundNodes
*BNodes
= nullptr;
850 struct CurMatchRAII
{
851 template <typename NodeType
>
852 CurMatchRAII(MatchASTVisitor
&MV
, const MatchCallback
*CB
,
855 MV
.CurMatchState
.SetCallbackAndRawNode(CB
, NT
);
858 ~CurMatchRAII() { MV
.CurMatchState
.reset(); }
865 class TraceReporter
: llvm::PrettyStackTraceEntry
{
866 static void dumpNode(const ASTContext
&Ctx
, const DynTypedNode
&Node
,
868 if (const auto *D
= Node
.get
<Decl
>()) {
869 OS
<< D
->getDeclKindName() << "Decl ";
870 if (const auto *ND
= dyn_cast
<NamedDecl
>(D
)) {
871 ND
->printQualifiedName(OS
);
875 D
->getSourceRange().print(OS
, Ctx
.getSourceManager());
876 } else if (const auto *S
= Node
.get
<Stmt
>()) {
877 OS
<< S
->getStmtClassName() << " : ";
878 S
->getSourceRange().print(OS
, Ctx
.getSourceManager());
879 } else if (const auto *T
= Node
.get
<Type
>()) {
880 OS
<< T
->getTypeClassName() << "Type : ";
881 QualType(T
, 0).print(OS
, Ctx
.getPrintingPolicy());
882 } else if (const auto *QT
= Node
.get
<QualType
>()) {
884 QT
->print(OS
, Ctx
.getPrintingPolicy());
886 OS
<< Node
.getNodeKind().asStringRef() << " : ";
887 Node
.getSourceRange().print(OS
, Ctx
.getSourceManager());
891 static void dumpNodeFromState(const ASTContext
&Ctx
,
892 const CurMatchData
&State
, raw_ostream
&OS
) {
893 if (const DynTypedNode
*MatchNode
= State
.getNode
<DynTypedNode
>()) {
894 dumpNode(Ctx
, *MatchNode
, OS
);
895 } else if (const auto *QT
= State
.getNode
<QualType
>()) {
896 dumpNode(Ctx
, DynTypedNode::create(*QT
), OS
);
897 } else if (const auto *TL
= State
.getNode
<TypeLoc
>()) {
898 dumpNode(Ctx
, DynTypedNode::create(*TL
), OS
);
899 } else if (const auto *NNS
= State
.getNode
<NestedNameSpecifier
>()) {
900 dumpNode(Ctx
, DynTypedNode::create(*NNS
), OS
);
901 } else if (const auto *NNSL
= State
.getNode
<NestedNameSpecifierLoc
>()) {
902 dumpNode(Ctx
, DynTypedNode::create(*NNSL
), OS
);
903 } else if (const auto *CtorInit
= State
.getNode
<CXXCtorInitializer
>()) {
904 dumpNode(Ctx
, DynTypedNode::create(*CtorInit
), OS
);
905 } else if (const auto *TAL
= State
.getNode
<TemplateArgumentLoc
>()) {
906 dumpNode(Ctx
, DynTypedNode::create(*TAL
), OS
);
907 } else if (const auto *At
= State
.getNode
<Attr
>()) {
908 dumpNode(Ctx
, DynTypedNode::create(*At
), OS
);
913 TraceReporter(const MatchASTVisitor
&MV
) : MV(MV
) {}
914 void print(raw_ostream
&OS
) const override
{
915 const CurMatchData
&State
= MV
.CurMatchState
;
916 const MatchCallback
*CB
= State
.getCallback();
918 OS
<< "ASTMatcher: Not currently matching\n";
922 assert(MV
.ActiveASTContext
&&
923 "ActiveASTContext should be set if there is a matched callback");
925 ASTContext
&Ctx
= MV
.getASTContext();
927 if (const BoundNodes
*Nodes
= State
.getBoundNodes()) {
928 OS
<< "ASTMatcher: Processing '" << CB
->getID() << "' against:\n\t";
929 dumpNodeFromState(Ctx
, State
, OS
);
930 const BoundNodes::IDToNodeMap
&Map
= Nodes
->getMap();
932 OS
<< "\nNo bound nodes\n";
935 OS
<< "\n--- Bound Nodes Begin ---\n";
936 for (const auto &Item
: Map
) {
937 OS
<< " " << Item
.first
<< " - { ";
938 dumpNode(Ctx
, Item
.second
, OS
);
941 OS
<< "--- Bound Nodes End ---\n";
943 OS
<< "ASTMatcher: Matching '" << CB
->getID() << "' against:\n\t";
944 dumpNodeFromState(Ctx
, State
, OS
);
950 const MatchASTVisitor
&MV
;
954 struct ASTNodeNotSpelledInSourceScope
{
955 ASTNodeNotSpelledInSourceScope(MatchASTVisitor
*V
, bool B
)
956 : MV(V
), MB(V
->TraversingASTNodeNotSpelledInSource
) {
957 V
->TraversingASTNodeNotSpelledInSource
= B
;
959 ~ASTNodeNotSpelledInSourceScope() {
960 MV
->TraversingASTNodeNotSpelledInSource
= MB
;
968 struct ASTNodeNotAsIsSourceScope
{
969 ASTNodeNotAsIsSourceScope(MatchASTVisitor
*V
, bool B
)
970 : MV(V
), MB(V
->TraversingASTNodeNotAsIs
) {
971 V
->TraversingASTNodeNotAsIs
= B
;
973 ~ASTNodeNotAsIsSourceScope() { MV
->TraversingASTNodeNotAsIs
= MB
; }
980 class TimeBucketRegion
{
982 TimeBucketRegion() : Bucket(nullptr) {}
983 ~TimeBucketRegion() { setBucket(nullptr); }
985 /// Start timing for \p NewBucket.
987 /// If there was a bucket already set, it will finish the timing for that
989 /// \p NewBucket will be timed until the next call to \c setBucket() or
990 /// until the \c TimeBucketRegion is destroyed.
991 /// If \p NewBucket is the same as the currently timed bucket, this call
993 void setBucket(llvm::TimeRecord
*NewBucket
) {
994 if (Bucket
!= NewBucket
) {
995 auto Now
= llvm::TimeRecord::getCurrentTime(true);
1005 llvm::TimeRecord
*Bucket
;
1008 /// Runs all the \p Matchers on \p Node.
1010 /// Used by \c matchDispatch() below.
1011 template <typename T
, typename MC
>
1012 void matchWithoutFilter(const T
&Node
, const MC
&Matchers
) {
1013 const bool EnableCheckProfiling
= Options
.CheckProfiling
.has_value();
1014 TimeBucketRegion Timer
;
1015 for (const auto &MP
: Matchers
) {
1016 if (EnableCheckProfiling
)
1017 Timer
.setBucket(&TimeByBucket
[MP
.second
->getID()]);
1018 BoundNodesTreeBuilder Builder
;
1019 CurMatchRAII
RAII(*this, MP
.second
, Node
);
1020 if (MP
.first
.matches(Node
, this, &Builder
)) {
1021 MatchVisitor
Visitor(*this, ActiveASTContext
, MP
.second
);
1022 Builder
.visitMatches(&Visitor
);
1027 void matchWithFilter(const DynTypedNode
&DynNode
) {
1028 auto Kind
= DynNode
.getNodeKind();
1029 auto it
= MatcherFiltersMap
.find(Kind
);
1030 const auto &Filter
=
1031 it
!= MatcherFiltersMap
.end() ? it
->second
: getFilterForKind(Kind
);
1036 const bool EnableCheckProfiling
= Options
.CheckProfiling
.has_value();
1037 TimeBucketRegion Timer
;
1038 auto &Matchers
= this->Matchers
->DeclOrStmt
;
1039 for (unsigned short I
: Filter
) {
1040 auto &MP
= Matchers
[I
];
1041 if (EnableCheckProfiling
)
1042 Timer
.setBucket(&TimeByBucket
[MP
.second
->getID()]);
1043 BoundNodesTreeBuilder Builder
;
1046 TraversalKindScope
RAII(getASTContext(), MP
.first
.getTraversalKind());
1047 if (getASTContext().getParentMapContext().traverseIgnored(DynNode
) !=
1052 CurMatchRAII
RAII(*this, MP
.second
, DynNode
);
1053 if (MP
.first
.matches(DynNode
, this, &Builder
)) {
1054 MatchVisitor
Visitor(*this, ActiveASTContext
, MP
.second
);
1055 Builder
.visitMatches(&Visitor
);
1060 const std::vector
<unsigned short> &getFilterForKind(ASTNodeKind Kind
) {
1061 auto &Filter
= MatcherFiltersMap
[Kind
];
1062 auto &Matchers
= this->Matchers
->DeclOrStmt
;
1063 assert((Matchers
.size() < USHRT_MAX
) && "Too many matchers.");
1064 for (unsigned I
= 0, E
= Matchers
.size(); I
!= E
; ++I
) {
1065 if (Matchers
[I
].first
.canMatchNodesOfKind(Kind
)) {
1066 Filter
.push_back(I
);
1073 /// Overloads to pair the different node types to their matchers.
1074 void matchDispatch(const Decl
*Node
) {
1075 return matchWithFilter(DynTypedNode::create(*Node
));
1077 void matchDispatch(const Stmt
*Node
) {
1078 return matchWithFilter(DynTypedNode::create(*Node
));
1081 void matchDispatch(const Type
*Node
) {
1082 matchWithoutFilter(QualType(Node
, 0), Matchers
->Type
);
1084 void matchDispatch(const TypeLoc
*Node
) {
1085 matchWithoutFilter(*Node
, Matchers
->TypeLoc
);
1087 void matchDispatch(const QualType
*Node
) {
1088 matchWithoutFilter(*Node
, Matchers
->Type
);
1090 void matchDispatch(const NestedNameSpecifier
*Node
) {
1091 matchWithoutFilter(*Node
, Matchers
->NestedNameSpecifier
);
1093 void matchDispatch(const NestedNameSpecifierLoc
*Node
) {
1094 matchWithoutFilter(*Node
, Matchers
->NestedNameSpecifierLoc
);
1096 void matchDispatch(const CXXCtorInitializer
*Node
) {
1097 matchWithoutFilter(*Node
, Matchers
->CtorInit
);
1099 void matchDispatch(const TemplateArgumentLoc
*Node
) {
1100 matchWithoutFilter(*Node
, Matchers
->TemplateArgumentLoc
);
1102 void matchDispatch(const Attr
*Node
) {
1103 matchWithoutFilter(*Node
, Matchers
->Attr
);
1105 void matchDispatch(const void *) { /* Do nothing. */ }
1108 // Returns whether a direct parent of \p Node matches \p Matcher.
1109 // Unlike matchesAnyAncestorOf there's no memoization: it doesn't save much.
1110 bool matchesParentOf(const DynTypedNode
&Node
, const DynTypedMatcher
&Matcher
,
1111 BoundNodesTreeBuilder
*Builder
) {
1112 for (const auto &Parent
: ActiveASTContext
->getParents(Node
)) {
1113 BoundNodesTreeBuilder BuilderCopy
= *Builder
;
1114 if (Matcher
.matches(Parent
, this, &BuilderCopy
)) {
1115 *Builder
= std::move(BuilderCopy
);
1122 // Returns whether an ancestor of \p Node matches \p Matcher.
1124 // The order of matching (which can lead to different nodes being bound in
1125 // case there are multiple matches) is breadth first search.
1127 // To allow memoization in the very common case of having deeply nested
1128 // expressions inside a template function, we first walk up the AST, memoizing
1129 // the result of the match along the way, as long as there is only a single
1132 // Once there are multiple parents, the breadth first search order does not
1133 // allow simple memoization on the ancestors. Thus, we only memoize as long
1134 // as there is a single parent.
1136 // We avoid a recursive implementation to prevent excessive stack use on
1137 // very deep ASTs (similarly to RecursiveASTVisitor's data recursion).
1138 bool matchesAnyAncestorOf(DynTypedNode Node
, ASTContext
&Ctx
,
1139 const DynTypedMatcher
&Matcher
,
1140 BoundNodesTreeBuilder
*Builder
) {
1142 // Memoization keys that can be updated with the result.
1143 // These are the memoizable nodes in the chain of unique parents, which
1144 // terminates when a node has multiple parents, or matches, or is the root.
1145 std::vector
<MatchKey
> Keys
;
1146 // When returning, update the memoization cache.
1147 auto Finish
= [&](bool Matched
) {
1148 for (const auto &Key
: Keys
) {
1149 MemoizedMatchResult
&CachedResult
= ResultCache
[Key
];
1150 CachedResult
.ResultOfMatch
= Matched
;
1151 CachedResult
.Nodes
= *Builder
;
1156 // Loop while there's a single parent and we want to attempt memoization.
1157 DynTypedNodeList Parents
{ArrayRef
<DynTypedNode
>()}; // after loop: size != 1
1159 // A cache key only makes sense if memoization is possible.
1160 if (Builder
->isComparable()) {
1161 Keys
.emplace_back();
1162 Keys
.back().MatcherID
= Matcher
.getID();
1163 Keys
.back().Node
= Node
;
1164 Keys
.back().BoundNodes
= *Builder
;
1165 Keys
.back().Traversal
= Ctx
.getParentMapContext().getTraversalKind();
1166 Keys
.back().Type
= MatchType::Ancestors
;
1169 MemoizationMap::iterator I
= ResultCache
.find(Keys
.back());
1170 if (I
!= ResultCache
.end()) {
1171 Keys
.pop_back(); // Don't populate the cache for the matching node!
1172 *Builder
= I
->second
.Nodes
;
1173 return Finish(I
->second
.ResultOfMatch
);
1177 Parents
= ActiveASTContext
->getParents(Node
);
1178 // Either no parents or multiple parents: leave chain+memoize mode and
1179 // enter bfs+forgetful mode.
1180 if (Parents
.size() != 1)
1183 // Check the next parent.
1184 Node
= *Parents
.begin();
1185 BoundNodesTreeBuilder BuilderCopy
= *Builder
;
1186 if (Matcher
.matches(Node
, this, &BuilderCopy
)) {
1187 *Builder
= std::move(BuilderCopy
);
1188 return Finish(true);
1191 // We reached the end of the chain.
1193 if (Parents
.empty()) {
1194 // Nodes may have no parents if:
1195 // a) the node is the TranslationUnitDecl
1196 // b) we have a limited traversal scope that excludes the parent edges
1197 // c) there is a bug in the AST, and the node is not reachable
1198 // Usually the traversal scope is the whole AST, which precludes b.
1199 // Bugs are common enough that it's worthwhile asserting when we can.
1201 if (!Node
.get
<TranslationUnitDecl
>() &&
1202 /* Traversal scope is full AST if any of the bounds are the TU */
1203 llvm::any_of(ActiveASTContext
->getTraversalScope(), [](Decl
*D
) {
1204 return D
->getKind() == Decl::TranslationUnit
;
1206 llvm::errs() << "Tried to match orphan node:\n";
1207 Node
.dump(llvm::errs(), *ActiveASTContext
);
1208 llvm_unreachable("Parent map should be complete!");
1212 assert(Parents
.size() > 1);
1213 // BFS starting from the parents not yet considered.
1214 // Memoization of newly visited nodes is not possible (but we still update
1215 // results for the elements in the chain we found above).
1216 std::deque
<DynTypedNode
> Queue(Parents
.begin(), Parents
.end());
1217 llvm::DenseSet
<const void *> Visited
;
1218 while (!Queue
.empty()) {
1219 BoundNodesTreeBuilder BuilderCopy
= *Builder
;
1220 if (Matcher
.matches(Queue
.front(), this, &BuilderCopy
)) {
1221 *Builder
= std::move(BuilderCopy
);
1222 return Finish(true);
1224 for (const auto &Parent
: ActiveASTContext
->getParents(Queue
.front())) {
1225 // Make sure we do not visit the same node twice.
1226 // Otherwise, we'll visit the common ancestors as often as there
1227 // are splits on the way down.
1228 if (Visited
.insert(Parent
.getMemoizationData()).second
)
1229 Queue
.push_back(Parent
);
1234 return Finish(false);
1237 // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
1238 // the aggregated bound nodes for each match.
1239 class MatchVisitor
: public BoundNodesTreeBuilder::Visitor
{
1240 struct CurBoundScope
{
1241 CurBoundScope(MatchASTVisitor::CurMatchData
&State
, const BoundNodes
&BN
)
1243 State
.SetBoundNodes(BN
);
1246 ~CurBoundScope() { State
.clearBoundNodes(); }
1249 MatchASTVisitor::CurMatchData
&State
;
1253 MatchVisitor(MatchASTVisitor
&MV
, ASTContext
*Context
,
1254 MatchFinder::MatchCallback
*Callback
)
1255 : State(MV
.CurMatchState
), Context(Context
), Callback(Callback
) {}
1257 void visitMatch(const BoundNodes
& BoundNodesView
) override
{
1258 TraversalKindScope
RAII(*Context
, Callback
->getCheckTraversalKind());
1259 CurBoundScope
RAII2(State
, BoundNodesView
);
1260 Callback
->run(MatchFinder::MatchResult(BoundNodesView
, Context
));
1264 MatchASTVisitor::CurMatchData
&State
;
1265 ASTContext
* Context
;
1266 MatchFinder::MatchCallback
* Callback
;
1269 // Returns true if 'TypeNode' has an alias that matches the given matcher.
1270 bool typeHasMatchingAlias(const Type
*TypeNode
,
1271 const Matcher
<NamedDecl
> &Matcher
,
1272 BoundNodesTreeBuilder
*Builder
) {
1273 const Type
*const CanonicalType
=
1274 ActiveASTContext
->getCanonicalType(TypeNode
);
1275 auto Aliases
= TypeAliases
.find(CanonicalType
);
1276 if (Aliases
== TypeAliases
.end())
1278 for (const TypedefNameDecl
*Alias
: Aliases
->second
) {
1279 BoundNodesTreeBuilder
Result(*Builder
);
1280 if (Matcher
.matches(*Alias
, this, &Result
)) {
1281 *Builder
= std::move(Result
);
1289 objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl
*InterfaceDecl
,
1290 const Matcher
<NamedDecl
> &Matcher
,
1291 BoundNodesTreeBuilder
*Builder
) {
1292 auto Aliases
= CompatibleAliases
.find(InterfaceDecl
);
1293 if (Aliases
== CompatibleAliases
.end())
1295 for (const ObjCCompatibleAliasDecl
*Alias
: Aliases
->second
) {
1296 BoundNodesTreeBuilder
Result(*Builder
);
1297 if (Matcher
.matches(*Alias
, this, &Result
)) {
1298 *Builder
= std::move(Result
);
1305 /// Bucket to record map.
1307 /// Used to get the appropriate bucket for each matcher.
1308 llvm::StringMap
<llvm::TimeRecord
> TimeByBucket
;
1310 const MatchFinder::MatchersByType
*Matchers
;
1312 /// Filtered list of matcher indices for each matcher kind.
1314 /// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
1315 /// kind (and derived kinds) so it is a waste to try every matcher on every
1317 /// We precalculate a list of matchers that pass the toplevel restrict check.
1318 llvm::DenseMap
<ASTNodeKind
, std::vector
<unsigned short>> MatcherFiltersMap
;
1320 const MatchFinder::MatchFinderOptions
&Options
;
1321 ASTContext
*ActiveASTContext
;
1323 // Maps a canonical type to its TypedefDecls.
1324 llvm::DenseMap
<const Type
*, std::set
<const TypedefNameDecl
*> > TypeAliases
;
1326 // Maps an Objective-C interface to its ObjCCompatibleAliasDecls.
1327 llvm::DenseMap
<const ObjCInterfaceDecl
*,
1328 llvm::SmallPtrSet
<const ObjCCompatibleAliasDecl
*, 2>>
1331 // Maps (matcher, node) -> the match result for memoization.
1332 typedef std::map
<MatchKey
, MemoizedMatchResult
> MemoizationMap
;
1333 MemoizationMap ResultCache
;
1336 static CXXRecordDecl
*
1337 getAsCXXRecordDeclOrPrimaryTemplate(const Type
*TypeNode
) {
1338 if (auto *RD
= TypeNode
->getAsCXXRecordDecl())
1341 // Find the innermost TemplateSpecializationType that isn't an alias template.
1342 auto *TemplateType
= TypeNode
->getAs
<TemplateSpecializationType
>();
1343 while (TemplateType
&& TemplateType
->isTypeAlias())
1345 TemplateType
->getAliasedType()->getAs
<TemplateSpecializationType
>();
1347 // If this is the name of a (dependent) template specialization, use the
1348 // definition of the template, even though it might be specialized later.
1350 if (auto *ClassTemplate
= dyn_cast_or_null
<ClassTemplateDecl
>(
1351 TemplateType
->getTemplateName().getAsTemplateDecl()))
1352 return ClassTemplate
->getTemplatedDecl();
1357 // Returns true if the given C++ class is directly or indirectly derived
1358 // from a base type with the given name. A class is not considered to be
1359 // derived from itself.
1360 bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl
*Declaration
,
1361 const Matcher
<NamedDecl
> &Base
,
1362 BoundNodesTreeBuilder
*Builder
,
1364 if (!Declaration
->hasDefinition())
1366 for (const auto &It
: Declaration
->bases()) {
1367 const Type
*TypeNode
= It
.getType().getTypePtr();
1369 if (typeHasMatchingAlias(TypeNode
, Base
, Builder
))
1372 // FIXME: Going to the primary template here isn't really correct, but
1373 // unfortunately we accept a Decl matcher for the base class not a Type
1374 // matcher, so it's the best thing we can do with our current interface.
1375 CXXRecordDecl
*ClassDecl
= getAsCXXRecordDeclOrPrimaryTemplate(TypeNode
);
1378 if (ClassDecl
== Declaration
) {
1379 // This can happen for recursive template definitions.
1382 BoundNodesTreeBuilder
Result(*Builder
);
1383 if (Base
.matches(*ClassDecl
, this, &Result
)) {
1384 *Builder
= std::move(Result
);
1387 if (!Directly
&& classIsDerivedFrom(ClassDecl
, Base
, Builder
, Directly
))
1393 // Returns true if the given Objective-C class is directly or indirectly
1394 // derived from a matching base class. A class is not considered to be derived
1396 bool MatchASTVisitor::objcClassIsDerivedFrom(
1397 const ObjCInterfaceDecl
*Declaration
, const Matcher
<NamedDecl
> &Base
,
1398 BoundNodesTreeBuilder
*Builder
, bool Directly
) {
1399 // Check if any of the superclasses of the class match.
1400 for (const ObjCInterfaceDecl
*ClassDecl
= Declaration
->getSuperClass();
1401 ClassDecl
!= nullptr; ClassDecl
= ClassDecl
->getSuperClass()) {
1402 // Check if there are any matching compatibility aliases.
1403 if (objcClassHasMatchingCompatibilityAlias(ClassDecl
, Base
, Builder
))
1406 // Check if there are any matching type aliases.
1407 const Type
*TypeNode
= ClassDecl
->getTypeForDecl();
1408 if (typeHasMatchingAlias(TypeNode
, Base
, Builder
))
1411 if (Base
.matches(*ClassDecl
, this, Builder
))
1414 // Not `return false` as a temporary workaround for PR43879.
1422 bool MatchASTVisitor::TraverseDecl(Decl
*DeclNode
) {
1427 bool ScopedTraversal
=
1428 TraversingASTNodeNotSpelledInSource
|| DeclNode
->isImplicit();
1429 bool ScopedChildren
= TraversingASTChildrenNotSpelledInSource
;
1431 if (const auto *CTSD
= dyn_cast
<ClassTemplateSpecializationDecl
>(DeclNode
)) {
1432 auto SK
= CTSD
->getSpecializationKind();
1433 if (SK
== TSK_ExplicitInstantiationDeclaration
||
1434 SK
== TSK_ExplicitInstantiationDefinition
)
1435 ScopedChildren
= true;
1436 } else if (const auto *FD
= dyn_cast
<FunctionDecl
>(DeclNode
)) {
1437 if (FD
->isDefaulted())
1438 ScopedChildren
= true;
1439 if (FD
->isTemplateInstantiation())
1440 ScopedTraversal
= true;
1441 } else if (isa
<BindingDecl
>(DeclNode
)) {
1442 ScopedChildren
= true;
1445 ASTNodeNotSpelledInSourceScope
RAII1(this, ScopedTraversal
);
1446 ASTChildrenNotSpelledInSourceScope
RAII2(this, ScopedChildren
);
1449 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseDecl(DeclNode
);
1452 bool MatchASTVisitor::TraverseStmt(Stmt
*StmtNode
, DataRecursionQueue
*Queue
) {
1456 bool ScopedTraversal
= TraversingASTNodeNotSpelledInSource
||
1457 TraversingASTChildrenNotSpelledInSource
;
1459 ASTNodeNotSpelledInSourceScope
RAII(this, ScopedTraversal
);
1461 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseStmt(StmtNode
, Queue
);
1464 bool MatchASTVisitor::TraverseType(QualType TypeNode
) {
1466 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseType(TypeNode
);
1469 bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode
) {
1470 // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
1471 // We still want to find those types via matchers, so we match them here. Note
1472 // that the TypeLocs are structurally a shadow-hierarchy to the expressed
1473 // type, so we visit all involved parts of a compound type when matching on
1476 match(TypeLocNode
.getType());
1477 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTypeLoc(TypeLocNode
);
1480 bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier
*NNS
) {
1482 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseNestedNameSpecifier(NNS
);
1485 bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
1486 NestedNameSpecifierLoc NNS
) {
1492 // We only match the nested name specifier here (as opposed to traversing it)
1493 // because the traversal is already done in the parallel "Loc"-hierarchy.
1494 if (NNS
.hasQualifier())
1495 match(*NNS
.getNestedNameSpecifier());
1497 RecursiveASTVisitor
<MatchASTVisitor
>::TraverseNestedNameSpecifierLoc(NNS
);
1500 bool MatchASTVisitor::TraverseConstructorInitializer(
1501 CXXCtorInitializer
*CtorInit
) {
1505 bool ScopedTraversal
= TraversingASTNodeNotSpelledInSource
||
1506 TraversingASTChildrenNotSpelledInSource
;
1508 if (!CtorInit
->isWritten())
1509 ScopedTraversal
= true;
1511 ASTNodeNotSpelledInSourceScope
RAII1(this, ScopedTraversal
);
1515 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseConstructorInitializer(
1519 bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc
) {
1521 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseTemplateArgumentLoc(Loc
);
1524 bool MatchASTVisitor::TraverseAttr(Attr
*AttrNode
) {
1526 return RecursiveASTVisitor
<MatchASTVisitor
>::TraverseAttr(AttrNode
);
1529 class MatchASTConsumer
: public ASTConsumer
{
1531 MatchASTConsumer(MatchFinder
*Finder
,
1532 MatchFinder::ParsingDoneTestCallback
*ParsingDone
)
1533 : Finder(Finder
), ParsingDone(ParsingDone
) {}
1536 void HandleTranslationUnit(ASTContext
&Context
) override
{
1537 if (ParsingDone
!= nullptr) {
1540 Finder
->matchAST(Context
);
1543 MatchFinder
*Finder
;
1544 MatchFinder::ParsingDoneTestCallback
*ParsingDone
;
1548 } // end namespace internal
1550 MatchFinder::MatchResult::MatchResult(const BoundNodes
&Nodes
,
1551 ASTContext
*Context
)
1552 : Nodes(Nodes
), Context(Context
),
1553 SourceManager(&Context
->getSourceManager()) {}
1555 MatchFinder::MatchCallback::~MatchCallback() {}
1556 MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
1558 MatchFinder::MatchFinder(MatchFinderOptions Options
)
1559 : Options(std::move(Options
)), ParsingDone(nullptr) {}
1561 MatchFinder::~MatchFinder() {}
1563 void MatchFinder::addMatcher(const DeclarationMatcher
&NodeMatch
,
1564 MatchCallback
*Action
) {
1565 llvm::Optional
<TraversalKind
> TK
;
1567 TK
= Action
->getCheckTraversalKind();
1569 Matchers
.DeclOrStmt
.emplace_back(traverse(*TK
, NodeMatch
), Action
);
1571 Matchers
.DeclOrStmt
.emplace_back(NodeMatch
, Action
);
1572 Matchers
.AllCallbacks
.insert(Action
);
1575 void MatchFinder::addMatcher(const TypeMatcher
&NodeMatch
,
1576 MatchCallback
*Action
) {
1577 Matchers
.Type
.emplace_back(NodeMatch
, Action
);
1578 Matchers
.AllCallbacks
.insert(Action
);
1581 void MatchFinder::addMatcher(const StatementMatcher
&NodeMatch
,
1582 MatchCallback
*Action
) {
1583 llvm::Optional
<TraversalKind
> TK
;
1585 TK
= Action
->getCheckTraversalKind();
1587 Matchers
.DeclOrStmt
.emplace_back(traverse(*TK
, NodeMatch
), Action
);
1589 Matchers
.DeclOrStmt
.emplace_back(NodeMatch
, Action
);
1590 Matchers
.AllCallbacks
.insert(Action
);
1593 void MatchFinder::addMatcher(const NestedNameSpecifierMatcher
&NodeMatch
,
1594 MatchCallback
*Action
) {
1595 Matchers
.NestedNameSpecifier
.emplace_back(NodeMatch
, Action
);
1596 Matchers
.AllCallbacks
.insert(Action
);
1599 void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher
&NodeMatch
,
1600 MatchCallback
*Action
) {
1601 Matchers
.NestedNameSpecifierLoc
.emplace_back(NodeMatch
, Action
);
1602 Matchers
.AllCallbacks
.insert(Action
);
1605 void MatchFinder::addMatcher(const TypeLocMatcher
&NodeMatch
,
1606 MatchCallback
*Action
) {
1607 Matchers
.TypeLoc
.emplace_back(NodeMatch
, Action
);
1608 Matchers
.AllCallbacks
.insert(Action
);
1611 void MatchFinder::addMatcher(const CXXCtorInitializerMatcher
&NodeMatch
,
1612 MatchCallback
*Action
) {
1613 Matchers
.CtorInit
.emplace_back(NodeMatch
, Action
);
1614 Matchers
.AllCallbacks
.insert(Action
);
1617 void MatchFinder::addMatcher(const TemplateArgumentLocMatcher
&NodeMatch
,
1618 MatchCallback
*Action
) {
1619 Matchers
.TemplateArgumentLoc
.emplace_back(NodeMatch
, Action
);
1620 Matchers
.AllCallbacks
.insert(Action
);
1623 void MatchFinder::addMatcher(const AttrMatcher
&AttrMatch
,
1624 MatchCallback
*Action
) {
1625 Matchers
.Attr
.emplace_back(AttrMatch
, Action
);
1626 Matchers
.AllCallbacks
.insert(Action
);
1629 bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher
&NodeMatch
,
1630 MatchCallback
*Action
) {
1631 if (NodeMatch
.canConvertTo
<Decl
>()) {
1632 addMatcher(NodeMatch
.convertTo
<Decl
>(), Action
);
1634 } else if (NodeMatch
.canConvertTo
<QualType
>()) {
1635 addMatcher(NodeMatch
.convertTo
<QualType
>(), Action
);
1637 } else if (NodeMatch
.canConvertTo
<Stmt
>()) {
1638 addMatcher(NodeMatch
.convertTo
<Stmt
>(), Action
);
1640 } else if (NodeMatch
.canConvertTo
<NestedNameSpecifier
>()) {
1641 addMatcher(NodeMatch
.convertTo
<NestedNameSpecifier
>(), Action
);
1643 } else if (NodeMatch
.canConvertTo
<NestedNameSpecifierLoc
>()) {
1644 addMatcher(NodeMatch
.convertTo
<NestedNameSpecifierLoc
>(), Action
);
1646 } else if (NodeMatch
.canConvertTo
<TypeLoc
>()) {
1647 addMatcher(NodeMatch
.convertTo
<TypeLoc
>(), Action
);
1649 } else if (NodeMatch
.canConvertTo
<CXXCtorInitializer
>()) {
1650 addMatcher(NodeMatch
.convertTo
<CXXCtorInitializer
>(), Action
);
1652 } else if (NodeMatch
.canConvertTo
<TemplateArgumentLoc
>()) {
1653 addMatcher(NodeMatch
.convertTo
<TemplateArgumentLoc
>(), Action
);
1655 } else if (NodeMatch
.canConvertTo
<Attr
>()) {
1656 addMatcher(NodeMatch
.convertTo
<Attr
>(), Action
);
1662 std::unique_ptr
<ASTConsumer
> MatchFinder::newASTConsumer() {
1663 return std::make_unique
<internal::MatchASTConsumer
>(this, ParsingDone
);
1666 void MatchFinder::match(const clang::DynTypedNode
&Node
, ASTContext
&Context
) {
1667 internal::MatchASTVisitor
Visitor(&Matchers
, Options
);
1668 Visitor
.set_active_ast_context(&Context
);
1669 Visitor
.match(Node
);
1672 void MatchFinder::matchAST(ASTContext
&Context
) {
1673 internal::MatchASTVisitor
Visitor(&Matchers
, Options
);
1674 internal::MatchASTVisitor::TraceReporter
StackTrace(Visitor
);
1675 Visitor
.set_active_ast_context(&Context
);
1676 Visitor
.onStartOfTranslationUnit();
1677 Visitor
.TraverseAST(Context
);
1678 Visitor
.onEndOfTranslationUnit();
1681 void MatchFinder::registerTestCallbackAfterParsing(
1682 MatchFinder::ParsingDoneTestCallback
*NewParsingDone
) {
1683 ParsingDone
= NewParsingDone
;
1686 StringRef
MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
1688 llvm::Optional
<TraversalKind
>
1689 MatchFinder::MatchCallback::getCheckTraversalKind() const {
1693 } // end namespace ast_matchers
1694 } // end namespace clang