Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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
// We use memoization to avoid running the same matcher on the same
47
// AST node twice.  This struct is the key for looking up match
48
// result.  It consists of an ID of the MatcherInterface (for
49
// identifying the matcher), a pointer to the AST node and the
50
// bound nodes before the matcher was executed.
51
//
52
// We currently only memoize on nodes whose pointers identify the
53
// nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
54
// For \c QualType and \c TypeLoc it is possible to implement
55
// generation of keys for each type.
56
// FIXME: Benchmark whether memoization of non-pointer typed nodes
57
// provides enough benefit for the additional amount of code.
58
struct MatchKey {
59
  DynTypedMatcher::MatcherIDType MatcherID;
60
  ast_type_traits::DynTypedNode Node;
61
  BoundNodesTreeBuilder BoundNodes;
62
63
59.6k
  bool operator<(const MatchKey &Other) const {
64
59.6k
    return std::tie(MatcherID, Node, BoundNodes) <
65
59.6k
           std::tie(Other.MatcherID, Other.Node, Other.BoundNodes);
66
59.6k
  }
67
};
68
69
// Used to store the result of a match and possibly bound nodes.
70
struct MemoizedMatchResult {
71
  bool ResultOfMatch;
72
  BoundNodesTreeBuilder Nodes;
73
};
74
75
// A RecursiveASTVisitor that traverses all children or all descendants of
76
// a node.
77
class MatchChildASTVisitor
78
    : public RecursiveASTVisitor<MatchChildASTVisitor> {
79
public:
80
  typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
81
82
  // Creates an AST visitor that matches 'matcher' on all children or
83
  // descendants of a traversed node. max_depth is the maximum depth
84
  // to traverse: use 1 for matching the children and INT_MAX for
85
  // matching the descendants.
86
  MatchChildASTVisitor(const DynTypedMatcher *Matcher, ASTMatchFinder *Finder,
87
                       BoundNodesTreeBuilder *Builder, int MaxDepth,
88
                       ast_type_traits::TraversalKind Traversal,
89
                       ASTMatchFinder::BindKind Bind)
90
      : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0),
91
7.18k
        MaxDepth(MaxDepth), Traversal(Traversal), Bind(Bind), Matches(false) {}
92
93
  // Returns true if a match is found in the subtree rooted at the
94
  // given AST node. This is done via a set of mutually recursive
95
  // functions. Here's how the recursion is done (the  *wildcard can
96
  // actually be Decl, Stmt, or Type):
97
  //
98
  //   - Traverse(node) calls BaseTraverse(node) when it needs
99
  //     to visit the descendants of node.
100
  //   - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
101
  //     Traverse*(c) for each child c of 'node'.
102
  //   - Traverse*(c) in turn calls Traverse(c), completing the
103
  //     recursion.
104
7.18k
  bool findMatch(const ast_type_traits::DynTypedNode &DynNode) {
105
7.18k
    reset();
106
7.18k
    if (const Decl *D = DynNode.get<Decl>())
107
2.09k
      traverse(*D);
108
5.09k
    else if (const Stmt *S = DynNode.get<Stmt>())
109
5.01k
      traverse(*S);
110
75
    else if (const NestedNameSpecifier *NNS =
111
5
             DynNode.get<NestedNameSpecifier>())
112
5
      traverse(*NNS);
113
70
    else if (const NestedNameSpecifierLoc *NNSLoc =
114
8
             DynNode.get<NestedNameSpecifierLoc>())
115
8
      traverse(*NNSLoc);
116
62
    else if (const QualType *Q = DynNode.get<QualType>())
117
44
      traverse(*Q);
118
18
    else if (const TypeLoc *T = DynNode.get<TypeLoc>())
119
18
      traverse(*T);
120
0
    else if (const auto *C = DynNode.get<CXXCtorInitializer>())
121
0
      traverse(*C);
122
7.18k
    // FIXME: Add other base types after adding tests.
123
7.18k
124
7.18k
    // It's OK to always overwrite the bound nodes, as if there was
125
7.18k
    // no match in this recursive branch, the result set is empty
126
7.18k
    // anyway.
127
7.18k
    *Builder = ResultBindings;
128
7.18k
129
7.18k
    return Matches;
130
7.18k
  }
131
132
  // The following are overriding methods from the base visitor class.
133
  // They are public only to allow CRTP to work. They are *not *part
134
  // of the public API of this class.
135
13.3k
  bool TraverseDecl(Decl *DeclNode) {
136
13.3k
    ScopedIncrement ScopedDepth(&CurrentDepth);
137
13.3k
    return (DeclNode == nullptr) || 
traverse(*DeclNode)13.3k
;
138
13.3k
  }
139
43.5k
  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) {
140
43.5k
    // If we need to keep track of the depth, we can't perform data recursion.
141
43.5k
    if (CurrentDepth == 0 || 
(33.8k
CurrentDepth <= MaxDepth33.8k
&&
MaxDepth < INT_MAX32.8k
))
142
10.0k
      Queue = nullptr;
143
43.5k
144
43.5k
    ScopedIncrement ScopedDepth(&CurrentDepth);
145
43.5k
    Stmt *StmtToTraverse = StmtNode;
146
43.5k
    if (Traversal ==
147
43.5k
        ast_type_traits::TraversalKind::TK_IgnoreImplicitCastsAndParentheses) {
148
1
      if (Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode))
149
0
        StmtToTraverse = ExprNode->IgnoreParenImpCasts();
150
1
    }
151
43.5k
    if (!StmtToTraverse)
152
3.05k
      return true;
153
40.4k
    if (!match(*StmtToTraverse))
154
1.00k
      return false;
155
39.4k
    return VisitorBase::TraverseStmt(StmtToTraverse, Queue);
156
39.4k
  }
157
  // We assume that the QualType and the contained type are on the same
158
  // hierarchy level. Thus, we try to match either of them.
159
2.84k
  bool TraverseType(QualType TypeNode) {
160
2.84k
    if (TypeNode.isNull())
161
492
      return true;
162
2.35k
    ScopedIncrement ScopedDepth(&CurrentDepth);
163
2.35k
    // Match the Type.
164
2.35k
    if (!match(*TypeNode))
165
16
      return false;
166
2.33k
    // The QualType is matched inside traverse.
167
2.33k
    return traverse(TypeNode);
168
2.33k
  }
169
  // We assume that the TypeLoc, contained QualType and contained Type all are
170
  // on the same hierarchy level. Thus, we try to match all of them.
171
14.0k
  bool TraverseTypeLoc(TypeLoc TypeLocNode) {
172
14.0k
    if (TypeLocNode.isNull())
173
0
      return true;
174
14.0k
    ScopedIncrement ScopedDepth(&CurrentDepth);
175
14.0k
    // Match the Type.
176
14.0k
    if (!match(*TypeLocNode.getType()))
177
18
      return false;
178
14.0k
    // Match the QualType.
179
14.0k
    if (!match(TypeLocNode.getType()))
180
9
      return false;
181
14.0k
    // The TypeLoc is matched inside traverse.
182
14.0k
    return traverse(TypeLocNode);
183
14.0k
  }
184
9
  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
185
9
    ScopedIncrement ScopedDepth(&CurrentDepth);
186
9
    return (NNS == nullptr) || traverse(*NNS);
187
9
  }
188
23.2k
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
189
23.2k
    if (!NNS)
