Coverage Report

Created: 2021-01-26 06:56

/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/Timer.h"
25
#include <deque>
26
#include <memory>
27
#include <set>
28
29
namespace clang {
30
namespace ast_matchers {
31
namespace internal {
32
namespace {
33
34
typedef MatchFinder::MatchCallback MatchCallback;
35
36
// The maximum number of memoization entries to store.
37
// 10k has been experimentally found to give a good trade-off
38
// of performance vs. memory consumption by running matcher
39
// that match on every statement over a very large codebase.
40
//
41
// FIXME: Do some performance optimization in general and
42
// revisit this number; also, put up micro-benchmarks that we can
43
// optimize this on.
44
static const unsigned MaxMemoizationEntries = 10000;
45
46
enum class MatchType {
47
  Ancestors,
48
49
  Descendants,
50
  Child,
51
};
52
53
// We use memoization to avoid running the same matcher on the same
54
// AST node twice.  This struct is the key for looking up match
55
// result.  It consists of an ID of the MatcherInterface (for
56
// identifying the matcher), a pointer to the AST node and the
57
// bound nodes before the matcher was executed.
58
//
59
// We currently only memoize on nodes whose pointers identify the
60
// nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
61
// For \c QualType and \c TypeLoc it is possible to implement
62
// generation of keys for each type.
63
// FIXME: Benchmark whether memoization of non-pointer typed nodes
64
// provides enough benefit for the additional amount of code.
65
struct MatchKey {
66
  DynTypedMatcher::MatcherIDType MatcherID;
67
  DynTypedNode Node;
68
  BoundNodesTreeBuilder BoundNodes;
69
  TraversalKind Traversal = TK_AsIs;
70
  MatchType Type;
71
72
137k
  bool operator<(const MatchKey &Other) const {
73
137k
    return std::tie(Traversal, Type, MatcherID, Node, BoundNodes) <
74
137k
           std::tie(Other.Traversal, Other.Type, Other.MatcherID, Other.Node,
75
137k
                    Other.BoundNodes);
76
137k
  }
77
};
78
79
// Used to store the result of a match and possibly bound nodes.
80
struct MemoizedMatchResult {
81
  bool ResultOfMatch;
82
  BoundNodesTreeBuilder Nodes;
83
};
84
85
// A RecursiveASTVisitor that traverses all children or all descendants of
86
// a node.
87
class MatchChildASTVisitor
88
    : public RecursiveASTVisitor<MatchChildASTVisitor> {
89
public:
90
  typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
91
92
  // Creates an AST visitor that matches 'matcher' on all children or
93
  // descendants of a traversed node. max_depth is the maximum depth
94
  // to traverse: use 1 for matching the children and INT_MAX for
95
  // matching the descendants.
96
  MatchChildASTVisitor(const DynTypedMatcher *Matcher, ASTMatchFinder *Finder,
97
                       BoundNodesTreeBuilder *Builder, int MaxDepth,
98
                       bool IgnoreImplicitChildren,
99
                       ASTMatchFinder::BindKind Bind)
100
      : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0),
101
        MaxDepth(MaxDepth), IgnoreImplicitChildren(IgnoreImplicitChildren),
102
15.3k
        Bind(Bind), Matches(false) {}
103
104
  // Returns true if a match is found in the subtree rooted at the
105
  // given AST node. This is done via a set of mutually recursive
106
  // functions. Here's how the recursion is done (the  *wildcard can
107
  // actually be Decl, Stmt, or Type):
108
  //
109
  //   - Traverse(node) calls BaseTraverse(node) when it needs
110
  //     to visit the descendants of node.
111
  //   - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
112
  //     Traverse*(c) for each child c of 'node'.
113
  //   - Traverse*(c) in turn calls Traverse(c), completing the
114
  //     recursion.
115
15.3k
  bool findMatch(const DynTypedNode &DynNode) {
116
15.3k
    reset();
117
15.3k
    if (const Decl *D = DynNode.get<Decl>())
118
9.43k
      traverse(*D);
119
5.91k
    else if (const Stmt *S = DynNode.get<Stmt>())
120
5.83k
      traverse(*S);
121
77
    else if (const NestedNameSpecifier *NNS =
122
5
             DynNode.get<NestedNameSpecifier>())
123
5
      traverse(*NNS);
124
72
    else if (const NestedNameSpecifierLoc *NNSLoc =
125
8
             DynNode.get<NestedNameSpecifierLoc>())
126
8
      traverse(*NNSLoc);
127
64
    else if (const QualType *Q = DynNode.get<QualType>())
128
44
      traverse(*Q);
129
20
    else if (const TypeLoc *T = DynNode.get<TypeLoc>())
130
20
      traverse(*T);
131
0
    else if (const auto *C = DynNode.get<CXXCtorInitializer>())
132
0
      traverse(*C);
133
0
    else if (const TemplateArgumentLoc *TALoc =
134
0
                 DynNode.get<TemplateArgumentLoc>())
135
0
      traverse(*TALoc);
136
    // FIXME: Add other base types after adding tests.
137
138
    // It's OK to always overwrite the bound nodes, as if there was
139
    // no match in this recursive branch, the result set is empty
140
    // anyway.
141
15.3k
    *Builder = ResultBindings;
142
143
15.3k
    return Matches;
144
15.3k
  }
145
146
  // The following are overriding methods from the base visitor class.
147
  // They are public only to allow CRTP to work. They are *not *part
148
  // of the public API of this class.
149
24.9k
  bool TraverseDecl(Decl *DeclNode) {
150
151
24.9k
    if (DeclNode && 
DeclNode->isImplicit()24.9k
&&
152
10.2k
        Finder->isTraversalIgnoringImplicitNodes())
153
52
      return baseTraverse(*DeclNode);
154
155
24.8k
    ScopedIncrement ScopedDepth(&CurrentDepth);
156
24.8k
    return (DeclNode == nullptr) || 
traverse(*DeclNode)24.8k
;
157
24.8k
  }
158
159
54.6k
  Stmt *getStmtToTraverse(Stmt *StmtNode) {
160
54.6k
    Stmt *StmtToTraverse = StmtNode;
161
54.6k
    if (auto *ExprNode = dyn_cast_or_null<Expr>(StmtNode)) {
162
39.6k
      auto *LambdaNode = dyn_cast_or_null<LambdaExpr>(StmtNode);
163
39.6k
      if (LambdaNode && 
Finder->isTraversalIgnoringImplicitNodes()136
)
164
1
        StmtToTraverse = LambdaNode;
165
39.6k
      else
166
39.6k
        StmtToTraverse =
167
39.6k
            Finder->getASTContext().getParentMapContext().traverseIgnored(
168
39.6k
                ExprNode);
169
39.6k
    }
170
54.6k
    return StmtToTraverse;
171
54.6k
  }
172
173
54.6k
  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) {
174
    // If we need to keep track of the depth, we can't perform data recursion.
175
54.6k
    if (CurrentDepth == 0 || 
(42.3k
CurrentDepth <= MaxDepth42.3k
&&
MaxDepth < INT_MAX41.0k
))
176
12.9k
      Queue = nullptr;
177
178
54.6k
    ScopedIncrement ScopedDepth(&CurrentDepth);
179
54.6k
    Stmt *StmtToTraverse = getStmtToTraverse(StmtNode);
180
54.6k
    if (!StmtToTraverse)
181
4.74k
      return true;
182
183
49.8k
    if (IgnoreImplicitChildren && 
isa<CXXDefaultArgExpr>(StmtNode)124
)
184
1
      return true;
185
186
49.8k
    if (!match(*StmtToTraverse))
187
1.39k
      return false;
188
48.4k
    return VisitorBase::TraverseStmt(StmtToTraverse, Queue);
189
48.4k
  }
190
  // We assume that the QualType and the contained type are on the same
191
  // hierarchy level. Thus, we try to match either of them.
192
3.62k
  bool TraverseType(QualType TypeNode) {
193
3.62k
    if (TypeNode.isNull())
194
736
      return true;
195
2.89k
    ScopedIncrement ScopedDepth(&CurrentDepth);
196
    // Match the Type.
197
2.89k
    if (!match(*TypeNode))
198
16
      return false;
199
    // The QualType is matched inside traverse.
200
2.87k
    return traverse(TypeNode);
201
2.87k
  }
202
  // We assume that the TypeLoc, contained QualType and contained Type all are
203
  // on the same hierarchy level. Thus, we try to match all of them.
204
20.3k
  bool TraverseTypeLoc(TypeLoc TypeLocNode) {
205
20.3k
    if (TypeLocNode.isNull())
206
0
      return true;
207
20.3k
    ScopedIncrement ScopedDepth(&CurrentDepth);
208
    // Match the Type.
209
20.3k
    if (!match(*TypeLocNode.getType()))
210
18
      return false;
211
    // Match the QualType.
212
20.3k
    if (!match(TypeLocNode.getType()))
213
9
      return false;
214
    // The TypeLoc is matched inside traverse.
215
20.3k
    return traverse(TypeLocNode);
216
20.3k
  }
217
9
  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
218
9
    ScopedIncrement ScopedDepth(&CurrentDepth);
219
9
    return (NNS == nullptr) || traverse(*NNS);
220
9
  }
221
40.5k
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
222
40.5k
    if (!NNS)
223
39.9k
      return true;
224
585
    ScopedIncrement ScopedDepth(&CurrentDepth);
225
585
    if (!match(*NNS.getNestedNameSpecifier()))
226
3
      return false;
227
582
    return traverse(NNS);
228
582
  }
229
157
  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
230
157
    if (!CtorInit)
231
0
      return true;
232
157
    ScopedIncrement ScopedDepth(&CurrentDepth);
233
157
    return traverse(*CtorInit);
234
157
  }
235
707
  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
236
707
    ScopedIncrement ScopedDepth(&CurrentDepth);
