clang  10.0.0git
ASTMatchFinder.cpp
Go to the documentation of this file.
1 //===--- ASTMatchFinder.cpp - Structural query framework ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implements an algorithm to efficiently search for matches on AST nodes.
10 // Uses memoization to support recursive matches like HasDescendant.
11 //
12 // The general idea is to visit all AST nodes with a RecursiveASTVisitor,
13 // calling the Matches(...) method of each matcher we are running on each
14 // AST node. The matcher can recurse via the ASTMatchFinder interface.
15 //
16 //===----------------------------------------------------------------------===//
17 
19 #include "clang/AST/ASTConsumer.h"
20 #include "clang/AST/ASTContext.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;
61  BoundNodesTreeBuilder BoundNodes;
63 
64  bool operator<(const MatchKey &Other) const {
65  return std::tie(MatcherID, Node, BoundNodes, Traversal) <
66  std::tie(Other.MatcherID, Other.Node, Other.BoundNodes,
67  Other.Traversal);
68  }
69 };
70 
71 // Used to store the result of a match and possibly bound nodes.
72 struct MemoizedMatchResult {
74  BoundNodesTreeBuilder Nodes;
75 };
76 
77 // A RecursiveASTVisitor that traverses all children or all descendants of
78 // a node.
79 class MatchChildASTVisitor
80  : public RecursiveASTVisitor<MatchChildASTVisitor> {
81 public:
82  typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
83 
84  // Creates an AST visitor that matches 'matcher' on all children or
85  // descendants of a traversed node. max_depth is the maximum depth
86  // to traverse: use 1 for matching the children and INT_MAX for
87  // matching the descendants.
88  MatchChildASTVisitor(const DynTypedMatcher *Matcher, ASTMatchFinder *Finder,
89  BoundNodesTreeBuilder *Builder, int MaxDepth,
91  ASTMatchFinder::BindKind Bind)
92  : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0),
93  MaxDepth(MaxDepth), Traversal(Traversal), Bind(Bind), Matches(false) {}
94 
95  // Returns true if a match is found in the subtree rooted at the
96  // given AST node. This is done via a set of mutually recursive
97  // functions. Here's how the recursion is done (the *wildcard can
98  // actually be Decl, Stmt, or Type):
99  //
100  // - Traverse(node) calls BaseTraverse(node) when it needs
101  // to visit the descendants of node.
102  // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
103  // Traverse*(c) for each child c of 'node'.
104  // - Traverse*(c) in turn calls Traverse(c), completing the
105  // recursion.
106  bool findMatch(const ast_type_traits::DynTypedNode &DynNode) {
107  reset();
108  if (const Decl *D = DynNode.get<Decl>())
109  traverse(*D);
110  else if (const Stmt *S = DynNode.get<Stmt>())
111  traverse(*S);
112  else if (const NestedNameSpecifier *NNS =
113  DynNode.get<NestedNameSpecifier>())
114  traverse(*NNS);
115  else if (const NestedNameSpecifierLoc *NNSLoc =
116  DynNode.get<NestedNameSpecifierLoc>())
117  traverse(*NNSLoc);
118  else if (const QualType *Q = DynNode.get<QualType>())
119  traverse(*Q);
120  else if (const TypeLoc *T = DynNode.get<TypeLoc>())
121  traverse(*T);
122  else if (const auto *C = DynNode.get<CXXCtorInitializer>())
123  traverse(*C);
124  // FIXME: Add other base types after adding tests.
125 
126  // It's OK to always overwrite the bound nodes, as if there was
127  // no match in this recursive branch, the result set is empty
128  // anyway.
129  *Builder = ResultBindings;
130 
131  return Matches;
132  }
133 
134  // The following are overriding methods from the base visitor class.
135  // They are public only to allow CRTP to work. They are *not *part
136  // of the public API of this class.
137  bool TraverseDecl(Decl *DeclNode) {
138  ScopedIncrement ScopedDepth(&CurrentDepth);
139  return (DeclNode == nullptr) || traverse(*DeclNode);
140  }
141 
142  Stmt *getStmtToTraverse(Stmt *StmtNode) {
143  Stmt *StmtToTraverse = StmtNode;
144  if (auto *ExprNode = dyn_cast_or_null<Expr>(StmtNode)) {
145  auto *LambdaNode = dyn_cast_or_null<LambdaExpr>(StmtNode);
146  if (LambdaNode && Finder->getASTContext().getTraversalKind() ==
148  StmtToTraverse = LambdaNode;
149  else
150  StmtToTraverse = Finder->getASTContext().traverseIgnored(ExprNode);
151  }
152  if (Traversal ==
154  if (Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode))
155  StmtToTraverse = ExprNode->IgnoreParenImpCasts();
156  }
157  return StmtToTraverse;
158  }
159 
160  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) {
161  // If we need to keep track of the depth, we can't perform data recursion.
162  if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX))
163  Queue = nullptr;
164 
165  ScopedIncrement ScopedDepth(&CurrentDepth);
166  Stmt *StmtToTraverse = getStmtToTraverse(StmtNode);
167  if (!StmtToTraverse)
168  return true;
169  if (!match(*StmtToTraverse))
170  return false;
171  return VisitorBase::TraverseStmt(StmtToTraverse, Queue);
172  }
173  // We assume that the QualType and the contained type are on the same
174  // hierarchy level. Thus, we try to match either of them.
175  bool TraverseType(QualType TypeNode) {
176  if (TypeNode.isNull())
177  return true;
178  ScopedIncrement ScopedDepth(&CurrentDepth);
179  // Match the Type.
180  if (!match(*TypeNode))
181  return false;
182  // The QualType is matched inside traverse.
183  return traverse(TypeNode);
184  }
185  // We assume that the TypeLoc, contained QualType and contained Type all are
186  // on the same hierarchy level. Thus, we try to match all of them.
187  bool TraverseTypeLoc(TypeLoc TypeLocNode) {
188  if (TypeLocNode.isNull())
189  return true;
190  ScopedIncrement ScopedDepth(&CurrentDepth);
191  // Match the Type.
192  if (!match(*TypeLocNode.getType()))
193  return false;
194  // Match the QualType.
195  if (!match(TypeLocNode.getType()))
196  return false;
197  // The TypeLoc is matched inside traverse.
198  return traverse(TypeLocNode);
199  }
200  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
201  ScopedIncrement ScopedDepth(&CurrentDepth);
202  return (NNS == nullptr) || traverse(*NNS);
203  }
204  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
205  if (!NNS)
206  return true;
207  ScopedIncrement ScopedDepth(&CurrentDepth);
208  if (!match(*NNS.getNestedNameSpecifier()))
209  return false;
210  return traverse(NNS);
211  }
212  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
213  if (!CtorInit)
214  return true;
215  ScopedIncrement ScopedDepth(&CurrentDepth);
216  return traverse(*CtorInit);
217  }
218  bool TraverseLambdaExpr(LambdaExpr *Node) {
219  if (Finder->getASTContext().getTraversalKind() !=
221  return VisitorBase::TraverseLambdaExpr(Node);
222  if (!Node)
223  return true;
224  ScopedIncrement ScopedDepth(&CurrentDepth);
225 
226  for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
227  const auto *C = Node->capture_begin() + I;
228  if (!C->isExplicit())
229  continue;
230  if (Node->isInitCapture(C) && !match(*C->getCapturedVar()))
231  return false;
232  if (!match(*Node->capture_init_begin()[I]))
233  return false;
234  }
235 
236  if (const auto *TPL = Node->getTemplateParameterList()) {
237  for (const auto *TP : *TPL) {
238  if (!match(*TP))
239  return false;
240  }
241  }
242 
243  for (const auto *P : Node->getCallOperator()->parameters()) {
244  if (!match(*P))
245  return false;
246  }
247 
248  if (!match(*Node->getBody()))
249  return false;
250 
251  return true;
252  }
253 
254  bool shouldVisitTemplateInstantiations() const { return true; }
255  bool shouldVisitImplicitCode() const { return true; }
256 
257 private:
258  // Used for updating the depth during traversal.
259  struct ScopedIncrement {
260  explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); }
261  ~ScopedIncrement() { --(*Depth); }
262 
263  private:
264  int *Depth;
265  };
266 
267  // Resets the state of this object.
268  void reset() {
269  Matches = false;
270  CurrentDepth = 0;
271  }
272 
273  // Forwards the call to the corresponding Traverse*() method in the
274  // base visitor class.
275  bool baseTraverse(const Decl &DeclNode) {
276  return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode));
277  }
278  bool baseTraverse(const Stmt &StmtNode) {
279  return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode));
280  }
281  bool baseTraverse(QualType TypeNode) {
282  return VisitorBase::TraverseType(TypeNode);
283  }
284  bool baseTraverse(TypeLoc TypeLocNode) {
285  return VisitorBase::TraverseTypeLoc(TypeLocNode);
286  }
287  bool baseTraverse(const NestedNameSpecifier &NNS) {
288  return VisitorBase::TraverseNestedNameSpecifier(
289  const_cast<NestedNameSpecifier*>(&NNS));
290  }
291  bool baseTraverse(NestedNameSpecifierLoc NNS) {
292  return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
293  }
294  bool baseTraverse(const CXXCtorInitializer &CtorInit) {
295  return VisitorBase::TraverseConstructorInitializer(
296  const_cast<CXXCtorInitializer *>(&CtorInit));
297  }
298 
299  // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
300  // 0 < CurrentDepth <= MaxDepth.
301  //
302  // Returns 'true' if traversal should continue after this function
303  // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
304  template <typename T>
305  bool match(const T &Node) {
306  if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
307  return true;
308  }
309  if (Bind != ASTMatchFinder::BK_All) {
310  BoundNodesTreeBuilder RecursiveBuilder(*Builder);
311  if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
312  &RecursiveBuilder)) {
313  Matches = true;
314  ResultBindings.addMatch(RecursiveBuilder);
315  return false; // Abort as soon as a match is found.
316  }
317  } else {
318  BoundNodesTreeBuilder RecursiveBuilder(*Builder);
319  if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
320  &RecursiveBuilder)) {
321  // After the first match the matcher succeeds.
322  Matches = true;
323  ResultBindings.addMatch(RecursiveBuilder);
324  }
325  }
326  return true;
327  }
328 
329  // Traverses the subtree rooted at 'Node'; returns true if the
330  // traversal should continue after this function returns.
331  template <typename T>
332  bool traverse(const T &Node) {
333  static_assert(IsBaseType<T>::value,
334  "traverse can only be instantiated with base type");
335  if (!match(Node))
336  return false;
337  return baseTraverse(Node);
338  }
339 
340  const DynTypedMatcher *const Matcher;
341  ASTMatchFinder *const Finder;
342  BoundNodesTreeBuilder *const Builder;
343  BoundNodesTreeBuilder ResultBindings;
344  int CurrentDepth;
345  const int MaxDepth;
347  const ASTMatchFinder::BindKind Bind;
348  bool Matches;
349 };
350 
351 // Controls the outermost traversal of the AST and allows to match multiple
352 // matchers.
353 class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
354  public ASTMatchFinder {
355 public:
356  MatchASTVisitor(const MatchFinder::MatchersByType *Matchers,
357  const MatchFinder::MatchFinderOptions &Options)
358  : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {}
359 
360  ~MatchASTVisitor() override {
361  if (Options.CheckProfiling) {
362  Options.CheckProfiling->Records = std::move(TimeByBucket);
363  }
364  }
365 
366  void onStartOfTranslationUnit() {
367  const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
368  TimeBucketRegion Timer;
369  for (MatchCallback *MC : Matchers->AllCallbacks) {
370  if (EnableCheckProfiling)
371  Timer.setBucket(&TimeByBucket[MC->getID()]);
372  MC->onStartOfTranslationUnit();
373  }
374  }
375 
376  void onEndOfTranslationUnit() {
377  const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
378  TimeBucketRegion Timer;
379  for (MatchCallback *MC : Matchers->AllCallbacks) {
380  if (EnableCheckProfiling)
381  Timer.setBucket(&TimeByBucket[MC->getID()]);
382  MC->onEndOfTranslationUnit();
383  }
384  }
385 
386  void set_active_ast_context(ASTContext *NewActiveASTContext) {
387  ActiveASTContext = NewActiveASTContext;
388  }
389 
390  // The following Visit*() and Traverse*() functions "override"
391  // methods in RecursiveASTVisitor.
392 
393  bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
394  // When we see 'typedef A B', we add name 'B' to the set of names
395  // A's canonical type maps to. This is necessary for implementing
396  // isDerivedFrom(x) properly, where x can be the name of the base
397  // class or any of its aliases.
398  //
399  // In general, the is-alias-of (as defined by typedefs) relation
400  // is tree-shaped, as you can typedef a type more than once. For
401  // example,
402  //
403  // typedef A B;
404  // typedef A C;
405  // typedef C D;
406  // typedef C E;
407  //
408  // gives you
409  //
410  // A
411  // |- B
412  // `- C
413  // |- D
414  // `- E
415  //
416  // It is wrong to assume that the relation is a chain. A correct
417  // implementation of isDerivedFrom() needs to recognize that B and
418  // E are aliases, even though neither is a typedef of the other.
419  // Therefore, we cannot simply walk through one typedef chain to
420  // find out whether the type name matches.
421  const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
422  const Type *CanonicalType = // root of the typedef tree
423  ActiveASTContext->getCanonicalType(TypeNode);
424  TypeAliases[CanonicalType].insert(DeclNode);
425  return true;
426  }
427 
428  bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
429  const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface();
430  CompatibleAliases[InterfaceDecl].insert(CAD);
431  return true;
432  }
433 
434  bool TraverseDecl(Decl *DeclNode);
435  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr);
436  bool TraverseType(QualType TypeNode);
437  bool TraverseTypeLoc(TypeLoc TypeNode);
438  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
439  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
440  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
441 
442  // Matches children or descendants of 'Node' with 'BaseMatcher'.
443  bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node,
444  ASTContext &Ctx,
445  const DynTypedMatcher &Matcher,
446  BoundNodesTreeBuilder *Builder, int MaxDepth,
448  BindKind Bind) {
449  // For AST-nodes that don't have an identity, we can't memoize.
450  if (!Node.getMemoizationData() || !Builder->isComparable())
451  return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal,
452  Bind);
453 
454  MatchKey Key;
455  Key.MatcherID = Matcher.getID();
456  Key.Node = Node;
457  // Note that we key on the bindings *before* the match.
458  Key.BoundNodes = *Builder;
459  Key.Traversal = Ctx.getTraversalKind();
460 
461  MemoizationMap::iterator I = ResultCache.find(Key);
462  if (I != ResultCache.end()) {
463  *Builder = I->second.Nodes;
464  return I->second.ResultOfMatch;
465  }
466 
467  MemoizedMatchResult Result;
468  Result.Nodes = *Builder;
469  Result.ResultOfMatch = matchesRecursively(Node, Matcher, &Result.Nodes,
470  MaxDepth, Traversal, Bind);
471 
472  MemoizedMatchResult &CachedResult = ResultCache[Key];
473  CachedResult = std::move(Result);
474 
475  *Builder = CachedResult.Nodes;
476  return CachedResult.ResultOfMatch;
477  }
478 
479  // Matches children or descendants of 'Node' with 'BaseMatcher'.
480  bool matchesRecursively(const ast_type_traits::DynTypedNode &Node,
481  const DynTypedMatcher &Matcher,
482  BoundNodesTreeBuilder *Builder, int MaxDepth,
484  BindKind Bind) {
485  MatchChildASTVisitor Visitor(
486  &Matcher, this, Builder, MaxDepth, Traversal, Bind);
487  return Visitor.findMatch(Node);
488  }
489 
490  bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
491  const Matcher<NamedDecl> &Base,
492  BoundNodesTreeBuilder *Builder,
493  bool Directly) override;
494 
495  bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
496  const Matcher<NamedDecl> &Base,
497  BoundNodesTreeBuilder *Builder,
498  bool Directly) override;
499 
500  // Implements ASTMatchFinder::matchesChildOf.
501  bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
502  ASTContext &Ctx, const DynTypedMatcher &Matcher,
503  BoundNodesTreeBuilder *Builder,
505  BindKind Bind) override {
506  if (ResultCache.size() > MaxMemoizationEntries)
507  ResultCache.clear();
508  return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, Traversal,
509  Bind);
510  }
511  // Implements ASTMatchFinder::matchesDescendantOf.
512  bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
513  ASTContext &Ctx, const DynTypedMatcher &Matcher,
514  BoundNodesTreeBuilder *Builder,
515  BindKind Bind) override {
516  if (ResultCache.size() > MaxMemoizationEntries)
517  ResultCache.clear();
518  return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, INT_MAX,
520  Bind);
521  }
522  // Implements ASTMatchFinder::matchesAncestorOf.
523  bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
524  ASTContext &Ctx, const DynTypedMatcher &Matcher,
525  BoundNodesTreeBuilder *Builder,
526  AncestorMatchMode MatchMode) override {
527  // Reset the cache outside of the recursive call to make sure we
528  // don't invalidate any iterators.
529  if (ResultCache.size() > MaxMemoizationEntries)
530  ResultCache.clear();
531  return memoizedMatchesAncestorOfRecursively(Node, Ctx, Matcher, Builder,
532  MatchMode);
533  }
534 
535  // Matches all registered matchers on the given node and calls the
536  // result callback for every node that matches.
537  void match(const ast_type_traits::DynTypedNode &Node) {
538  // FIXME: Improve this with a switch or a visitor pattern.
539  if (auto *N = Node.get<Decl>()) {
540  match(*N);
541  } else if (auto *N = Node.get<Stmt>()) {
542  match(*N);
543  } else if (auto *N = Node.get<Type>()) {
544  match(*N);
545  } else if (auto *N = Node.get<QualType>()) {
546  match(*N);
547  } else if (auto *N = Node.get<NestedNameSpecifier>()) {
548  match(*N);
549  } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
550  match(*N);
551  } else if (auto *N = Node.get<TypeLoc>()) {
552  match(*N);
553  } else if (auto *N = Node.get<CXXCtorInitializer>()) {
554  match(*N);
555  }
556  }
557 
558  template <typename T> void match(const T &Node) {
559  matchDispatch(&Node);
560  }
561 
562  // Implements ASTMatchFinder::getASTContext.
563  ASTContext &getASTContext() const override { return *ActiveASTContext; }
564 
565  bool shouldVisitTemplateInstantiations() const { return true; }
566  bool shouldVisitImplicitCode() const { return true; }
567 
568 private:
569  class TimeBucketRegion {
570  public:
571  TimeBucketRegion() : Bucket(nullptr) {}
572  ~TimeBucketRegion() { setBucket(nullptr); }
573 
574  /// Start timing for \p NewBucket.
575  ///
576  /// If there was a bucket already set, it will finish the timing for that
577  /// other bucket.
578  /// \p NewBucket will be timed until the next call to \c setBucket() or
579  /// until the \c TimeBucketRegion is destroyed.
580  /// If \p NewBucket is the same as the currently timed bucket, this call
581  /// does nothing.
582  void setBucket(llvm::TimeRecord *NewBucket) {
583  if (Bucket != NewBucket) {
584  auto Now = llvm::TimeRecord::getCurrentTime(true);
585  if (Bucket)
586  *Bucket += Now;
587  if (NewBucket)
588  *NewBucket -= Now;
589  Bucket = NewBucket;
590  }
591  }
592 
593  private:
594  llvm::TimeRecord *Bucket;
595  };
596 
597  /// Runs all the \p Matchers on \p Node.
598  ///
599  /// Used by \c matchDispatch() below.
600  template <typename T, typename MC>
601  void matchWithoutFilter(const T &Node, const MC &Matchers) {
602  const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
603  TimeBucketRegion Timer;
604  for (const auto &MP : Matchers) {
605  if (EnableCheckProfiling)
606  Timer.setBucket(&TimeByBucket[MP.second->getID()]);
607  BoundNodesTreeBuilder Builder;
608  if (MP.first.matches(Node, this, &Builder)) {
609  MatchVisitor Visitor(ActiveASTContext, MP.second);
610  Builder.visitMatches(&Visitor);
611  }
612  }
613  }
614 
615  void matchWithFilter(const ast_type_traits::DynTypedNode &DynNode) {
616  auto Kind = DynNode.getNodeKind();
617  auto it = MatcherFiltersMap.find(Kind);
618  const auto &Filter =
619  it != MatcherFiltersMap.end() ? it->second : getFilterForKind(Kind);
620 
621  if (Filter.empty())
622  return;
623 
624  const bool EnableCheckProfiling = Options.CheckProfiling.hasValue();
625  TimeBucketRegion Timer;
626  auto &Matchers = this->Matchers->DeclOrStmt;
627  for (unsigned short I : Filter) {
628  auto &MP = Matchers[I];
629  if (EnableCheckProfiling)
630  Timer.setBucket(&TimeByBucket[MP.second->getID()]);
631  BoundNodesTreeBuilder Builder;
632  if (MP.first.matches(DynNode, this, &Builder)) {
633  MatchVisitor Visitor(ActiveASTContext, MP.second);
634  Builder.visitMatches(&Visitor);
635  }
636  }
637  }
638 
639  const std::vector<unsigned short> &
640  getFilterForKind(ast_type_traits::ASTNodeKind Kind) {
641  auto &Filter = MatcherFiltersMap[Kind];
642  auto &Matchers = this->Matchers->DeclOrStmt;
643  assert((Matchers.size() < USHRT_MAX) && "Too many matchers.");
644  for (unsigned I = 0, E = Matchers.size(); I != E; ++I) {
645  if (Matchers[I].first.canMatchNodesOfKind(Kind)) {
646  Filter.push_back(I);
647  }
648  }
649  return Filter;
650  }
651 
652  /// @{
653  /// Overloads to pair the different node types to their matchers.
654  void matchDispatch(const Decl *Node) {
655  return matchWithFilter(ast_type_traits::DynTypedNode::create(*Node));
656  }
657  void matchDispatch(const Stmt *Node) {
658  return matchWithFilter(ast_type_traits::DynTypedNode::create(*Node));
659  }
660 
661  void matchDispatch(const Type *Node) {
662  matchWithoutFilter(QualType(Node, 0), Matchers->Type);
663  }
664  void matchDispatch(const TypeLoc *Node) {
665  matchWithoutFilter(*Node, Matchers->TypeLoc);
666  }
667  void matchDispatch(const QualType *Node) {
668  matchWithoutFilter(*Node, Matchers->Type);
669  }
670  void matchDispatch(const NestedNameSpecifier *Node) {
671  matchWithoutFilter(*Node, Matchers->NestedNameSpecifier);
672  }
673  void matchDispatch(const NestedNameSpecifierLoc *Node) {
674  matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
675  }
676  void matchDispatch(const CXXCtorInitializer *Node) {
677  matchWithoutFilter(*Node, Matchers->CtorInit);
678  }
679  void matchDispatch(const void *) { /* Do nothing. */ }
680  /// @}
681 
682  // Returns whether an ancestor of \p Node matches \p Matcher.
683  //
684  // The order of matching ((which can lead to different nodes being bound in
685  // case there are multiple matches) is breadth first search.
686  //
687  // To allow memoization in the very common case of having deeply nested
688  // expressions inside a template function, we first walk up the AST, memoizing
689  // the result of the match along the way, as long as there is only a single
690  // parent.
691  //
692  // Once there are multiple parents, the breadth first search order does not
693  // allow simple memoization on the ancestors. Thus, we only memoize as long
694  // as there is a single parent.
695  bool memoizedMatchesAncestorOfRecursively(
696  const ast_type_traits::DynTypedNode &Node, ASTContext &Ctx,
697  const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder,
698  AncestorMatchMode MatchMode) {
699  // For AST-nodes that don't have an identity, we can't memoize.
700  if (!Builder->isComparable())
701  return matchesAncestorOfRecursively(Node, Ctx, Matcher, Builder,
702  MatchMode);
703 
704  MatchKey Key;
705  Key.MatcherID = Matcher.getID();
706  Key.Node = Node;
707  Key.BoundNodes = *Builder;
708  Key.Traversal = Ctx.getTraversalKind();
709 
710  // Note that we cannot use insert and reuse the iterator, as recursive
711  // calls to match might invalidate the result cache iterators.
712  MemoizationMap::iterator I = ResultCache.find(Key);
713  if (I != ResultCache.end()) {
714  *Builder = I->second.Nodes;
715  return I->second.ResultOfMatch;
716  }
717 
718  MemoizedMatchResult Result;
719  Result.Nodes = *Builder;
720  Result.ResultOfMatch = matchesAncestorOfRecursively(
721  Node, Ctx, Matcher, &Result.Nodes, MatchMode);
722 
723  MemoizedMatchResult &CachedResult = ResultCache[Key];
724  CachedResult = std::move(Result);
725 
726  *Builder = CachedResult.Nodes;
727  return CachedResult.ResultOfMatch;
728  }
729 
730  bool matchesAncestorOfRecursively(const ast_type_traits::DynTypedNode &Node,
731  ASTContext &Ctx,
732  const DynTypedMatcher &Matcher,
733  BoundNodesTreeBuilder *Builder,
734  AncestorMatchMode MatchMode) {
735  const auto &Parents = ActiveASTContext->getParents(Node);
736  if (Parents.empty()) {
737  // Nodes may have no parents if:
738  // a) the node is the TranslationUnitDecl
739  // b) we have a limited traversal scope that excludes the parent edges
740  // c) there is a bug in the AST, and the node is not reachable
741  // Usually the traversal scope is the whole AST, which precludes b.
742  // Bugs are common enough that it's worthwhile asserting when we can.
743 #ifndef NDEBUG
744  if (!Node.get<TranslationUnitDecl>() &&
745  /* Traversal scope is full AST if any of the bounds are the TU */
746  llvm::any_of(ActiveASTContext->getTraversalScope(), [](Decl *D) {
747  return D->getKind() == Decl::TranslationUnit;
748  })) {
749  llvm::errs() << "Tried to match orphan node:\n";
750  Node.dump(llvm::errs(), ActiveASTContext->getSourceManager());
751  llvm_unreachable("Parent map should be complete!");
752  }
753 #endif
754  return false;
755  }
756  if (Parents.size() == 1) {
757  // Only one parent - do recursive memoization.
758  const ast_type_traits::DynTypedNode Parent = Parents[0];
759  BoundNodesTreeBuilder BuilderCopy = *Builder;
760  if (Matcher.matches(Parent, this, &BuilderCopy)) {
761  *Builder = std::move(BuilderCopy);
762  return true;
763  }
764  if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
765  return memoizedMatchesAncestorOfRecursively(Parent, Ctx, Matcher,
766  Builder, MatchMode);
767  // Once we get back from the recursive call, the result will be the
768  // same as the parent's result.
769  }
770  } else {
771  // Multiple parents - BFS over the rest of the nodes.
773  std::deque<ast_type_traits::DynTypedNode> Queue(Parents.begin(),
774  Parents.end());
775  while (!Queue.empty()) {
776  BoundNodesTreeBuilder BuilderCopy = *Builder;
777  if (Matcher.matches(Queue.front(), this, &BuilderCopy)) {
778  *Builder = std::move(BuilderCopy);
779  return true;
780  }
781  if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
782  for (const auto &Parent :
783  ActiveASTContext->getParents(Queue.front())) {
784  // Make sure we do not visit the same node twice.
785  // Otherwise, we'll visit the common ancestors as often as there
786  // are splits on the way down.
787  if (Visited.insert(Parent.getMemoizationData()).second)
788  Queue.push_back(Parent);
789  }
790  }
791  Queue.pop_front();
792  }
793  }
794  return false;
795  }
796 
797  // Implements a BoundNodesTree::Visitor that calls a MatchCallback with
798  // the aggregated bound nodes for each match.
799  class MatchVisitor : public BoundNodesTreeBuilder::Visitor {
800  public:
801  MatchVisitor(ASTContext* Context,
802  MatchFinder::MatchCallback* Callback)
803  : Context(Context),
804  Callback(Callback) {}
805 
806  void visitMatch(const BoundNodes& BoundNodesView) override {
807  Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
808  }
809 
810  private:
811  ASTContext* Context;
812  MatchFinder::MatchCallback* Callback;
813  };
814 
815  // Returns true if 'TypeNode' has an alias that matches the given matcher.
816  bool typeHasMatchingAlias(const Type *TypeNode,
817  const Matcher<NamedDecl> &Matcher,
818  BoundNodesTreeBuilder *Builder) {
819  const Type *const CanonicalType =
820  ActiveASTContext->getCanonicalType(TypeNode);
821  auto Aliases = TypeAliases.find(CanonicalType);
822  if (Aliases == TypeAliases.end())
823  return false;
824  for (const TypedefNameDecl *Alias : Aliases->second) {
825  BoundNodesTreeBuilder Result(*Builder);
826  if (Matcher.matches(*Alias, this, &Result)) {
827  *Builder = std::move(Result);
828  return true;
829  }
830  }
831  return false;
832  }
833 
834  bool
835  objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl *InterfaceDecl,
836  const Matcher<NamedDecl> &Matcher,
837  BoundNodesTreeBuilder *Builder) {
838  auto Aliases = CompatibleAliases.find(InterfaceDecl);
839  if (Aliases == CompatibleAliases.end())
840  return false;
841  for (const ObjCCompatibleAliasDecl *Alias : Aliases->second) {
842  BoundNodesTreeBuilder Result(*Builder);
843  if (Matcher.matches(*Alias, this, &Result)) {
844  *Builder = std::move(Result);
845  return true;
846  }
847  }
848  return false;
849  }
850 
851  /// Bucket to record map.
852  ///
853  /// Used to get the appropriate bucket for each matcher.
854  llvm::StringMap<llvm::TimeRecord> TimeByBucket;
855 
856  const MatchFinder::MatchersByType *Matchers;
857 
858  /// Filtered list of matcher indices for each matcher kind.
859  ///
860  /// \c Decl and \c Stmt toplevel matchers usually apply to a specific node
861  /// kind (and derived kinds) so it is a waste to try every matcher on every
862  /// node.
863  /// We precalculate a list of matchers that pass the toplevel restrict check.
864  llvm::DenseMap<ast_type_traits::ASTNodeKind, std::vector<unsigned short>>
865  MatcherFiltersMap;
866 
867  const MatchFinder::MatchFinderOptions &Options;
868  ASTContext *ActiveASTContext;
869 
870  // Maps a canonical type to its TypedefDecls.
871  llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
872 
873  // Maps an Objective-C interface to its ObjCCompatibleAliasDecls.
874  llvm::DenseMap<const ObjCInterfaceDecl *,
875  llvm::SmallPtrSet<const ObjCCompatibleAliasDecl *, 2>>
876  CompatibleAliases;
877 
878  // Maps (matcher, node) -> the match result for memoization.
879  typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
880  MemoizationMap ResultCache;
881 };
882 
883 static CXXRecordDecl *
884 getAsCXXRecordDeclOrPrimaryTemplate(const Type *TypeNode) {
885  if (auto *RD = TypeNode->getAsCXXRecordDecl())
886  return RD;
887 
888  // Find the innermost TemplateSpecializationType that isn't an alias template.
889  auto *TemplateType = TypeNode->getAs<TemplateSpecializationType>();
890  while (TemplateType && TemplateType->isTypeAlias())
891  TemplateType =
892  TemplateType->getAliasedType()->getAs<TemplateSpecializationType>();
893 
894  // If this is the name of a (dependent) template specialization, use the
895  // definition of the template, even though it might be specialized later.
896  if (TemplateType)
897  if (auto *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(
898  TemplateType->getTemplateName().getAsTemplateDecl()))
899  return ClassTemplate->getTemplatedDecl();
900 
901  return nullptr;
902 }
903 
904 // Returns true if the given C++ class is directly or indirectly derived
905 // from a base type with the given name. A class is not considered to be
906 // derived from itself.
907 bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
908  const Matcher<NamedDecl> &Base,
909  BoundNodesTreeBuilder *Builder,
910  bool Directly) {
911  if (!Declaration->hasDefinition())
912  return false;
913  for (const auto &It : Declaration->bases()) {
914  const Type *TypeNode = It.getType().getTypePtr();
915 
916  if (typeHasMatchingAlias(TypeNode, Base, Builder))
917  return true;
918 
919  // FIXME: Going to the primary template here isn't really correct, but
920  // unfortunately we accept a Decl matcher for the base class not a Type
921  // matcher, so it's the best thing we can do with our current interface.
922  CXXRecordDecl *ClassDecl = getAsCXXRecordDeclOrPrimaryTemplate(TypeNode);
923  if (!ClassDecl)
924  continue;
925  if (ClassDecl == Declaration) {
926  // This can happen for recursive template definitions; if the
927  // current declaration did not match, we can safely return false.
928  return false;
929  }
930  BoundNodesTreeBuilder Result(*Builder);
931  if (Base.matches(*ClassDecl, this, &Result)) {
932  *Builder = std::move(Result);
933  return true;
934  }
935  if (!Directly && classIsDerivedFrom(ClassDecl, Base, Builder, Directly))
936  return true;
937  }
938  return false;
939 }
940 
941 // Returns true if the given Objective-C class is directly or indirectly
942 // derived from a matching base class. A class is not considered to be derived
943 // from itself.
944 bool MatchASTVisitor::objcClassIsDerivedFrom(
945  const ObjCInterfaceDecl *Declaration, const Matcher<NamedDecl> &Base,
946  BoundNodesTreeBuilder *Builder, bool Directly) {
947  // Check if any of the superclasses of the class match.
948  for (const ObjCInterfaceDecl *ClassDecl = Declaration->getSuperClass();
949  ClassDecl != nullptr; ClassDecl = ClassDecl->getSuperClass()) {
950  // Check if there are any matching compatibility aliases.
951  if (objcClassHasMatchingCompatibilityAlias(ClassDecl, Base, Builder))
952  return true;
953 
954  // Check if there are any matching type aliases.
955  const Type *TypeNode = ClassDecl->getTypeForDecl();
956  if (typeHasMatchingAlias(TypeNode, Base, Builder))
957  return true;
958 
959  if (Base.matches(*ClassDecl, this, Builder))
960  return true;
961 
962  // Not `return false` as a temporary workaround for PR43879.
963  if (Directly)
964  break;
965  }
966 
967  return false;
968 }
969 
970 bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
971  if (!DeclNode) {
972  return true;
973  }
974  match(*DeclNode);
976 }
977 
978 bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
979  if (!StmtNode) {
980  return true;
981  }
982  match(*StmtNode);
984 }
985 
986 bool MatchASTVisitor::TraverseType(QualType TypeNode) {
987  match(TypeNode);
989 }
990 
991 bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) {
992  // The RecursiveASTVisitor only visits types if they're not within TypeLocs.
993  // We still want to find those types via matchers, so we match them here. Note
994  // that the TypeLocs are structurally a shadow-hierarchy to the expressed
995  // type, so we visit all involved parts of a compound type when matching on
996  // each TypeLoc.
997  match(TypeLocNode);
998  match(TypeLocNode.getType());
1000 }
1001 
1002 bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
1003  match(*NNS);
1005 }
1006 
1007 bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
1008  NestedNameSpecifierLoc NNS) {
1009  if (!NNS)
1010  return true;
1011 
1012  match(NNS);
1013 
1014  // We only match the nested name specifier here (as opposed to traversing it)
1015  // because the traversal is already done in the parallel "Loc"-hierarchy.
1016  if (NNS.hasQualifier())
1017  match(*NNS.getNestedNameSpecifier());
1018  return
1020 }
1021 
1022 bool MatchASTVisitor::TraverseConstructorInitializer(
1023  CXXCtorInitializer *CtorInit) {
1024  if (!CtorInit)
1025  return true;
1026 
1027  match(*CtorInit);
1028 
1030  CtorInit);
1031 }
1032 
1033 class MatchASTConsumer : public ASTConsumer {
1034 public:
1035  MatchASTConsumer(MatchFinder *Finder,
1036  MatchFinder::ParsingDoneTestCallback *ParsingDone)
1037  : Finder(Finder), ParsingDone(ParsingDone) {}
1038 
1039 private:
1040  void HandleTranslationUnit(ASTContext &Context) override {
1041  if (ParsingDone != nullptr) {
1042  ParsingDone->run();
1043  }
1044  Finder->matchAST(Context);
1045  }
1046 
1047  MatchFinder *Finder;
1048  MatchFinder::ParsingDoneTestCallback *ParsingDone;
1049 };
1050 
1051 } // end namespace
1052 } // end namespace internal
1053 
1055  ASTContext *Context)
1056  : Nodes(Nodes), Context(Context),
1057  SourceManager(&Context->getSourceManager()) {}
1058 
1061 
1063  : Options(std::move(Options)), ParsingDone(nullptr) {}
1064 
1066 
1068  MatchCallback *Action) {
1069  Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
1070  Matchers.AllCallbacks.insert(Action);
1071 }
1072 
1073 void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
1074  MatchCallback *Action) {
1075  Matchers.Type.emplace_back(NodeMatch, Action);
1076  Matchers.AllCallbacks.insert(Action);
1077 }
1078 
1080  MatchCallback *Action) {
1081  Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
1082  Matchers.AllCallbacks.insert(Action);
1083 }
1084 
1086  MatchCallback *Action) {
1087  Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action);
1088  Matchers.AllCallbacks.insert(Action);
1089 }
1090 
1092  MatchCallback *Action) {
1093  Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action);
1094  Matchers.AllCallbacks.insert(Action);
1095 }
1096 
1098  MatchCallback *Action) {
1099  Matchers.TypeLoc.emplace_back(NodeMatch, Action);
1100  Matchers.AllCallbacks.insert(Action);
1101 }
1102 
1104  MatchCallback *Action) {
1105  Matchers.CtorInit.emplace_back(NodeMatch, Action);
1106  Matchers.AllCallbacks.insert(Action);
1107 }
1108 
1109 bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
1110  MatchCallback *Action) {
1111  if (NodeMatch.canConvertTo<Decl>()) {
1112  addMatcher(NodeMatch.convertTo<Decl>(), Action);
1113  return true;
1114  } else if (NodeMatch.canConvertTo<QualType>()) {
1115  addMatcher(NodeMatch.convertTo<QualType>(), Action);
1116  return true;
1117  } else if (NodeMatch.canConvertTo<Stmt>()) {
1118  addMatcher(NodeMatch.convertTo<Stmt>(), Action);
1119  return true;
1120  } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) {
1121  addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action);
1122  return true;
1123  } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) {
1124  addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action);
1125  return true;
1126  } else if (NodeMatch.canConvertTo<TypeLoc>()) {
1127  addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
1128  return true;
1129  } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
1130  addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
1131  return true;
1132  }
1133  return false;
1134 }
1135 
1136 std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
1137  return std::make_unique<internal::MatchASTConsumer>(this, ParsingDone);
1138 }
1139 
1141  ASTContext &Context) {
1142  internal::MatchASTVisitor Visitor(&Matchers, Options);
1143  Visitor.set_active_ast_context(&Context);
1144  Visitor.match(Node);
1145 }
1146 
1148  internal::MatchASTVisitor Visitor(&Matchers, Options);
1149  Visitor.set_active_ast_context(&Context);
1150  Visitor.onStartOfTranslationUnit();
1151  Visitor.TraverseAST(Context);
1152  Visitor.onEndOfTranslationUnit();
1153 }
1154 
1156  MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
1157  ParsingDone = NewParsingDone;
1158 }
1159 
1160 StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
1161 
1162 } // end namespace ast_matchers
1163 } // end namespace clang
Defines the clang::ASTContext interface.
A (possibly-)qualified type.
Definition: Type.h:654
internal::Matcher< NestedNameSpecifier > NestedNameSpecifierMatcher
Definition: ASTMatchers.h:142
Stmt - This represents one statement.
Definition: Stmt.h:66
internal::Matcher< Stmt > StatementMatcher
Definition: ASTMatchers.h:139
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
StringRef P
MatchFinder::MatchResult MatchResult
llvm::SmallPtrSet< MatchCallback *, 16 > AllCallbacks
All the callbacks in one container to simplify iteration.
Called when parsing is finished. Intended for testing only.
MatchFinder(MatchFinderOptions Options=MatchFinderOptions())
internal::Matcher< QualType > TypeMatcher
Definition: ASTMatchers.h:140
BoundNodesTreeBuilder Nodes
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument&#39;s dynamic ty...
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:58
void match(const T &Node, ASTContext &Context)
Calls the registered callbacks on all matches on the given Node.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:168
A C++ nested-name-specifier augmented with source location information.
Will traverse all child nodes.
Definition: ASTTypeTraits.h:42
Definition: Format.h:2445
void addMatcher(const DeclarationMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
std::vector< std::pair< CXXCtorInitializerMatcher, MatchCallback * > > CtorInit
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
DynTypedMatcher::MatcherIDType MatcherID
NodeId Parent
Definition: ASTDiff.cpp:191
ast_type_traits::TraversalKind Traversal
bool TraverseConstructorInitializer(CXXCtorInitializer *Init)
Recursively visit a constructor initializer.
Will not traverse implicit casts and parentheses.
Definition: ASTTypeTraits.h:46
Ignore AST nodes not written in the source.
Definition: ASTTypeTraits.h:49
int Depth
Definition: ASTDiff.cpp:190
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone)
Registers a callback to notify the end of parsing.
MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context)
std::unique_ptr< clang::ASTConsumer > newASTConsumer()
Creates a clang ASTConsumer that finds all matches.
#define USHRT_MAX
Definition: limits.h:55
Maps string IDs to AST nodes matched by parts of a matcher.
Definition: ASTMatchers.h:104
bool ResultOfMatch
llvm::cl::opt< std::string > Filter
Kind
virtual StringRef getID() const
An id used to group the matchers.
bool TraverseTypeLoc(TypeLoc TL)
Recursively visit a type with location, by dispatching to Traverse*TypeLoc() based on the argument ty...
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)
Recursively visit a C++ nested-name-specifier with location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
void matchAST(ASTContext &Context)
Finds all matches in the given AST.
std::vector< std::pair< NestedNameSpecifierLocMatcher, MatchCallback * > > NestedNameSpecifierLoc
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument&#39;s dy...
std::vector< std::pair< internal::DynTypedMatcher, MatchCallback * > > DeclOrStmt
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
bool TraverseType(QualType T)
Recursively visit a type, by dispatching to Traverse*Type() based on the argument&#39;s getTypeClass() pr...
static DynTypedNode create(const T &Node)
Creates a DynTypedNode from Node.
std::vector< std::pair< NestedNameSpecifierMatcher, MatchCallback * > > NestedNameSpecifier
std::vector< std::pair< TypeMatcher, MatchCallback * > > Type
BoundNodesTreeBuilder BoundNodes
ast_type_traits::DynTypedNode DynTypedNode
ast_type_traits::DynTypedNode Node
Optional< types::ID > Type
Dataflow Directional Tag Classes.
internal::Matcher< CXXCtorInitializer > CXXCtorInitializerMatcher
Definition: ASTMatchers.h:144
A dynamically typed AST node container.
std::vector< std::pair< TypeLocMatcher, MatchCallback * > > TypeLoc
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2155
TraversalKind
Defines how we descend a level in the AST when we pass through expressions.
Definition: ASTTypeTraits.h:40
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS)
Recursively visit a C++ nested-name-specifier.
internal::Matcher< T > traverse(ast_type_traits::TraversalKind TK, const internal::Matcher< T > &InnerMatcher)
Causes all nested matchers to be matched with the specified traversal kind.
Definition: ASTMatchers.h:710
#define INT_MAX
Definition: limits.h:46
internal::Matcher< NestedNameSpecifierLoc > NestedNameSpecifierLocMatcher
Definition: ASTMatchers.h:143
internal::Matcher< TypeLoc > TypeLocMatcher
Definition: ASTMatchers.h:141
Called when the Match registered for it was successfully found in the AST.
This class handles loading and caching of source files into memory.
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
Definition: ASTMatchers.h:138
bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.