190
22.7k
      return true;
191
497
    ScopedIncrement ScopedDepth(&CurrentDepth);
192
497
    if (!match(*NNS.getNestedNameSpecifier()))
193
3
      return false;
194
494
    return traverse(NNS);
195
494
  }
196
113
  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
197
113
    if (!CtorInit)
198
0
      return true;
199
113
    ScopedIncrement ScopedDepth(&CurrentDepth);
200
113
    return traverse(*CtorInit);
201
113
  }
202
203
288
  bool shouldVisitTemplateInstantiations() const { return true; }
204
16.5k
  bool shouldVisitImplicitCode() const { return true; }
205
206
private:
207
  // Used for updating the depth during traversal.
208
  struct ScopedIncrement {
209
73.9k
    explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
210
73.9k
    ~ScopedIncrement() { --(*Depth); }
211
212
   private:
213
    int *Depth;
214
  };
215
216
  // Resets the state of this object.
217
7.18k
  void reset() {
218
7.18k
    Matches = false;
219
7.18k
    CurrentDepth = 0;
220
7.18k
  }
221
222
  // Forwards the call to the corresponding Traverse*() method in the
223
  // base visitor class.
224
14.7k
  bool baseTraverse(const Decl &DeclNode) {
225
14.7k
    return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
226
14.7k
  }
227
5.01k
  bool baseTraverse(const Stmt &StmtNode) {
228
5.01k
    return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
229
5.01k
  }
230
2.38k
  bool baseTraverse(QualType TypeNode) {
231
2.38k
    return VisitorBase::TraverseType(TypeNode);
232
2.38k
  }
233
14.0k
  bool baseTraverse(TypeLoc TypeLocNode) {
234
14.0k
    return VisitorBase::TraverseTypeLoc(TypeLocNode);
235
14.0k
  }
236
12
  bool baseTraverse(const NestedNameSpecifier &NNS) {
237
12
    return VisitorBase::TraverseNestedNameSpecifier(
238
12
        const_cast<NestedNameSpecifier*>(&NNS));
239
12
  }
240
495
  bool baseTraverse(NestedNameSpecifierLoc NNS) {
241
495
    return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
242
495
  }
243
109
  bool baseTraverse(const CXXCtorInitializer &CtorInit) {
244
109
    return VisitorBase::TraverseConstructorInitializer(
245
109
        const_cast<CXXCtorInitializer *>(&CtorInit));
246
109
  }
247
248
  // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
249
  //   0 < CurrentDepth <= MaxDepth.
250
  //
251
  // Returns 'true' if traversal should continue after this function
252
  // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
253
  template <typename T>
254
109k
  bool match(const T &Node) {
255
109k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth101k
) {
256
20.2k
      return true;
257
20.2k
    }
258
88.8k
    if (Bind != ASTMatchFinder::BK_All) {
259
26.5k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
26.5k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
26.5k
                           &RecursiveBuilder)) {
262
1.80k
        Matches = true;
263
1.80k
        ResultBindings.addMatch(RecursiveBuilder);
264
1.80k
        return false; // Abort as soon as a match is found.
265
1.80k
      }
266
62.2k
    } else {
267
62.2k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
62.2k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
62.2k
                           &RecursiveBuilder)) {
270
673
        // After the first match the matcher succeeds.
271
673
        Matches = true;
272
673
        ResultBindings.addMatch(RecursiveBuilder);
273
673
      }
274
62.2k
    }
275
88.8k
    
return true87.0k
;
276
88.8k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::Decl>(clang::Decl const&)
Line
Count
Source
254
15.4k
  bool match(const T &Node) {
255
15.4k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth13.3k
) {
256
3.35k
      return true;
257
3.35k
    }
258
12.1k
    if (Bind != ASTMatchFinder::BK_All) {
259
4.69k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
4.69k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
4.69k
                           &RecursiveBuilder)) {
262
716
        Matches = true;
263
716
        ResultBindings.addMatch(RecursiveBuilder);
264
716
        return false; // Abort as soon as a match is found.
265
716
      }
266
7.44k
    } else {
267
7.44k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
7.44k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
7.44k
                           &RecursiveBuilder)) {
270
146
        // After the first match the matcher succeeds.
271
146
        Matches = true;
272
146
        ResultBindings.addMatch(RecursiveBuilder);
273
146
      }
274
7.44k
    }
275
12.1k
    
return true11.4k
;
276
12.1k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::Type>(clang::Type const&)
Line
Count
Source
254
16.4k
  bool match(const T &Node) {
255
16.4k
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
256
3.76k
      return true;
257
3.76k
    }
258
12.6k
    if (Bind != ASTMatchFinder::BK_All) {
259
3.32k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
3.32k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
3.32k
                           &RecursiveBuilder)) {
262
34
        Matches = true;
263
34
        ResultBindings.addMatch(RecursiveBuilder);
264
34
        return false; // Abort as soon as a match is found.
265
34
      }
266
9.34k
    } else {
267
9.34k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
9.34k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
9.34k
                           &RecursiveBuilder)) {
270
4
        // After the first match the matcher succeeds.
271
4
        Matches = true;
272
4
        ResultBindings.addMatch(RecursiveBuilder);
273
4
      }
274
9.34k
    }
275
12.6k
    
return true12.6k
;
276
12.6k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::QualType>(clang::QualType const&)
Line
Count
Source
254
16.4k
  bool match(const T &Node) {
255
16.4k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth16.4k
) {
256
3.81k
      return true;
257
3.81k
    }
258
12.6k
    if (Bind != ASTMatchFinder::BK_All) {
259
3.28k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
3.28k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
3.28k
                           &RecursiveBuilder)) {
262
9
        Matches = true;
263
9
        ResultBindings.addMatch(RecursiveBuilder);
264
9
        return false; // Abort as soon as a match is found.
265
9
      }
266
9.34k
    } else {
267
9.34k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
9.34k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
9.34k
                           &RecursiveBuilder)) {
270
4
        // After the first match the matcher succeeds.
271
4
        Matches = true;
272
4
        ResultBindings.addMatch(RecursiveBuilder);
273
4
      }
274
9.34k
    }
275
12.6k
    
return true12.6k
;
276
12.6k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::Stmt>(clang::Stmt const&)
Line
Count
Source
254
45.5k
  bool match(const T &Node) {
255
45.5k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth40.4k
) {
256
5.97k
      return true;
257
5.97k
    }
258
39.5k
    if (Bind != ASTMatchFinder::BK_All) {
259
12.0k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
12.0k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
12.0k
                           &RecursiveBuilder)) {
262
1.00k
        Matches = true;
263
1.00k
        ResultBindings.addMatch(RecursiveBuilder);
264
1.00k
        return false; // Abort as soon as a match is found.
265
1.00k
      }
266
27.5k
    } else {
267
27.5k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
27.5k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
27.5k
                           &RecursiveBuilder)) {
270
503
        // After the first match the matcher succeeds.
271
503
        Matches = true;
272
503
        ResultBindings.addMatch(RecursiveBuilder);
273
503
      }
274
27.5k
    }
275
39.5k
    
return true38.5k
;
276
39.5k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::NestedNameSpecifier>(clang::NestedNameSpecifier const&)
Line
Count
Source
254
511
  bool match(const T &Node) {
255
511
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth506
) {
256
34
      return true;
257
34
    }
