23#include "llvm/ADT/DenseMap.h" 
   24#include "llvm/ADT/SmallPtrSet.h" 
   25#include "llvm/ADT/StringMap.h" 
   26#include "llvm/Support/PrettyStackTrace.h" 
   27#include "llvm/Support/Timer.h" 
   37typedef MatchFinder::MatchCallback MatchCallback;
 
   47static const unsigned MaxMemoizationEntries = 10000;
 
   69  DynTypedMatcher::MatcherIDType MatcherID;
 
   71  BoundNodesTreeBuilder BoundNodes;
 
   76    return std::tie(Traversal, Type, MatcherID, Node, BoundNodes) <
 
   83struct MemoizedMatchResult {
 
   85  BoundNodesTreeBuilder Nodes;
 
   90class MatchChildASTVisitor
 
   91    : 
public RecursiveASTVisitor<MatchChildASTVisitor> {
 
   93  typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
 
   99  MatchChildASTVisitor(
const DynTypedMatcher *Matcher, ASTMatchFinder *Finder,
 
  100                       BoundNodesTreeBuilder *Builder, 
int MaxDepth,
 
  101                       bool IgnoreImplicitChildren,
 
  102                       ASTMatchFinder::BindKind Bind)
 
  103      : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0),
 
  104        MaxDepth(MaxDepth), IgnoreImplicitChildren(IgnoreImplicitChildren),
 
  105        Bind(Bind), Matches(
false) {}
 
  118  bool findMatch(
const DynTypedNode &DynNode) {
 
  120    if (
const Decl *D = DynNode.get<Decl>())
 
  122    else if (
const Stmt *S = DynNode.get<Stmt>())
 
  124    else if (
const NestedNameSpecifier *NNS =
 
  125                 DynNode.get<NestedNameSpecifier>())
 
  127    else if (
const NestedNameSpecifierLoc *NNSLoc =
 
  128             DynNode.get<NestedNameSpecifierLoc>())
 
  130    else if (
const QualType *Q = DynNode.get<QualType>())
 
  132    else if (
const TypeLoc *
T = DynNode.get<TypeLoc>())
 
  134    else if (
const auto *
C = DynNode.get<CXXCtorInitializer>())
 
  136    else if (
const TemplateArgumentLoc *TALoc =
 
  137                 DynNode.get<TemplateArgumentLoc>())
 
  139    else if (
const Attr *A = DynNode.get<Attr>())
 
  146    *Builder = ResultBindings;
 
  154  bool TraverseDecl(Decl *DeclNode) {
 
  156    if (DeclNode && DeclNode->isImplicit() &&
 
  157        Finder->isTraversalIgnoringImplicitNodes())
 
  158      return baseTraverse(*DeclNode);
 
  160    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  161    return (DeclNode == 
nullptr) || 
traverse(*DeclNode);
 
  164  Stmt *getStmtToTraverse(Stmt *StmtNode) {
 
  165    Stmt *StmtToTraverse = StmtNode;
 
  166    if (
auto *ExprNode = dyn_cast_or_null<Expr>(StmtNode)) {
 
  167      auto *LambdaNode = dyn_cast_or_null<LambdaExpr>(StmtNode);
 
  168      if (LambdaNode && Finder->isTraversalIgnoringImplicitNodes())
 
  169        StmtToTraverse = LambdaNode;
 
  172            Finder->getASTContext().getParentMapContext().traverseIgnored(
 
  175    return StmtToTraverse;
 
  178  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = 
nullptr) {
 
  180    if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < 
INT_MAX))
 
  183    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  184    Stmt *StmtToTraverse = getStmtToTraverse(StmtNode);
 
  191    if (!
match(*StmtToTraverse))
 
  197  bool TraverseType(QualType TypeNode, 
bool TraverseQualifier = 
true) {
 
  198    if (TypeNode.isNull())
 
  200    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  202    if (!
match(*TypeNode))
 
  205    return traverse(TypeNode, TraverseQualifier);
 
  209  bool TraverseTypeLoc(TypeLoc TypeLocNode, 
bool TraverseQualifier = 
true) {
 
  210    if (TypeLocNode.isNull())
 
  212    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  214    if (!
match(*TypeLocNode.getType()))
 
  217    if (!
match(TypeLocNode.getType()))
 
  220    return traverse(TypeLocNode, TraverseQualifier);
 
  222  bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
 
  223    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  229    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  230    if (!
match(NNS.getNestedNameSpecifier()))
 
  234  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
 
  237    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  240  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
 
  241    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  244  bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) {
 
  245    if (!Finder->isTraversalIgnoringImplicitNodes())
 
  246      return VisitorBase::TraverseCXXForRangeStmt(Node);
 
  249    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  250    if (
auto *
Init = Node->getInit())
 
  253    if (!
match(*Node->getLoopVariable()))
 
  255    if (
match(*Node->getRangeInit()))
 
  258    if (!
match(*Node->getBody()))
 
  262  bool TraverseCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *Node) {
 
  263    if (!Finder->isTraversalIgnoringImplicitNodes())
 
  264      return VisitorBase::TraverseCXXRewrittenBinaryOperator(Node);
 
  267    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  269    return match(*Node->getLHS()) && 
match(*Node->getRHS());
 
  271  bool TraverseAttr(Attr *A) {
 
  274         Finder->getASTContext().getParentMapContext().getTraversalKind() ==
 
  277    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  281    if (!Finder->isTraversalIgnoringImplicitNodes())
 
  282      return VisitorBase::TraverseLambdaExpr(Node);
 
  285    ScopedIncrement ScopedDepth(&CurrentDepth);
 
  287    for (
unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
 
  288      const LambdaCapture *
C = Node->capture_begin() + I;
 
  289      if (!
C->isExplicit())
 
  291      if (Node->isInitCapture(
C) && !
match(*
C->getCapturedVar()))
 
  293      const Expr *CIE = Node->capture_init_begin()[I];
 
  294      if (CIE != 
nullptr && !
match(*CIE))
 
  298    if (
const auto *TPL = Node->getTemplateParameterList()) {
 
  299      for (
const auto *TP : *TPL) {
 
  305    for (
const auto *P : Node->getCallOperator()->parameters()) {
 
  310    if (!
match(*Node->getBody()))
 
  316  bool shouldVisitTemplateInstantiations()
 const { 
return true; }
 
  317  bool shouldVisitImplicitCode()
 const { 
return !IgnoreImplicitChildren; }
 
  321  struct ScopedIncrement {
 
  322    explicit ScopedIncrement(
int *Depth) : Depth(Depth) { ++(*Depth); }
 
  323    ~ScopedIncrement() { --(*Depth); }
 
  337  bool baseTraverse(
const Decl &DeclNode) {
 
  340  bool baseTraverse(
const Stmt &StmtNode) {
 
  343  bool baseTraverse(QualType TypeNode, 
bool TraverseQualifier) {
 
  346  bool baseTraverse(TypeLoc TypeLocNode, 
bool TraverseQualifier) {
 
  349  bool baseTraverse(NestedNameSpecifier NNS) {
 
  352  bool baseTraverse(NestedNameSpecifierLoc NNS) {
 
  355  bool baseTraverse(
const CXXCtorInitializer &CtorInit) {
 
  357        const_cast<CXXCtorInitializer *
>(&CtorInit));
 
  359  bool baseTraverse(TemplateArgumentLoc TAL) {
 
  362  bool baseTraverse(
const Attr &AttrNode) {
 
  371  template <
typename T>
 
  372  bool match(
const T &Node) {
 
  373    if (CurrentDepth == 0 || CurrentDepth > MaxDepth) {
 
  376    if (Bind != ASTMatchFinder::BK_All) {
 
  377      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
 
  379                           &RecursiveBuilder)) {
 
  381        ResultBindings.addMatch(RecursiveBuilder);
 
  385      BoundNodesTreeBuilder RecursiveBuilder(*Builder);
 
  387                           &RecursiveBuilder)) {
 
  390        ResultBindings.addMatch(RecursiveBuilder);
 
  398  template <
typename T, 
class... Args>
 
  399  bool traverse(
const T &Node, Args &&...args) {
 
  400    static_assert(IsBaseType<T>::value,
 
  401                  "traverse can only be instantiated with base type");
 
  404    return baseTraverse(Node, std::forward<Args>(args)...);
 
  407  const DynTypedMatcher *
const Matcher;
 
  408  ASTMatchFinder *
const Finder;
 
  409  BoundNodesTreeBuilder *
const Builder;
 
  410  BoundNodesTreeBuilder ResultBindings;
 
  413  const bool IgnoreImplicitChildren;
 
  414  const ASTMatchFinder::BindKind Bind;
 
  420class MatchASTVisitor : 
public RecursiveASTVisitor<MatchASTVisitor>,
 
  421                        public ASTMatchFinder {
 
  423  MatchASTVisitor(
const MatchFinder::MatchersByType *Matchers,
 
  424                  const MatchFinder::MatchFinderOptions &Options)
 
  425      : Matchers(Matchers), Options(Options), ActiveASTContext(
nullptr) {}
 
  427  ~MatchASTVisitor()
 override {
 
  428    if (Options.CheckProfiling) {
 
  429      Options.CheckProfiling->Records = std::move(TimeByBucket);
 
  433  void onStartOfTranslationUnit() {
 
  434    const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
 
  435    TimeBucketRegion Timer;
 
  436    for (MatchCallback *MC : Matchers->AllCallbacks) {
 
  437      if (EnableCheckProfiling)
 
  438        Timer.setBucket(&TimeByBucket[MC->getID()]);
 
  439      MC->onStartOfTranslationUnit();
 
  443  void onEndOfTranslationUnit() {
 
  444    const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
 
  445    TimeBucketRegion Timer;
 
  446    for (MatchCallback *MC : Matchers->AllCallbacks) {
 
  447      if (EnableCheckProfiling)
 
  448        Timer.setBucket(&TimeByBucket[MC->getID()]);
 
  449      MC->onEndOfTranslationUnit();
 
  453  void set_active_ast_context(ASTContext *NewActiveASTContext) {
 
  454    ActiveASTContext = NewActiveASTContext;
 
  460  bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
 
  488    const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
 
  489    const Type *CanonicalType =  
 
  491    TypeAliases[CanonicalType].insert(DeclNode);
 
  495  bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
 
  496    const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface();
 
  497    CompatibleAliases[InterfaceDecl].insert(CAD);
 
  501  bool TraverseDecl(Decl *DeclNode);
 
  502  bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = 
nullptr);
 
  503  bool TraverseType(QualType TypeNode, 
bool TraverseQualifier = 
true);
 
  504  bool TraverseTypeLoc(TypeLoc TypeNode, 
bool TraverseQualifier = 
true);
 
  505  bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS);
 
  507  bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
 
  508  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
 
  509  bool TraverseAttr(Attr *AttrNode);
 
  511  bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) {
 
  512    if (
auto *RF = dyn_cast<CXXForRangeStmt>(S)) {
 
  514        ASTNodeNotAsIsSourceScope RAII(
this, 
true);
 
  515        TraverseStmt(RF->getInit());
 
  517        match(*RF->getLoopVariable());
 
  518        TraverseStmt(RF->getRangeInit());
 
  521        ASTNodeNotSpelledInSourceScope RAII(
this, 
true);
 
  522        for (
auto *SubStmt : RF->children()) {
 
  523          if (SubStmt != RF->getBody())
 
  524            TraverseStmt(SubStmt);
 
  527      TraverseStmt(RF->getBody());
 
  529    } 
else if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
 
  531        ASTNodeNotAsIsSourceScope RAII(
this, 
true);
 
  532        TraverseStmt(
const_cast<Expr *
>(RBO->getLHS()));
 
  533        TraverseStmt(
const_cast<Expr *
>(RBO->getRHS()));
 
  536        ASTNodeNotSpelledInSourceScope RAII(
this, 
true);
 
  537        for (
auto *SubStmt : RBO->children()) {
 
  538          TraverseStmt(SubStmt);
 
  542    } 
else if (
auto *LE = dyn_cast<LambdaExpr>(S)) {
 
  543      for (
auto I : llvm::zip(
LE->captures(), 
LE->capture_inits())) {
 
  544        auto C = std::get<0>(I);
 
  545        ASTNodeNotSpelledInSourceScope RAII(
 
  546            this, TraversingASTNodeNotSpelledInSource || !
C.isExplicit());
 
  547        TraverseLambdaCapture(LE, &
C, std::get<1>(I));
 
  551        ASTNodeNotSpelledInSourceScope RAII(
this, 
true);
 
  552        TraverseDecl(
LE->getLambdaClass());
 
  555        ASTNodeNotAsIsSourceScope RAII(
this, 
true);
 
  559        TypeLoc TL = 
LE->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
 
  560        FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
 
  562        if (
auto *TPL = 
LE->getTemplateParameterList()) {
 
  563          for (NamedDecl *D : *TPL) {
 
  566          if (Expr *RequiresClause = TPL->getRequiresClause()) {
 
  567            TraverseStmt(RequiresClause);
 
  571        if (
LE->hasExplicitParameters()) {
 
  573          for (ParmVarDecl *Param : Proto.getParams())
 
  577        const auto *
T = Proto.getTypePtr();
 
  579          TraverseType(E, 
true);
 
  582          TraverseStmt(NE, Queue);
 
  584        if (
LE->hasExplicitResultType())
 
  585          TraverseTypeLoc(Proto.getReturnLoc(), 
true);
 
  587            const_cast<Expr *
>(
LE->getTrailingRequiresClause().ConstraintExpr));
 
  590      TraverseStmt(
LE->getBody());
 
  597  bool memoizedMatchesRecursively(
const DynTypedNode &Node, ASTContext &Ctx,
 
  598                                  const DynTypedMatcher &Matcher,
 
  599                                  BoundNodesTreeBuilder *Builder, 
int MaxDepth,
 
  602    if (!Node.getMemoizationData() || !Builder->isComparable())
 
  603      return matchesRecursively(Node, Matcher, Builder, MaxDepth, 
Bind);
 
  606    Key.MatcherID = Matcher.getID();
 
  609    Key.BoundNodes = *Builder;
 
  612    Key.Type = MaxDepth == 1 ? MatchType::Child : MatchType::Descendants;
 
  613    MemoizationMap::iterator I = ResultCache.find(Key);
 
  614    if (I != ResultCache.end()) {
 
  615      *Builder = I->second.Nodes;
 
  616      return I->second.ResultOfMatch;
 
  619    MemoizedMatchResult 
Result;
 
  622        matchesRecursively(Node, Matcher, &
Result.Nodes, MaxDepth, 
Bind);
 
  624    MemoizedMatchResult &CachedResult = ResultCache[Key];
 
  625    CachedResult = std::move(
Result);
 
  627    *Builder = CachedResult.Nodes;
 
  628    return CachedResult.ResultOfMatch;
 
  632  bool matchesRecursively(
const DynTypedNode &Node,
 
  633                          const DynTypedMatcher &Matcher,
 
  634                          BoundNodesTreeBuilder *Builder, 
int MaxDepth,
 
  636    bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
 
  637                           TraversingASTChildrenNotSpelledInSource;
 
  639    bool IgnoreImplicitChildren = 
false;
 
  641    if (isTraversalIgnoringImplicitNodes()) {
 
  642      IgnoreImplicitChildren = 
true;
 
  645    ASTNodeNotSpelledInSourceScope RAII(
this, ScopedTraversal);
 
  647    MatchChildASTVisitor Visitor(&Matcher, 
this, Builder, MaxDepth,
 
  648                                 IgnoreImplicitChildren, 
Bind);
 
  649    return Visitor.findMatch(Node);
 
  652  bool classIsDerivedFrom(
const CXXRecordDecl *
Declaration,
 
  653                          const Matcher<NamedDecl> &Base,
 
  654                          BoundNodesTreeBuilder *Builder,
 
  655                          bool Directly) 
override;
 
  659  classIsDerivedFromImpl(
const CXXRecordDecl *
Declaration,
 
  660                         const Matcher<NamedDecl> &Base,
 
  661                         BoundNodesTreeBuilder *Builder, 
bool Directly,
 
  662                         llvm::SmallPtrSetImpl<const CXXRecordDecl *> &Visited);
 
  665  bool objcClassIsDerivedFrom(
const ObjCInterfaceDecl *
Declaration,
 
  666                              const Matcher<NamedDecl> &Base,
 
  667                              BoundNodesTreeBuilder *Builder,
 
  668                              bool Directly) 
override;
 
  672  bool matchesChildOf(
const DynTypedNode &Node, ASTContext &Ctx,
 
  673                      const DynTypedMatcher &Matcher,
 
  674                      BoundNodesTreeBuilder *Builder, BindKind 
Bind)
 override {
 
  675    if (ResultCache.size() > MaxMemoizationEntries)
 
  677    return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, 
Bind);
 
  680  bool matchesDescendantOf(
const DynTypedNode &Node, ASTContext &Ctx,
 
  681                           const DynTypedMatcher &Matcher,
 
  682                           BoundNodesTreeBuilder *Builder,
 
  683                           BindKind 
Bind)
 override {
 
  684    if (ResultCache.size() > MaxMemoizationEntries)
 
  686    return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 
INT_MAX,
 
  690  bool matchesAncestorOf(
const DynTypedNode &Node, ASTContext &Ctx,
 
  691                         const DynTypedMatcher &Matcher,
 
  692                         BoundNodesTreeBuilder *Builder,
 
  693                         AncestorMatchMode MatchMode)
 override {
 
  696    if (ResultCache.size() > MaxMemoizationEntries)
 
  698    if (MatchMode == AncestorMatchMode::AMM_ParentOnly)
 
  699      return matchesParentOf(Node, Matcher, Builder);
 
  700    return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
 
  705  void match(
const DynTypedNode &Node) {
 
  707    if (
auto *N = Node.get<Decl>()) {
 
  709    } 
else if (
auto *N = Node.get<Stmt>()) {
 
  711    } 
else if (
auto *N = Node.get<
Type>()) {
 
  713    } 
else if (
auto *N = Node.get<QualType>()) {
 
  715    } 
else if (
auto *N = Node.get<NestedNameSpecifier>()) {
 
  717    } 
else if (
auto *N = Node.get<NestedNameSpecifierLoc>()) {
 
  719    } 
else if (
auto *N = Node.get<TypeLoc>()) {
 
  721    } 
else if (
auto *N = Node.get<CXXCtorInitializer>()) {
 
  723    } 
else if (
auto *N = Node.get<TemplateArgumentLoc>()) {
 
  725    } 
else if (
auto *N = Node.get<Attr>()) {
 
  730  template <
typename T> 
void match(
const T &Node) {
 
  731    matchDispatch(&Node);
 
  735  ASTContext &getASTContext()
 const override { 
return *ActiveASTContext; }
 
  737  bool shouldVisitTemplateInstantiations()
 const { 
return true; }
 
  738  bool shouldVisitImplicitCode()
 const { 
return true; }
 
  742  bool shouldVisitLambdaBody()
 const { 
return false; }
 
  744  bool IsMatchingInASTNodeNotSpelledInSource()
 const override {
 
  745    return TraversingASTNodeNotSpelledInSource;
 
  747  bool isMatchingChildrenNotSpelledInSource()
 const override {
 
  748    return TraversingASTChildrenNotSpelledInSource;
 
  750  void setMatchingChildrenNotSpelledInSource(
bool Set)
 override {
 
  751    TraversingASTChildrenNotSpelledInSource = 
Set;
 
  754  bool IsMatchingInASTNodeNotAsIs()
 const override {
 
  755    return TraversingASTNodeNotAsIs;
 
  758  bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
 
  759    ASTNodeNotSpelledInSourceScope RAII(
this, 
true);
 
  760    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
 
  764  bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
 
  765    ASTNodeNotSpelledInSourceScope RAII(
this, 
true);
 
  766    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
 
  770  bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
 
  771    ASTNodeNotSpelledInSourceScope RAII(
this, 
true);
 
  772    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
 
  777  bool TraversingASTNodeNotSpelledInSource = 
false;
 
  778  bool TraversingASTNodeNotAsIs = 
false;
 
  779  bool TraversingASTChildrenNotSpelledInSource = 
false;
 
  786  const QualType *, const TypeLoc *, const NestedNameSpecifier *,              \ 
  787      const NestedNameSpecifierLoc * 
 
  789  const CXXCtorInitializer *, const TemplateArgumentLoc *, const Attr *,       \ 
 
  793  template <typename NodeType>                                                 \ 
  795      llvm::is_one_of<const NodeType *, CMD_TYPES_##Index>::value>             \ 
  796  SetCallbackAndRawNode(const MatchCallback *CB, const NodeType &N) {          \ 
  798    Callback.setPointerAndInt(CB, Index);                                      \ 
  802  template <typename T>                                                        \ 
  803  std::enable_if_t<llvm::is_one_of<const T *, CMD_TYPES_##Index>::value,       \ 
  806    assertHoldsState();                                                        \ 
  807    return Callback.getInt() == (Index) ? Node##Index.dyn_cast<const T *>()    \ 
 
  812    CurMatchData() : Node0(
nullptr) {}
 
  817    const MatchCallback *getCallback()
 const { 
return Callback.getPointer(); }
 
  819    void SetBoundNodes(
const BoundNodes &BN) {
 
  824    void clearBoundNodes() {
 
  829    const BoundNodes *getBoundNodes()
 const {
 
  836      Callback.setPointerAndInt(
nullptr, 0);
 
  841    void assertHoldsState()
 const {
 
  842      assert(Callback.getPointer() != 
nullptr && !Node0.isNull());
 
  845    void assertEmpty()
 const {
 
  846      assert(Callback.getPointer() == 
nullptr && Node0.isNull() &&
 
  850    llvm::PointerIntPair<const MatchCallback *, 1> Callback;
 
  852      llvm::PointerUnion<CMD_TYPES_0> Node0;
 
  853      llvm::PointerUnion<CMD_TYPES_1> Node1;
 
  855    const BoundNodes *BNodes = 
nullptr;
 
  862  struct CurMatchRAII {
 
  863    template <
typename NodeType>
 
  864    CurMatchRAII(MatchASTVisitor &MV, 
const MatchCallback *CB,
 
  867      MV.CurMatchState.SetCallbackAndRawNode(CB, NT);
 
  870    ~CurMatchRAII() { MV.CurMatchState.reset(); }
 
  877  class TraceReporter : llvm::PrettyStackTraceEntry {
 
  878    static void dumpNode(
const ASTContext &Ctx, 
const DynTypedNode &Node,
 
  880      if (
const auto *D = Node.get<Decl>()) {
 
  881        OS << D->getDeclKindName() << 
"Decl ";
 
  882        if (
const auto *ND = dyn_cast<NamedDecl>(D)) {
 
  883          ND->printQualifiedName(OS);
 
  888      } 
else if (
const auto *S = Node.get<Stmt>()) {
 
  889        OS << S->getStmtClassName() << 
" : ";
 
  891      } 
else if (
const auto *
T = Node.get<
Type>()) {
 
  894      } 
else if (
const auto *QT = Node.get<QualType>()) {
 
  898        OS << Node.getNodeKind().asStringRef() << 
" : ";
 
  903    static void dumpNodeFromState(
const ASTContext &Ctx,
 
  904                                  const CurMatchData &State, raw_ostream &OS) {
 
  905      if (
const DynTypedNode *MatchNode = State.getNode<DynTypedNode>()) {
 
  906        dumpNode(Ctx, *MatchNode, OS);
 
  907      } 
else if (
const auto *QT = State.getNode<QualType>()) {
 
  909      } 
else if (
const auto *TL = State.getNode<TypeLoc>()) {
 
  911      } 
else if (
const auto *NNS = State.getNode<NestedNameSpecifier>()) {
 
  913      } 
else if (
const auto *NNSL = State.getNode<NestedNameSpecifierLoc>()) {
 
  915      } 
else if (
const auto *CtorInit = State.getNode<CXXCtorInitializer>()) {
 
  917      } 
else if (
const auto *TAL = State.getNode<TemplateArgumentLoc>()) {
 
  919      } 
else if (
const auto *At = State.getNode<Attr>()) {
 
  925    TraceReporter(
const MatchASTVisitor &MV) : MV(MV) {}
 
  926    void print(raw_ostream &OS)
 const override {
 
  927      const CurMatchData &State = MV.CurMatchState;
 
  928      const MatchCallback *CB = State.getCallback();
 
  930        OS << 
"ASTMatcher: Not currently matching\n";
 
  934      assert(MV.ActiveASTContext &&
 
  935             "ActiveASTContext should be set if there is a matched callback");
 
  937      ASTContext &Ctx = MV.getASTContext();
 
  939      if (
const BoundNodes *Nodes = State.getBoundNodes()) {
 
  940        OS << 
"ASTMatcher: Processing '" << CB->getID() << 
"' against:\n\t";
 
  941        dumpNodeFromState(Ctx, State, OS);
 
  944          OS << 
"\nNo bound nodes\n";
 
  947        OS << 
"\n--- Bound Nodes Begin ---\n";
 
  948        for (
const auto &Item : Map) {
 
  949          OS << 
"    " << Item.first << 
" - { ";
 
  950          dumpNode(Ctx, Item.second, OS);
 
  953        OS << 
"--- Bound Nodes End ---\n";
 
  955        OS << 
"ASTMatcher: Matching '" << CB->getID() << 
"' against:\n\t";
 
  956        dumpNodeFromState(Ctx, State, OS);
 
  962    const MatchASTVisitor &MV;
 
  966  struct ASTNodeNotSpelledInSourceScope {
 
  967    ASTNodeNotSpelledInSourceScope(MatchASTVisitor *
V, 
bool B)
 
  968        : MV(
V), MB(
V->TraversingASTNodeNotSpelledInSource) {
 
  969      V->TraversingASTNodeNotSpelledInSource = B;
 
  971    ~ASTNodeNotSpelledInSourceScope() {
 
  972      MV->TraversingASTNodeNotSpelledInSource = MB;
 
  980  struct ASTNodeNotAsIsSourceScope {
 
  981    ASTNodeNotAsIsSourceScope(MatchASTVisitor *
V, 
bool B)
 
  982        : MV(
V), MB(
V->TraversingASTNodeNotAsIs) {
 
  983      V->TraversingASTNodeNotAsIs = B;
 
  985    ~ASTNodeNotAsIsSourceScope() { MV->TraversingASTNodeNotAsIs = MB; }
 
  992  class TimeBucketRegion {
 
  994    TimeBucketRegion() = 
default;
 
  995    ~TimeBucketRegion() { setBucket(
nullptr); }
 
 1005    void setBucket(llvm::TimeRecord *NewBucket) {
 
 1006      if (Bucket != NewBucket) {
 
 1007        auto Now = llvm::TimeRecord::getCurrentTime(
true);
 
 1017    llvm::TimeRecord *Bucket = 
nullptr;
 
 1023  template <
typename T, 
typename MC>
 
 1024  void matchWithoutFilter(
const T &Node, 
const MC &Matchers) {
 
 1025    const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
 
 1026    TimeBucketRegion Timer;
 
 1027    for (
const auto &MP : Matchers) {
 
 1028      if (EnableCheckProfiling)
 
 1029        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
 
 1030      BoundNodesTreeBuilder Builder;
 
 1031      CurMatchRAII RAII(*
this, MP.second, Node);
 
 1032      if (MP.first.matches(Node, 
this, &Builder)) {
 
 1033        MatchVisitor Visitor(*
this, ActiveASTContext, MP.second);
 
 1034        Builder.visitMatches(&Visitor);
 
 1039  void matchWithFilter(
const DynTypedNode &DynNode) {
 
 1040    auto Kind = DynNode.getNodeKind();
 
 1041    auto it = MatcherFiltersMap.find(Kind);
 
 1043        it != MatcherFiltersMap.end() ? it->second : getFilterForKind(Kind);
 
 1048    const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
 
 1049    TimeBucketRegion Timer;
 
 1050    auto &Matchers = this->Matchers->DeclOrStmt;
 
 1051    for (
unsigned short I : Filter) {
 
 1052      auto &MP = Matchers[I];
 
 1053      if (EnableCheckProfiling)
 
 1054        Timer.setBucket(&TimeByBucket[MP.second->getID()]);
 
 1055      BoundNodesTreeBuilder Builder;
 
 1058        TraversalKindScope RAII(getASTContext(), MP.first.getTraversalKind());
 
 1059        if (getASTContext().getParentMapContext().traverseIgnored(DynNode) !=
 
 1064      CurMatchRAII RAII(*
this, MP.second, DynNode);
 
 1065      if (MP.first.matches(DynNode, 
this, &Builder)) {
 
 1066        MatchVisitor Visitor(*
this, ActiveASTContext, MP.second);
 
 1067        Builder.visitMatches(&Visitor);
 
 1072  const std::vector<unsigned short> &getFilterForKind(ASTNodeKind Kind) {
 
 1074    auto &Matchers = this->Matchers->DeclOrStmt;
 
 1075    assert((Matchers.size() < 
USHRT_MAX) && 
"Too many matchers.");
 
 1076    for (
unsigned I = 0, E = Matchers.size(); I != E; ++I) {
 
 1077      if (Matchers[I].first.canMatchNodesOfKind(Kind)) {
 
 1086  void matchDispatch(
const Decl *Node) {
 
 1089  void matchDispatch(
const Stmt *Node) {
 
 1093  void matchDispatch(
const Type *Node) {
 
 1094    matchWithoutFilter(QualType(Node, 0), Matchers->Type);
 
 1096  void matchDispatch(
const TypeLoc *Node) {
 
 1097    matchWithoutFilter(*Node, Matchers->TypeLoc);
 
 1099  void matchDispatch(
const QualType *Node) {
 
 1100    matchWithoutFilter(*Node, Matchers->Type);
 
 1102  void matchDispatch(
const NestedNameSpecifier *Node) {
 
 1103    matchWithoutFilter(*Node, Matchers->NestedNameSpecifier);
 
 1105  void matchDispatch(
const NestedNameSpecifierLoc *Node) {
 
 1106    matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
 
 1108  void matchDispatch(
const CXXCtorInitializer *Node) {
 
 1109    matchWithoutFilter(*Node, Matchers->CtorInit);
 
 1111  void matchDispatch(
const TemplateArgumentLoc *Node) {
 
 1112    matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc);
 
 1114  void matchDispatch(
const Attr *Node) {
 
 1115    matchWithoutFilter(*Node, Matchers->Attr);
 
 1117  void matchDispatch(
const void *) {  }
 
 1122  bool matchesParentOf(
const DynTypedNode &Node, 
const DynTypedMatcher &Matcher,
 
 1123                       BoundNodesTreeBuilder *Builder) {
 
 1124    for (
const auto &Parent : ActiveASTContext->getParents(Node)) {
 
 1125      BoundNodesTreeBuilder BuilderCopy = *Builder;
 
 1126      if (Matcher.matches(Parent, 
this, &BuilderCopy)) {
 
 1127        *Builder = std::move(BuilderCopy);
 
 1150  bool matchesAnyAncestorOf(DynTypedNode Node, ASTContext &Ctx,
 
 1151                            const DynTypedMatcher &Matcher,
 
 1152                            BoundNodesTreeBuilder *Builder) {
 
 1157    std::vector<MatchKey> Keys;
 
 1159    auto Finish = [&](
bool Matched) {
 
 1160      for (
const auto &Key : Keys) {
 
 1161        MemoizedMatchResult &CachedResult = ResultCache[Key];
 
 1162        CachedResult.ResultOfMatch = Matched;
 
 1163        CachedResult.Nodes = *Builder;
 
 1169    DynTypedNodeList Parents{ArrayRef<DynTypedNode>()}; 
 
 1172      if (Builder->isComparable()) {
 
 1173        Keys.emplace_back();
 
 1174        Keys.back().MatcherID = Matcher.getID();
 
 1175        Keys.back().Node = Node;
 
 1176        Keys.back().BoundNodes = *Builder;
 
 1178        Keys.back().Type = MatchType::Ancestors;
 
 1181        MemoizationMap::iterator I = ResultCache.find(Keys.back());
 
 1182        if (I != ResultCache.end()) {
 
 1184          *Builder = I->second.Nodes;
 
 1185          return Finish(I->second.ResultOfMatch);
 
 1189      Parents = ActiveASTContext->getParents(Node);
 
 1192      if (Parents.size() != 1)
 
 1196      Node = *Parents.begin();
 
 1197      BoundNodesTreeBuilder BuilderCopy = *Builder;
 
 1198      if (Matcher.matches(Node, 
this, &BuilderCopy)) {
 
 1199        *Builder = std::move(BuilderCopy);
 
 1200        return Finish(
true);
 
 1205    if (Parents.empty()) {
 
 1213      if (!Node.get<TranslationUnitDecl>() &&
 
 1215          llvm::any_of(ActiveASTContext->getTraversalScope(), [](Decl *D) {
 
 1216            return D->getKind() == Decl::TranslationUnit;
 
 1218        llvm::errs() << 
"Tried to match orphan node:\n";
 
 1219        Node.dump(llvm::errs(), *ActiveASTContext);
 
 1220        llvm_unreachable(
"Parent map should be complete!");
 
 1224      assert(Parents.size() > 1);
 
 1228      std::deque<DynTypedNode> Queue(Parents.begin(), Parents.end());
 
 1229      llvm::DenseSet<const void *> Visited;
 
 1230      while (!Queue.empty()) {
 
 1231        BoundNodesTreeBuilder BuilderCopy = *Builder;
 
 1232        if (Matcher.matches(Queue.front(), 
this, &BuilderCopy)) {
 
 1233          *Builder = std::move(BuilderCopy);
 
 1234          return Finish(
true);
 
 1236        for (
const auto &Parent : ActiveASTContext->getParents(Queue.front())) {
 
 1240          if (Visited.insert(Parent.getMemoizationData()).second)
 
 1241            Queue.push_back(Parent);
 
 1246    return Finish(
false);
 
 1251  class MatchVisitor : 
public BoundNodesTreeBuilder::Visitor {
 
 1252    struct CurBoundScope {
 
 1253      CurBoundScope(MatchASTVisitor::CurMatchData &State, 
const BoundNodes &BN)
 
 1255        State.SetBoundNodes(BN);
 
 1258      ~CurBoundScope() { State.clearBoundNodes(); }
 
 1261      MatchASTVisitor::CurMatchData &State;
 
 1265    MatchVisitor(MatchASTVisitor &MV, ASTContext *Context,
 
 1266                 MatchFinder::MatchCallback *Callback)
 
 1267        : State(MV.CurMatchState), Context(Context), Callback(Callback) {}
 
 1269    void visitMatch(
const BoundNodes& BoundNodesView)
 override {
 
 1270      TraversalKindScope RAII(*Context, Callback->getCheckTraversalKind());
 
 1271      CurBoundScope RAII2(State, BoundNodesView);
 
 1272      Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
 
 1276    MatchASTVisitor::CurMatchData &State;
 
 1277    ASTContext* Context;
 
 1278    MatchFinder::MatchCallback* Callback;
 
 1282  bool typeHasMatchingAlias(
const Type *TypeNode,
 
 1283                            const Matcher<NamedDecl> &Matcher,
 
 1284                            BoundNodesTreeBuilder *Builder) {
 
 1285    const Type *
const CanonicalType =
 
 1286      ActiveASTContext->getCanonicalType(TypeNode);
 
 1287    auto Aliases = TypeAliases.find(CanonicalType);
 
 1288    if (Aliases == TypeAliases.end())
 
 1291    auto matches = [&](
const TypedefNameDecl *Alias) {
 
 1292      BoundNodesTreeBuilder 
Result(*Builder);
 
 1293      if (Matcher.matches(*Alias, 
this, &
Result)) {
 
 1294        *Builder = std::move(
Result);
 
 1300    if (
const auto *
T = TypeNode->getAs<TypedefType>()) {
 
 1301      const auto *TD = 
T->getDecl()->getCanonicalDecl();
 
 1304      SmallVector<const TypedefNameDecl *, 8> NonExactMatches;
 
 1305      for (
const TypedefNameDecl *Alias : Aliases->second) {
 
 1307          NonExactMatches.push_back(Alias);
 
 1314      for (
const TypedefNameDecl *Alias : NonExactMatches) {
 
 1315        BoundNodesTreeBuilder 
Result(*Builder);
 
 1316        if (Matcher.matches(*Alias, 
this, &
Result)) {
 
 1317          *Builder = std::move(
Result);
 
 1324    for (
const TypedefNameDecl *Alias : Aliases->second)
 
 1331  objcClassHasMatchingCompatibilityAlias(
const ObjCInterfaceDecl *InterfaceDecl,
 
 1332                                         const Matcher<NamedDecl> &Matcher,
 
 1333                                         BoundNodesTreeBuilder *Builder) {
 
 1334    auto Aliases = CompatibleAliases.find(InterfaceDecl);
 
 1335    if (Aliases == CompatibleAliases.end())
 
 1337    for (
const ObjCCompatibleAliasDecl *Alias : Aliases->second) {
 
 1338      BoundNodesTreeBuilder 
Result(*Builder);
 
 1339      if (Matcher.matches(*Alias, 
this, &
Result)) {
 
 1340        *Builder = std::move(
Result);
 
 1347  template <
typename T> 
static SourceLocation getNodeLocation(
const T &Node) {
 
 1348    return Node.getBeginLoc();
 
 1351  static SourceLocation getNodeLocation(
const CXXCtorInitializer &Node) {
 
 1352    return Node.getSourceLocation();
 
 1355  static SourceLocation getNodeLocation(
const TemplateArgumentLoc &Node) {
 
 1356    return Node.getLocation();
 
 1359  static SourceLocation getNodeLocation(
const Attr &Node) {
 
 1360    return Node.getLocation();
 
 1363  bool isInSystemHeader(SourceLocation Loc) {
 
 1364    const SourceManager &
SM = getASTContext().getSourceManager();
 
 1365    return SM.isInSystemHeader(Loc);
 
 1368  template <
typename T> 
bool shouldSkipNode(
T &Node) {
 
 1369    if (Options.IgnoreSystemHeaders && isInSystemHeader(getNodeLocation(Node)))
 
 1374  template <
typename T> 
bool shouldSkipNode(
T *Node) {
 
 1375    return (Node == 
nullptr) || shouldSkipNode(*Node);
 
 1378  bool shouldSkipNode(QualType &) { 
return false; }
 
 1380  bool shouldSkipNode(NestedNameSpecifier &) { 
return false; }
 
 1385  llvm::StringMap<llvm::TimeRecord> TimeByBucket;
 
 1387  const MatchFinder::MatchersByType *Matchers;
 
 1395  llvm::DenseMap<ASTNodeKind, std::vector<unsigned short>> MatcherFiltersMap;
 
 1397  const MatchFinder::MatchFinderOptions &Options;
 
 1398  ASTContext *ActiveASTContext;
 
 1401  llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
 
 1404  llvm::DenseMap<
const ObjCInterfaceDecl *,
 
 1405                 llvm::SmallPtrSet<const ObjCCompatibleAliasDecl *, 2>>
 
 1409  typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
 
 1410  MemoizationMap ResultCache;
 
 1413static CXXRecordDecl *
 
 1414getAsCXXRecordDeclOrPrimaryTemplate(
const Type *TypeNode) {
 
 1415  if (
auto *RD = TypeNode->getAsCXXRecordDecl())
 
 1419  auto *TemplateType = TypeNode->getAs<TemplateSpecializationType>();
 
 1420  while (TemplateType && TemplateType->isTypeAlias())
 
 1422        TemplateType->getAliasedType()->getAs<TemplateSpecializationType>();
 
 1427    if (
auto *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(
 
 1428          TemplateType->getTemplateName().getAsTemplateDecl()))
 
 1429      return ClassTemplate->getTemplatedDecl();
 
 1437bool MatchASTVisitor::classIsDerivedFrom(
const CXXRecordDecl *
Declaration,
 
 1438                                         const Matcher<NamedDecl> &Base,
 
 1439                                         BoundNodesTreeBuilder *Builder,
 
 1441  llvm::SmallPtrSet<const CXXRecordDecl *, 8> Visited;
 
 1442  return classIsDerivedFromImpl(Declaration, Base, Builder, Directly, Visited);
 
 1445bool MatchASTVisitor::classIsDerivedFromImpl(
 
 1446    const CXXRecordDecl *
Declaration, 
const Matcher<NamedDecl> &Base,
 
 1447    BoundNodesTreeBuilder *Builder, 
bool Directly,
 
 1448    llvm::SmallPtrSetImpl<const CXXRecordDecl *> &Visited) {
 
 1451  if (!Visited.insert(Declaration).second)
 
 1454    const Type *TypeNode = It.getType().getTypePtr();
 
 1456    if (typeHasMatchingAlias(TypeNode, Base, Builder))
 
 1462    CXXRecordDecl *ClassDecl = getAsCXXRecordDeclOrPrimaryTemplate(TypeNode);
 
 1465    if (ClassDecl == Declaration) {
 
 1469    BoundNodesTreeBuilder 
Result(*Builder);
 
 1470    if (
Base.matches(*ClassDecl, 
this, &Result)) {
 
 1471      *Builder = std::move(Result);
 
 1475        classIsDerivedFromImpl(ClassDecl, Base, Builder, Directly, Visited))
 
 1484bool MatchASTVisitor::objcClassIsDerivedFrom(
 
 1485    const ObjCInterfaceDecl *
Declaration, 
const Matcher<NamedDecl> &Base,
 
 1486    BoundNodesTreeBuilder *Builder, 
bool Directly) {
 
 1488  for (
const ObjCInterfaceDecl *ClassDecl = 
Declaration->getSuperClass();
 
 1489       ClassDecl != 
nullptr; ClassDecl = ClassDecl->getSuperClass()) {
 
 1491    if (objcClassHasMatchingCompatibilityAlias(ClassDecl, Base, Builder))
 
 1495    const Type *TypeNode = ClassDecl->getTypeForDecl();
 
 1496    if (typeHasMatchingAlias(TypeNode, Base, Builder))
 
 1499    if (
Base.matches(*ClassDecl, 
this, Builder))
 
 1510bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
 
 1511  if (shouldSkipNode(DeclNode))
 
 1514  bool ScopedTraversal =
 
 1515      TraversingASTNodeNotSpelledInSource || DeclNode->isImplicit();
 
 1516  bool ScopedChildren = TraversingASTChildrenNotSpelledInSource;
 
 1518  if (
const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DeclNode)) {
 
 1519    auto SK = CTSD->getSpecializationKind();
 
 1520    if (SK == TSK_ExplicitInstantiationDeclaration ||
 
 1521        SK == TSK_ExplicitInstantiationDefinition)
 
 1522      ScopedChildren = 
true;
 
 1523  } 
else if (
const auto *FD = dyn_cast<FunctionDecl>(DeclNode)) {
 
 1524    if (FD->isDefaulted())
 
 1525      ScopedChildren = 
true;
 
 1526    if (FD->isTemplateInstantiation())
 
 1527      ScopedTraversal = 
true;
 
 1528  } 
else if (isa<BindingDecl>(DeclNode)) {
 
 1529    ScopedChildren = 
true;
 
 1532  ASTNodeNotSpelledInSourceScope RAII1(
this, ScopedTraversal);
 
 1533  ASTChildrenNotSpelledInSourceScope RAII2(
this, ScopedChildren);
 
 1536  return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
 
 1539bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
 
 1540  if (shouldSkipNode(StmtNode))
 
 1543  bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
 
 1544                         TraversingASTChildrenNotSpelledInSource;
 
 1546  ASTNodeNotSpelledInSourceScope RAII(
this, ScopedTraversal);
 
 1548  return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode, Queue);
 
 1551bool MatchASTVisitor::TraverseType(QualType TypeNode, 
bool TraverseQualifier) {
 
 1552  if (shouldSkipNode(TypeNode))
 
 1556  return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode,
 
 1560bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode,
 
 1561                                      bool TraverseQualifier) {
 
 1562  if (shouldSkipNode(TypeLocNode))
 
 1570  match(TypeLocNode.getType());
 
 1571  return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(
 
 1572      TypeLocNode, TraverseQualifier);
 
 1575bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
 
 1576  if (shouldSkipNode(NNS))
 
 1580  return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
 
 1583bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
 
 1584    NestedNameSpecifierLoc NNS) {
 
 1588  if (shouldSkipNode(NNS))
 
 1595  if (NNS.hasQualifier())
 
 1596    match(NNS.getNestedNameSpecifier());
 
 1598      RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
 
 1601bool MatchASTVisitor::TraverseConstructorInitializer(
 
 1602    CXXCtorInitializer *CtorInit) {
 
 1603  if (shouldSkipNode(CtorInit))
 
 1606  bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
 
 1607                         TraversingASTChildrenNotSpelledInSource;
 
 1609  if (!CtorInit->isWritten())
 
 1610    ScopedTraversal = 
true;
 
 1612  ASTNodeNotSpelledInSourceScope RAII1(
this, ScopedTraversal);
 
 1616  return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
 
 1620bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
 
 1621  if (shouldSkipNode(Loc))
 
 1625  return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
 
 1628bool MatchASTVisitor::TraverseAttr(Attr *AttrNode) {
 
 1629  if (shouldSkipNode(AttrNode))
 
 1633  return RecursiveASTVisitor<MatchASTVisitor>::TraverseAttr(AttrNode);
 
 1636class MatchASTConsumer : 
public ASTConsumer {
 
 1638  MatchASTConsumer(MatchFinder *Finder,
 
 1639                   MatchFinder::ParsingDoneTestCallback *ParsingDone)
 
 1640      : Finder(Finder), ParsingDone(ParsingDone) {}
 
 1643  void HandleTranslationUnit(ASTContext &Context)
 override {
 
 1644    if (ParsingDone != 
nullptr) {
 
 1650  MatchFinder *Finder;
 
 1651  MatchFinder::ParsingDoneTestCallback *ParsingDone;
 
 1666    : Options(
std::move(Options)), ParsingDone(
nullptr) {}
 
 
 1672  std::optional<TraversalKind> TK;
 
 1676    Matchers.DeclOrStmt.emplace_back(
traverse(*TK, NodeMatch), Action);
 
 1678    Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
 
 1679  Matchers.AllCallbacks.insert(Action);
 
 
 1684  Matchers.Type.emplace_back(NodeMatch, Action);
 
 1685  Matchers.AllCallbacks.insert(Action);
 
 
 1690  std::optional<TraversalKind> TK;
 
 1694    Matchers.DeclOrStmt.emplace_back(
traverse(*TK, NodeMatch), Action);
 
 1696    Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
 
 1697  Matchers.AllCallbacks.insert(Action);
 
 
 1702  Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action);
 
 1703  Matchers.AllCallbacks.insert(Action);
 
 
 1708  Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action);
 
 1709  Matchers.AllCallbacks.insert(Action);
 
 
 1714  Matchers.TypeLoc.emplace_back(NodeMatch, Action);
 
 1715  Matchers.AllCallbacks.insert(Action);
 
 
 1720  Matchers.CtorInit.emplace_back(NodeMatch, Action);
 
 1721  Matchers.AllCallbacks.insert(Action);
 
 
 1726  Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action);
 
 1727  Matchers.AllCallbacks.insert(Action);
 
 
 1732  Matchers.Attr.emplace_back(AttrMatch, Action);
 
 1733  Matchers.AllCallbacks.insert(Action);
 
 
 1738  if (NodeMatch.canConvertTo<
Decl>()) {
 
 1741  } 
else if (NodeMatch.canConvertTo<
QualType>()) {
 
 1744  } 
else if (NodeMatch.canConvertTo<
Stmt>()) {
 
 1753  } 
else if (NodeMatch.canConvertTo<
TypeLoc>()) {
 
 1762  } 
else if (NodeMatch.canConvertTo<
Attr>()) {
 
 
 1770  return std::make_unique<internal::MatchASTConsumer>(
this, ParsingDone);
 
 
 1774  internal::MatchASTVisitor Visitor(&Matchers, Options);
 
 1775  Visitor.set_active_ast_context(&Context);
 
 1776  Visitor.match(Node);
 
 
 1780  internal::MatchASTVisitor Visitor(&Matchers, Options);
 
 1781  internal::MatchASTVisitor::TraceReporter StackTrace(Visitor);
 
 1782  Visitor.set_active_ast_context(&Context);
 
 1783  Visitor.onStartOfTranslationUnit();
 
 1784  Visitor.TraverseAST(Context);
 
 1785  Visitor.onEndOfTranslationUnit();
 
 
 1790  ParsingDone = NewParsingDone;
 
 
 1795std::optional<TraversalKind>
 
 1797  return std::nullopt;
 
 
Defines the clang::ASTContext interface.
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
SourceManager & getSourceManager()
ParentMapContext & getParentMapContext()
Returns the dynamic AST node parent map context.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const clang::PrintingPolicy & getPrintingPolicy() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Attr - This represents one attribute.
Represents a C++ base or member initializer.
Decl - This represents one declaration (or definition), e.g.
A dynamically typed AST node container.
static DynTypedNode create(const T &Node)
Creates a DynTypedNode from Node.
Expr * getNoexceptExpr() const
Return the expression inside noexcept(expression), or a null pointer if there is none (because the ex...
ArrayRef< QualType > exceptions() const
A C++ nested-name-specifier augmented with source location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
A (possibly-)qualified type.
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS)
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc)
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)
bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier=true)
bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue)
bool TraverseDecl(Decl *D)
bool TraverseAttr(Attr *At)
bool TraverseType(QualType T, bool TraverseQualifier=true)
bool TraverseConstructorInitializer(CXXCtorInitializer *Init)
Stmt - This represents one statement.
Location wrapper for a TemplateArgument.
Base wrapper for a particular "section" of type source info.
const char * getTypeClassName() const
Maps string IDs to AST nodes matched by parts of a matcher.
internal::BoundNodesMap::IDToNodeMap IDToNodeMap
Type of mapping from binding identifiers to bound nodes.
Called when the Match registered for it was successfully found in the AST.
virtual std::optional< TraversalKind > getCheckTraversalKind() const
TraversalKind to use while matching and processing the result nodes.
virtual StringRef getID() const
An id used to group the matchers.
Called when parsing is finished. Intended for testing only.
virtual ~ParsingDoneTestCallback()
MatchFinder(MatchFinderOptions Options=MatchFinderOptions())
bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
void addMatcher(const DeclarationMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
void match(const T &Node, ASTContext &Context)
Calls the registered callbacks on all matches on the given Node.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone)
Registers a callback to notify the end of parsing.
std::unique_ptr< clang::ASTConsumer > newASTConsumer()
Creates a clang ASTConsumer that finds all matches.
void matchAST(ASTContext &Context)
Finds all matches in the given AST.
internal::Matcher< QualType > TypeMatcher
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< Attr > AttrMatcher
internal::Matcher< CXXCtorInitializer > CXXCtorInitializerMatcher
internal::Matcher< Stmt > StatementMatcher
internal::Matcher< TemplateArgumentLoc > TemplateArgumentLocMatcher
internal::Matcher< NestedNameSpecifierLoc > NestedNameSpecifierLocMatcher
internal::Matcher< T > traverse(TraversalKind TK, const internal::Matcher< T > &InnerMatcher)
Causes all nested matchers to be matched with the specified traversal kind.
internal::Matcher< NestedNameSpecifier > NestedNameSpecifierMatcher
internal::Matcher< TypeLoc > TypeLocMatcher
DynTypedNode DynTypedNode
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
bool matches(const til::SExpr *E1, const til::SExpr *E2)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ Bind
'bind' clause, allowed on routine constructs.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
TraversalKind
Defines how we descend a level in the AST when we pass through expressions.
@ TK_AsIs
Will traverse all child nodes.
@ TK_IgnoreUnlessSpelledInSource
Ignore AST nodes not written in the source.
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ Type
The name was classified as a type.
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
@ Other
Other implicit parameter.
clang::SourceManager *const SourceManager
MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context)
const BoundNodes Nodes
Contains the nodes bound on the current match.
clang::ASTContext *const Context
Utilities for interpreting the matched AST structures.