237
707
    return traverse(TAL);
238
707
  }
239
163
  bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) {
240
163
    if (!Finder->isTraversalIgnoringImplicitNodes())
241
150
      return VisitorBase::TraverseCXXForRangeStmt(Node);
242
13
    if (!Node)
243
0
      return true;
244
13
    ScopedIncrement ScopedDepth(&CurrentDepth);
245
13
    if (auto *Init = Node->getInit())
246
5
      if (!match(*Init))
247
1
        return false;
248
12
    if (!match(*Node->getLoopVariable()) || 
!match(*Node->getRangeInit())11
||
249
10
        !match(*Node->getBody()))
250
3
      return false;
251
9
    return VisitorBase::TraverseStmt(Node->getBody());
252
9
  }
253
40
  bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *Node) {
254
40
    if (!Finder->isTraversalIgnoringImplicitNodes())
255
19
      return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node);
256
21
    if (!Node)
257
0
      return true;
258
21
    ScopedIncrement ScopedDepth(&CurrentDepth);
259
260
21
    return match(*Node->getLHS()) && 
match(*Node->getRHS())17
;
261
21
  }
262
141
  bool TraverseLambdaExpr(LambdaExpr *Node) {
263
141
    if (!Finder->isTraversalIgnoringImplicitNodes())
264
135
      return VisitorBase::TraverseLambdaExpr(Node);
265
6
    if (!Node)
266
0
      return true;
267
6
    ScopedIncrement ScopedDepth(&CurrentDepth);
268
269
11
    for (unsigned I = 0, N = Node->capture_size(); I != N; 
++I5
) {
270
7
      const auto *C = Node->capture_begin() + I;
271
7
      if (!C->isExplicit())
272
0
        continue;
273
7
      if (Node->isInitCapture(C) && 
!match(*C->getCapturedVar())3
)
274
1
        return false;
275
6
      if (!match(*Node->capture_init_begin()[I]))
276
1
        return false;
277
6
    }
278
279
4
    if (const auto *TPL = Node->getTemplateParameterList()) {
280
2
      for (const auto *TP : *TPL) {
281
2
        if (!match(*TP))
282
1
          return false;
283
2
      }
284
2
    }
285
286
4
    
for (const auto *P : Node->getCallOperator()->parameters())3
{
287
4
      if (!match(*P))
288
1
        return false;
289
4
    }
290
291
2
    if (!match(*Node->getBody()))
292
1
      return false;
293
294
1
    return true;
295
1
  }
296
297
443
  bool shouldVisitTemplateInstantiations() const { return true; }
298
35.6k
  bool shouldVisitImplicitCode() const { return !IgnoreImplicitChildren; }
299
300
private:
301
  // Used for updating the depth during traversal.
302
  struct ScopedIncrement {
303
104k
    explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
304
104k
    ~ScopedIncrement() { --(*Depth); }
305
306
   private:
307
    int *Depth;
308
  };
309
310
  // Resets the state of this object.
311
15.3k
  void reset() {
312
15.3k
    Matches = false;
313
15.3k
    CurrentDepth = 0;
314
15.3k
  }
315
316
  // Forwards the call to the corresponding Traverse*() method in the
317
  // base visitor class.
318
31.9k
  bool baseTraverse(const Decl &DeclNode) {
319
31.9k
    return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
320
31.9k
  }
321
5.83k
  bool baseTraverse(const Stmt &StmtNode) {
322
5.83k
    return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
323
5.83k
  }
324
2.91k
  bool baseTraverse(QualType TypeNode) {
325
2.91k
    return VisitorBase::TraverseType(TypeNode);
326
2.91k
  }
327
20.2k
  bool baseTraverse(TypeLoc TypeLocNode) {
328
20.2k
    return VisitorBase::TraverseTypeLoc(TypeLocNode);
329
20.2k
  }
330
12
  bool baseTraverse(const NestedNameSpecifier &NNS) {
331
12
    return VisitorBase::TraverseNestedNameSpecifier(
332
12
        const_cast<NestedNameSpecifier*>(&NNS));
333
12
  }
334
583
  bool baseTraverse(NestedNameSpecifierLoc NNS) {
335
583
    return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
336
583
  }
337
147
  bool baseTraverse(const CXXCtorInitializer &CtorInit) {
338
147
    return VisitorBase::TraverseConstructorInitializer(
339
147
        const_cast<CXXCtorInitializer *>(&CtorInit));
340
147
  }
341
707
  bool baseTraverse(TemplateArgumentLoc TAL) {
342
707
    return VisitorBase::TraverseTemplateArgumentLoc(TAL);
343
707
  }
344
345
  // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
346
  //   0 < CurrentDepth <= MaxDepth.
347
  //
348
  // Returns 'true' if traversal should continue after this function
349
  // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
350
  template <typename T>
351
159k
  bool match(const T &Node) {
352
159k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth143k
) {
353
36.0k
      return true;
354
36.0k
    }
355
123k
    if (Bind != ASTMatchFinder::BK_All) {
356
44.5k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
44.5k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
4.04k
                           &RecursiveBuilder)) {
359
4.04k
        Matches = true;
360
4.04k
        ResultBindings.addMatch(RecursiveBuilder);
361
4.04k
        return false; // Abort as soon as a match is found.
362
4.04k
      }
363
78.4k
    } else {
364
78.4k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
78.4k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
1.04k
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
1.04k
        Matches = true;
369
1.04k
        ResultBindings.addMatch(RecursiveBuilder);
370
1.04k
      }
371
78.4k
    }
372
118k
    return true;
373
123k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::Decl>(clang::Decl const&)
Line
Count
Source
351
34.3k
  bool match(const T &Node) {
352
34.3k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth24.8k
) {
353
12.8k
      return true;
354
12.8k
    }
355
21.4k
    if (Bind != ASTMatchFinder::BK_All) {
356
12.1k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
12.1k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
2.45k
                           &RecursiveBuilder)) {
359
2.45k
        Matches = true;
360
2.45k
        ResultBindings.addMatch(RecursiveBuilder);
361
2.45k
        return false; // Abort as soon as a match is found.
362
2.45k
      }
363
9.35k
    } else {
364
9.35k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
9.35k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
269
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
269
        Matches = true;
369
269
        ResultBindings.addMatch(RecursiveBuilder);
370
269
      }
371
9.35k
    }
372
19.0k
    return true;
373
21.4k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::Stmt>(clang::Stmt const&)
Line
Count
Source
351
55.7k
  bool match(const T &Node) {
352
55.7k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth49.8k
) {
353
7.33k
      return true;
354
7.33k
    }
355
48.3k
    if (Bind != ASTMatchFinder::BK_All) {
356
13.7k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
13.7k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
1.39k
                           &RecursiveBuilder)) {
359
1.39k
        Matches = true;
360
1.39k
        ResultBindings.addMatch(RecursiveBuilder);
361
1.39k
        return false; // Abort as soon as a match is found.
362
1.39k
      }
363
34.6k
    } else {
364
34.6k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
34.6k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
752
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
752
        Matches = true;
369
752
        ResultBindings.addMatch(RecursiveBuilder);
370
752
      }
371
34.6k
    }
372
46.9k
    return true;
373
48.3k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::VarDecl>(clang::VarDecl const&)
Line
Count
Source
351
15
  bool match(const T &Node) {
352
15
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
353
0
      return true;
354
0
    }
355
15
    if (Bind != ASTMatchFinder::BK_All) {
356
15
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
15
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
2
                           &RecursiveBuilder)) {
359
2
        Matches = true;
360
2
        ResultBindings.addMatch(RecursiveBuilder);
361
2
        return false; // Abort as soon as a match is found.
362
2
      }
363
0
    } else {
364
0
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
0
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
0
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
0
        Matches = true;
369
0
        ResultBindings.addMatch(RecursiveBuilder);
370
0
      }
371
0
    }
372
13
    return true;
373
15
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::Expr>(clang::Expr const&)
Line
Count
Source
351
55
  bool match(const T &Node) {
352
55
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
353
0
      return true;
354
0
    }
355
55
    if (Bind != ASTMatchFinder::BK_All) {
356
55
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
55
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
10
                           &RecursiveBuilder)) {
359
10
        Matches = true;
360
10
        ResultBindings.addMatch(RecursiveBuilder);
361
10
        return false; // Abort as soon as a match is found.
362
10
      }
363
0
    } else {
364
0
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
0
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
0
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
0
        Matches = true;
369
0
        ResultBindings.addMatch(RecursiveBuilder);
370
0
      }
371
0
    }
372
45
    return true;
373
55
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::NestedNameSpecifier>(clang::NestedNameSpecifier const&)
Line
Count
Source
351
599
  bool match(const T &Node) {
352
599
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth594
) {
353
43
      return true;
354
43
    }
355
556
    if (Bind != ASTMatchFinder::BK_All) {
356
94
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
94
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
5
                           &RecursiveBuilder)) {
359
5
        Matches = true;
360
5
        ResultBindings.addMatch(RecursiveBuilder);
361
5
        return false; // Abort as soon as a match is found.
362
5
      }
363
462
    } else {
364
462
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
462
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
8
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
8
        Matches = true;
369
8
        ResultBindings.addMatch(RecursiveBuilder);
370
8
      }
371
462
    }
372
551
    return true;
373
556
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::Type>(clang::Type const&)
Line
Count
Source
351
23.2k
  bool match(const T &Node) {
352
23.2k
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
353
5.41k
      return true;
354
5.41k
    }
355
17.8k
    if (Bind != ASTMatchFinder::BK_All) {
356
6.28k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
6.28k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
34
                           &RecursiveBuilder)) {
359
34
        Matches = true;
360
34
        ResultBindings.addMatch(RecursiveBuilder);
361
34
        return false; // Abort as soon as a match is found.
362
34
      }