258
477
    if (Bind != ASTMatchFinder::BK_All) {
259
94
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
94
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
94
                           &RecursiveBuilder)) {
262
5
        Matches = true;
263
5
        ResultBindings.addMatch(RecursiveBuilder);
264
5
        return false; // Abort as soon as a match is found.
265
5
      }
266
383
    } else {
267
383
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
383
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
383
                           &RecursiveBuilder)) {
270
8
        // After the first match the matcher succeeds.
271
8
        Matches = true;
272
8
        ResultBindings.addMatch(RecursiveBuilder);
273
8
      }
274
383
    }
275
477
    
return true472
;
276
477
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc const&)
Line
Count
Source
254
502
  bool match(const T &Node) {
255
502
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth494
) {
256
34
      return true;
257
34
    }
258
468
    if (Bind != ASTMatchFinder::BK_All) {
259
87
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
87
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
87
                           &RecursiveBuilder)) {
262
7
        Matches = true;
263
7
        ResultBindings.addMatch(RecursiveBuilder);
264
7
        return false; // Abort as soon as a match is found.
265
7
      }
266
381
    } else {
267
381
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
381
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
381
                           &RecursiveBuilder)) {
270
8
        // After the first match the matcher succeeds.
271
8
        Matches = true;
272
8
        ResultBindings.addMatch(RecursiveBuilder);
273
8
      }
274
381
    }
275
468
    
return true461
;
276
468
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::TypeLoc>(clang::TypeLoc const&)
Line
Count
Source
254
14.0k
  bool match(const T &Node) {
255
14.0k
    if (CurrentDepth == 0 || 
CurrentDepth > MaxDepth14.0k
) {
256
3.23k
      return true;
257
3.23k
    }
258
10.8k
    if (Bind != ASTMatchFinder::BK_All) {
259
3.06k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
3.06k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
3.06k
                           &RecursiveBuilder)) {
262
21
        Matches = true;
263
21
        ResultBindings.addMatch(RecursiveBuilder);
264
21
        return false; // Abort as soon as a match is found.
265
21
      }
266
7.77k
    } else {
267
7.77k
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
7.77k
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
7.77k
                           &RecursiveBuilder)) {
270
0
        // After the first match the matcher succeeds.
271
0
        Matches = true;
272
0
        ResultBindings.addMatch(RecursiveBuilder);
273
0
      }
274
7.77k
    }
275
10.8k
    
return true10.8k
;
276
10.8k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::match<clang::CXXCtorInitializer>(clang::CXXCtorInitializer const&)
Line
Count
Source
254
113
  bool match(const T &Node) {
255
113
    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
256
4
      return true;
257
4
    }
258
109
    if (Bind != ASTMatchFinder::BK_All) {
259
7
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
260
7
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
261
7
                           &RecursiveBuilder)) {
262
4
        Matches = true;
263
4
        ResultBindings.addMatch(RecursiveBuilder);
264
4
        return false; // Abort as soon as a match is found.
265
4
      }
266
102
    } else {
267
102
      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
268
102
      if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
269
102
                           &RecursiveBuilder)) {
270
0
        // After the first match the matcher succeeds.
271
0
        Matches = true;
272
0
        ResultBindings.addMatch(RecursiveBuilder);
273
0
      }
274
102
    }
275
109
    
return true105
;
276
109
  }
277
278
  // Traverses the subtree rooted at 'Node'; returns true if the
279
  // traversal should continue after this function returns.
280
  template <typename T>
