Coverage Report

Created: 2022-05-17 06:19

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