363
11.5k
    } else {
364
11.5k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
11.5k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
4
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
4
        Matches = true;
369
4
        ResultBindings.addMatch(RecursiveBuilder);
370
4
      }
371
11.5k
    }
372
17.8k
    return true;
373
17.8k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::QualType>(clang::QualType const&)
Line
Count
Source
351
23.2k
  bool match(const T &Node) {
352
23.2k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth23.2k
) {
353
5.45k
      return true;
354
5.45k
    }
355
17.8k
    if (Bind != ASTMatchFinder::BK_All) {
356
6.24k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
6.24k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
9
                           &RecursiveBuilder)) {
359
9
        Matches = true;
360
9
        ResultBindings.addMatch(RecursiveBuilder);
361
9
        return false; // Abort as soon as a match is found.
362
9
      }
363
11.5k
    } else {
364
11.5k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
11.5k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
4
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
4
        Matches = true;
369
4
        ResultBindings.addMatch(RecursiveBuilder);
370
4
      }
371
11.5k
    }
372
17.8k
    return true;
373
17.8k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::NamedDecl>(clang::NamedDecl const&)
Line
Count
Source
351
2
  bool match(const T &Node) {
352
2
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
353
0
      return true;
354
0
    }
355
2
    if (Bind != ASTMatchFinder::BK_All) {
356
2
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
2
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
1
                           &RecursiveBuilder)) {
359
1
        Matches = true;
360
1
        ResultBindings.addMatch(RecursiveBuilder);
361
1
        return false; // Abort as soon as a match is found.
362
1
      }
363
0
    } else {
364
0
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
0
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
0
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
0
        Matches = true;
369
0
        ResultBindings.addMatch(RecursiveBuilder);
370
0
      }
371
0
    }
372
1
    return true;
373
2
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::ParmVarDecl>(clang::ParmVarDecl const&)
Line
Count
Source
351
4
  bool match(const T &Node) {
352
4
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
353
0
      return true;
354
0
    }
355
4
    if (Bind != ASTMatchFinder::BK_All) {
356
4
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
4
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
1
                           &RecursiveBuilder)) {
359
1
        Matches = true;
360
1
        ResultBindings.addMatch(RecursiveBuilder);
361
1
        return false; // Abort as soon as a match is found.
362
1
      }
363
0
    } else {
364
0
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
0
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
0
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
0
        Matches = true;
369
0
        ResultBindings.addMatch(RecursiveBuilder);
370
0
      }
371
0
    }
372
3
    return true;
373
4
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc const&)
Line
Count
Source
351
590
  bool match(const T &Node) {
352
590
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth582
) {
353
43
      return true;
354
43
    }
355
547
    if (Bind != ASTMatchFinder::BK_All) {
356
87
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
87
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
7
                           &RecursiveBuilder)) {
359
7
        Matches = true;
360
7
        ResultBindings.addMatch(RecursiveBuilder);
361
7
        return false; // Abort as soon as a match is found.
362
7
      }
363
460
    } else {
364
460
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
460
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
8
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
8
        Matches = true;
369
8
        ResultBindings.addMatch(RecursiveBuilder);
370
8
      }
371
460
    }
372
540
    return true;
373
547
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::TypeLoc>(clang::TypeLoc const&)
Line
Count
Source
351
20.3k
  bool match(const T &Node) {
352
20.3k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth20.3k
) {
353
4.70k
      return true;
354
4.70k
    }
355
15.6k
    if (Bind != ASTMatchFinder::BK_All) {
356
5.92k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
5.92k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
114
                           &RecursiveBuilder)) {
359
114
        Matches = true;
360
114
        ResultBindings.addMatch(RecursiveBuilder);
361
114
        return false; // Abort as soon as a match is found.
362
114
      }
363
9.75k
    } else {
364
9.75k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
9.75k
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
4
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
4
        Matches = true;
369
4
        ResultBindings.addMatch(RecursiveBuilder);
370
4
      }
371
9.75k
    }
372
15.5k
    return true;
373
15.6k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::CXXCtorInitializer>(clang::CXXCtorInitializer const&)
Line
Count
Source
351
157
  bool match(const T &Node) {
352
157
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
353
7
      return true;
354
7
    }
355
150
    if (Bind != ASTMatchFinder::BK_All) {
356
24
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
24
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
10
                           &RecursiveBuilder)) {
359
10
        Matches = true;
360
10
        ResultBindings.addMatch(RecursiveBuilder);
361
10
        return false; // Abort as soon as a match is found.
362
10
      }
363
126
    } else {
364
126
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
126
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
0
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
0
        Matches = true;
369
0
        ResultBindings.addMatch(RecursiveBuilder);
370
0
      }
371
126
    }
372
140
    return true;
373
150
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::TemplateArgumentLoc>(clang::TemplateArgumentLoc const&)
Line
Count
Source
351
707
  bool match(const T &Node) {
352
707
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
353
243
      return true;
354
243
    }
355
464
    if (Bind != ASTMatchFinder::BK_All) {
356
29
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
357
29
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
358
0
                           &RecursiveBuilder)) {
359
0
        Matches = true;
360
0
        ResultBindings.addMatch(RecursiveBuilder);
361
0
        return false; // Abort as soon as a match is found.
362
0
      }
363
435
    } else {
364
435
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
365
435
      if (Matcher->matches(DynTypedNode::create(Node), Finder,
366
0
                           &RecursiveBuilder)) {
367
        // After the first match the matcher succeeds.
368
0
        Matches = true;
369
0
        ResultBindings.addMatch(RecursiveBuilder);
370
0
      }
371
435
    }
372
464
    return true;
373
464
  }
374
375
  // Traverses the subtree rooted at 'Node'; returns true if the
376
  // traversal should continue after this function returns.
377
  template <typename T>