281
37.5k
  bool traverse(const T &Node) {
282
37.5k
    static_assert(IsBaseType<T>::value,
283
37.5k
                  "traverse can only be instantiated with base type");
284
37.5k
    if (!match(Node))
285
750
      return false;
286
36.8k
    return baseTraverse(Node);
287
36.8k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::Decl>(clang::Decl const&)
Line
Count
Source
281
15.4k
  bool traverse(const T &Node) {
282
15.4k
    static_assert(IsBaseType<T>::value,
283
15.4k
                  "traverse can only be instantiated with base type");
284
15.4k
    if (!match(Node))
285
716
      return false;
286
14.7k
    return baseTraverse(Node);
287
14.7k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::Stmt>(clang::Stmt const&)
Line
Count
Source
281
5.01k
  bool traverse(const T &Node) {
282
5.01k
    static_assert(IsBaseType<T>::value,
283
5.01k
                  "traverse can only be instantiated with base type");
284
5.01k
    if (!match(Node))
285
0
      return false;
286
5.01k
    return baseTraverse(Node);
287
5.01k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::NestedNameSpecifier>(clang::NestedNameSpecifier const&)
Line
Count
Source
281
14
  bool traverse(const T &Node) {
282
14
    static_assert(IsBaseType<T>::value,
283
14
                  "traverse can only be instantiated with base type");
284
14
    if (!match(Node))
285
2
      return false;
286
12
    return baseTraverse(Node);
287
12
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc const&)
Line
Count
Source
281
502
  bool traverse(const T &Node) {
282
502
    static_assert(IsBaseType<T>::value,
283
502
                  "traverse can only be instantiated with base type");
284
502
    if (!match(Node))
285
7
      return false;
286
495
    return baseTraverse(Node);
287
495
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::QualType>(clang::QualType const&)
Line
Count
Source
281
2.38k
  bool traverse(const T &Node) {
282
2.38k
    static_assert(IsBaseType<T>::value,
283
2.38k
                  "traverse can only be instantiated with base type");
284
2.38k
    if (!match(Node))
285
0
      return false;
286
2.38k
    return baseTraverse(Node);
287
2.38k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::TypeLoc>(clang::TypeLoc const&)
Line
Count
Source
281
14.0k
  bool traverse(const T &Node) {
282
14.0k
    static_assert(IsBaseType<T>::value,
283
14.0k
                  "traverse can only be instantiated with base type");
284
14.0k
    if (!match(Node))
285
21
      return false;
286
14.0k
    return baseTraverse(Node);
287
14.0k
  }
ASTMatchFinder.cpp:bool clang::ast_matchers::internal::(anonymous namespace)::MatchChildASTVisitor::traverse<clang::CXXCtorInitializer>(clang::CXXCtorInitializer const&)
Line
Count
Source
281
113
  bool traverse(const T &Node) {
282
113
    static_assert(IsBaseType<T>::value,
283
113
                  "traverse can only be instantiated with base type");
284
113
    if (!match(Node))
285
4
      return false;
286
109
    return baseTraverse(Node);
287
109
  }
288
289
  const DynTypedMatcher *const Matcher;
290
  ASTMatchFinder *const Finder;
291
  BoundNodesTreeBuilder *const Builder;
292
  BoundNodesTreeBuilder ResultBindings;
293
  int CurrentDepth;
294
  const int MaxDepth;
295
  const ast_type_traits::TraversalKind Traversal;
296
  const ASTMatchFinder::BindKind Bind;
297
  bool Matches;
298
};
299
300
// Controls the outermost traversal of the AST and allows to match multiple
301
// matchers.
302
class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
303
                        public ASTMatchFinder {
304
public:
305
  MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
306
                  const MatchFinder::MatchFinderOptions &Options)
307
26.7k
      : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
308
309
26.7k
  ~MatchASTVisitor() override {
310
26.7k
    if (Options.CheckProfiling) {
311
1
      Options.CheckProfiling->Records = std::move(TimeByBucket);
312
1
    }
313
26.7k
  }
314
315
6.32k
  void onStartOfTranslationUnit() {
316
6.32k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
317
6.32k
    TimeBucketRegion Timer;
318
8.01k
    for (MatchCallback *MC : Matchers->AllCallbacks) {
319
8.01k
      if (EnableCheckProfiling)
320
1
        Timer.setBucket(&TimeByBucket[MC->getID()]);
321
8.01k
      MC->onStartOfTranslationUnit();
322
8.01k
    }
323
6.32k
  }
324
325
6.32k
  void onEndOfTranslationUnit() {
326
6.32k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
327
6.32k
    TimeBucketRegion Timer;
328
8.01k
    for (MatchCallback *MC : Matchers->AllCallbacks) {
329
8.01k
      if (EnableCheckProfiling)
330
1
        Timer.setBucket(&TimeByBucket[MC->getID()]);
331
8.01k
      MC->onEndOfTranslationUnit();
332
8.01k
    }
333
6.32k
  }
334
335
26.7k
  void set_active_ast_context(ASTContext *NewActiveASTContext) {
336
26.7k
    ActiveASTContext = NewActiveASTContext;
337
26.7k
  }
338
339
  // The following Visit*() and Traverse*() functions "override"
340
  // methods in RecursiveASTVisitor.
341
342
28.1k
  bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
343
28.1k
    // When we see 'typedef A B', we add name 'B' to the set of names
344
28.1k
    // A's canonical type maps to.  This is necessary for implementing
345
28.1k
    // isDerivedFrom(x) properly, where x can be the name of the base
346
28.1k
    // class or any of its aliases.
347
28.1k
    //
348
28.1k
    // In general, the is-alias-of (as defined by typedefs) relation
349
28.1k
    // is tree-shaped, as you can typedef a type more than once.  For
350
28.1k
    // example,
351
28.1k
    //
352
28.1k
    //   typedef A B;
353
28.1k
    //   typedef A C;
354
28.1k
    //   typedef C D;
355
28.1k
    //   typedef C E;
356
28.1k
    //
357
28.1k
    // gives you
358
28.1k
    //
359
28.1k
    //   A
360
28.1k
    //   |- B
361
28.1k
    //   `- C
362
28.1k
    //      |- D
363
28.1k
    //      `- E
364
28.1k
    //
365
28.1k
    // It is wrong to assume that the relation is a chain.  A correct
366
28.1k
    // implementation of isDerivedFrom() needs to recognize that B and
367
28.1k
    // E are aliases, even though neither is a typedef of the other.
368
28.1k
    // Therefore, we cannot simply walk through one typedef chain to
369
28.1k
    // find out whether the type name matches.
370
28.1k
    const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
371
28.1k
    const Type *CanonicalType =  // root of the typedef tree
372
28.1k
        ActiveASTContext->getCanonicalType(TypeNode);
373
28.1k
    TypeAliases[CanonicalType].insert(DeclNode);
374
28.1k
    return true;
375
28.1k
  }
376
377
  bool TraverseDecl(Decl *DeclNode);
378
  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
379
  bool TraverseType(QualType TypeNode);
380
  bool TraverseTypeLoc(TypeLoc TypeNode);
381
  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
382
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
383
  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
384
385
  // Matches children or descendants of 'Node' with 'BaseMatcher'.
386
  bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node,
387
                                  const DynTypedMatcher &Matcher,
388
                                  BoundNodesTreeBuilder *Builder, int MaxDepth,
389
                                  ast_type_traits::TraversalKind Traversal,
390
7.62k
                                  BindKind Bind) {
391
7.62k
    // For AST-nodes that don't have an identity, we can't memoize.
392
7.62k
    if (!Node.getMemoizationData() || 
!Builder->isComparable()7.55k
)
393
194
      return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal,
394
194
                                Bind);
395
7.43k
396
7.43k
    MatchKey Key;
397
7.43k
    Key.MatcherID = Matcher.getID();
398
7.43k
    Key.Node = Node;
399
7.43k
    // Note that we key on the bindings *before* the match.
400
7.43k
    Key.BoundNodes = *Builder;
401
7.43k
402
7.43k
    MemoizationMap::iterator I = ResultCache.find(Key);
403
7.43k
    if (I != ResultCache.end()) {
404
436
      *Builder = I->second.Nodes;
405
436
      return I->second.ResultOfMatch;
406
436
    }
407
6.99k
408
6.99k
    MemoizedMatchResult Result;
409
6.99k
    Result.Nodes = *Builder;
410
6.99k
    Result.ResultOfMatch = matchesRecursively(Node, Matcher, &Result.Nodes,
411
6.99k
                                              MaxDepth, Traversal, Bind);
412
6.99k
413
6.99k
    MemoizedMatchResult &CachedResult = ResultCache[Key];
414
6.99k
    CachedResult = std::move(Result);
415
6.99k
416
6.99k
    *Builder = CachedResult.Nodes;
417
6.99k
    return CachedResult.ResultOfMatch;
418
6.99k
  }
419
420
  // Matches children or descendants of 'Node' with 'BaseMatcher'.
421
  bool matchesRecursively(const ast_type_traits::DynTypedNode &Node,
422
                          const DynTypedMatcher &Matcher,
423
                          BoundNodesTreeBuilder *Builder, int MaxDepth,
424
                          ast_type_traits::TraversalKind Traversal,
425
7.18k
                          BindKind Bind) {
426
7.18k
    MatchChildASTVisitor Visitor(
427
7.18k
      &Matcher, this, Builder, MaxDepth, Traversal, Bind);
428
7.18k
    return Visitor.findMatch(Node);
429
7.18k
  }
430
431
  bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
432
                          const Matcher<NamedDecl> &Base,
433
                          BoundNodesTreeBuilder *Builder) override;
434
435
  // Implements ASTMatchFinder::matchesChildOf.
436
  bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
437
                      const DynTypedMatcher &Matcher,
438
                      BoundNodesTreeBuilder *Builder,
439
                      ast_type_traits::TraversalKind Traversal,
440
1.91k
                      BindKind Bind) override {
441
1.91k
    if (ResultCache.size() > MaxMemoizationEntries)
442
0
      ResultCache.clear();
443
1.91k
    return memoizedMatchesRecursively(Node, Matcher, Builder, 1, Traversal,
444
1.91k
                                      Bind);
445
1.91k
  }
446
  // Implements ASTMatchFinder::matchesDescendantOf.
447
  bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
448
                           const DynTypedMatcher &Matcher,
449
                           BoundNodesTreeBuilder *Builder,
450
5.70k
                           BindKind Bind) override {
451
5.70k
    if (ResultCache.size() > MaxMemoizationEntries)
452
0
      ResultCache.clear();
453
5.70k
    return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX,
454
5.70k
                                      ast_type_traits::TraversalKind::TK_AsIs,
455
5.70k
                                      Bind);
456
5.70k
  }
457
  // Implements ASTMatchFinder::matchesAncestorOf.
458
  bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
459
                         const DynTypedMatcher &Matcher,
460
                         BoundNodesTreeBuilder *Builder,
