clang 20.0.0git
ASTMatchFinder.cpp
Go to the documentation of this file.
1//===--- ASTMatchFinder.cpp - Structural query framework ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implements an algorithm to efficiently search for matches on AST nodes.
10// Uses memoization to support recursive matches like HasDescendant.
11//
12// The general idea is to visit all AST nodes with a RecursiveASTVisitor,
13// calling the Matches(...) method of each matcher we are running on each
14// AST node. The matcher can recurse via the ASTMatchFinder interface.
15//
16//===----------------------------------------------------------------------===//
17
21#include "clang/AST/DeclCXX.h"
23#include "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"
28#include <deque>
29#include <memory>
30#include <set>
31
32namespace clang {
33namespace ast_matchers {
34namespace internal {
35namespace {
36
37typedef MatchFinder::MatchCallback MatchCallback;
38
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.
43//
44// FIXME: Do some performance optimization in general and
45// revisit this number; also, put up micro-benchmarks that we can
46// optimize this on.
47static const unsigned MaxMemoizationEntries = 10000;
48
49enum class MatchType {
50 Ancestors,
51
52 Descendants,
53 Child,
54};
55
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.
61//
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.
68struct MatchKey {
69 DynTypedMatcher::MatcherIDType MatcherID;
70 DynTypedNode Node;
71 BoundNodesTreeBuilder BoundNodes;
73 MatchType Type;
74
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,
78 Other.BoundNodes);
79 }
80};
81
82// Used to store the result of a match and possibly bound nodes.
83struct MemoizedMatchResult {
85 BoundNodesTreeBuilder Nodes;
86};
87
88// A RecursiveASTVisitor that traverses all children or all descendants of
89// a node.
90class MatchChildASTVisitor
91 : public RecursiveASTVisitor<MatchChildASTVisitor> {
92public:
93 typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
94
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) {}
106
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):
111 //
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
117 // recursion.
118 bool findMatch(const DynTypedNode &DynNode) {
119 reset();
120 if (const Decl *D = DynNode.get<Decl>())
121 traverse(*D);
122 else if (const Stmt *S = DynNode.get<Stmt>())
123 traverse(*S);
124 else if (const NestedNameSpecifier *NNS =
125 DynNode.get<NestedNameSpecifier>())
126 traverse(*NNS);
127 else if (const NestedNameSpecifierLoc *NNSLoc =
128 DynNode.get<NestedNameSpecifierLoc>())
129 traverse(*NNSLoc);
130 else if (const QualType *Q = DynNode.get<QualType>())
131 traverse(*Q);
132 else if (const TypeLoc *T = DynNode.get<TypeLoc>())
133 traverse(*T);
134 else if (const auto *C = DynNode.get<CXXCtorInitializer>())
135 traverse(*C);
136 else if (const TemplateArgumentLoc *TALoc =
137 DynNode.get<TemplateArgumentLoc>())
138 traverse(*TALoc);
139 else if (const Attr *A = DynNode.get<Attr>())
140 traverse(*A);
141 // FIXME: Add other base types after adding tests.
142
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
145 // anyway.
146 *Builder = ResultBindings;
147
148 return Matches;
149 }
150
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) {
155
156 if (DeclNode && DeclNode->isImplicit() &&
157 Finder->isTraversalIgnoringImplicitNodes())
158 return baseTraverse(*DeclNode);
159
160 ScopedIncrement ScopedDepth(&CurrentDepth);
161 return (DeclNode == nullptr) || traverse(*DeclNode);
162 }
163
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;
170 else
171 StmtToTraverse =
172 Finder->getASTContext().getParentMapContext().traverseIgnored(
173 ExprNode);
174 }
175 return StmtToTraverse;
176 }
177
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))
181 Queue = nullptr;
182
183 ScopedIncrement ScopedDepth(&CurrentDepth);
184 Stmt *StmtToTraverse = getStmtToTraverse(StmtNode);
185 if (!StmtToTraverse)
186 return true;
187
188 if (IgnoreImplicitChildren && isa<CXXDefaultArgExpr>(StmtNode))
189 return true;
190
191 if (!match(*StmtToTraverse))
192 return false;
193 return VisitorBase::TraverseStmt(StmtToTraverse, Queue);
194 }
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())
199 return true;
200 ScopedIncrement ScopedDepth(&CurrentDepth);
201 // Match the Type.
202 if (!match(*TypeNode))
203 return false;
204 // The QualType is matched inside traverse.
205 return traverse(TypeNode);
206 }
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())
211 return true;
212 ScopedIncrement ScopedDepth(&CurrentDepth);
213 // Match the Type.
214 if (!match(*TypeLocNode.getType()))
215 return false;
216 // Match the QualType.
217 if (!match(TypeLocNode.getType()))
218 return false;
219 // The TypeLoc is matched inside traverse.
220 return traverse(TypeLocNode);
221 }
222 bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
223 ScopedIncrement ScopedDepth(&CurrentDepth);
224 return (NNS == nullptr) || traverse(*NNS);
225 }
226 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
227 if (!NNS)
228 return true;
229 ScopedIncrement ScopedDepth(&CurrentDepth);
230 if (!match(*NNS.getNestedNameSpecifier()))
231 return false;
232 return traverse(NNS);
233 }
234 bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
235 if (!CtorInit)
236 return true;
237 ScopedIncrement ScopedDepth(&CurrentDepth);
238 return traverse(*CtorInit);
239 }
240 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
241 ScopedIncrement ScopedDepth(&CurrentDepth);
242 return traverse(TAL);
243 }
244 bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) {
245 if (!Finder->isTraversalIgnoringImplicitNodes())
246 return VisitorBase::TraverseCXXForRangeStmt(Node);
247 if (!Node)
248 return true;
249 ScopedIncrement ScopedDepth(&CurrentDepth);
250 if (auto *Init = Node->getInit())
251 if (!traverse(*Init))
252 return false;
253 if (!match(*Node->getLoopVariable()))
254 return false;
255 if (match(*Node->getRangeInit()))
256 if (!VisitorBase::TraverseStmt(Node->getRangeInit()))
257 return false;
258 if (!match(*Node->getBody()))
259 return false;
260 return VisitorBase::TraverseStmt(Node->getBody());
261 }
262 bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *Node) {
263 if (!Finder->isTraversalIgnoringImplicitNodes())
264 return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node);
265 if (!Node)
266 return true;
267 ScopedIncrement ScopedDepth(&CurrentDepth);
268
269 return match(*Node->getLHS()) && match(*Node->getRHS());
270 }
271 bool TraverseAttr(Attr *A) {
272 if (A == nullptr ||
273 (A->isImplicit() &&
274 Finder->getASTContext().getParentMapContext().getTraversalKind() ==
276 return true;
277 ScopedIncrement ScopedDepth(&CurrentDepth);
278 return traverse(*A);
279 }
280 bool TraverseLambdaExpr(LambdaExpr *Node) {
281 if (!Finder->isTraversalIgnoringImplicitNodes())
282 return VisitorBase::TraverseLambdaExpr(Node);
283 if (!Node)
284 return true;
285 ScopedIncrement ScopedDepth(&CurrentDepth);
286
287 for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
288 const LambdaCapture *C = Node->capture_begin() + I;
289 if (!C->isExplicit())
290 continue;
291 if (Node->isInitCapture(C) && !match(*C->getCapturedVar()))
292 return false;
293 const Expr *CIE = Node->capture_init_begin()[I];
294 if (CIE != nullptr && !match(*CIE))
295 return false;
296 }
297
298 if (const auto *TPL = Node->getTemplateParameterList()) {
299 for (const auto *TP : *TPL) {
300 if (!match(*TP))
301 return false;
302 }
303 }
304
305 for (const auto *P : Node->getCallOperator()->parameters()) {
306 if (!match(*P))
307 return false;
308 }
309
310 if (!match(*Node->getBody()))
311 return false;
312
313 return VisitorBase::TraverseStmt(Node->getBody());
314 }
315
316 bool shouldVisitTemplateInstantiations() const { return true; }
317 bool shouldVisitImplicitCode() const { return !IgnoreImplicitChildren; }
318
319private:
320 // Used for updating the depth during traversal.
321 struct ScopedIncrement {
322 explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
323 ~ScopedIncrement() { --(*Depth); }
324
325 private:
326 int *Depth;
327 };
328
329 // Resets the state of this object.
330 void reset() {
331 Matches = false;
332 CurrentDepth = 0;
333 }
334
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));
339 }
340 bool baseTraverse(const Stmt &StmtNode) {
341 return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
342 }
343 bool baseTraverse(QualType TypeNode) {
344 return VisitorBase::TraverseType(TypeNode);
345 }
346 bool baseTraverse(TypeLoc TypeLocNode) {
347 return VisitorBase::TraverseTypeLoc(TypeLocNode);
348 }
349 bool baseTraverse(const NestedNameSpecifier &NNS) {
351 const_cast<NestedNameSpecifier*>(&NNS));
352 }
353 bool baseTraverse(NestedNameSpecifierLoc NNS) {
355 }
356 bool baseTraverse(const CXXCtorInitializer &CtorInit) {
358 const_cast<CXXCtorInitializer *>(&CtorInit));
359 }
360 bool baseTraverse(TemplateArgumentLoc TAL) {
362 }
363 bool baseTraverse(const Attr &AttrNode) {
364 return VisitorBase::TraverseAttr(const_cast<Attr *>(&AttrNode));
365 }
366
367 // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
368 // 0 < CurrentDepth <= MaxDepth.
369 //
370 // Returns 'true' if traversal should continue after this function
371 // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
372 template <typename T>
373 bool match(const T &Node) {
374 if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
375 return true;
376 }
377 if (Bind != ASTMatchFinder::BK_All) {
378 BoundNodesTreeBuilder RecursiveBuilder(*Builder);
379 if (Matcher->matches(DynTypedNode::create(Node), Finder,
380 &RecursiveBuilder)) {
381 Matches = true;
382 ResultBindings.addMatch(RecursiveBuilder);
383 return false; // Abort as soon as a match is found.
384 }
385 } else {
386 BoundNodesTreeBuilder RecursiveBuilder(*Builder);
387 if (Matcher->matches(DynTypedNode::create(Node), Finder,
388 &RecursiveBuilder)) {
389 // After the first match the matcher succeeds.
390 Matches = true;
391 ResultBindings.addMatch(RecursiveBuilder);
392 }
393 }
394 return true;
395 }
396
397 // Traverses the subtree rooted at 'Node'; returns true if the
398 // traversal should continue after this function returns.
399 template <typename T>
400 bool traverse(const T &Node) {
401 static_assert(IsBaseType<T>::value,
402 "traverse can only be instantiated with base type");
403 if (!match(Node))
404 return false;
405 return baseTraverse(Node);
406 }
407
408 const DynTypedMatcher *const Matcher;
409 ASTMatchFinder *const Finder;
410 BoundNodesTreeBuilder *const Builder;
411 BoundNodesTreeBuilder ResultBindings;
412 int CurrentDepth;
413 const int MaxDepth;
414 const bool IgnoreImplicitChildren;
415 const ASTMatchFinder::BindKind Bind;
416 bool Matches;
417};
418
419// Controls the outermost traversal of the AST and allows to match multiple
420// matchers.
421class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
422 public ASTMatchFinder {
423public:
424 MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
425 const MatchFinder::MatchFinderOptions &Options)
426 : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
427
428 ~MatchASTVisitor() override {
429 if (Options.CheckProfiling) {
430 Options.CheckProfiling->Records = std::move(TimeByBucket);
431 }
432 }
433
434 void onStartOfTranslationUnit() {
435 const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
436 TimeBucketRegion Timer;
437 for (MatchCallback *MC : Matchers->AllCallbacks) {
438 if (EnableCheckProfiling)
439 Timer.setBucket(&TimeByBucket[MC->getID()]);
440 MC->onStartOfTranslationUnit();
441 }
442 }
443
444 void onEndOfTranslationUnit() {
445 const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
446 TimeBucketRegion Timer;
447 for (MatchCallback *MC : Matchers->AllCallbacks) {
448 if (EnableCheckProfiling)
449 Timer.setBucket(&TimeByBucket[MC->getID()]);
450 MC->onEndOfTranslationUnit();
451 }
452 }
453
454 void set_active_ast_context(ASTContext *NewActiveASTContext) {
455 ActiveASTContext = NewActiveASTContext;
456 }
457
458 // The following Visit*() and Traverse*() functions "override"
459 // methods in RecursiveASTVisitor.
460
461 bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
462 // When we see 'typedef A B', we add name 'B' to the set of names
463 // A's canonical type maps to. This is necessary for implementing
464 // isDerivedFrom(x) properly, where x can be the name of the base
465 // class or any of its aliases.
466 //
467 // In general, the is-alias-of (as defined by typedefs) relation
468 // is tree-shaped, as you can typedef a type more than once. For
469 // example,
470 //
471 // typedef A B;
472 // typedef A C;
473 // typedef C D;
474 // typedef C E;
475 //
476 // gives you
477 //
478 // A
479 // |- B
480 // `- C
481 // |- D
482 // `- E
483 //
484 // It is wrong to assume that the relation is a chain. A correct
485 // implementation of isDerivedFrom() needs to recognize that B and
486 // E are aliases, even though neither is a typedef of the other.
487 // Therefore, we cannot simply walk through one typedef chain to
488 // find out whether the type name matches.
489 const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
490 const Type *CanonicalType = // root of the typedef tree
491 ActiveASTContext->getCanonicalType(TypeNode);
492 TypeAliases[CanonicalType].insert(DeclNode);
493 return true;
494 }
495
496 bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
497 const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface();
498 CompatibleAliases[InterfaceDecl].insert(CAD);
499 return true;
500 }
501
502 bool TraverseDecl(Decl *DeclNode);
503 bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
504 bool TraverseType(QualType TypeNode);
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);
511
512 bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
513 if (auto *RF = dyn_cast<CXXForRangeStmt>(S)) {
514 {
515 ASTNodeNotAsIsSourceScope RAII(this, true);
516 TraverseStmt(RF->getInit());
517 // Don't traverse under the loop variable
518 match(*RF->getLoopVariable());
519 TraverseStmt(RF->getRangeInit());
520 }
521 {
522 ASTNodeNotSpelledInSourceScope RAII(this, true);
523 for (auto *SubStmt : RF->children()) {
524 if (SubStmt != RF->getBody())
525 TraverseStmt(SubStmt);
526 }
527 }
528 TraverseStmt(RF->getBody());
529 return true;
530 } else if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
531 {
532 ASTNodeNotAsIsSourceScope RAII(this, true);
533 TraverseStmt(const_cast<Expr *>(RBO->getLHS()));
534 TraverseStmt(const_cast<Expr *>(RBO->getRHS()));
535 }
536 {
537 ASTNodeNotSpelledInSourceScope RAII(this, true);
538 for (auto *SubStmt : RBO->children()) {
539 TraverseStmt(SubStmt);
540 }
541 }
542 return true;
543 } else if (auto *LE = dyn_cast<LambdaExpr>(S)) {
544 for (auto I : llvm::zip(LE->captures(), LE->capture_inits())) {
545 auto C = std::get<0>(I);
546 ASTNodeNotSpelledInSourceScope RAII(
547 this, TraversingASTNodeNotSpelledInSource || !C.isExplicit());
548 TraverseLambdaCapture(LE, &C, std::get<1>(I));
549 }
550
551 {
552 ASTNodeNotSpelledInSourceScope RAII(this, true);
553 TraverseDecl(LE->getLambdaClass());
554 }
555 {
556 ASTNodeNotAsIsSourceScope RAII(this, true);
557
558 // We need to poke around to find the bits that might be explicitly
559 // written.
560 TypeLoc TL = LE->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
561 FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
562
563 if (auto *TPL = LE->getTemplateParameterList()) {
564 for (NamedDecl *D : *TPL) {
565 TraverseDecl(D);
566 }
567 if (Expr *RequiresClause = TPL->getRequiresClause()) {
568 TraverseStmt(RequiresClause);
569 }
570 }
571
572 if (LE->hasExplicitParameters()) {
573 // Visit parameters.
574 for (ParmVarDecl *Param : Proto.getParams())
575 TraverseDecl(Param);
576 }
577
578 const auto *T = Proto.getTypePtr();
579 for (const auto &E : T->exceptions())
580 TraverseType(E);
581
582 if (Expr *NE = T->getNoexceptExpr())
583 TraverseStmt(NE, Queue);
584
585 if (LE->hasExplicitResultType())
586 TraverseTypeLoc(Proto.getReturnLoc());
587 TraverseStmt(LE->getTrailingRequiresClause());
588 }
589
590 TraverseStmt(LE->getBody());
591 return true;
592 }
594 }
595
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,
600 BindKind Bind) {
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);
604
605 MatchKey Key;
606 Key.MatcherID = Matcher.getID();
607 Key.Node = Node;
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;
617 }
618
619 MemoizedMatchResult Result;
620 Result.Nodes = *Builder;
621 Result.ResultOfMatch =
622 matchesRecursively(Node, Matcher, &Result.Nodes, MaxDepth, Bind);
623
624 MemoizedMatchResult &CachedResult = ResultCache[Key];
625 CachedResult = std::move(Result);
626
627 *Builder = CachedResult.Nodes;
628 return CachedResult.ResultOfMatch;
629 }
630
631 // Matches children or descendants of 'Node' with 'BaseMatcher'.
632 bool matchesRecursively(const DynTypedNode &Node,
633 const DynTypedMatcher &Matcher,
634 BoundNodesTreeBuilder *Builder, int MaxDepth,
635 BindKind Bind) {
636 bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
637 TraversingASTChildrenNotSpelledInSource;
638
639 bool IgnoreImplicitChildren = false;
640
641 if (isTraversalIgnoringImplicitNodes()) {
642 IgnoreImplicitChildren = true;
643 }
644
645 ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
646
647 MatchChildASTVisitor Visitor(&Matcher, this, Builder, MaxDepth,
648 IgnoreImplicitChildren, Bind);
649 return Visitor.findMatch(Node);
650 }
651
652 bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
653 const Matcher<NamedDecl> &Base,
654 BoundNodesTreeBuilder *Builder,
655 bool Directly) override;
656
657private:
658 bool
659 classIsDerivedFromImpl(const CXXRecordDecl *Declaration,
660 const Matcher<NamedDecl> &Base,
661 BoundNodesTreeBuilder *Builder, bool Directly,
662 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &Visited);
663
664public:
665 bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
666 const Matcher<NamedDecl> &Base,
667 BoundNodesTreeBuilder *Builder,
668 bool Directly) override;
669
670public:
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)
676 ResultCache.clear();
677 return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, Bind);
678 }
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)
685 ResultCache.clear();
686 return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, INT_MAX,
687 Bind);
688 }
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)
697 ResultCache.clear();
698 if (MatchMode == AncestorMatchMode::AMM_ParentOnly)
699 return matchesParentOf(Node, Matcher, Builder);
700 return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
701 }
702
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>()) {
708 match(*N);
709 } else if (auto *N = Node.get<Stmt>()) {
710 match(*N);
711 } else if (auto *N = Node.get<Type>()) {
712 match(*N);
713 } else if (auto *N = Node.get<QualType>()) {
714 match(*N);
715 } else if (auto *N = Node.get<NestedNameSpecifier>()) {
716 match(*N);
717 } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
718 match(*N);
719 } else if (auto *N = Node.get<TypeLoc>()) {
720 match(*N);
721 } else if (auto *N = Node.get<CXXCtorInitializer>()) {
722 match(*N);
723 } else if (auto *N = Node.get<TemplateArgumentLoc>()) {
724 match(*N);
725 } else if (auto *N = Node.get<Attr>()) {
726 match(*N);
727 }
728 }
729
730 template <typename T> void match(const T &Node) {
731 matchDispatch(&Node);
732 }
733
734 // Implements ASTMatchFinder::getASTContext.
735 ASTContext &getASTContext() const override { return *ActiveASTContext; }
736
737 bool shouldVisitTemplateInstantiations() const { return true; }
738 bool shouldVisitImplicitCode() const { return true; }
739
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; }
743
744 bool IsMatchingInASTNodeNotSpelledInSource() const override {
745 return TraversingASTNodeNotSpelledInSource;
746 }
747 bool isMatchingChildrenNotSpelledInSource() const override {
748 return TraversingASTChildrenNotSpelledInSource;
749 }
750 void setMatchingChildrenNotSpelledInSource(bool Set) override {
751 TraversingASTChildrenNotSpelledInSource = Set;
752 }
753
754 bool IsMatchingInASTNodeNotAsIs() const override {
755 return TraversingASTNodeNotAsIs;
756 }
757
758 bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
759 ASTNodeNotSpelledInSourceScope RAII(this, true);
760 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
761 D);
762 }
763
764 bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
765 ASTNodeNotSpelledInSourceScope RAII(this, true);
766 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
767 D);
768 }
769
770 bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
771 ASTNodeNotSpelledInSourceScope RAII(this, true);
772 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
773 D);
774 }
775
776private:
777 bool TraversingASTNodeNotSpelledInSource = false;
778 bool TraversingASTNodeNotAsIs = false;
779 bool TraversingASTChildrenNotSpelledInSource = false;
780
781 class CurMatchData {
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
784// callback pointer.
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 *, \
790 const DynTypedNode *
791
792#define IMPL(Index) \
793 template <typename NodeType> \
794 std::enable_if_t< \
795 llvm::is_one_of<const NodeType *, CMD_TYPES_##Index>::value> \
796 SetCallbackAndRawNode(const MatchCallback *CB, const NodeType &N) { \
797 assertEmpty(); \
798 Callback.setPointerAndInt(CB, Index); \
799 Node##Index = &N; \
800 } \
801 \
802 template <typename T> \
803 std::enable_if_t<llvm::is_one_of<const T *, CMD_TYPES_##Index>::value, \
804 const T *> \
805 getNode() const { \
806 assertHoldsState(); \
807 return Callback.getInt() == (Index) ? Node##Index.dyn_cast<const T *>() \
808 : nullptr; \
809 }
810
811 public:
812 CurMatchData() : Node0(nullptr) {}
813
814 IMPL(0)
815 IMPL(1)
816
817 const MatchCallback *getCallback() const { return Callback.getPointer(); }
818
819 void SetBoundNodes(const BoundNodes &BN) {
820 assertHoldsState();
821 BNodes = &BN;
822 }
823
824 void clearBoundNodes() {
825 assertHoldsState();
826 BNodes = nullptr;
827 }
828
829 const BoundNodes *getBoundNodes() const {
830 assertHoldsState();
831 return BNodes;
832 }
833
834 void reset() {
835 assertHoldsState();
836 Callback.setPointerAndInt(nullptr, 0);
837 Node0 = nullptr;
838 }
839
840 private:
841 void assertHoldsState() const {
842 assert(Callback.getPointer() != nullptr && !Node0.isNull());
843 }
844
845 void assertEmpty() const {
846 assert(Callback.getPointer() == nullptr && Node0.isNull() &&
847 BNodes == nullptr);
848 }
849
850 llvm::PointerIntPair<const MatchCallback *, 1> Callback;
851 union {
852 llvm::PointerUnion<CMD_TYPES_0> Node0;
853 llvm::PointerUnion<CMD_TYPES_1> Node1;
854 };
855 const BoundNodes *BNodes = nullptr;
856
857#undef CMD_TYPES_0
858#undef CMD_TYPES_1
859#undef IMPL
860 } CurMatchState;
861
862 struct CurMatchRAII {
863 template <typename NodeType>
864 CurMatchRAII(MatchASTVisitor &MV, const MatchCallback *CB,
865 const NodeType &NT)
866 : MV(MV) {
867 MV.CurMatchState.SetCallbackAndRawNode(CB, NT);
868 }
869
870 ~CurMatchRAII() { MV.CurMatchState.reset(); }
871
872 private:
873 MatchASTVisitor &MV;
874 };
875
876public:
877 class TraceReporter : llvm::PrettyStackTraceEntry {
878 static void dumpNode(const ASTContext &Ctx, const DynTypedNode &Node,
879 raw_ostream &OS) {
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);
884 OS << " : ";
885 } else
886 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>()) {
895 OS << "QualType : ";
896 QT->print(OS, Ctx.getPrintingPolicy());
897 } else {
898 OS << Node.getNodeKind().asStringRef() << " : ";
899 Node.getSourceRange().print(OS, Ctx.getSourceManager());
900 }
901 }
902
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);
921 }
922 }
923
924 public:
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();
929 if (!CB) {
930 OS << "ASTMatcher: Not currently matching\n";
931 return;
932 }
933
934 assert(MV.ActiveASTContext &&
935 "ActiveASTContext should be set if there is a matched callback");
936
937 ASTContext &Ctx = MV.getASTContext();
938
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();
943 if (Map.empty()) {
944 OS << "\nNo bound nodes\n";
945 return;
946 }
947 OS << "\n--- Bound Nodes Begin ---\n";
948 for (const auto &Item : Map) {
949 OS << " " << Item.first << " - { ";
950 dumpNode(Ctx, Item.second, OS);
951 OS << " }\n";
952 }
953 OS << "--- Bound Nodes End ---\n";
954 } else {
955 OS << "ASTMatcher: Matching '" << CB->getID() << "' against:\n\t";
956 dumpNodeFromState(Ctx, State, OS);
957 OS << '\n';
958 }
959 }
960
961 private:
962 const MatchASTVisitor &MV;
963 };
964
965private:
966 struct ASTNodeNotSpelledInSourceScope {
967 ASTNodeNotSpelledInSourceScope(MatchASTVisitor *V, bool B)
968 : MV(V), MB(V->TraversingASTNodeNotSpelledInSource) {
969 V->TraversingASTNodeNotSpelledInSource = B;
970 }
971 ~ASTNodeNotSpelledInSourceScope() {
972 MV->TraversingASTNodeNotSpelledInSource = MB;
973 }
974
975 private:
976 MatchASTVisitor *MV;
977 bool MB;
978 };
979
980 struct ASTNodeNotAsIsSourceScope {
981 ASTNodeNotAsIsSourceScope(MatchASTVisitor *V, bool B)
982 : MV(V), MB(V->TraversingASTNodeNotAsIs) {
983 V->TraversingASTNodeNotAsIs = B;
984 }
985 ~ASTNodeNotAsIsSourceScope() { MV->TraversingASTNodeNotAsIs = MB; }
986
987 private:
988 MatchASTVisitor *MV;
989 bool MB;
990 };
991
992 class TimeBucketRegion {
993 public:
994 TimeBucketRegion() = default;
995 ~TimeBucketRegion() { setBucket(nullptr); }
996
997 /// Start timing for \p NewBucket.
998 ///
999 /// If there was a bucket already set, it will finish the timing for that
1000 /// other bucket.
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
1004 /// does nothing.
1005 void setBucket(llvm::TimeRecord *NewBucket) {
1006 if (Bucket != NewBucket) {
1007 auto Now = llvm::TimeRecord::getCurrentTime(true);
1008 if (Bucket)
1009 *Bucket += Now;
1010 if (NewBucket)
1011 *NewBucket -= Now;
1012 Bucket = NewBucket;
1013 }
1014 }
1015
1016 private:
1017 llvm::TimeRecord *Bucket = nullptr;
1018 };
1019
1020 /// Runs all the \p Matchers on \p Node.
1021 ///
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);
1035 }
1036 }
1037 }
1038
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);
1044
1045 if (Filter.empty())
1046 return;
1047
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;
1056
1057 {
1058 TraversalKindScope RAII(getASTContext(), MP.first.getTraversalKind());
1059 if (getASTContext().getParentMapContext().traverseIgnored(DynNode) !=
1060 DynNode)
1061 continue;
1062 }
1063
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);
1068 }
1069 }
1070 }
1071
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);
1079 }
1080 }
1081 return Filter;
1082 }
1083
1084 /// @{
1085 /// Overloads to pair the different node types to their matchers.
1086 void matchDispatch(const Decl *Node) {
1087 return matchWithFilter(DynTypedNode::create(*Node));
1088 }
1089 void matchDispatch(const Stmt *Node) {
1090 return matchWithFilter(DynTypedNode::create(*Node));
1091 }
1092
1093 void matchDispatch(const Type *Node) {
1094 matchWithoutFilter(QualType(Node, 0), Matchers->Type);
1095 }
1096 void matchDispatch(const TypeLoc *Node) {
1097 matchWithoutFilter(*Node, Matchers->TypeLoc);
1098 }
1099 void matchDispatch(const QualType *Node) {
1100 matchWithoutFilter(*Node, Matchers->Type);
1101 }
1102 void matchDispatch(const NestedNameSpecifier *Node) {
1103 matchWithoutFilter(*Node, Matchers->NestedNameSpecifier);
1104 }
1105 void matchDispatch(const NestedNameSpecifierLoc *Node) {
1106 matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
1107 }
1108 void matchDispatch(const CXXCtorInitializer *Node) {
1109 matchWithoutFilter(*Node, Matchers->CtorInit);
1110 }
1111 void matchDispatch(const TemplateArgumentLoc *Node) {
1112 matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc);
1113 }
1114 void matchDispatch(const Attr *Node) {
1115 matchWithoutFilter(*Node, Matchers->Attr);
1116 }
1117 void matchDispatch(const void *) { /* Do nothing. */ }
1118 /// @}
1119
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);
1128 return true;
1129 }
1130 }
1131 return false;
1132 }
1133
1134 // Returns whether an ancestor of \p Node matches \p Matcher.
1135 //
1136 // The order of matching (which can lead to different nodes being bound in
1137 // case there are multiple matches) is breadth first search.
1138 //
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
1142 // parent.
1143 //
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.
1147 //
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) {
1153
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;
1164 }
1165 return Matched;
1166 };
1167
1168 // Loop while there's a single parent and we want to attempt memoization.
1169 DynTypedNodeList Parents{ArrayRef<DynTypedNode>()}; // after loop: size != 1
1170 for (;;) {
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;
1179
1180 // Check the cache.
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);
1186 }
1187 }
1188
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)
1193 break;
1194
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);
1201 }
1202 }
1203 // We reached the end of the chain.
1204
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.
1212#ifndef NDEBUG
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;
1217 })) {
1218 llvm::errs() << "Tried to match orphan node:\n";
1219 Node.dump(llvm::errs(), *ActiveASTContext);
1220 llvm_unreachable("Parent map should be complete!");
1221 }
1222#endif
1223 } else {
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);
1235 }
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);
1242 }
1243 Queue.pop_front();
1244 }
1245 }
1246 return Finish(false);
1247 }
1248
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)
1254 : State(State) {
1255 State.SetBoundNodes(BN);
1256 }
1257
1258 ~CurBoundScope() { State.clearBoundNodes(); }
1259
1260 private:
1261 MatchASTVisitor::CurMatchData &State;
1262 };
1263
1264 public:
1265 MatchVisitor(MatchASTVisitor &MV, ASTContext *Context,
1266 MatchFinder::MatchCallback *Callback)
1267 : State(MV.CurMatchState), Context(Context), Callback(Callback) {}
1268
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));
1273 }
1274
1275 private:
1276 MatchASTVisitor::CurMatchData &State;
1277 ASTContext* Context;
1278 MatchFinder::MatchCallback* Callback;
1279 };
1280
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())
1289 return false;
1290 for (const TypedefNameDecl *Alias : Aliases->second) {
1291 BoundNodesTreeBuilder Result(*Builder);
1292 if (Matcher.matches(*Alias, this, &Result)) {
1293 *Builder = std::move(Result);
1294 return true;
1295 }
1296 }
1297 return false;
1298 }
1299
1300 bool
1301 objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl *InterfaceDecl,
1302 const Matcher<NamedDecl> &Matcher,
1303 BoundNodesTreeBuilder *Builder) {
1304 auto Aliases = CompatibleAliases.find(InterfaceDecl);
1305 if (Aliases == CompatibleAliases.end())
1306 return false;
1307 for (const ObjCCompatibleAliasDecl *Alias : Aliases->second) {
1308 BoundNodesTreeBuilder Result(*Builder);
1309 if (Matcher.matches(*Alias, this, &Result)) {
1310 *Builder = std::move(Result);
1311 return true;
1312 }
1313 }
1314 return false;
1315 }
1316
1317 /// Bucket to record map.
1318 ///
1319 /// Used to get the appropriate bucket for each matcher.
1320 llvm::StringMap<llvm::TimeRecord> TimeByBucket;
1321
1322 const MatchFinder::MatchersByType *Matchers;
1323
1324 /// Filtered list of matcher indices for each matcher kind.
1325 ///
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
1328 /// node.
1329 /// We precalculate a list of matchers that pass the toplevel restrict check.
1330 llvm::DenseMap<ASTNodeKind, std::vector<unsigned short>> MatcherFiltersMap;
1331
1332 const MatchFinder::MatchFinderOptions &Options;
1333 ASTContext *ActiveASTContext;
1334
1335 // Maps a canonical type to its TypedefDecls.
1336 llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
1337
1338 // Maps an Objective-C interface to its ObjCCompatibleAliasDecls.
1339 llvm::DenseMap<const ObjCInterfaceDecl *,
1341 CompatibleAliases;
1342
1343 // Maps (matcher, node) -> the match result for memoization.
1344 typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
1345 MemoizationMap ResultCache;
1346};
1347
1348static CXXRecordDecl *
1349getAsCXXRecordDeclOrPrimaryTemplate(const Type *TypeNode) {
1350 if (auto *RD = TypeNode->getAsCXXRecordDecl())
1351 return RD;
1352
1353 // Find the innermost TemplateSpecializationType that isn't an alias template.
1354 auto *TemplateType = TypeNode->getAs<TemplateSpecializationType>();
1355 while (TemplateType && TemplateType->isTypeAlias())
1356 TemplateType =
1357 TemplateType->getAliasedType()->getAs<TemplateSpecializationType>();
1358
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.
1361 if (TemplateType)
1362 if (auto *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(
1363 TemplateType->getTemplateName().getAsTemplateDecl()))
1364 return ClassTemplate->getTemplatedDecl();
1365
1366 return nullptr;
1367}
1368
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.
1372bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
1373 const Matcher<NamedDecl> &Base,
1374 BoundNodesTreeBuilder *Builder,
1375 bool Directly) {
1377 return classIsDerivedFromImpl(Declaration, Base, Builder, Directly, Visited);
1378}
1379
1380bool 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())
1385 return false;
1386 if (!Visited.insert(Declaration).second)
1387 return false;
1388 for (const auto &It : Declaration->bases()) {
1389 const Type *TypeNode = It.getType().getTypePtr();
1390
1391 if (typeHasMatchingAlias(TypeNode, Base, Builder))
1392 return true;
1393
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);
1398 if (!ClassDecl)
1399 continue;
1400 if (ClassDecl == Declaration) {
1401 // This can happen for recursive template definitions.
1402 continue;
1403 }
1404 BoundNodesTreeBuilder Result(*Builder);
1405 if (Base.matches(*ClassDecl, this, &Result)) {
1406 *Builder = std::move(Result);
1407 return true;
1408 }
1409 if (!Directly &&
1410 classIsDerivedFromImpl(ClassDecl, Base, Builder, Directly, Visited))
1411 return true;
1412 }
1413 return false;
1414}
1415
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
1418// from itself.
1419bool 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))
1427 return true;
1428
1429 // Check if there are any matching type aliases.
1430 const Type *TypeNode = ClassDecl->getTypeForDecl();
1431 if (typeHasMatchingAlias(TypeNode, Base, Builder))
1432 return true;
1433
1434 if (Base.matches(*ClassDecl, this, Builder))
1435 return true;
1436
1437 // Not `return false` as a temporary workaround for PR43879.
1438 if (Directly)
1439 break;
1440 }
1441
1442 return false;
1443}
1444
1445bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
1446 if (!DeclNode) {
1447 return true;
1448 }
1449
1450 bool ScopedTraversal =
1451 TraversingASTNodeNotSpelledInSource || DeclNode->isImplicit();
1452 bool ScopedChildren = TraversingASTChildrenNotSpelledInSource;
1453
1454 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DeclNode)) {
1455 auto SK = CTSD->getSpecializationKind();
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;
1466 }
1467
1468 ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
1469 ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren);
1470
1471 match(*DeclNode);
1473}
1474
1475bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
1476 if (!StmtNode) {
1477 return true;
1478 }
1479 bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
1480 TraversingASTChildrenNotSpelledInSource;
1481
1482 ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
1483 match(*StmtNode);
1485}
1486
1487bool MatchASTVisitor::TraverseType(QualType TypeNode) {
1488 match(TypeNode);
1490}
1491
1492bool 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
1497 // each TypeLoc.
1498 match(TypeLocNode);
1499 match(TypeLocNode.getType());
1501}
1502
1503bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
1504 match(*NNS);
1506}
1507
1508bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
1509 NestedNameSpecifierLoc NNS) {
1510 if (!NNS)
1511 return true;
1512
1513 match(NNS);
1514
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());
1519 return
1521}
1522
1523bool MatchASTVisitor::TraverseConstructorInitializer(
1524 CXXCtorInitializer *CtorInit) {
1525 if (!CtorInit)
1526 return true;
1527
1528 bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
1529 TraversingASTChildrenNotSpelledInSource;
1530
1531 if (!CtorInit->isWritten())
1532 ScopedTraversal = true;
1533
1534 ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
1535
1536 match(*CtorInit);
1537
1539 CtorInit);
1540}
1541
1542bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
1543 match(Loc);
1545}
1546
1547bool MatchASTVisitor::TraverseAttr(Attr *AttrNode) {
1548 match(*AttrNode);
1550}
1551
1552class MatchASTConsumer : public ASTConsumer {
1553public:
1554 MatchASTConsumer(MatchFinder *Finder,
1555 MatchFinder::ParsingDoneTestCallback *ParsingDone)
1556 : Finder(Finder), ParsingDone(ParsingDone) {}
1557
1558private:
1559 void HandleTranslationUnit(ASTContext &Context) override {
1560 if (ParsingDone != nullptr) {
1561 ParsingDone->run();
1562 }
1563 Finder->matchAST(Context);
1564 }
1565
1566 MatchFinder *Finder;
1567 MatchFinder::ParsingDoneTestCallback *ParsingDone;
1568};
1569
1570} // end namespace
1571} // end namespace internal
1572
1574 ASTContext *Context)
1575 : Nodes(Nodes), Context(Context),
1576 SourceManager(&Context->getSourceManager()) {}
1577
1580
1582 : Options(std::move(Options)), ParsingDone(nullptr) {}
1583
1585
1587 MatchCallback *Action) {
1588 std::optional<TraversalKind> TK;
1589 if (Action)
1590 TK = Action->getCheckTraversalKind();
1591 if (TK)
1592 Matchers.DeclOrStmt.emplace_back(traverse(*TK, NodeMatch), Action);
1593 else
1594 Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
1595 Matchers.AllCallbacks.insert(Action);
1596}
1597
1599 MatchCallback *Action) {
1600 Matchers.Type.emplace_back(NodeMatch, Action);
1601 Matchers.AllCallbacks.insert(Action);
1602}
1603
1605 MatchCallback *Action) {
1606 std::optional<TraversalKind> TK;
1607 if (Action)
1608 TK = Action->getCheckTraversalKind();
1609 if (TK)
1610 Matchers.DeclOrStmt.emplace_back(traverse(*TK, NodeMatch), Action);
1611 else
1612 Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
1613 Matchers.AllCallbacks.insert(Action);
1614}
1615
1617 MatchCallback *Action) {
1618 Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action);
1619 Matchers.AllCallbacks.insert(Action);
1620}
1621
1623 MatchCallback *Action) {
1624 Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action);
1625 Matchers.AllCallbacks.insert(Action);
1626}
1627
1629 MatchCallback *Action) {
1630 Matchers.TypeLoc.emplace_back(NodeMatch, Action);
1631 Matchers.AllCallbacks.insert(Action);
1632}
1633
1635 MatchCallback *Action) {
1636 Matchers.CtorInit.emplace_back(NodeMatch, Action);
1637 Matchers.AllCallbacks.insert(Action);
1638}
1639
1641 MatchCallback *Action) {
1642 Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action);
1643 Matchers.AllCallbacks.insert(Action);
1644}
1645
1647 MatchCallback *Action) {
1648 Matchers.Attr.emplace_back(AttrMatch, Action);
1649 Matchers.AllCallbacks.insert(Action);
1650}
1651
1652bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
1653 MatchCallback *Action) {
1654 if (NodeMatch.canConvertTo<Decl>()) {
1655 addMatcher(NodeMatch.convertTo<Decl>(), Action);
1656 return true;
1657 } else if (NodeMatch.canConvertTo<QualType>()) {
1658 addMatcher(NodeMatch.convertTo<QualType>(), Action);
1659 return true;
1660 } else if (NodeMatch.canConvertTo<Stmt>()) {
1661 addMatcher(NodeMatch.convertTo<Stmt>(), Action);
1662 return true;
1663 } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) {
1664 addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action);
1665 return true;
1666 } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) {
1667 addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action);
1668 return true;
1669 } else if (NodeMatch.canConvertTo<TypeLoc>()) {
1670 addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
1671 return true;
1672 } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
1673 addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
1674 return true;
1675 } else if (NodeMatch.canConvertTo<TemplateArgumentLoc>()) {
1676 addMatcher(NodeMatch.convertTo<TemplateArgumentLoc>(), Action);
1677 return true;
1678 } else if (NodeMatch.canConvertTo<Attr>()) {
1679 addMatcher(NodeMatch.convertTo<Attr>(), Action);
1680 return true;
1681 }
1682 return false;
1683}
1684
1685std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
1686 return std::make_unique<internal::MatchASTConsumer>(this, ParsingDone);
1687}
1688
1690 internal::MatchASTVisitor Visitor(&Matchers, Options);
1691 Visitor.set_active_ast_context(&Context);
1692 Visitor.match(Node);
1693}
1694
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();
1702}
1703
1705 MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
1706 ParsingDone = NewParsingDone;
1707}
1708
1709StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
1710
1711std::optional<TraversalKind>
1713 return std::nullopt;
1714}
1715
1716} // end namespace ast_matchers
1717} // end namespace clang
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3443
NodeId Parent
Definition: ASTDiff.cpp:191
MatchType Type
BoundNodesTreeBuilder BoundNodes
BoundNodesTreeBuilder Nodes
DynTypedNode Node
#define IMPL(Index)
DynTypedMatcher::MatcherIDType MatcherID
llvm::PointerUnion< CMD_TYPES_1 > Node1
TraversalKind Traversal
llvm::PointerUnion< CMD_TYPES_0 > Node0
bool ResultOfMatch
StringRef P
const Decl * D
Expr * E
enum clang::sema::@1718::IndirectLocalPathEntry::EntryKind Kind
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:145
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
SourceLocation Loc
Definition: SemaObjC.cpp:759
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
Attr - This represents one attribute.
Definition: Attr.h:43
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2318
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
A dynamically typed AST node container.
static DynTypedNode create(const T &Node)
Creates a DynTypedNode from Node.
Expr * getNoexceptExpr() const
Return the expression inside noexcept(expression), or a null pointer if there is none (because the ex...
Definition: Type.h:5440
ArrayRef< QualType > exceptions() const
Definition: Type.h:5525
A C++ nested-name-specifier augmented with source location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
A (possibly-)qualified type.
Definition: Type.h:929
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...
bool TraverseType(QualType T)
Recursively visit a type, by dispatching to Traverse*Type() based on the argument's getTypeClass() pr...
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc)
Recursively visit a template argument location and dispatch to the appropriate method for the argumen...
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)
Recursively visit a C++ nested-name-specifier with location information.
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS)
Recursively visit a C++ nested-name-specifier.
bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue)
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
bool TraverseTypeLoc(TypeLoc TL)
Recursively visit a type with location, by dispatching to Traverse*TypeLoc() based on the argument ty...
bool TraverseAttr(Attr *At)
Recursively visit an attribute, by dispatching to Traverse*Attr() based on the argument's dynamic typ...
bool TraverseConstructorInitializer(CXXCtorInitializer *Init)
Recursively visit a constructor initializer.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
Definition: Stmt.h:84
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:524
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
const char * getTypeClassName() const
Definition: Type.cpp:3318
Maps string IDs to AST nodes matched by parts of a matcher.
Definition: ASTMatchers.h:109
internal::BoundNodesMap::IDToNodeMap IDToNodeMap
Type of mapping from binding identifiers to bound nodes.
Definition: ASTMatchers.h:123
Called when the Match registered for it was successfully found in the AST.
virtual std::optional< TraversalKind > getCheckTraversalKind() const
TraversalKind to use while matching and processing the result nodes.
virtual StringRef getID() const
An id used to group the matchers.
Called when parsing is finished. Intended for testing only.
MatchFinder(MatchFinderOptions Options=MatchFinderOptions())
bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
void addMatcher(const DeclarationMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
void match(const T &Node, ASTContext &Context)
Calls the registered callbacks on all matches on the given Node.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone)
Registers a callback to notify the end of parsing.
std::unique_ptr< clang::ASTConsumer > newASTConsumer()
Creates a clang ASTConsumer that finds all matches.
void matchAST(ASTContext &Context)
Finds all matches in the given AST.
#define USHRT_MAX
Definition: limits.h:62
#define INT_MAX
Definition: limits.h:50
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
internal::Matcher< QualType > TypeMatcher
Definition: ASTMatchers.h:145
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
Definition: ASTMatchers.h:143
internal::Matcher< NestedNameSpecifier > NestedNameSpecifierMatcher
Definition: ASTMatchers.h:147
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< CXXCtorInitializer > CXXCtorInitializerMatcher
Definition: ASTMatchers.h:150
internal::Matcher< Stmt > StatementMatcher
Definition: ASTMatchers.h:144
internal::Matcher< TypeLoc > TypeLocMatcher
Definition: ASTMatchers.h:146
internal::Matcher< TemplateArgumentLoc > TemplateArgumentLocMatcher
Definition: ASTMatchers.h:152
internal::Matcher< T > traverse(TraversalKind TK, const internal::Matcher< T > &InnerMatcher)
Causes all nested matchers to be matched with the specified traversal kind.
Definition: ASTMatchers.h:817
internal::Matcher< Attr > AttrMatcher
Definition: ASTMatchers.h:154
internal::Matcher< NestedNameSpecifierLoc > NestedNameSpecifierLocMatcher
Definition: ASTMatchers.h:148
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1171
llvm::cl::opt< std::string > Filter
The JSON file list parser is used to communicate input to InstallAPI.
@ Bind
'bind' clause, allowed on routine constructs.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
TraversalKind
Defines how we descend a level in the AST when we pass through expressions.
Definition: ASTTypeTraits.h:38
@ TK_AsIs
Will traverse all child nodes.
Definition: ASTTypeTraits.h:40
@ TK_IgnoreUnlessSpelledInSource
Ignore AST nodes not written in the source.
Definition: ASTTypeTraits.h:43
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
Definition: Specifiers.h:206
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
Definition: Specifiers.h:202
@ Other
Other implicit parameter.
MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context)