378
64.9k
  bool traverse(const T &Node) {
379
64.9k
    static_assert(IsBaseType<T>::value,
380
64.9k
                  "traverse can only be instantiated with base type");
381
64.9k
    if (!match(Node))
382
2.58k
      return false;
383
62.3k
    return baseTraverse(Node);
384
62.3k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::Decl>(clang::Decl const&)
Line
Count
Source
378
34.3k
  bool traverse(const T &Node) {
379
34.3k
    static_assert(IsBaseType<T>::value,
380
34.3k
                  "traverse can only be instantiated with base type");
381
34.3k
    if (!match(Node))
382
2.45k
      return false;
383
31.8k
    return baseTraverse(Node);
384
31.8k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::Stmt>(clang::Stmt const&)
Line
Count
Source
378
5.83k
  bool traverse(const T &Node) {
379
5.83k
    static_assert(IsBaseType<T>::value,
380
5.83k
                  "traverse can only be instantiated with base type");
381
5.83k
    if (!match(Node))
382
0
      return false;
383
5.83k
    return baseTraverse(Node);
384
5.83k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::NestedNameSpecifier>(clang::NestedNameSpecifier const&)
Line
Count
Source
378
14
  bool traverse(const T &Node) {
379
14
    static_assert(IsBaseType<T>::value,
380
14
                  "traverse can only be instantiated with base type");
381
14
    if (!match(Node))
382
2
      return false;
383
12
    return baseTraverse(Node);
384
12
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc const&)
Line
Count
Source
378
590
  bool traverse(const T &Node) {
379
590
    static_assert(IsBaseType<T>::value,
380
590
                  "traverse can only be instantiated with base type");
381
590
    if (!match(Node))
382
7
      return false;
383
583
    return baseTraverse(Node);
384
583
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::QualType>(clang::QualType const&)
Line
Count
Source
378
2.91k
  bool traverse(const T &Node) {
379
2.91k
    static_assert(IsBaseType<T>::value,
380
2.91k
                  "traverse can only be instantiated with base type");
381
2.91k
    if (!match(Node))
382
0
      return false;
383
2.91k
    return baseTraverse(Node);
384
2.91k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::TypeLoc>(clang::TypeLoc const&)
Line
Count
Source
378
20.3k
  bool traverse(const T &Node) {
379
20.3k
    static_assert(IsBaseType<T>::value,
380
20.3k
                  "traverse can only be instantiated with base type");
381
20.3k
    if (!match(Node))
382
114
      return false;
383
20.2k
    return baseTraverse(Node);
384
20.2k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::CXXCtorInitializer>(clang::CXXCtorInitializer const&)
Line
Count
Source
378
157
  bool traverse(const T &Node) {
379
157
    static_assert(IsBaseType<T>::value,
380
157
                  "traverse can only be instantiated with base type");
381
157
    if (!match(Node))
382
10
      return false;
383
147
    return baseTraverse(Node);
384
147
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::TemplateArgumentLoc>(clang::TemplateArgumentLoc const&)
Line
Count
Source
378
707
  bool traverse(const T &Node) {
379
707
    static_assert(IsBaseType<T>::value,
380
707
                  "traverse can only be instantiated with base type");
381
707
    if (!match(Node))
382
0
      return false;
383
707
    return baseTraverse(Node);
384
707
  }
385
386
  const DynTypedMatcher *const Matcher;
387
  ASTMatchFinder *const Finder;
388
  BoundNodesTreeBuilder *const Builder;
389
  BoundNodesTreeBuilder ResultBindings;
390
  int CurrentDepth;
391
  const int MaxDepth;
392
  const bool IgnoreImplicitChildren;
393
  const ASTMatchFinder::BindKind Bind;
394
  bool Matches;
395
};
396
397
// Controls the outermost traversal of the AST and allows to match multiple
398
// matchers.
399
class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
400
                        public ASTMatchFinder {
401
public:
402
  MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
403
                  const MatchFinder::MatchFinderOptions &Options)
404
43.5k
      : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
405
406
43.5k
  ~MatchASTVisitor() override {
407
43.5k
    if (Options.CheckProfiling) {
408
1
      Options.CheckProfiling->Records = std::move(TimeByBucket);
409
1
    }
410
43.5k
  }
411
412
22.0k
  void onStartOfTranslationUnit() {
413
22.0k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
414
22.0k
    TimeBucketRegion Timer;
415
36.5k
    for (MatchCallback *MC : Matchers->AllCallbacks) {
416
36.5k
      if (EnableCheckProfiling)
417
1
        Timer.setBucket(&TimeByBucket[MC->getID()]);
418
36.5k
      MC->onStartOfTranslationUnit();
419
36.5k
    }
420
22.0k
  }
421
422
22.0k
  void onEndOfTranslationUnit() {
423
22.0k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
424
22.0k
    TimeBucketRegion Timer;
425
36.5k
    for (MatchCallback *MC : Matchers->AllCallbacks) {
426
36.5k
      if (EnableCheckProfiling)
427
1
        Timer.setBucket(&TimeByBucket[MC->getID()]);
428
36.5k
      MC->onEndOfTranslationUnit();
429
36.5k
    }
430
22.0k
  }
431
432
43.5k
  void set_active_ast_context(ASTContext *NewActiveASTContext) {
433
43.5k
    ActiveASTContext = NewActiveASTContext;
434
43.5k
  }
435
436
  // The following Visit*() and Traverse*() functions "override"
437
  // methods in RecursiveASTVisitor.
438
439
96.4k
  bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
440
    // When we see 'typedef A B', we add name 'B' to the set of names
441
    // A's canonical type maps to.  This is necessary for implementing
442
    // isDerivedFrom(x) properly, where x can be the name of the base
443
    // class or any of its aliases.
444
    //
445
    // In general, the is-alias-of (as defined by typedefs) relation
446
    // is tree-shaped, as you can typedef a type more than once.  For
447
    // example,
448
    //
449
    //   typedef A B;
450
    //   typedef A C;
451
    //   typedef C D;
452
    //   typedef C E;
453
    //
454
    // gives you
455
    //
456
    //   A
457
    //   |- B
458
    //   `- C
459
    //      |- D
460
    //      `- E
461
    //
462
    // It is wrong to assume that the relation is a chain.  A correct
463
    // implementation of isDerivedFrom() needs to recognize that B and
464
    // E are aliases, even though neither is a typedef of the other.
465
    // Therefore, we cannot simply walk through one typedef chain to
466
    // find out whether the type name matches.
467
96.4k
    const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
468
96.4k
    const Type *CanonicalType =  // root of the typedef tree
469
96.4k
        ActiveASTContext->getCanonicalType(TypeNode);
470
96.4k
    TypeAliases[CanonicalType].insert(DeclNode);
471
96.4k
    return true;
472
96.4k
  }
473
474
224
  bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
475
224
    const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface();
476
224
    CompatibleAliases[InterfaceDecl].insert(CAD);
477
224
    return true;
478
224
  }
479
480
  bool TraverseDecl(Decl *DeclNode);
481
  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
482
  bool TraverseType(QualType TypeNode);
483
  bool TraverseTypeLoc(TypeLoc TypeNode);
484
  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
485
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
486
  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
487
  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
488
489
93.2k
  bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
490
93.2k
    if (auto *RF = dyn_cast<CXXForRangeStmt>(S)) {
491
800
      for (auto *SubStmt : RF->children()) {
492
800
        if (SubStmt == RF->getInit() || 
SubStmt == RF->getLoopVarStmt()696
||
493
596
            SubStmt == RF->getRangeInit() || SubStmt == RF->getBody()) {
494
304
          TraverseStmt(SubStmt, Queue);
495
496
        } else {
496
496
          ASTNodeNotSpelledInSourceScope RAII(this, true);
497
496
          TraverseStmt(SubStmt, Queue);
498
496
        }
499
800
      }
500
100
      return true;
501
93.1k
    } else if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
502
173
      {
503
173
        ASTNodeNotAsIsSourceScope RAII(this, true);
504
173
        TraverseStmt(const_cast<Expr *>(RBO->getLHS()));
505
173
        TraverseStmt(const_cast<Expr *>(RBO->getRHS()));
506
173
      }
507
173
      {
508
173
        ASTNodeNotSpelledInSourceScope RAII(this, true);
509
173
        for (auto *SubStmt : RBO->children()) {
510
173
          TraverseStmt(SubStmt);
511
173
        }
512
173
      }
513
173
      return true;
514
92.9k
    } else if (auto *LE = dyn_cast<LambdaExpr>(S)) {
515
116
      for (auto I : llvm::zip(LE->captures(), LE->capture_inits())) {
516
116
        auto C = std::get<0>(I);
517
116
        ASTNodeNotSpelledInSourceScope RAII(
518
116
            this, TraversingASTNodeNotSpelledInSource || !C.isExplicit());
519
116
        TraverseLambdaCapture(LE, &C, std::get<1>(I));
520
116
      }
521
522
376
      {
523
376
        ASTNodeNotSpelledInSourceScope RAII(this, true);
524
376
        TraverseDecl(LE->getLambdaClass());
525
376
      }
526
376
      {
527
376
        ASTNodeNotAsIsSourceScope RAII(this, true);
528
529
        // We need to poke around to find the bits that might be explicitly
530
        // written.
531
376
        TypeLoc TL = LE->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
532
376
        FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
533
534
376
        if (auto *TPL = LE->getTemplateParameterList()) {
535
36
          for (NamedDecl *D : *TPL) {
536
36
            TraverseDecl(D);
537
36
          }
538
29
          if (Expr *RequiresClause = TPL->getRequiresClause()) {
539
0
            TraverseStmt(RequiresClause);
540
0
          }
541
29
        }
542
543
376
        if (LE->hasExplicitParameters()) {
544
          // Visit parameters.
545
230
          for (ParmVarDecl *Param : Proto.getParams())
546
206
            TraverseDecl(Param);
547
230
        }
548
549
376
        const auto *T = Proto.getTypePtr();
550
376
        for (const auto &E : T->exceptions())
551
0
          TraverseType(E);
552
553
376
        if (Expr *NE = T->getNoexceptExpr())
554
0
          TraverseStmt(NE, Queue);
555
556
376
        if (LE->hasExplicitResultType())
557
8
          TraverseTypeLoc(Proto.getReturnLoc());
558
376
        TraverseStmt(LE->getTrailingRequiresClause());
559
560
376
        TraverseStmt(LE->getBody());
561
376
      }
562
376
      return true;
563
376
    }
564
92.5k
    return RecursiveASTVisitor<MatchASTVisitor>::dataTraverseNode(S, Queue);
565
92.5k
  }
566
567
  // Matches children or descendants of 'Node' with 'BaseMatcher'.
568
  bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx,
569
                                  const DynTypedMatcher &Matcher,
570
                                  BoundNodesTreeBuilder *Builder, int MaxDepth,
571
19.5k
                                  BindKind Bind) {
572
    // For AST-nodes that don't have an identity, we can't memoize.
573
19.5k
    if (!Node.getMemoizationData() || 
!Builder->isComparable()19.4k
)
574
426
      return matchesRecursively(Node, Matcher, Builder, MaxDepth, Bind);
575
576
19.1k
    MatchKey Key;
577
19.1k
    Key.MatcherID = Matcher.getID();
578
19.1k
    Key.Node = Node;
579
    // Note that we key on the bindings *before* the match.
580
19.1k
    Key.BoundNodes = *Builder;
581
19.1k
    Key.Traversal = Ctx.getParentMapContext().getTraversalKind();
582
    // Memoize result even doing a single-level match, it might be expensive.
583
9.84k
    Key.Type = MaxDepth == 1 ? 
MatchType::Child9.27k
: MatchType::Descendants;
584
19.1k
    MemoizationMap::iterator I = ResultCache.find(Key);
585
19.1k
    if (I != ResultCache.end()) {
586
4.19k
      *Builder = I->second.Nodes;
587
4.19k
      return I->second.ResultOfMatch;
588
4.19k
    }
589
590
14.9k
    MemoizedMatchResult Result;
591
14.9k
    Result.Nodes = *Builder;
592
14.9k
    Result.ResultOfMatch =
593
14.9k
        matchesRecursively(Node, Matcher, &Result.Nodes, MaxDepth, Bind);
594
595
14.9k
    MemoizedMatchResult &CachedResult = ResultCache[Key];
596
14.9k
    CachedResult = std::move(Result);
597
598
14.9k
    *Builder = CachedResult.Nodes;
599
14.9k
    return CachedResult.ResultOfMatch;
600
14.9k
  }
601
602
  // Matches children or descendants of 'Node' with 'BaseMatcher'.
603
  bool matchesRecursively(const DynTypedNode &Node,
604
                          const DynTypedMatcher &Matcher,
605
                          BoundNodesTreeBuilder *Builder, int MaxDepth,
606
15.3k
                          BindKind Bind) {
607
15.3k
    bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
608
12.7k
                           TraversingASTChildrenNotSpelledInSource;
609
610
15.3k
    bool IgnoreImplicitChildren = false;
611
612
15.3k
    if (isTraversalIgnoringImplicitNodes()) {
613
95
      IgnoreImplicitChildren = true;
614
95
    }
615
616
15.3k
    ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
617
618
15.3k
    MatchChildASTVisitor Visitor(&Matcher, this, Builder, MaxDepth,
619
15.3k
                                 IgnoreImplicitChildren, Bind);
620
15.3k
    return Visitor.findMatch(Node);
621
15.3k
  }
622
623
  bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
624
                          const Matcher<NamedDecl> &Base,
625
                          BoundNodesTreeBuilder *Builder,
626
                          bool Directly) override;
627
628
  bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
629
                              const Matcher<NamedDecl> &Base,
630
                              BoundNodesTreeBuilder *Builder,
631
                              bool Directly) override;
632
633
  // Implements ASTMatchFinder::matchesChildOf.
634
  bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
635
                      const DynTypedMatcher &Matcher,