461
1.49k
                         AncestorMatchMode MatchMode) override {
462
1.49k
    // Reset the cache outside of the recursive call to make sure we
463
1.49k
    // don't invalidate any iterators.
464
1.49k
    if (ResultCache.size() > MaxMemoizationEntries)
465
0
      ResultCache.clear();
466
1.49k
    return memoizedMatchesAncestorOfRecursively(Node, Matcher, Builder,
467
1.49k
                                                MatchMode);
468
1.49k
  }
469
470
  // Matches all registered matchers on the given node and calls the
471
  // result callback for every node that matches.
472
20.4k
  void match(const ast_type_traits::DynTypedNode &Node) {
473
20.4k
    // FIXME: Improve this with a switch or a visitor pattern.
474
20.4k
    if (auto *N = Node.get<Decl>()) {
475
1.95k
      match(*N);
476
18.4k
    } else if (auto *N = Node.get<Stmt>()) {
477
18.4k
      match(*N);
478
18.4k
    } else 
if (auto *0
N0
= Node.get<Type>()) {
479
0
      match(*N);
480
0
    } else if (auto *N = Node.get<QualType>()) {
481
0
      match(*N);
482
0
    } else if (auto *N = Node.get<NestedNameSpecifier>()) {
483
0
      match(*N);
484
0
    } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
485
0
      match(*N);
486
0
    } else if (auto *N = Node.get<TypeLoc>()) {
487
0
      match(*N);
488
0
    } else if (auto *N = Node.get<CXXCtorInitializer>()) {
489
0
      match(*N);
490
0
    }
491
20.4k
  }
492
493
263k
  template <typename T> void match(const T &Node) {
494
263k
    matchDispatch(&Node);
495
263k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::Decl>(clang::Decl const&)
Line
Count
Source
493
75.0k
  template <typename T> void match(const T &Node) {
494
75.0k
    matchDispatch(&Node);
495
75.0k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::Stmt>(clang::Stmt const&)
Line
Count
Source
493
46.5k
  template <typename T> void match(const T &Node) {
494
46.5k
    matchDispatch(&Node);
495
46.5k
  }
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
493
74.1k
  template <typename T> void match(const T &Node) {
494
74.1k
    matchDispatch(&Node);
495
74.1k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::NestedNameSpecifier>(clang::NestedNameSpecifier const&)
Line
Count
Source
493
572
  template <typename T> void match(const T &Node) {
494
572
    matchDispatch(&Node);
495
572
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc const&)
Line
Count
Source
493
570
  template <typename T> void match(const T &Node) {
494
570
    matchDispatch(&Node);
495
570
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::TypeLoc>(clang::TypeLoc const&)
Line
Count
Source
493
66.2k
  template <typename T> void match(const T &Node) {
494
66.2k
    matchDispatch(&Node);
495
66.2k
  }
ASTMatchFinder.cpp:void clang::ast_matchers::internal::(anonymous namespace)::MatchASTVisitor::match<clang::CXXCtorInitializer>(clang::CXXCtorInitializer const&)
Line
Count
Source
493
491
  template <typename T> void match(const T &Node) {
494
491
    matchDispatch(&Node);
495
491
  }
496
497
  // Implements ASTMatchFinder::getASTContext.
498
80
  ASTContext &getASTContext() const override { return *ActiveASTContext; }
499
500
3.15k
  bool shouldVisitTemplateInstantiations() const { return true; }
501
77.8k
  bool shouldVisitImplicitCode() const { return true; }
502
503
private:
504
  class TimeBucketRegion {
505
  public:
506
193k
    TimeBucketRegion() : Bucket(nullptr) {}
507
193k
    ~TimeBucketRegion() { setBucket(nullptr); }
508
509
    /// Start timing for \p NewBucket.
510
    ///
511
    /// If there was a bucket already set, it will finish the timing for that
512
    /// other bucket.
513
    /// \p NewBucket will be timed until the next call to \c setBucket() or
514
    /// until the \c TimeBucketRegion is destroyed.
515
    /// If \p NewBucket is the same as the currently timed bucket, this call
516
    /// does nothing.
517
193k
    void setBucket(llvm::TimeRecord *NewBucket) {
518
193k
      if (Bucket != NewBucket) {
519
18
        auto Now = llvm::TimeRecord::getCurrentTime(true);
520
18
        if (Bucket)
521
9
          *Bucket += Now;
522
18
        if (NewBucket)
523
9
          *NewBucket -= Now;
524
18
        Bucket = NewBucket;
525
18
      }
526
193k
    }
527
528
  private:
529
    llvm::TimeRecord *Bucket;
530
  };
531
532
  /// Runs all the \p Matchers on \p Node.
533
  ///
534
  /// Used by \c matchDispatch() below.
535
  template <typename T, typename MC>
536
142k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
537
142k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
538
142k
    TimeBucketRegion Timer;
539
142k
    for (const auto &MP : Matchers) {
540
1.80k
      if (EnableCheckProfiling)
541
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
542
1.80k
      BoundNodesTreeBuilder Builder;
543
1.80k
      if (MP.first.matches(Node, this, &Builder)) {
544
379
        MatchVisitor Visitor(ActiveASTContext, MP.second);
545
379
        Builder.visitMatches(&Visitor);
546
379
      }
547
1.80k
    }
548
142k
  }
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
536
74.1k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
537
74.1k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
538
74.1k
    TimeBucketRegion Timer;
539
74.1k
    for (const auto &MP : Matchers) {
540
1.36k
      if (EnableCheckProfiling)
541
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
542
1.36k
      BoundNodesTreeBuilder Builder;
543
1.36k
      if (MP.first.matches(Node, this, &Builder)) {
544
164
        MatchVisitor Visitor(ActiveASTContext, MP.second);
545
164
        Builder.visitMatches(&Visitor);
546
164
      }
547
1.36k
    }
548
74.1k
  }
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
536
572
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
537
572
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
538
572
    TimeBucketRegion Timer;
539
572
    for (const auto &MP : Matchers) {
540
56
      if (EnableCheckProfiling)
541
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
542
56
      BoundNodesTreeBuilder Builder;
543
56
      if (MP.first.matches(Node, this, &Builder)) {
544
26
        MatchVisitor Visitor(ActiveASTContext, MP.second);
545
26
        Builder.visitMatches(&Visitor);
546
26
      }
547
56
    }
548
572
  }
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
536
570
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
537
570
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
538
570
    TimeBucketRegion Timer;
539
570
    for (const auto &MP : Matchers) {
540
40
      if (EnableCheckProfiling)
541
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
542
40
      BoundNodesTreeBuilder Builder;
543
40
      if (MP.first.matches(Node, this, &Builder)) {
544
16
        MatchVisitor Visitor(ActiveASTContext, MP.second);
545
16
        Builder.visitMatches(&Visitor);
546
16
      }
547
40
    }
548
570
  }
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
536
66.2k
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
537
66.2k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
538
66.2k
    TimeBucketRegion Timer;
539
66.2k
    for (const auto &MP : Matchers) {
540
335
      if (EnableCheckProfiling)
541
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
542
335
      BoundNodesTreeBuilder Builder;
543
335
      if (MP.first.matches(Node, this, &Builder)) {
544
170
        MatchVisitor Visitor(ActiveASTContext, MP.second);
545
170
        Builder.visitMatches(&Visitor);
546
170
      }
547
335
    }
