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