636
9.61k
                      BoundNodesTreeBuilder *Builder, BindKind Bind) override {
637
9.61k
    if (ResultCache.size() > MaxMemoizationEntries)
638
0
      ResultCache.clear();
639
9.61k
    return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, Bind);
640
9.61k
  }
641
  // Implements ASTMatchFinder::matchesDescendantOf.
642
  bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
643
                           const DynTypedMatcher &Matcher,
644
                           BoundNodesTreeBuilder *Builder,
645
9.93k
                           BindKind Bind) override {
646
9.93k
    if (ResultCache.size() > MaxMemoizationEntries)
647
0
      ResultCache.clear();
648
9.93k
    return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, INT_MAX,
649
9.93k
                                      Bind);
650
9.93k
  }
651
  // Implements ASTMatchFinder::matchesAncestorOf.
652
  bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
653
                         const DynTypedMatcher &Matcher,
654
                         BoundNodesTreeBuilder *Builder,
655
2.96k
                         AncestorMatchMode MatchMode) override {
656
    // Reset the cache outside of the recursive call to make sure we
657
    // don't invalidate any iterators.
658
2.96k
    if (ResultCache.size() > MaxMemoizationEntries)
659
0
      ResultCache.clear();
660
2.96k
    if (MatchMode == AncestorMatchMode::AMM_ParentOnly)
661
840
      return matchesParentOf(Node, Matcher, Builder);
662
2.12k
    return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
663
2.12k
  }
664
665
  // Matches all registered matchers on the given node and calls the
666
  // result callback for every node that matches.
667
21.5k
  void match(const DynTypedNode &Node) {
668
    // FIXME: Improve this with a switch or a visitor pattern.
669
21.5k
    if (auto *N = Node.get<Decl>()) {
670
2.42k
      match(*N);
671
19.0k
    } else if (auto *N = Node.get<Stmt>()) {
672
19.0k
      match(*N);
673
8
    } else if (auto *N = Node.get<Type>()) {
674
0
      match(*N);
675
8
    } else if (auto *N = Node.get<QualType>()) {
676
6
      match(*N);
677
2
    } else if (auto *N = Node.get<NestedNameSpecifier>()) {
678
0
      match(*N);
679
2
    } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
680
0
      match(*N);
681
2
    } else if (auto *N = Node.get<TypeLoc>()) {
682
2
      match(*N);
683
0
    } else if (auto *N = Node.get<CXXCtorInitializer>()) {
684
0
      match(*N);
685
0
    } else if (auto *N = Node.get<TemplateArgumentLoc>()) {
686
0
      match(*N);
687
0
    }
688
21.5k
  }
689
690
864k
  template <typename T> void match(const T &Node) {
691
864k
    matchDispatch(&Node);
692
864k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::Decl>(clang::Decl const&)
Line
Count
Source
690
263k
  template <typename T> void match(const T &Node) {
691
263k
    matchDispatch(&Node);
692
263k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::Stmt>(clang::Stmt const&)
Line
Count
Source
690
112k
  template <typename T> void match(const T &Node) {
691
112k
    matchDispatch(&Node);
692
112k
  }
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
690
254k
  template <typename T> void match(const T &Node) {
691
254k
    matchDispatch(&Node);
692
254k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::NestedNameSpecifier>(clang::NestedNameSpecifier const&)
Line
Count
Source
690
1.53k
  template <typename T> void match(const T &Node) {
691
1.53k
    matchDispatch(&Node);
692
1.53k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc const&)
Line
Count
Source
690
1.53k
  template <typename T> void match(const T &Node) {
691
1.53k
    matchDispatch(&Node);
692
1.53k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::TypeLoc>(clang::TypeLoc const&)
Line
Count
Source
690
225k
  template <typename T> void match(const T &Node) {
691
225k
    matchDispatch(&Node);
692
225k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::CXXCtorInitializer>(clang::CXXCtorInitializer const&)
Line
Count
Source
690
1.54k
  template <typename T> void match(const T &Node) {
691
1.54k
    matchDispatch(&Node);
692
1.54k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::TemplateArgumentLoc>(clang::TemplateArgumentLoc const&)
Line
Count
Source
690
4.17k
  template <typename T> void match(const T &Node) {
691
4.17k
    matchDispatch(&Node);
692
4.17k
  }
693
694
  // Implements ASTMatchFinder::getASTContext.
695
3.14M
  ASTContext &getASTContext() const override { return *ActiveASTContext; }
696
697
8.09k
  bool shouldVisitTemplateInstantiations() const { return true; }
698
292k
  bool shouldVisitImplicitCode() const { return true; }
699
700
66.5k
  bool IsMatchingInASTNodeNotSpelledInSource() const override {
701
66.5k
    return TraversingASTNodeNotSpelledInSource;
702
66.5k
  }
703
261k
  bool isMatchingChildrenNotSpelledInSource() const override {
704
261k
    return TraversingASTChildrenNotSpelledInSource;
705
261k
  }
706
523k
  void setMatchingChildrenNotSpelledInSource(bool Set) override {
707
523k
    TraversingASTChildrenNotSpelledInSource = Set;
708
523k
  }
709
710
695k
  bool IsMatchingInASTNodeNotAsIs() const override {
711
695k
    return TraversingASTNodeNotAsIs;
712
695k
  }
713
714
2.48k
  bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
715
2.48k
    ASTNodeNotSpelledInSourceScope RAII(this, true);
716
2.48k
    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
717
2.48k
        D);
718
2.48k
  }
719
720
364
  bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
721
364
    ASTNodeNotSpelledInSourceScope RAII(this, true);
722
364
    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
723
364
        D);
724
364
  }
725
726
1.74k
  bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
727
1.74k
    ASTNodeNotSpelledInSourceScope RAII(this, true);
728
1.74k
    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
729
1.74k
        D);
730
1.74k
  }
731
732
private:
733
  bool TraversingASTNodeNotSpelledInSource = false;
734
  bool TraversingASTNodeNotAsIs = false;
735
  bool TraversingASTChildrenNotSpelledInSource = false;
736
737
  struct ASTNodeNotSpelledInSourceScope {
738
    ASTNodeNotSpelledInSourceScope(MatchASTVisitor *V, bool B)
739
376k
        : MV(V), MB(V->TraversingASTNodeNotSpelledInSource) {
740
376k
      V->TraversingASTNodeNotSpelledInSource = B;
741
376k
    }
742
376k
    ~ASTNodeNotSpelledInSourceScope() {
743
376k
      MV->TraversingASTNodeNotSpelledInSource = MB;
744
376k
    }
745
746
  private:
747
    MatchASTVisitor *MV;
748
    bool MB;
749
  };
750
751
  struct ASTNodeNotAsIsSourceScope {
752
    ASTNodeNotAsIsSourceScope(MatchASTVisitor *V, bool B)
753
549
        : MV(V), MB(V->TraversingASTNodeNotAsIs) {
754
549
      V->TraversingASTNodeNotAsIs = B;
755
549
    }
756
549
    ~ASTNodeNotAsIsSourceScope() { MV->TraversingASTNodeNotAsIs = MB; }
757
758
  private:
759
    MatchASTVisitor *MV;
760
    bool MB;
761
  };
762
763
  class TimeBucketRegion {
764
  public:
765
621k
    TimeBucketRegion() : Bucket(nullptr) {}
766
621k
    ~TimeBucketRegion() { setBucket(nullptr); }
767
768
    /// Start timing for \p NewBucket.
769
    ///
770
    /// If there was a bucket already set, it will finish the timing for that
771
    /// other bucket.
772
    /// \p NewBucket will be timed until the next call to \c setBucket() or
773
    /// until the \c TimeBucketRegion is destroyed.
774
    /// If \p NewBucket is the same as the currently timed bucket, this call
775
    /// does nothing.
776
621k
    void setBucket(llvm::TimeRecord *NewBucket) {
777
621k
      if (Bucket != NewBucket) {
778
18
        auto Now = llvm::TimeRecord::getCurrentTime(true);
779
18
        if (Bucket)
780
9
          *Bucket += Now;
781
18
        if (NewBucket)
782
9
          *NewBucket -= Now;
783
18
        Bucket = NewBucket;
784
18
      }
785
621k
    }
786
787
  private:
788
    llvm::TimeRecord *Bucket;
789
  };
790
791
  /// Runs all the \p Matchers on \p Node.
792
  ///
793
  /// Used by \c matchDispatch() below.
794
  template <typename T, typename MC>
795
488k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
796
488k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
797
488k
    TimeBucketRegion Timer;
798
17.6k
    for (const auto &MP : Matchers) {
799
17.6k
      if (EnableCheckProfiling)
800
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
801
17.6k
      BoundNodesTreeBuilder Builder;
802
17.6k
      if (MP.first.matches(Node, this, &Builder)) {
803
2.42k
        MatchVisitor Visitor(ActiveASTContext, MP.second);
804
2.42k
        Builder.visitMatches(&Visitor);
805
2.42k
      }
806
17.6k
    }
807
488k
  }
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
795
254k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
796
254k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
797
254k
    TimeBucketRegion Timer;
798
14.9k
    for (const auto &MP : Matchers) {
799
14.9k
      if (EnableCheckProfiling)
800
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
801
14.9k
      BoundNodesTreeBuilder Builder;
802
14.9k
      if (MP.first.matches(Node, this, &Builder)) {
803
1.57k
        MatchVisitor Visitor(ActiveASTContext, MP.second);
804
1.57k
        Builder.visitMatches(&Visitor);
805
1.57k
      }
806
14.9k
    }
807
254k
  }
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
795
1.53k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
796
1.53k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
797
1.53k
    TimeBucketRegion Timer;
798
308
    for (const auto &MP : Matchers) {
799
308
      if (EnableCheckProfiling)
800
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
801
308
      BoundNodesTreeBuilder Builder;
802
308
      if (MP.first.matches(Node, this, &Builder)) {
803
188
        MatchVisitor Visitor(ActiveASTContext, MP.second);
804
188
        Builder.visitMatches(&Visitor);
805
188
      }
806
308
    }