548
66.2k
  }
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
536
491
  void matchWithoutFilter(const T &Node, const MC &Matchers) {
537
491
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
538
491
    TimeBucketRegion Timer;
539
491
    for (const auto &MP : Matchers) {
540
3
      if (EnableCheckProfiling)
541
0
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
542
3
      BoundNodesTreeBuilder Builder;
543
3
      if (MP.first.matches(Node, this, &Builder)) {
544
3
        MatchVisitor Visitor(ActiveASTContext, MP.second);
545
3
        Builder.visitMatches(&Visitor);
546
3
      }
547
3
    }
548
491
  }
549
550
121k
  void matchWithFilter(const ast_type_traits::DynTypedNode &DynNode) {
551
121k
    auto Kind = DynNode.getNodeKind();
552
121k
    auto it = MatcherFiltersMap.find(Kind);
553
121k
    const auto &Filter =
554
121k
        it != MatcherFiltersMap.end() ? 
it->second54.7k
:
getFilterForKind(Kind)66.7k
;
555
121k
556
121k
    if (Filter.empty())
557
83.1k
      return;
558
38.4k
559
38.4k
    const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
560
38.4k
    TimeBucketRegion Timer;
561
38.4k
    auto &Matchers = this->Matchers->DeclOrStmt;
562
41.5k
    for (unsigned short I : Filter) {
563
41.5k
      auto &MP = Matchers[I];
564
41.5k
      if (EnableCheckProfiling)
565
7
        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
566
41.5k
      BoundNodesTreeBuilder Builder;
567
41.5k
      if (MP.first.matchesNoKindCheck(DynNode, this, &Builder)) {
568
9.46k
        MatchVisitor Visitor(ActiveASTContext, MP.second);
569
9.46k
        Builder.visitMatches(&Visitor);
570
9.46k
      }
571
41.5k
    }
572
38.4k
  }
573
574
  const std::vector<unsigned short> &
575
66.7k
  getFilterForKind(ast_type_traits::ASTNodeKind Kind) {
576
66.7k
    auto &Filter = MatcherFiltersMap[Kind];
577
66.7k
    auto &Matchers = this->Matchers->DeclOrStmt;
578
66.7k
    assert((Matchers.size() < USHRT_MAX) && "Too many matchers.");
579
143k
    for (unsigned I = 0, E = Matchers.size(); I != E; 
++I76.8k
) {
580
76.8k
      if (Matchers[I].first.canMatchNodesOfKind(Kind)) {
581
30.5k
        Filter.push_back(I);
582
30.5k
      }
583
76.8k
    }
584
66.7k
    return Filter;
585
66.7k
  }
586
587
  /// @{
588
  /// Overloads to pair the different node types to their matchers.
589
75.0k
  void matchDispatch(const Decl *Node) {
590
75.0k
    return matchWithFilter(ast_type_traits::DynTypedNode::create(*Node));
591
75.0k
  }
592
46.5k
  void matchDispatch(const Stmt *Node) {
593
46.5k
    return matchWithFilter(ast_type_traits::DynTypedNode::create(*Node));
594
46.5k
  }
595
596
0
  void matchDispatch(const Type *Node) {
597
0
    matchWithoutFilter(QualType(Node, 0), Matchers->Type);
598
0
  }
599
66.2k
  void matchDispatch(const TypeLoc *Node) {
600
66.2k
    matchWithoutFilter(*Node, Matchers->TypeLoc);
601
66.2k
  }
602
74.1k
  void matchDispatch(const QualType *Node) {
603
74.1k
    matchWithoutFilter(*Node, Matchers->Type);
604
74.1k
  }
605
572
  void matchDispatch(const NestedNameSpecifier *Node) {
606
572
    matchWithoutFilter(*Node, Matchers->NestedNameSpecifier);
607
572
  }
608
570
  void matchDispatch(const NestedNameSpecifierLoc *Node) {
609
570
    matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
610
570
  }
611
491
  void matchDispatch(const CXXCtorInitializer *Node) {
612
491
    matchWithoutFilter(*Node, Matchers->CtorInit);
613
491
  }
614
0
  void matchDispatch(const void *) { /* Do nothing. */ }
615
  /// @}
616
617
  // Returns whether an ancestor of \p Node matches \p Matcher.
618
  //
619
  // The order of matching ((which can lead to different nodes being bound in
620
  // case there are multiple matches) is breadth first search.
621
  //
622
  // To allow memoization in the very common case of having deeply nested
623
  // expressions inside a template function, we first walk up the AST, memoizing
624
  // the result of the match along the way, as long as there is only a single
625
  // parent.
626
  //
627
  // Once there are multiple parents, the breadth first search order does not
628
  // allow simple memoization on the ancestors. Thus, we only memoize as long
629
  // as there is a single parent.
630
  bool memoizedMatchesAncestorOfRecursively(
631
      const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher,
632
4.95k
      BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) {
633
4.95k
    // For AST-nodes that don't have an identity, we can't memoize.
634
4.95k
    if (!Builder->isComparable())
635
12
      return matchesAncestorOfRecursively(Node, Matcher, Builder, MatchMode);
636
4.94k
637
4.94k
    MatchKey Key;
638
4.94k
    Key.MatcherID = Matcher.getID();
639
4.94k
    Key.Node = Node;
640
4.94k
    Key.BoundNodes = *Builder;
641
4.94k
642
4.94k
    // Note that we cannot use insert and reuse the iterator, as recursive
643
4.94k
    // calls to match might invalidate the result cache iterators.
644
4.94k
    MemoizationMap::iterator I = ResultCache.find(Key);
645
4.94k
    if (I != ResultCache.end()) {
646
97
      *Builder = I->second.Nodes;
647
97
      return I->second.ResultOfMatch;
648
97
    }
649
4.84k
650
4.84k
    MemoizedMatchResult Result;
651
4.84k
    Result.Nodes = *Builder;
652
4.84k
    Result.ResultOfMatch =
653
4.84k
        matchesAncestorOfRecursively(Node, Matcher, &Result.Nodes, MatchMode);
654
4.84k
655
4.84k
    MemoizedMatchResult &CachedResult = ResultCache[Key];
656
4.84k
    CachedResult = std::move(Result);
657
4.84k
658
4.84k
    *Builder = CachedResult.Nodes;
659
4.84k
    return CachedResult.ResultOfMatch;
660
4.84k
  }
