Coverage Report

Created: 2024-01-17 10:31

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