807
1.53k
  }
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
795
1.53k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
796
1.53k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
797
1.53k
    TimeBucketRegion Timer;
798
130
    for (const auto &MP : Matchers) {
799
130
      if (EnableCheckProfiling)
800
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
801
130
      BoundNodesTreeBuilder Builder;
802
130
      if (MP.first.matches(Node, this, &Builder)) {
803
52
        MatchVisitor Visitor(ActiveASTContext, MP.second);
804
52
        Builder.visitMatches(&Visitor);
805
52
      }
806
130
    }
807
1.53k
  }
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
795
225k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
796
225k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
797
225k
    TimeBucketRegion Timer;
798
2.18k
    for (const auto &MP : Matchers) {
799
2.18k
      if (EnableCheckProfiling)
800
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
801
2.18k
      BoundNodesTreeBuilder Builder;
802
2.18k
      if (MP.first.matches(Node, this, &Builder)) {
803
576
        MatchVisitor Visitor(ActiveASTContext, MP.second);
804
576
        Builder.visitMatches(&Visitor);
805
576
      }
806
2.18k
    }
807
225k
  }
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
795
1.54k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
796
1.54k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
797
1.54k
    TimeBucketRegion Timer;
798
61
    for (const auto &MP : Matchers) {
799
61
      if (EnableCheckProfiling)
800
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
801
61
      BoundNodesTreeBuilder Builder;
802
61
      if (MP.first.matches(Node, this, &Builder)) {
803
25
        MatchVisitor Visitor(ActiveASTContext, MP.second);
804
25
        Builder.visitMatches(&Visitor);
805
25
      }
806
61
    }
807
1.54k
  }
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
795
4.17k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
796
4.17k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
797
4.17k
    TimeBucketRegion Timer;
798
6
    for (const auto &MP : Matchers) {
799
6
      if (EnableCheckProfiling)
800
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
801
6
      BoundNodesTreeBuilder Builder;
802
6
      if (MP.first.matches(Node, this, &Builder)) {
803
6
        MatchVisitor Visitor(ActiveASTContext, MP.second);
804
6
        Builder.visitMatches(&Visitor);
805
6
      }
806
6
    }
807
4.17k
  }
808
809
375k
  void matchWithFilter(const DynTypedNode &DynNode) {
810
375k
    auto Kind = DynNode.getNodeKind();
811
375k
    auto it = MatcherFiltersMap.find(Kind);
812
375k
    const auto &Filter =
813
199k
        it != MatcherFiltersMap.end() ? it->second : 
getFilterForKind(Kind)176k
;
814
815
375k
    if (Filter.empty())
816
287k
      return;
817
818
88.3k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
819
88.3k
    TimeBucketRegion Timer;
820
88.3k
    auto &Matchers = this->Matchers->DeclOrStmt;
821
129k
    for (unsigned short I : Filter) {
822
129k
      auto &MP = Matchers[I];
823
129k
      if (EnableCheckProfiling)
824
7
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
825
129k
      BoundNodesTreeBuilder Builder;
826
129k
      if (MP.first.matches(DynNode, this, &Builder)) {
827
29.3k
        MatchVisitor Visitor(ActiveASTContext, MP.second);
828
29.3k
        Builder.visitMatches(&Visitor);
829
29.3k
      }
830
129k
    }
831
88.3k
  }
832
833
176k
  const std::vector<unsigned short> &getFilterForKind(ASTNodeKind Kind) {
834
176k
    auto &Filter = MatcherFiltersMap[Kind];
835
176k
    auto &Matchers = this->Matchers->DeclOrStmt;
836
176k
    assert((Matchers.size() < USHRT_MAX) && "Too many matchers.");
837
438k
    for (unsigned I = 0, E = Matchers.size(); I != E; 
++I262k
) {
838
262k
      if (Matchers[I].first.canMatchNodesOfKind(Kind)) {
839
64.5k
        Filter.push_back(I);
840
64.5k
      }
841
262k
    }
842
176k
    return Filter;
843
176k
  }
844
845
  /// @{
846
  /// Overloads to pair the different node types to their matchers.
847
263k
  void matchDispatch(const Decl *Node) {
848
263k
    return matchWithFilter(DynTypedNode::create(*Node));
849
263k
  }
850
112k
  void matchDispatch(const Stmt *Node) {
851
112k
    return matchWithFilter(DynTypedNode::create(*Node));
852
112k
  }
853
854
0
  void matchDispatch(const Type *Node) {
855
0
    matchWithoutFilter(QualType(Node, 0), Matchers->Type);
856
0
  }
857
225k
  void matchDispatch(const TypeLoc *Node) {
858
225k
    matchWithoutFilter(*Node, Matchers->TypeLoc);
859
225k
  }
860
254k
  void matchDispatch(const QualType *Node) {
861
254k
    matchWithoutFilter(*Node, Matchers->Type);
862
254k
  }
863
1.53k
  void matchDispatch(const NestedNameSpecifier *Node) {
864
1.53k
    matchWithoutFilter(*Node, Matchers->NestedNameSpecifier);
865
1.53k
  }
866
1.53k
  void matchDispatch(const NestedNameSpecifierLoc *Node) {
867
1.53k
    matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
868
1.53k
  }
869
1.54k
  void matchDispatch(const CXXCtorInitializer *Node) {
870
1.54k
    matchWithoutFilter(*Node, Matchers->CtorInit);
871
1.54k
  }
872
4.17k
  void matchDispatch(const TemplateArgumentLoc *Node) {
873
4.17k
    matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc);
874
4.17k
  }
875
0
  void matchDispatch(const void *) { /* Do nothing. */ }
876
  /// @}
877
878
  // Returns whether a direct parent of \p Node matches \p Matcher.
879
  // Unlike matchesAnyAncestorOf there's no memoization: it doesn't save much.
880
  bool matchesParentOf(const DynTypedNode &Node, const DynTypedMatcher &Matcher,
881
840
                       BoundNodesTreeBuilder *Builder) {
882
852
    for (const auto &Parent : ActiveASTContext->getParents(Node)) {
883
852
      BoundNodesTreeBuilder BuilderCopy = *Builder;
884
852
      if (Matcher.matches(Parent, this, &BuilderCopy)) {
885
485
        *Builder = std::move(BuilderCopy);
886
485
        return true;
887
485
      }
888
852
    }
889
355
    return false;
890
840
  }
891
892
  // Returns whether an ancestor of \p Node matches \p Matcher.
893
  //
894
  // The order of matching (which can lead to different nodes being bound in
895
  // case there are multiple matches) is breadth first search.
896
  //
897
  // To allow memoization in the very common case of having deeply nested
898
  // expressions inside a template function, we first walk up the AST, memoizing
899
  // the result of the match along the way, as long as there is only a single
900
  // parent.
901
  //
902
  // Once there are multiple parents, the breadth first search order does not
903
  // allow simple memoization on the ancestors. Thus, we only memoize as long
904
  // as there is a single parent.
905
  //
906
  // We avoid a recursive implementation to prevent excessive stack use on
907
  // very deep ASTs (similarly to RecursiveASTVisitor's data recursion).
908
  bool matchesAnyAncestorOf(DynTypedNode Node, ASTContext &Ctx,
909
                            const DynTypedMatcher &Matcher,
910
2.12k
                            BoundNodesTreeBuilder *Builder) {
911
912
    // Memoization keys that can be updated with the result.
913
    // These are the memoizable nodes in the chain of unique parents, which
914
    // terminates when a node has multiple parents, or matches, or is the root.
915
2.12k
    std::vector<MatchKey> Keys;
916
    // When returning, update the memoization cache.
917
2.12k
    auto Finish = [&](bool Matched) {
918
6.46k
      for (const auto &Key : Keys) {
919
6.46k
        MemoizedMatchResult &CachedResult = ResultCache[Key];
920
6.46k
        CachedResult.ResultOfMatch = Matched;
921
6.46k
        CachedResult.Nodes = *Builder;
922
6.46k
      }
923
2.12k
      return Matched;
924
2.12k
    };
925
926
    // Loop while there's a single parent and we want to attempt memoization.
927
2.12k
    DynTypedNodeList Parents{ArrayRef<DynTypedNode>()}; // after loop: size != 1
928
7.37k
    for (;;) {
929
      // A cache key only makes sense if memoization is possible.
930
7.37k
      if (Builder->isComparable()) {
931
7.25k
        Keys.emplace_back();
932
7.25k
        Keys.back().MatcherID = Matcher.getID();
933
7.25k
        Keys.back().Node = Node;
934
7.25k
        Keys.back().BoundNodes = *Builder;
935
7.25k
        Keys.back().Traversal = Ctx.getParentMapContext().getTraversalKind();
936
7.25k
        Keys.back().Type = MatchType::Ancestors;
937
938
        // Check the cache.
939
7.25k
        MemoizationMap::iterator I = ResultCache.find(Keys.back());
940
7.25k
        if (I != ResultCache.end()) {
941
796
          Keys.pop_back(); // Don't populate the cache for the matching node!
942
796
          *Builder = I->second.Nodes;
943
796
          return Finish(I->second.ResultOfMatch);
944
796
        }
945
6.58k
      }
946
947
6.58k
      Parents = ActiveASTContext->getParents(Node);
948
      // Either no parents or multiple parents: leave chain+memoize mode and
949
      // enter bfs+forgetful mode.
950
6.58k
      if (Parents.size() != 1)
951
902
        break;
952
953
      // Check the next parent.
954
5.67k
      Node = *Parents.begin();
955
5.67k
      BoundNodesTreeBuilder BuilderCopy = *Builder;
956
5.67k
      if (Matcher.matches(Node, this, &BuilderCopy)) {
957
422
        *Builder = std::move(BuilderCopy);
958
422
        return Finish(true);
959
422
      }
960
5.67k
    }
961
    // We reached the end of the chain.
962
963
902
    if (Parents.empty()) {
964
      // Nodes may have no parents if:
965
      //  a) the node is the TranslationUnitDecl
966
      //  b) we have a limited traversal scope that excludes the parent edges
967
      //  c) there is a bug in the AST, and the node is not reachable
968
      // Usually the traversal scope is the whole AST, which precludes b.
969
      // Bugs are common enough that it's worthwhile asserting when we can.
970
883
#ifndef NDEBUG
971
883
      if (!Node.get<TranslationUnitDecl>() &&
972
          /* Traversal scope is full AST if any of the bounds are the TU */
973
0
          llvm::any_of(ActiveASTContext->getTraversalScope(), [](Decl *D) {
974
0
            return D->getKind() == Decl::TranslationUnit;
975
0
          })) {
976
0
        llvm::errs() << "Tried to match orphan node:\n";
977
0
        Node.dump(llvm::errs(), *ActiveASTContext);
978
0
        llvm_unreachable("Parent map should be complete!");
979
0
      }
980
19
#endif
981
19
    } else {
982
19
      assert(Parents.size() > 1);
983
      // BFS starting from the parents not yet considered.
984
      // Memoization of newly visited nodes is not possible (but we still update
985
      // results for the elements in the chain we found above).
986
19
      std::deque<DynTypedNode> Queue(Parents.begin(), Parents.end());
987
19
      llvm::DenseSet<const void *> Visited;
988
62
      while (!Queue.empty()) {
989
60
        BoundNodesTreeBuilder BuilderCopy = *Builder;
990
60
        if (Matcher.matches(Queue.front(), this, &BuilderCopy)) {
991
17
          *Builder = std::move(BuilderCopy);
992
17
          return Finish(true);
993
17
        }
994
43
        for (const auto &Parent : ActiveASTContext->getParents(Queue.front())) {
995
          // Make sure we do not visit the same node twice.
996
          // Otherwise, we'll visit the common ancestors as often as there
997
          // are splits on the way down.
998
41
          if (Visited.insert(Parent.getMemoizationData()).second)
999
38
            Queue.push_back(Parent);
1000
41
        }
1001
43
        Queue.pop_front();
1002
43
      }
1003
19
    }
1004
885
    return Finish(false);
1005
902
  }