661
662
  bool matchesAncestorOfRecursively(const ast_type_traits::DynTypedNode &Node,
663
                                    const DynTypedMatcher &Matcher,
664
                                    BoundNodesTreeBuilder *Builder,
665
4.85k
                                    AncestorMatchMode MatchMode) {
666
4.85k
    const auto &Parents = ActiveASTContext->getParents(Node);
667
4.85k
    if (Parents.empty()) {
668
594
      // Nodes may have no parents if:
669
594
      //  a) the node is the TranslationUnitDecl
670
594
      //  b) we have a limited traversal scope that excludes the parent edges
671
594
      //  c) there is a bug in the AST, and the node is not reachable
672
594
      // Usually the traversal scope is the whole AST, which precludes b.
673
594
      // Bugs are common enough that it's worthwhile asserting when we can.
674
#ifndef NDEBUG
675
      if (!Node.get<TranslationUnitDecl>() &&
676
          /* Traversal scope is full AST if any of the bounds are the TU */
677
          llvm::any_of(ActiveASTContext->getTraversalScope(), [](Decl *D) {
678
            return D->getKind() == Decl::TranslationUnit;
679
          })) {
680
        llvm::errs() << "Tried to match orphan node:\n";
681
        Node.dump(llvm::errs(), ActiveASTContext->getSourceManager());
682
        llvm_unreachable("Parent map should be complete!");
683
      }
684
#endif
685
      return false;
686
594
    }
687
4.26k
    if (Parents.size() == 1) {
688
4.24k
      // Only one parent - do recursive memoization.
689
4.24k
      const ast_type_traits::DynTypedNode Parent = Parents[0];
690
4.24k
      BoundNodesTreeBuilder BuilderCopy = *Builder;
691
4.24k
      if (Matcher.matches(Parent, this, &BuilderCopy)) {
692
494
        *Builder = std::move(BuilderCopy);
693
494
        return true;
694
494
      }
695
3.75k
      if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
696
3.45k
        return memoizedMatchesAncestorOfRecursively(Parent, Matcher, Builder,
697
3.45k
                                                    MatchMode);
698
3.45k
        // Once we get back from the recursive call, the result will be the
699
3.45k
        // same as the parent's result.
700
3.45k
      }
701
15
    } else {
702
15
      // Multiple parents - BFS over the rest of the nodes.
703
15
      llvm::DenseSet<const void *> Visited;
704
15
      std::deque<ast_type_traits::DynTypedNode> Queue(Parents.begin(),
705
15
                                                      Parents.end());
706
53
      while (!Queue.empty()) {
707
50
        BoundNodesTreeBuilder BuilderCopy = *Builder;
708
50
        if (Matcher.matches(Queue.front(), this, &BuilderCopy)) {
709
12
          *Builder = std::move(BuilderCopy);
710
12
          return true;
711
12
        }
712
38
        if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
713
34
          for (const auto &Parent :
714
34
               ActiveASTContext->getParents(Queue.front())) {
715
32
            // Make sure we do not visit the same node twice.
716
32
            // Otherwise, we'll visit the common ancestors as often as there
717
32
            // are splits on the way down.
718
32
            if (Visited.insert(Parent.getMemoizationData()).second)
719
29
              Queue.push_back(Parent);
720
32
          }
721
34
        }
722
38
        Queue.pop_front();
723
38
      }
724
15
    }
725
4.26k
    
return false298
;
726
4.26k
  }
727
728
  // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
729
  // the aggregated bound nodes for each match.
730
  class MatchVisitor : public BoundNodesTreeBuilder::Visitor {
731
  public:
732
    MatchVisitor(ASTContext* Context,
733
                 MatchFinder::MatchCallback* Callback)
734
      : Context(Context),
735
9.84k
        Callback(Callback) {}
736
737
10.0k
    void visitMatch(const BoundNodes& BoundNodesView) override {
738
10.0k
      Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
739
10.0k
    }
740
741
  private:
742
    ASTContext* Context;
743
    MatchFinder::MatchCallback* Callback;
744
  };
745
746
  // Returns true if 'TypeNode' has an alias that matches the given matcher.
747
  bool typeHasMatchingAlias(const Type *TypeNode,
748
                            const Matcher<NamedDecl> &Matcher,
749
563
                            BoundNodesTreeBuilder *Builder) {
750
563
    const Type *const CanonicalType =
751
563
      ActiveASTContext->getCanonicalType(TypeNode);
752
563
    auto Aliases = TypeAliases.find(CanonicalType);
753
563
    if (Aliases == TypeAliases.end())
754
533
      return false;
755
48
    
for (const TypedefNameDecl *Alias : Aliases->second)30
{
756
48
      BoundNodesTreeBuilder Result(*Builder);
757
48
      if (Matcher.matches(*Alias, this, &Result)) {
758
12
        *Builder = std::move(Result);
759
12
        return true;
760
12
      }
761
48
    }
762
30
    
return false18
;
763
30
  }
764
765
  /// Bucket to record map.
766
  ///
767
  /// Used to get the appropriate bucket for each matcher.
768
  llvm::StringMap<llvm::TimeRecord> TimeByBucket;
769
770
  const MatchFinder::MatchersByType *Matchers;
771
772
  /// Filtered list of matcher indices for each matcher kind.
773
  ///
774
  /// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
775
  /// kind (and derived kinds) so it is a waste to try every matcher on every
776
  /// node.
777
  /// We precalculate a list of matchers that pass the toplevel restrict check.
778
  /// This also allows us to skip the restrict check at matching time. See
779
  /// use \c matchesNoKindCheck() above.
780
  llvm::DenseMap<ast_type_traits::ASTNodeKind, std::vector<unsigned short>>
781
      MatcherFiltersMap;
782
783
  const MatchFinder::MatchFinderOptions &Options;
784
  ASTContext *ActiveASTContext;
785
786
  // Maps a canonical type to its TypedefDecls.
787
  llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
788
789
  // Maps (matcher, node) -> the match result for memoization.
790
  typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
791
  MemoizationMap ResultCache;
792
};
793
794
static CXXRecordDecl *
795
551
getAsCXXRecordDeclOrPrimaryTemplate(const Type *TypeNode) {
796
551
  if (auto *RD = TypeNode->getAsCXXRecordDecl())
797
513
    return RD;
798
38
799
38
  // Find the innermost TemplateSpecializationType that isn't an alias template.
800
38
  auto *TemplateType = TypeNode->getAs<TemplateSpecializationType>();
801
40
  while (TemplateType && 
TemplateType->isTypeAlias()22
)
802
2
    TemplateType =
803
2
        TemplateType->getAliasedType()->getAs<TemplateSpecializationType>();
804
38
805
38
  // If this is the name of a (dependent) template specialization, use the
806
38
  // definition of the template, even though it might be specialized later.
807
38
  if (TemplateType)
808
20
    if (auto *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(
809
16
          TemplateType->getTemplateName().getAsTemplateDecl()))
810
16
      return ClassTemplate->getTemplatedDecl();
811
22
812
22
  return nullptr;
813
22
}
814
815
// Returns true if the given class is directly or indirectly derived
816
// from a base type with the given name.  A class is not considered to be
817
// derived from itself.
818
bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
819
                                         const Matcher<NamedDecl> &Base,
820
1.26k
                                         BoundNodesTreeBuilder *Builder) {
821
1.26k
  if (!Declaration->hasDefinition())
822
463
    return false;
823
805
  for (const auto &It : Declaration->bases()) {
824
563
    const Type *TypeNode = It.getType().getTypePtr();
825
563
826
563
    if (typeHasMatchingAlias(TypeNode, Base, Builder))
827
12
      return true;
828
551
829
551
    // FIXME: Going to the primary template here isn't really correct, but
830
551
    // unfortunately we accept a Decl matcher for the base class not a Type
831
551
    // matcher, so it's the best thing we can do with our current interface.
832
551
    CXXRecordDecl *ClassDecl = getAsCXXRecordDeclOrPrimaryTemplate(TypeNode);
833
551
    if (!ClassDecl)
834
22
      continue;
835
529
    if (ClassDecl == Declaration) {
836
4
      // This can happen for recursive template definitions; if the
837
4
      // current declaration did not match, we can safely return false.
838
4
      return false;
839
4
    }
840
525
    BoundNodesTreeBuilder Result(*Builder);
841
525
    if (Base.matches(*ClassDecl, this, &Result)) {
842
258
      *Builder = std::move(Result);
843
258
      return true;
844
258
    }
845
267
    if (classIsDerivedFrom(ClassDecl, Base, Builder))
846
220
      return true;
847
267
  }
848
805
  
return false311
;
849
805
}
850
851
73.0k
bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
852
73.0k
  if (!DeclNode) {
853
27
    return true;
854
27
  }