1006
1007
  // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
1008
  // the aggregated bound nodes for each match.
1009
  class MatchVisitor : public BoundNodesTreeBuilder::Visitor {
1010
  public:
1011
    MatchVisitor(ASTContext* Context,
1012
                 MatchFinder::MatchCallback* Callback)
1013
      : Context(Context),
1014
31.7k
        Callback(Callback) {}
1015
1016
32.1k
    void visitMatch(const BoundNodes& BoundNodesView) override {
1017
32.1k
      Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
1018
32.1k
    }
1019
1020
  private:
1021
    ASTContext* Context;
1022
    MatchFinder::MatchCallback* Callback;
1023
  };
1024
1025
  // Returns true if 'TypeNode' has an alias that matches the given matcher.
1026
  bool typeHasMatchingAlias(const Type *TypeNode,
1027
                            const Matcher<NamedDecl> &Matcher,
1028
4.07k
                            BoundNodesTreeBuilder *Builder) {
1029
4.07k
    const Type *const CanonicalType =
1030
4.07k
      ActiveASTContext->getCanonicalType(TypeNode);
1031
4.07k
    auto Aliases = TypeAliases.find(CanonicalType);
1032
4.07k
    if (Aliases == TypeAliases.end())
1033
3.46k
      return false;
1034
820
    
for (const TypedefNameDecl *Alias : Aliases->second)610
{
1035
820
      BoundNodesTreeBuilder Result(*Builder);
1036
820
      if (Matcher.matches(*Alias, this, &Result)) {
1037
270
        *Builder = std::move(Result);
1038
270
        return true;
1039
270
      }
1040
820
    }
1041
340
    return false;
1042
610
  }
1043
1044
  bool
1045
  objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl *InterfaceDecl,
1046
                                         const Matcher<NamedDecl> &Matcher,
1047
812
                                         BoundNodesTreeBuilder *Builder) {
1048
812
    auto Aliases = CompatibleAliases.find(InterfaceDecl);
1049
812
    if (Aliases == CompatibleAliases.end())
1050
476
      return false;
1051
336
    for (const ObjCCompatibleAliasDecl *Alias : Aliases->second) {
1052
336
      BoundNodesTreeBuilder Result(*Builder);
1053
336
      if (Matcher.matches(*Alias, this, &Result)) {
1054
168
        *Builder = std::move(Result);
1055
168
        return true;
1056
168
      }
1057
336
    }
1058
168
    return false;
1059
336
  }
1060
1061
  /// Bucket to record map.
1062
  ///
1063
  /// Used to get the appropriate bucket for each matcher.
1064
  llvm::StringMap<llvm::TimeRecord> TimeByBucket;
1065
1066
  const MatchFinder::MatchersByType *Matchers;
1067
1068
  /// Filtered list of matcher indices for each matcher kind.
1069
  ///
1070
  /// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
1071
  /// kind (and derived kinds) so it is a waste to try every matcher on every
1072
  /// node.
1073
  /// We precalculate a list of matchers that pass the toplevel restrict check.
1074
  llvm::DenseMap<ASTNodeKind, std::vector<unsigned short>> MatcherFiltersMap;
1075
1076
  const MatchFinder::MatchFinderOptions &Options;
1077
  ASTContext *ActiveASTContext;
1078
1079
  // Maps a canonical type to its TypedefDecls.
1080
  llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
1081
1082
  // Maps an Objective-C interface to its ObjCCompatibleAliasDecls.
1083
  llvm::DenseMap<const ObjCInterfaceDecl *,
1084
                 llvm::SmallPtrSet<const ObjCCompatibleAliasDecl *, 2>>
1085
      CompatibleAliases;
1086
1087
  // Maps (matcher, node) -> the match result for memoization.
1088
  typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
1089
  MemoizationMap ResultCache;
1090
};
1091
1092
static CXXRecordDecl *
1093
3.32k
getAsCXXRecordDeclOrPrimaryTemplate(const Type *TypeNode) {
1094
3.32k
  if (auto *RD = TypeNode->getAsCXXRecordDecl())
1095
2.94k
    return RD;
1096
1097
  // Find the innermost TemplateSpecializationType that isn't an alias template.
1098
382
  auto *TemplateType = TypeNode->getAs<TemplateSpecializationType>();
1099
402
  while (TemplateType && 
TemplateType->isTypeAlias()240
)
1100
20
    TemplateType =
1101
20
        TemplateType->getAliasedType()->getAs<TemplateSpecializationType>();
1102
1103
  // If this is the name of a (dependent) template specialization, use the
1104
  // definition of the template, even though it might be specialized later.
1105
382
  if (TemplateType)
1106
220
    if (auto *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(
1107
180
          TemplateType->getTemplateName().getAsTemplateDecl()))
1108
180
      return ClassTemplate->getTemplatedDecl();
1109
1110
202
  return nullptr;
1111
202
}
1112
1113
// Returns true if the given C++ class is directly or indirectly derived
1114
// from a base type with the given name.  A class is not considered to be
1115
// derived from itself.
1116
bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
1117
                                         const Matcher<NamedDecl> &Base,
1118
                                         BoundNodesTreeBuilder *Builder,
1119
7.00k
                                         bool Directly) {
1120
7.00k
  if (!Declaration->hasDefinition())
1121
2.57k
    return false;
1122
4.43k
  for (const auto &It : Declaration->bases()) {
1123
3.42k
    const Type *TypeNode = It.getType().getTypePtr();
1124
1125
3.42k
    if (typeHasMatchingAlias(TypeNode, Base, Builder))
1126
102
      return true;
1127
1128
    // FIXME: Going to the primary template here isn't really correct, but
1129
    // unfortunately we accept a Decl matcher for the base class not a Type
1130
    // matcher, so it's the best thing we can do with our current interface.
1131
3.32k
    CXXRecordDecl *ClassDecl = getAsCXXRecordDeclOrPrimaryTemplate(TypeNode);
1132
3.32k
    if (!ClassDecl)
1133
202
      continue;
1134
3.12k
    if (ClassDecl == Declaration) {
1135
      // This can happen for recursive template definitions.
1136
60
      continue;
1137
60
    }
1138
3.06k
    BoundNodesTreeBuilder Result(*Builder);
1139
3.06k
    if (Base.matches(*ClassDecl, this, &Result)) {
1140
1.09k
      *Builder = std::move(Result);
1141
1.09k
      return true;
1142
1.09k
    }
1143
1.97k
    if (!Directly && 
classIsDerivedFrom(ClassDecl, Base, Builder, Directly)1.89k
)
1144
1.26k
      return true;
1145
1.97k
  }
1146
1.96k
  return false;
1147
4.43k
}
1148
1149
// Returns true if the given Objective-C class is directly or indirectly
1150
// derived from a matching base class. A class is not considered to be derived
1151
// from itself.
1152
bool MatchASTVisitor::objcClassIsDerivedFrom(
1153
    const ObjCInterfaceDecl *Declaration, const Matcher<NamedDecl> &Base,
1154
1.96k
    BoundNodesTreeBuilder *Builder, bool Directly) {
1155
  // Check if any of the superclasses of the class match.
1156
1.96k
  for (const ObjCInterfaceDecl *ClassDecl = Declaration->getSuperClass();
1157
2.01k
       ClassDecl != nullptr; 
ClassDecl = ClassDecl->getSuperClass()56
) {
1158
    // Check if there are any matching compatibility aliases.
1159
812
    if (objcClassHasMatchingCompatibilityAlias(ClassDecl, Base, Builder))
1160
168
      return true;
1161
1162
    // Check if there are any matching type aliases.
1163
644
    const Type *TypeNode = ClassDecl->getTypeForDecl();
1164
644
    if (typeHasMatchingAlias(TypeNode, Base, Builder))
1165
168
      return true;
1166
1167
476
    if (Base.matches(*ClassDecl, this, Builder))
1168
420
      return true;
1169
1170
    // Not `return false` as a temporary workaround for PR43879.
1171
56
    if (Directly)
1172
0
      break;
1173
56
  }
1174
1175
1.20k
  return false;
1176
1.96k
}
1177
1178
261k
bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
1179
261k
  if (!DeclNode) {
1180
97
    return true;
1181
97
  }
1182
1183
261k
  bool ScopedTraversal =
1184
261k
      TraversingASTNodeNotSpelledInSource || 
DeclNode->isImplicit()239k
;
1185
261k
  bool ScopedChildren = TraversingASTChildrenNotSpelledInSource;
1186
1187
261k
  if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DeclNode)) {
1188
2.72k
    auto SK = CTSD->getSpecializationKind();
1189
2.72k
    if (SK == TSK_ExplicitInstantiationDeclaration ||
1190
2.67k
        SK == TSK_ExplicitInstantiationDefinition)
1191
144
      ScopedChildren = true;
1192
258k
  } else if (const auto *FD = dyn_cast<FunctionDecl>(DeclNode)) {
1193
34.8k
    if (FD->isDefaulted())
1194
13.5k
      ScopedChildren = true;
1195
34.8k
    if (FD->isTemplateInstantiation())
1196
1.12k
      ScopedTraversal = true;
1197
34.8k
  }
1198
1199
261k
  ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
1200
261k
  ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren);
1201
1202
261k
  match(*DeclNode);
1203
261k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
1204
261k
}
1205
1206
116k
bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
1207
116k
  if (!StmtNode) {
1208
23.6k
    return true;
1209
23.6k
  }
1210
93.2k
  bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
1211
73.8k
                         TraversingASTChildrenNotSpelledInSource;
1212
1213
93.2k
  ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal);
1214
93.2k
  match(*StmtNode);
1215
93.2k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode, Queue);
1216
93.2k
}
1217
1218
28.3k
bool MatchASTVisitor::TraverseType(QualType TypeNode) {
1219
28.3k
  match(TypeNode);
1220
28.3k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
1221
28.3k
}
1222
1223
225k
bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
1224
  // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
1225
  // We still want to find those types via matchers, so we match them here. Note
1226
  // that the TypeLocs are structurally a shadow-hierarchy to the expressed
1227
  // type, so we visit all involved parts of a compound type when matching on
1228
  // each TypeLoc.
1229
225k
  match(TypeLocNode);
1230
225k
  match(TypeLocNode.getType());
1231
225k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
1232
225k
}
1233
1234
2
bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
1235
2
  match(*NNS);
1236
2
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
1237
2
}
1238
1239
bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
1240
139k
    NestedNameSpecifierLoc NNS) {
1241
139k
  if (!NNS)
1242
137k
    return true;
1243
1244
1.53k
  match(NNS);
1245
1246
  // We only match the nested name specifier here (as opposed to traversing it)
1247
  // because the traversal is already done in the parallel "Loc"-hierarchy.
1248
1.53k
  if (NNS.hasQualifier())
1249
1.53k
    match(*NNS.getNestedNameSpecifier());
1250
1.53k
  return
1251
1.53k
      RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
1252
1.53k
}
1253
1254
bool MatchASTVisitor::TraverseConstructorInitializer(
1255
1.54k
    CXXCtorInitializer *CtorInit) {
1256
1.54k
  if (!CtorInit)
1257
0
    return true;
1258
1259
1.54k
  bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
1260
491
                         TraversingASTChildrenNotSpelledInSource;
1261
1262
1.54k
  if (!CtorInit->isWritten())
1263
1.21k
    ScopedTraversal = true;
1264
1265
1.54k
  ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
1266
1267
1.54k
  match(*CtorInit);
1268
1269
1.54k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
1270
1.54k
      CtorInit);
1271
1.54k
}
1272
1273
4.17k
bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
1274
4.17k
  match(Loc);
1275
4.17k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
1276
4.17k
}
1277
1278
class MatchASTConsumer : public ASTConsumer {
1279
public:
1280
  MatchASTConsumer(MatchFinder *Finder,
1281
                   MatchFinder::ParsingDoneTestCallback *ParsingDone)
1282
15.2k
      : Finder(Finder), ParsingDone(ParsingDone) {}
1283
1284
private:
1285
15.2k
  void HandleTranslationUnit(ASTContext &Context) override {
1286
15.2k
    if (ParsingDone != nullptr) {
1287
0
      ParsingDone->run();
1288
0
    }
1289
15.2k
    Finder->matchAST(Context);
1290
15.2k
  }
1291
1292
  MatchFinder *Finder;
1293
  MatchFinder::ParsingDoneTestCallback *ParsingDone;
1294
};
1295
1296
} // end namespace
1297
} // end namespace internal
1298
1299
MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes,
1300
                                      ASTContext *Context)
1301
  : Nodes(Nodes), Context(Context),
1302
32.3k
    SourceManager(&Context->getSourceManager()) {}
1303
1304
57.3k
MatchFinder::MatchCallback::~MatchCallback() {}
1305
0
MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
1306
1307
MatchFinder::MatchFinder(MatchFinderOptions Options)
1308
43.1k
    : Options(std::move(Options)), ParsingDone(nullptr) {}
1309
1310
43.1k
MatchFinder::~MatchFinder() {}
1311
1312
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
1313
25.1k
                             MatchCallback *Action) {
1314
25.1k
  Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
1315
25.1k
  Matchers.AllCallbacks.insert(Action);
1316
25.1k
}
1317
1318
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
1319
1.69k
                             MatchCallback *Action) {
1320
1.69k
  Matchers.Type.emplace_back(NodeMatch, Action);
1321
1.69k
  Matchers.AllCallbacks.insert(Action);
1322
1.69k
}
1323
1324
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
1325
30.2k
                             MatchCallback *Action) {
1326
30.2k
  Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
1327
30.2k
  Matchers.AllCallbacks.insert(Action);
1328
30.2k
}
1329
1330
void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
1331
268
                             MatchCallback *Action) {
1332
268
  Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action);
1333
268
  Matchers.AllCallbacks.insert(Action);
1334
268
}
1335
1336
void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
1337
54
                             MatchCallback *Action) {
1338
54
  Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action);
1339
54
  Matchers.AllCallbacks.insert(Action);
1340
54
}
1341
1342
void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
1343
265
                             MatchCallback *Action) {
1344
265
  Matchers.TypeLoc.emplace_back(NodeMatch, Action);
1345
265
  Matchers.AllCallbacks.insert(Action);
1346
265
}
1347
1348
void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
1349
25
                             MatchCallback *Action) {
1350
25
  Matchers.CtorInit.emplace_back(NodeMatch, Action);
1351
25
  Matchers.AllCallbacks.insert(Action);
1352
25
}
1353
1354
void MatchFinder::addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
1355
1
                             MatchCallback *Action) {
1356
1
  Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action);
1357
1
  Matchers.AllCallbacks.insert(Action);
1358
1
}
1359
1360
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
1361
14.5k
                                    MatchCallback *Action) {
1362
14.5k
  if (NodeMatch.canConvertTo<Decl>()) {
1363
8.13k
    addMatcher(NodeMatch.convertTo<Decl>(), Action);
1364
8.13k
    return true;
1365
6.40k
  } else if (NodeMatch.canConvertTo<QualType>()) {
1366
836
    addMatcher(NodeMatch.convertTo<QualType>(), Action);
1367
836
    return true;
1368
5.56k
  } else if (NodeMatch.canConvertTo<Stmt>()) {
1369
5.27k
    addMatcher(NodeMatch.convertTo<Stmt>(), Action);
1370
5.27k
    return true;
1371
291
  } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) {
1372
133
    addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action);
1373
133
    return true;
1374
158
  } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) {
1375
25
    addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action);
1376
25
    return true;
1377
133
  } else if (NodeMatch.canConvertTo<TypeLoc>()) {
1378
119
    addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
1379
119
    return true;
1380
14
  } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
1381
12
    addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
1382
12
    return true;
1383
2
  } else if (NodeMatch.canConvertTo<TemplateArgumentLoc>()) {
1384
0
    addMatcher(NodeMatch.convertTo<TemplateArgumentLoc>(), Action);
1385
0
    return true;
1386
0
  }
1387
2
  return false;
1388
2
}
1389
1390
15.2k
std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
1391
15.2k
  return std::make_unique<internal::MatchASTConsumer>(this, ParsingDone);
1392
15.2k
}
1393
1394
21.5k
void MatchFinder::match(const clang::DynTypedNode &Node, ASTContext &Context) {
1395
21.5k
  internal::MatchASTVisitor Visitor(&Matchers, Options);
1396
21.5k
  Visitor.set_active_ast_context(&Context);
1397
21.5k
  Visitor.match(Node);
1398
21.5k
}
1399
1400
22.0k
void MatchFinder::matchAST(ASTContext &Context) {
1401
22.0k
  internal::MatchASTVisitor Visitor(&Matchers, Options);
1402
22.0k
  Visitor.set_active_ast_context(&Context);
1403
22.0k
  Visitor.onStartOfTranslationUnit();
1404
22.0k
  Visitor.TraverseAST(Context);
1405
22.0k
  Visitor.onEndOfTranslationUnit();
1406
22.0k
}
1407
1408
void MatchFinder::registerTestCallbackAfterParsing(
1409
0
    MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
1410
0
  ParsingDone = NewParsingDone;
1411
0
}
1412
1413
0
StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
1414
1415
} // end namespace ast_matchers
1416
} // end namespace clang