855
73.0k
  match(*DeclNode);
856
73.0k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
857
73.0k
}
858
859
36.3k
bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
860
36.3k
  if (!StmtNode) {
861
8.27k
    return true;
862
8.27k
  }
863
28.1k
  match(*StmtNode);
864
28.1k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode, Queue);
865
28.1k
}
866
867
7.92k
bool MatchASTVisitor::TraverseType(QualType TypeNode) {
868
7.92k
  match(TypeNode);
869
7.92k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
870
7.92k
}
871
872
66.2k
bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
873
66.2k
  // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
874
66.2k
  // We still want to find those types via matchers, so we match them here. Note
875
66.2k
  // that the TypeLocs are structurally a shadow-hierarchy to the expressed
876
66.2k
  // type, so we visit all involved parts of a compound type when matching on
877
66.2k
  // each TypeLoc.
878
66.2k
  match(TypeLocNode);
879
66.2k
  match(TypeLocNode.getType());
880
66.2k
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode);
881
66.2k
}
882
883
2
bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
884
2
  match(*NNS);
885
2
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
886
2
}
887
888
bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
889
38.2k
    NestedNameSpecifierLoc NNS) {
890
38.2k
  if (!NNS)
891
37.7k
    return true;
892
570
893
570
  match(NNS);
894
570
895
570
  // We only match the nested name specifier here (as opposed to traversing it)
896
570
  // because the traversal is already done in the parallel "Loc"-hierarchy.
897
570
  if (NNS.hasQualifier())
898
570
    match(*NNS.getNestedNameSpecifier());
899
570
  return
900
570
      RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
901
570
}
902
903
bool MatchASTVisitor::TraverseConstructorInitializer(
904
491
    CXXCtorInitializer *CtorInit) {
905
491
  if (!CtorInit)
906
0
    return true;
907
491
908
491
  match(*CtorInit);
909
491
910
491
  return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
911
491
      CtorInit);
912
491
}
913
914
class MatchASTConsumer : public ASTConsumer {
915
public:
916
  MatchASTConsumer(MatchFinder *Finder,
917
                   MatchFinder::ParsingDoneTestCallback *ParsingDone)
918
2.30k
      : Finder(Finder), ParsingDone(ParsingDone) {}
919
920
private:
921
2.30k
  void HandleTranslationUnit(ASTContext &Context) override {
922
2.30k
    if (ParsingDone != nullptr) {
923
0
      ParsingDone->run();
924
0
    }
925
2.30k
    Finder->matchAST(Context);
926
2.30k
  }
927
928
  MatchFinder *Finder;
929
  MatchFinder::ParsingDoneTestCallback *ParsingDone;
930
};
931
932
} // end namespace
933
} // end namespace internal
934
935
MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes,
936
                                      ASTContext *Context)
937
  : Nodes(Nodes), Context(Context),
938
10.1k
    SourceManager(&Context->getSourceManager()) {}
939
940
28.0k
MatchFinder::MatchCallback::~MatchCallback() {}
941
0
MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
942
943
MatchFinder::MatchFinder(MatchFinderOptions Options)
944
26.6k
    : Options(std::move(Options)), ParsingDone(nullptr) {}
945
946
26.6k
MatchFinder::~MatchFinder() {}
947
948
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
949
7.68k
                             MatchCallback *Action) {
950
7.68k
  Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
951
7.68k
  Matchers.AllCallbacks.insert(Action);
952
7.68k
}
953
954
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
955
199
                             MatchCallback *Action) {
956
199
  Matchers.Type.emplace_back(NodeMatch, Action);
957
199
  Matchers.AllCallbacks.insert(Action);
958
199
}
959
960
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
961
20.3k
                             MatchCallback *Action) {
962
20.3k
  Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
963
20.3k
  Matchers.AllCallbacks.insert(Action);
964
20.3k
}
965
966
void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
967
34
                             MatchCallback *Action) {
968
34
  Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action);
969
34
  Matchers.AllCallbacks.insert(Action);
970
34
}
971
972
void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
973
18
                             MatchCallback *Action) {
974
18
  Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action);
975
18
  Matchers.AllCallbacks.insert(Action);
976
18
}
977
978
void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
979
45
                             MatchCallback *Action) {
980
45
  Matchers.TypeLoc.emplace_back(NodeMatch, Action);
981
45
  Matchers.AllCallbacks.insert(Action);
982
45
}
983
984
void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
985
3
                             MatchCallback *Action) {
986
3
  Matchers.CtorInit.emplace_back(NodeMatch, Action);
987
3
  Matchers.AllCallbacks.insert(Action);
988
3
}
989
990
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
991
1.72k
                                    MatchCallback *Action) {
992
1.72k
  if (NodeMatch.canConvertTo<Decl>()) {
993
883
    addMatcher(NodeMatch.convertTo<Decl>(), Action);
994
883
    return true;
995
883
  } else 
if (843
NodeMatch.canConvertTo<QualType>()843
) {
996
98
    addMatcher(NodeMatch.convertTo<QualType>(), Action);
997
98
    return true;
998
745
  } else if (NodeMatch.canConvertTo<Stmt>()) {
999
709
    addMatcher(NodeMatch.convertTo<Stmt>(), Action);
1000
709
    return true;
1001
709
  } else 
if (36
NodeMatch.canConvertTo<NestedNameSpecifier>()36
) {
1002
16
    addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action);
1003
16
    return true;
1004
20
  } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) {
1005
7
    addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action);
1006
7
    return true;
1007
13
  } else if (NodeMatch.canConvertTo<TypeLoc>()) {
1008
10
    addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
1009
10
    return true;
1010
10
  } else 
if (3
NodeMatch.canConvertTo<CXXCtorInitializer>()3
) {
1011
1
    addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
1012
1
    return true;
1013
1
  }
1014
2
  return false;
1015
2
}
1016
1017
2.30k
std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
1018
2.30k
  return llvm::make_unique<internal::MatchASTConsumer>(this, ParsingDone);
1019
2.30k
}
1020
1021
void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
1022
20.4k
                        ASTContext &Context) {
1023
20.4k
  internal::MatchASTVisitor Visitor(&Matchers, Options);
1024
20.4k
  Visitor.set_active_ast_context(&Context);
1025
20.4k
  Visitor.match(Node);
1026
20.4k
}
1027
1028
6.32k
void MatchFinder::matchAST(ASTContext &Context) {
1029
6.32k
  internal::MatchASTVisitor Visitor(&Matchers, Options);
1030
6.32k
  Visitor.set_active_ast_context(&Context);
1031
6.32k
  Visitor.onStartOfTranslationUnit();
1032
6.32k
  Visitor.TraverseAST(Context);
1033
6.32k
  Visitor.onEndOfTranslationUnit();
1034
6.32k
}
1035
1036
void MatchFinder::registerTestCallbackAfterParsing(
1037
0
    MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
1038
0
  ParsingDone = NewParsingDone;
1039
0
}
1040
1041
0
StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
1042
1043
} // end namespace ast_matchers
1044
} // end namespace clang