1*f4a2713aSLionel Sambuc //===--- ASTMatchFinder.cpp - Structural query framework ------------------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // Implements an algorithm to efficiently search for matches on AST nodes. 11*f4a2713aSLionel Sambuc // Uses memoization to support recursive matches like HasDescendant. 12*f4a2713aSLionel Sambuc // 13*f4a2713aSLionel Sambuc // The general idea is to visit all AST nodes with a RecursiveASTVisitor, 14*f4a2713aSLionel Sambuc // calling the Matches(...) method of each matcher we are running on each 15*f4a2713aSLionel Sambuc // AST node. The matcher can recurse via the ASTMatchFinder interface. 16*f4a2713aSLionel Sambuc // 17*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 18*f4a2713aSLionel Sambuc 19*f4a2713aSLionel Sambuc #include "clang/ASTMatchers/ASTMatchFinder.h" 20*f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h" 21*f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h" 22*f4a2713aSLionel Sambuc #include "clang/AST/RecursiveASTVisitor.h" 23*f4a2713aSLionel Sambuc #include <deque> 24*f4a2713aSLionel Sambuc #include <set> 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc namespace clang { 27*f4a2713aSLionel Sambuc namespace ast_matchers { 28*f4a2713aSLionel Sambuc namespace internal { 29*f4a2713aSLionel Sambuc namespace { 30*f4a2713aSLionel Sambuc 31*f4a2713aSLionel Sambuc typedef MatchFinder::MatchCallback MatchCallback; 32*f4a2713aSLionel Sambuc 33*f4a2713aSLionel Sambuc // The maximum number of memoization entries to store. 34*f4a2713aSLionel Sambuc // 10k has been experimentally found to give a good trade-off 35*f4a2713aSLionel Sambuc // of performance vs. memory consumption by running matcher 36*f4a2713aSLionel Sambuc // that match on every statement over a very large codebase. 37*f4a2713aSLionel Sambuc // 38*f4a2713aSLionel Sambuc // FIXME: Do some performance optimization in general and 39*f4a2713aSLionel Sambuc // revisit this number; also, put up micro-benchmarks that we can 40*f4a2713aSLionel Sambuc // optimize this on. 41*f4a2713aSLionel Sambuc static const unsigned MaxMemoizationEntries = 10000; 42*f4a2713aSLionel Sambuc 43*f4a2713aSLionel Sambuc // We use memoization to avoid running the same matcher on the same 44*f4a2713aSLionel Sambuc // AST node twice. This struct is the key for looking up match 45*f4a2713aSLionel Sambuc // result. It consists of an ID of the MatcherInterface (for 46*f4a2713aSLionel Sambuc // identifying the matcher), a pointer to the AST node and the 47*f4a2713aSLionel Sambuc // bound nodes before the matcher was executed. 48*f4a2713aSLionel Sambuc // 49*f4a2713aSLionel Sambuc // We currently only memoize on nodes whose pointers identify the 50*f4a2713aSLionel Sambuc // nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc). 51*f4a2713aSLionel Sambuc // For \c QualType and \c TypeLoc it is possible to implement 52*f4a2713aSLionel Sambuc // generation of keys for each type. 53*f4a2713aSLionel Sambuc // FIXME: Benchmark whether memoization of non-pointer typed nodes 54*f4a2713aSLionel Sambuc // provides enough benefit for the additional amount of code. 55*f4a2713aSLionel Sambuc struct MatchKey { 56*f4a2713aSLionel Sambuc uint64_t MatcherID; 57*f4a2713aSLionel Sambuc ast_type_traits::DynTypedNode Node; 58*f4a2713aSLionel Sambuc BoundNodesTreeBuilder BoundNodes; 59*f4a2713aSLionel Sambuc 60*f4a2713aSLionel Sambuc bool operator<(const MatchKey &Other) const { 61*f4a2713aSLionel Sambuc if (MatcherID != Other.MatcherID) 62*f4a2713aSLionel Sambuc return MatcherID < Other.MatcherID; 63*f4a2713aSLionel Sambuc if (Node != Other.Node) 64*f4a2713aSLionel Sambuc return Node < Other.Node; 65*f4a2713aSLionel Sambuc return BoundNodes < Other.BoundNodes; 66*f4a2713aSLionel Sambuc } 67*f4a2713aSLionel Sambuc }; 68*f4a2713aSLionel Sambuc 69*f4a2713aSLionel Sambuc // Used to store the result of a match and possibly bound nodes. 70*f4a2713aSLionel Sambuc struct MemoizedMatchResult { 71*f4a2713aSLionel Sambuc bool ResultOfMatch; 72*f4a2713aSLionel Sambuc BoundNodesTreeBuilder Nodes; 73*f4a2713aSLionel Sambuc }; 74*f4a2713aSLionel Sambuc 75*f4a2713aSLionel Sambuc // A RecursiveASTVisitor that traverses all children or all descendants of 76*f4a2713aSLionel Sambuc // a node. 77*f4a2713aSLionel Sambuc class MatchChildASTVisitor 78*f4a2713aSLionel Sambuc : public RecursiveASTVisitor<MatchChildASTVisitor> { 79*f4a2713aSLionel Sambuc public: 80*f4a2713aSLionel Sambuc typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase; 81*f4a2713aSLionel Sambuc 82*f4a2713aSLionel Sambuc // Creates an AST visitor that matches 'matcher' on all children or 83*f4a2713aSLionel Sambuc // descendants of a traversed node. max_depth is the maximum depth 84*f4a2713aSLionel Sambuc // to traverse: use 1 for matching the children and INT_MAX for 85*f4a2713aSLionel Sambuc // matching the descendants. 86*f4a2713aSLionel Sambuc MatchChildASTVisitor(const DynTypedMatcher *Matcher, 87*f4a2713aSLionel Sambuc ASTMatchFinder *Finder, 88*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder, 89*f4a2713aSLionel Sambuc int MaxDepth, 90*f4a2713aSLionel Sambuc ASTMatchFinder::TraversalKind Traversal, 91*f4a2713aSLionel Sambuc ASTMatchFinder::BindKind Bind) 92*f4a2713aSLionel Sambuc : Matcher(Matcher), 93*f4a2713aSLionel Sambuc Finder(Finder), 94*f4a2713aSLionel Sambuc Builder(Builder), 95*f4a2713aSLionel Sambuc CurrentDepth(0), 96*f4a2713aSLionel Sambuc MaxDepth(MaxDepth), 97*f4a2713aSLionel Sambuc Traversal(Traversal), 98*f4a2713aSLionel Sambuc Bind(Bind), 99*f4a2713aSLionel Sambuc Matches(false) {} 100*f4a2713aSLionel Sambuc 101*f4a2713aSLionel Sambuc // Returns true if a match is found in the subtree rooted at the 102*f4a2713aSLionel Sambuc // given AST node. This is done via a set of mutually recursive 103*f4a2713aSLionel Sambuc // functions. Here's how the recursion is done (the *wildcard can 104*f4a2713aSLionel Sambuc // actually be Decl, Stmt, or Type): 105*f4a2713aSLionel Sambuc // 106*f4a2713aSLionel Sambuc // - Traverse(node) calls BaseTraverse(node) when it needs 107*f4a2713aSLionel Sambuc // to visit the descendants of node. 108*f4a2713aSLionel Sambuc // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node)) 109*f4a2713aSLionel Sambuc // Traverse*(c) for each child c of 'node'. 110*f4a2713aSLionel Sambuc // - Traverse*(c) in turn calls Traverse(c), completing the 111*f4a2713aSLionel Sambuc // recursion. 112*f4a2713aSLionel Sambuc bool findMatch(const ast_type_traits::DynTypedNode &DynNode) { 113*f4a2713aSLionel Sambuc reset(); 114*f4a2713aSLionel Sambuc if (const Decl *D = DynNode.get<Decl>()) 115*f4a2713aSLionel Sambuc traverse(*D); 116*f4a2713aSLionel Sambuc else if (const Stmt *S = DynNode.get<Stmt>()) 117*f4a2713aSLionel Sambuc traverse(*S); 118*f4a2713aSLionel Sambuc else if (const NestedNameSpecifier *NNS = 119*f4a2713aSLionel Sambuc DynNode.get<NestedNameSpecifier>()) 120*f4a2713aSLionel Sambuc traverse(*NNS); 121*f4a2713aSLionel Sambuc else if (const NestedNameSpecifierLoc *NNSLoc = 122*f4a2713aSLionel Sambuc DynNode.get<NestedNameSpecifierLoc>()) 123*f4a2713aSLionel Sambuc traverse(*NNSLoc); 124*f4a2713aSLionel Sambuc else if (const QualType *Q = DynNode.get<QualType>()) 125*f4a2713aSLionel Sambuc traverse(*Q); 126*f4a2713aSLionel Sambuc else if (const TypeLoc *T = DynNode.get<TypeLoc>()) 127*f4a2713aSLionel Sambuc traverse(*T); 128*f4a2713aSLionel Sambuc // FIXME: Add other base types after adding tests. 129*f4a2713aSLionel Sambuc 130*f4a2713aSLionel Sambuc // It's OK to always overwrite the bound nodes, as if there was 131*f4a2713aSLionel Sambuc // no match in this recursive branch, the result set is empty 132*f4a2713aSLionel Sambuc // anyway. 133*f4a2713aSLionel Sambuc *Builder = ResultBindings; 134*f4a2713aSLionel Sambuc 135*f4a2713aSLionel Sambuc return Matches; 136*f4a2713aSLionel Sambuc } 137*f4a2713aSLionel Sambuc 138*f4a2713aSLionel Sambuc // The following are overriding methods from the base visitor class. 139*f4a2713aSLionel Sambuc // They are public only to allow CRTP to work. They are *not *part 140*f4a2713aSLionel Sambuc // of the public API of this class. 141*f4a2713aSLionel Sambuc bool TraverseDecl(Decl *DeclNode) { 142*f4a2713aSLionel Sambuc ScopedIncrement ScopedDepth(&CurrentDepth); 143*f4a2713aSLionel Sambuc return (DeclNode == NULL) || traverse(*DeclNode); 144*f4a2713aSLionel Sambuc } 145*f4a2713aSLionel Sambuc bool TraverseStmt(Stmt *StmtNode) { 146*f4a2713aSLionel Sambuc ScopedIncrement ScopedDepth(&CurrentDepth); 147*f4a2713aSLionel Sambuc const Stmt *StmtToTraverse = StmtNode; 148*f4a2713aSLionel Sambuc if (Traversal == 149*f4a2713aSLionel Sambuc ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) { 150*f4a2713aSLionel Sambuc const Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode); 151*f4a2713aSLionel Sambuc if (ExprNode != NULL) { 152*f4a2713aSLionel Sambuc StmtToTraverse = ExprNode->IgnoreParenImpCasts(); 153*f4a2713aSLionel Sambuc } 154*f4a2713aSLionel Sambuc } 155*f4a2713aSLionel Sambuc return (StmtToTraverse == NULL) || traverse(*StmtToTraverse); 156*f4a2713aSLionel Sambuc } 157*f4a2713aSLionel Sambuc // We assume that the QualType and the contained type are on the same 158*f4a2713aSLionel Sambuc // hierarchy level. Thus, we try to match either of them. 159*f4a2713aSLionel Sambuc bool TraverseType(QualType TypeNode) { 160*f4a2713aSLionel Sambuc if (TypeNode.isNull()) 161*f4a2713aSLionel Sambuc return true; 162*f4a2713aSLionel Sambuc ScopedIncrement ScopedDepth(&CurrentDepth); 163*f4a2713aSLionel Sambuc // Match the Type. 164*f4a2713aSLionel Sambuc if (!match(*TypeNode)) 165*f4a2713aSLionel Sambuc return false; 166*f4a2713aSLionel Sambuc // The QualType is matched inside traverse. 167*f4a2713aSLionel Sambuc return traverse(TypeNode); 168*f4a2713aSLionel Sambuc } 169*f4a2713aSLionel Sambuc // We assume that the TypeLoc, contained QualType and contained Type all are 170*f4a2713aSLionel Sambuc // on the same hierarchy level. Thus, we try to match all of them. 171*f4a2713aSLionel Sambuc bool TraverseTypeLoc(TypeLoc TypeLocNode) { 172*f4a2713aSLionel Sambuc if (TypeLocNode.isNull()) 173*f4a2713aSLionel Sambuc return true; 174*f4a2713aSLionel Sambuc ScopedIncrement ScopedDepth(&CurrentDepth); 175*f4a2713aSLionel Sambuc // Match the Type. 176*f4a2713aSLionel Sambuc if (!match(*TypeLocNode.getType())) 177*f4a2713aSLionel Sambuc return false; 178*f4a2713aSLionel Sambuc // Match the QualType. 179*f4a2713aSLionel Sambuc if (!match(TypeLocNode.getType())) 180*f4a2713aSLionel Sambuc return false; 181*f4a2713aSLionel Sambuc // The TypeLoc is matched inside traverse. 182*f4a2713aSLionel Sambuc return traverse(TypeLocNode); 183*f4a2713aSLionel Sambuc } 184*f4a2713aSLionel Sambuc bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { 185*f4a2713aSLionel Sambuc ScopedIncrement ScopedDepth(&CurrentDepth); 186*f4a2713aSLionel Sambuc return (NNS == NULL) || traverse(*NNS); 187*f4a2713aSLionel Sambuc } 188*f4a2713aSLionel Sambuc bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { 189*f4a2713aSLionel Sambuc if (!NNS) 190*f4a2713aSLionel Sambuc return true; 191*f4a2713aSLionel Sambuc ScopedIncrement ScopedDepth(&CurrentDepth); 192*f4a2713aSLionel Sambuc if (!match(*NNS.getNestedNameSpecifier())) 193*f4a2713aSLionel Sambuc return false; 194*f4a2713aSLionel Sambuc return traverse(NNS); 195*f4a2713aSLionel Sambuc } 196*f4a2713aSLionel Sambuc 197*f4a2713aSLionel Sambuc bool shouldVisitTemplateInstantiations() const { return true; } 198*f4a2713aSLionel Sambuc bool shouldVisitImplicitCode() const { return true; } 199*f4a2713aSLionel Sambuc // Disables data recursion. We intercept Traverse* methods in the RAV, which 200*f4a2713aSLionel Sambuc // are not triggered during data recursion. 201*f4a2713aSLionel Sambuc bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; } 202*f4a2713aSLionel Sambuc 203*f4a2713aSLionel Sambuc private: 204*f4a2713aSLionel Sambuc // Used for updating the depth during traversal. 205*f4a2713aSLionel Sambuc struct ScopedIncrement { 206*f4a2713aSLionel Sambuc explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); } 207*f4a2713aSLionel Sambuc ~ScopedIncrement() { --(*Depth); } 208*f4a2713aSLionel Sambuc 209*f4a2713aSLionel Sambuc private: 210*f4a2713aSLionel Sambuc int *Depth; 211*f4a2713aSLionel Sambuc }; 212*f4a2713aSLionel Sambuc 213*f4a2713aSLionel Sambuc // Resets the state of this object. 214*f4a2713aSLionel Sambuc void reset() { 215*f4a2713aSLionel Sambuc Matches = false; 216*f4a2713aSLionel Sambuc CurrentDepth = 0; 217*f4a2713aSLionel Sambuc } 218*f4a2713aSLionel Sambuc 219*f4a2713aSLionel Sambuc // Forwards the call to the corresponding Traverse*() method in the 220*f4a2713aSLionel Sambuc // base visitor class. 221*f4a2713aSLionel Sambuc bool baseTraverse(const Decl &DeclNode) { 222*f4a2713aSLionel Sambuc return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode)); 223*f4a2713aSLionel Sambuc } 224*f4a2713aSLionel Sambuc bool baseTraverse(const Stmt &StmtNode) { 225*f4a2713aSLionel Sambuc return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode)); 226*f4a2713aSLionel Sambuc } 227*f4a2713aSLionel Sambuc bool baseTraverse(QualType TypeNode) { 228*f4a2713aSLionel Sambuc return VisitorBase::TraverseType(TypeNode); 229*f4a2713aSLionel Sambuc } 230*f4a2713aSLionel Sambuc bool baseTraverse(TypeLoc TypeLocNode) { 231*f4a2713aSLionel Sambuc return VisitorBase::TraverseTypeLoc(TypeLocNode); 232*f4a2713aSLionel Sambuc } 233*f4a2713aSLionel Sambuc bool baseTraverse(const NestedNameSpecifier &NNS) { 234*f4a2713aSLionel Sambuc return VisitorBase::TraverseNestedNameSpecifier( 235*f4a2713aSLionel Sambuc const_cast<NestedNameSpecifier*>(&NNS)); 236*f4a2713aSLionel Sambuc } 237*f4a2713aSLionel Sambuc bool baseTraverse(NestedNameSpecifierLoc NNS) { 238*f4a2713aSLionel Sambuc return VisitorBase::TraverseNestedNameSpecifierLoc(NNS); 239*f4a2713aSLionel Sambuc } 240*f4a2713aSLionel Sambuc 241*f4a2713aSLionel Sambuc // Sets 'Matched' to true if 'Matcher' matches 'Node' and: 242*f4a2713aSLionel Sambuc // 0 < CurrentDepth <= MaxDepth. 243*f4a2713aSLionel Sambuc // 244*f4a2713aSLionel Sambuc // Returns 'true' if traversal should continue after this function 245*f4a2713aSLionel Sambuc // returns, i.e. if no match is found or 'Bind' is 'BK_All'. 246*f4a2713aSLionel Sambuc template <typename T> 247*f4a2713aSLionel Sambuc bool match(const T &Node) { 248*f4a2713aSLionel Sambuc if (CurrentDepth == 0 || CurrentDepth > MaxDepth) { 249*f4a2713aSLionel Sambuc return true; 250*f4a2713aSLionel Sambuc } 251*f4a2713aSLionel Sambuc if (Bind != ASTMatchFinder::BK_All) { 252*f4a2713aSLionel Sambuc BoundNodesTreeBuilder RecursiveBuilder(*Builder); 253*f4a2713aSLionel Sambuc if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder, 254*f4a2713aSLionel Sambuc &RecursiveBuilder)) { 255*f4a2713aSLionel Sambuc Matches = true; 256*f4a2713aSLionel Sambuc ResultBindings.addMatch(RecursiveBuilder); 257*f4a2713aSLionel Sambuc return false; // Abort as soon as a match is found. 258*f4a2713aSLionel Sambuc } 259*f4a2713aSLionel Sambuc } else { 260*f4a2713aSLionel Sambuc BoundNodesTreeBuilder RecursiveBuilder(*Builder); 261*f4a2713aSLionel Sambuc if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder, 262*f4a2713aSLionel Sambuc &RecursiveBuilder)) { 263*f4a2713aSLionel Sambuc // After the first match the matcher succeeds. 264*f4a2713aSLionel Sambuc Matches = true; 265*f4a2713aSLionel Sambuc ResultBindings.addMatch(RecursiveBuilder); 266*f4a2713aSLionel Sambuc } 267*f4a2713aSLionel Sambuc } 268*f4a2713aSLionel Sambuc return true; 269*f4a2713aSLionel Sambuc } 270*f4a2713aSLionel Sambuc 271*f4a2713aSLionel Sambuc // Traverses the subtree rooted at 'Node'; returns true if the 272*f4a2713aSLionel Sambuc // traversal should continue after this function returns. 273*f4a2713aSLionel Sambuc template <typename T> 274*f4a2713aSLionel Sambuc bool traverse(const T &Node) { 275*f4a2713aSLionel Sambuc TOOLING_COMPILE_ASSERT(IsBaseType<T>::value, 276*f4a2713aSLionel Sambuc traverse_can_only_be_instantiated_with_base_type); 277*f4a2713aSLionel Sambuc if (!match(Node)) 278*f4a2713aSLionel Sambuc return false; 279*f4a2713aSLionel Sambuc return baseTraverse(Node); 280*f4a2713aSLionel Sambuc } 281*f4a2713aSLionel Sambuc 282*f4a2713aSLionel Sambuc const DynTypedMatcher *const Matcher; 283*f4a2713aSLionel Sambuc ASTMatchFinder *const Finder; 284*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *const Builder; 285*f4a2713aSLionel Sambuc BoundNodesTreeBuilder ResultBindings; 286*f4a2713aSLionel Sambuc int CurrentDepth; 287*f4a2713aSLionel Sambuc const int MaxDepth; 288*f4a2713aSLionel Sambuc const ASTMatchFinder::TraversalKind Traversal; 289*f4a2713aSLionel Sambuc const ASTMatchFinder::BindKind Bind; 290*f4a2713aSLionel Sambuc bool Matches; 291*f4a2713aSLionel Sambuc }; 292*f4a2713aSLionel Sambuc 293*f4a2713aSLionel Sambuc // Controls the outermost traversal of the AST and allows to match multiple 294*f4a2713aSLionel Sambuc // matchers. 295*f4a2713aSLionel Sambuc class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>, 296*f4a2713aSLionel Sambuc public ASTMatchFinder { 297*f4a2713aSLionel Sambuc public: 298*f4a2713aSLionel Sambuc MatchASTVisitor( 299*f4a2713aSLionel Sambuc std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > * 300*f4a2713aSLionel Sambuc MatcherCallbackPairs) 301*f4a2713aSLionel Sambuc : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(NULL) {} 302*f4a2713aSLionel Sambuc 303*f4a2713aSLionel Sambuc void onStartOfTranslationUnit() { 304*f4a2713aSLionel Sambuc for (std::vector<std::pair<internal::DynTypedMatcher, 305*f4a2713aSLionel Sambuc MatchCallback *> >::const_iterator 306*f4a2713aSLionel Sambuc I = MatcherCallbackPairs->begin(), 307*f4a2713aSLionel Sambuc E = MatcherCallbackPairs->end(); 308*f4a2713aSLionel Sambuc I != E; ++I) { 309*f4a2713aSLionel Sambuc I->second->onStartOfTranslationUnit(); 310*f4a2713aSLionel Sambuc } 311*f4a2713aSLionel Sambuc } 312*f4a2713aSLionel Sambuc 313*f4a2713aSLionel Sambuc void onEndOfTranslationUnit() { 314*f4a2713aSLionel Sambuc for (std::vector<std::pair<internal::DynTypedMatcher, 315*f4a2713aSLionel Sambuc MatchCallback *> >::const_iterator 316*f4a2713aSLionel Sambuc I = MatcherCallbackPairs->begin(), 317*f4a2713aSLionel Sambuc E = MatcherCallbackPairs->end(); 318*f4a2713aSLionel Sambuc I != E; ++I) { 319*f4a2713aSLionel Sambuc I->second->onEndOfTranslationUnit(); 320*f4a2713aSLionel Sambuc } 321*f4a2713aSLionel Sambuc } 322*f4a2713aSLionel Sambuc 323*f4a2713aSLionel Sambuc void set_active_ast_context(ASTContext *NewActiveASTContext) { 324*f4a2713aSLionel Sambuc ActiveASTContext = NewActiveASTContext; 325*f4a2713aSLionel Sambuc } 326*f4a2713aSLionel Sambuc 327*f4a2713aSLionel Sambuc // The following Visit*() and Traverse*() functions "override" 328*f4a2713aSLionel Sambuc // methods in RecursiveASTVisitor. 329*f4a2713aSLionel Sambuc 330*f4a2713aSLionel Sambuc bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) { 331*f4a2713aSLionel Sambuc // When we see 'typedef A B', we add name 'B' to the set of names 332*f4a2713aSLionel Sambuc // A's canonical type maps to. This is necessary for implementing 333*f4a2713aSLionel Sambuc // isDerivedFrom(x) properly, where x can be the name of the base 334*f4a2713aSLionel Sambuc // class or any of its aliases. 335*f4a2713aSLionel Sambuc // 336*f4a2713aSLionel Sambuc // In general, the is-alias-of (as defined by typedefs) relation 337*f4a2713aSLionel Sambuc // is tree-shaped, as you can typedef a type more than once. For 338*f4a2713aSLionel Sambuc // example, 339*f4a2713aSLionel Sambuc // 340*f4a2713aSLionel Sambuc // typedef A B; 341*f4a2713aSLionel Sambuc // typedef A C; 342*f4a2713aSLionel Sambuc // typedef C D; 343*f4a2713aSLionel Sambuc // typedef C E; 344*f4a2713aSLionel Sambuc // 345*f4a2713aSLionel Sambuc // gives you 346*f4a2713aSLionel Sambuc // 347*f4a2713aSLionel Sambuc // A 348*f4a2713aSLionel Sambuc // |- B 349*f4a2713aSLionel Sambuc // `- C 350*f4a2713aSLionel Sambuc // |- D 351*f4a2713aSLionel Sambuc // `- E 352*f4a2713aSLionel Sambuc // 353*f4a2713aSLionel Sambuc // It is wrong to assume that the relation is a chain. A correct 354*f4a2713aSLionel Sambuc // implementation of isDerivedFrom() needs to recognize that B and 355*f4a2713aSLionel Sambuc // E are aliases, even though neither is a typedef of the other. 356*f4a2713aSLionel Sambuc // Therefore, we cannot simply walk through one typedef chain to 357*f4a2713aSLionel Sambuc // find out whether the type name matches. 358*f4a2713aSLionel Sambuc const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr(); 359*f4a2713aSLionel Sambuc const Type *CanonicalType = // root of the typedef tree 360*f4a2713aSLionel Sambuc ActiveASTContext->getCanonicalType(TypeNode); 361*f4a2713aSLionel Sambuc TypeAliases[CanonicalType].insert(DeclNode); 362*f4a2713aSLionel Sambuc return true; 363*f4a2713aSLionel Sambuc } 364*f4a2713aSLionel Sambuc 365*f4a2713aSLionel Sambuc bool TraverseDecl(Decl *DeclNode); 366*f4a2713aSLionel Sambuc bool TraverseStmt(Stmt *StmtNode); 367*f4a2713aSLionel Sambuc bool TraverseType(QualType TypeNode); 368*f4a2713aSLionel Sambuc bool TraverseTypeLoc(TypeLoc TypeNode); 369*f4a2713aSLionel Sambuc bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); 370*f4a2713aSLionel Sambuc bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); 371*f4a2713aSLionel Sambuc 372*f4a2713aSLionel Sambuc // Matches children or descendants of 'Node' with 'BaseMatcher'. 373*f4a2713aSLionel Sambuc bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node, 374*f4a2713aSLionel Sambuc const DynTypedMatcher &Matcher, 375*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder, int MaxDepth, 376*f4a2713aSLionel Sambuc TraversalKind Traversal, BindKind Bind) { 377*f4a2713aSLionel Sambuc // For AST-nodes that don't have an identity, we can't memoize. 378*f4a2713aSLionel Sambuc if (!Node.getMemoizationData()) 379*f4a2713aSLionel Sambuc return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal, 380*f4a2713aSLionel Sambuc Bind); 381*f4a2713aSLionel Sambuc 382*f4a2713aSLionel Sambuc MatchKey Key; 383*f4a2713aSLionel Sambuc Key.MatcherID = Matcher.getID(); 384*f4a2713aSLionel Sambuc Key.Node = Node; 385*f4a2713aSLionel Sambuc // Note that we key on the bindings *before* the match. 386*f4a2713aSLionel Sambuc Key.BoundNodes = *Builder; 387*f4a2713aSLionel Sambuc 388*f4a2713aSLionel Sambuc MemoizationMap::iterator I = ResultCache.find(Key); 389*f4a2713aSLionel Sambuc if (I != ResultCache.end()) { 390*f4a2713aSLionel Sambuc *Builder = I->second.Nodes; 391*f4a2713aSLionel Sambuc return I->second.ResultOfMatch; 392*f4a2713aSLionel Sambuc } 393*f4a2713aSLionel Sambuc 394*f4a2713aSLionel Sambuc MemoizedMatchResult Result; 395*f4a2713aSLionel Sambuc Result.Nodes = *Builder; 396*f4a2713aSLionel Sambuc Result.ResultOfMatch = matchesRecursively(Node, Matcher, &Result.Nodes, 397*f4a2713aSLionel Sambuc MaxDepth, Traversal, Bind); 398*f4a2713aSLionel Sambuc ResultCache[Key] = Result; 399*f4a2713aSLionel Sambuc *Builder = Result.Nodes; 400*f4a2713aSLionel Sambuc return Result.ResultOfMatch; 401*f4a2713aSLionel Sambuc } 402*f4a2713aSLionel Sambuc 403*f4a2713aSLionel Sambuc // Matches children or descendants of 'Node' with 'BaseMatcher'. 404*f4a2713aSLionel Sambuc bool matchesRecursively(const ast_type_traits::DynTypedNode &Node, 405*f4a2713aSLionel Sambuc const DynTypedMatcher &Matcher, 406*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder, int MaxDepth, 407*f4a2713aSLionel Sambuc TraversalKind Traversal, BindKind Bind) { 408*f4a2713aSLionel Sambuc MatchChildASTVisitor Visitor( 409*f4a2713aSLionel Sambuc &Matcher, this, Builder, MaxDepth, Traversal, Bind); 410*f4a2713aSLionel Sambuc return Visitor.findMatch(Node); 411*f4a2713aSLionel Sambuc } 412*f4a2713aSLionel Sambuc 413*f4a2713aSLionel Sambuc virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration, 414*f4a2713aSLionel Sambuc const Matcher<NamedDecl> &Base, 415*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder); 416*f4a2713aSLionel Sambuc 417*f4a2713aSLionel Sambuc // Implements ASTMatchFinder::matchesChildOf. 418*f4a2713aSLionel Sambuc virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, 419*f4a2713aSLionel Sambuc const DynTypedMatcher &Matcher, 420*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder, 421*f4a2713aSLionel Sambuc TraversalKind Traversal, 422*f4a2713aSLionel Sambuc BindKind Bind) { 423*f4a2713aSLionel Sambuc if (ResultCache.size() > MaxMemoizationEntries) 424*f4a2713aSLionel Sambuc ResultCache.clear(); 425*f4a2713aSLionel Sambuc return memoizedMatchesRecursively(Node, Matcher, Builder, 1, Traversal, 426*f4a2713aSLionel Sambuc Bind); 427*f4a2713aSLionel Sambuc } 428*f4a2713aSLionel Sambuc // Implements ASTMatchFinder::matchesDescendantOf. 429*f4a2713aSLionel Sambuc virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, 430*f4a2713aSLionel Sambuc const DynTypedMatcher &Matcher, 431*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder, 432*f4a2713aSLionel Sambuc BindKind Bind) { 433*f4a2713aSLionel Sambuc if (ResultCache.size() > MaxMemoizationEntries) 434*f4a2713aSLionel Sambuc ResultCache.clear(); 435*f4a2713aSLionel Sambuc return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX, 436*f4a2713aSLionel Sambuc TK_AsIs, Bind); 437*f4a2713aSLionel Sambuc } 438*f4a2713aSLionel Sambuc // Implements ASTMatchFinder::matchesAncestorOf. 439*f4a2713aSLionel Sambuc virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, 440*f4a2713aSLionel Sambuc const DynTypedMatcher &Matcher, 441*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder, 442*f4a2713aSLionel Sambuc AncestorMatchMode MatchMode) { 443*f4a2713aSLionel Sambuc // Reset the cache outside of the recursive call to make sure we 444*f4a2713aSLionel Sambuc // don't invalidate any iterators. 445*f4a2713aSLionel Sambuc if (ResultCache.size() > MaxMemoizationEntries) 446*f4a2713aSLionel Sambuc ResultCache.clear(); 447*f4a2713aSLionel Sambuc return memoizedMatchesAncestorOfRecursively(Node, Matcher, Builder, 448*f4a2713aSLionel Sambuc MatchMode); 449*f4a2713aSLionel Sambuc } 450*f4a2713aSLionel Sambuc 451*f4a2713aSLionel Sambuc // Matches all registered matchers on the given node and calls the 452*f4a2713aSLionel Sambuc // result callback for every node that matches. 453*f4a2713aSLionel Sambuc void match(const ast_type_traits::DynTypedNode& Node) { 454*f4a2713aSLionel Sambuc for (std::vector<std::pair<internal::DynTypedMatcher, 455*f4a2713aSLionel Sambuc MatchCallback *> >::const_iterator 456*f4a2713aSLionel Sambuc I = MatcherCallbackPairs->begin(), 457*f4a2713aSLionel Sambuc E = MatcherCallbackPairs->end(); 458*f4a2713aSLionel Sambuc I != E; ++I) { 459*f4a2713aSLionel Sambuc BoundNodesTreeBuilder Builder; 460*f4a2713aSLionel Sambuc if (I->first.matches(Node, this, &Builder)) { 461*f4a2713aSLionel Sambuc MatchVisitor Visitor(ActiveASTContext, I->second); 462*f4a2713aSLionel Sambuc Builder.visitMatches(&Visitor); 463*f4a2713aSLionel Sambuc } 464*f4a2713aSLionel Sambuc } 465*f4a2713aSLionel Sambuc } 466*f4a2713aSLionel Sambuc 467*f4a2713aSLionel Sambuc template <typename T> void match(const T &Node) { 468*f4a2713aSLionel Sambuc match(ast_type_traits::DynTypedNode::create(Node)); 469*f4a2713aSLionel Sambuc } 470*f4a2713aSLionel Sambuc 471*f4a2713aSLionel Sambuc // Implements ASTMatchFinder::getASTContext. 472*f4a2713aSLionel Sambuc virtual ASTContext &getASTContext() const { return *ActiveASTContext; } 473*f4a2713aSLionel Sambuc 474*f4a2713aSLionel Sambuc bool shouldVisitTemplateInstantiations() const { return true; } 475*f4a2713aSLionel Sambuc bool shouldVisitImplicitCode() const { return true; } 476*f4a2713aSLionel Sambuc // Disables data recursion. We intercept Traverse* methods in the RAV, which 477*f4a2713aSLionel Sambuc // are not triggered during data recursion. 478*f4a2713aSLionel Sambuc bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; } 479*f4a2713aSLionel Sambuc 480*f4a2713aSLionel Sambuc private: 481*f4a2713aSLionel Sambuc // Returns whether an ancestor of \p Node matches \p Matcher. 482*f4a2713aSLionel Sambuc // 483*f4a2713aSLionel Sambuc // The order of matching ((which can lead to different nodes being bound in 484*f4a2713aSLionel Sambuc // case there are multiple matches) is breadth first search. 485*f4a2713aSLionel Sambuc // 486*f4a2713aSLionel Sambuc // To allow memoization in the very common case of having deeply nested 487*f4a2713aSLionel Sambuc // expressions inside a template function, we first walk up the AST, memoizing 488*f4a2713aSLionel Sambuc // the result of the match along the way, as long as there is only a single 489*f4a2713aSLionel Sambuc // parent. 490*f4a2713aSLionel Sambuc // 491*f4a2713aSLionel Sambuc // Once there are multiple parents, the breadth first search order does not 492*f4a2713aSLionel Sambuc // allow simple memoization on the ancestors. Thus, we only memoize as long 493*f4a2713aSLionel Sambuc // as there is a single parent. 494*f4a2713aSLionel Sambuc bool memoizedMatchesAncestorOfRecursively( 495*f4a2713aSLionel Sambuc const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher, 496*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) { 497*f4a2713aSLionel Sambuc if (Node.get<TranslationUnitDecl>() == 498*f4a2713aSLionel Sambuc ActiveASTContext->getTranslationUnitDecl()) 499*f4a2713aSLionel Sambuc return false; 500*f4a2713aSLionel Sambuc assert(Node.getMemoizationData() && 501*f4a2713aSLionel Sambuc "Invariant broken: only nodes that support memoization may be " 502*f4a2713aSLionel Sambuc "used in the parent map."); 503*f4a2713aSLionel Sambuc ASTContext::ParentVector Parents = ActiveASTContext->getParents(Node); 504*f4a2713aSLionel Sambuc if (Parents.empty()) { 505*f4a2713aSLionel Sambuc assert(false && "Found node that is not in the parent map."); 506*f4a2713aSLionel Sambuc return false; 507*f4a2713aSLionel Sambuc } 508*f4a2713aSLionel Sambuc MatchKey Key; 509*f4a2713aSLionel Sambuc Key.MatcherID = Matcher.getID(); 510*f4a2713aSLionel Sambuc Key.Node = Node; 511*f4a2713aSLionel Sambuc Key.BoundNodes = *Builder; 512*f4a2713aSLionel Sambuc 513*f4a2713aSLionel Sambuc // Note that we cannot use insert and reuse the iterator, as recursive 514*f4a2713aSLionel Sambuc // calls to match might invalidate the result cache iterators. 515*f4a2713aSLionel Sambuc MemoizationMap::iterator I = ResultCache.find(Key); 516*f4a2713aSLionel Sambuc if (I != ResultCache.end()) { 517*f4a2713aSLionel Sambuc *Builder = I->second.Nodes; 518*f4a2713aSLionel Sambuc return I->second.ResultOfMatch; 519*f4a2713aSLionel Sambuc } 520*f4a2713aSLionel Sambuc MemoizedMatchResult Result; 521*f4a2713aSLionel Sambuc Result.ResultOfMatch = false; 522*f4a2713aSLionel Sambuc Result.Nodes = *Builder; 523*f4a2713aSLionel Sambuc if (Parents.size() == 1) { 524*f4a2713aSLionel Sambuc // Only one parent - do recursive memoization. 525*f4a2713aSLionel Sambuc const ast_type_traits::DynTypedNode Parent = Parents[0]; 526*f4a2713aSLionel Sambuc if (Matcher.matches(Parent, this, &Result.Nodes)) { 527*f4a2713aSLionel Sambuc Result.ResultOfMatch = true; 528*f4a2713aSLionel Sambuc } else if (MatchMode != ASTMatchFinder::AMM_ParentOnly) { 529*f4a2713aSLionel Sambuc // Reset the results to not include the bound nodes from the failed 530*f4a2713aSLionel Sambuc // match above. 531*f4a2713aSLionel Sambuc Result.Nodes = *Builder; 532*f4a2713aSLionel Sambuc Result.ResultOfMatch = memoizedMatchesAncestorOfRecursively( 533*f4a2713aSLionel Sambuc Parent, Matcher, &Result.Nodes, MatchMode); 534*f4a2713aSLionel Sambuc // Once we get back from the recursive call, the result will be the 535*f4a2713aSLionel Sambuc // same as the parent's result. 536*f4a2713aSLionel Sambuc } 537*f4a2713aSLionel Sambuc } else { 538*f4a2713aSLionel Sambuc // Multiple parents - BFS over the rest of the nodes. 539*f4a2713aSLionel Sambuc llvm::DenseSet<const void *> Visited; 540*f4a2713aSLionel Sambuc std::deque<ast_type_traits::DynTypedNode> Queue(Parents.begin(), 541*f4a2713aSLionel Sambuc Parents.end()); 542*f4a2713aSLionel Sambuc while (!Queue.empty()) { 543*f4a2713aSLionel Sambuc Result.Nodes = *Builder; 544*f4a2713aSLionel Sambuc if (Matcher.matches(Queue.front(), this, &Result.Nodes)) { 545*f4a2713aSLionel Sambuc Result.ResultOfMatch = true; 546*f4a2713aSLionel Sambuc break; 547*f4a2713aSLionel Sambuc } 548*f4a2713aSLionel Sambuc if (MatchMode != ASTMatchFinder::AMM_ParentOnly) { 549*f4a2713aSLionel Sambuc ASTContext::ParentVector Ancestors = 550*f4a2713aSLionel Sambuc ActiveASTContext->getParents(Queue.front()); 551*f4a2713aSLionel Sambuc for (ASTContext::ParentVector::const_iterator I = Ancestors.begin(), 552*f4a2713aSLionel Sambuc E = Ancestors.end(); 553*f4a2713aSLionel Sambuc I != E; ++I) { 554*f4a2713aSLionel Sambuc // Make sure we do not visit the same node twice. 555*f4a2713aSLionel Sambuc // Otherwise, we'll visit the common ancestors as often as there 556*f4a2713aSLionel Sambuc // are splits on the way down. 557*f4a2713aSLionel Sambuc if (Visited.insert(I->getMemoizationData()).second) 558*f4a2713aSLionel Sambuc Queue.push_back(*I); 559*f4a2713aSLionel Sambuc } 560*f4a2713aSLionel Sambuc } 561*f4a2713aSLionel Sambuc Queue.pop_front(); 562*f4a2713aSLionel Sambuc } 563*f4a2713aSLionel Sambuc } 564*f4a2713aSLionel Sambuc ResultCache[Key] = Result; 565*f4a2713aSLionel Sambuc 566*f4a2713aSLionel Sambuc *Builder = Result.Nodes; 567*f4a2713aSLionel Sambuc return Result.ResultOfMatch; 568*f4a2713aSLionel Sambuc } 569*f4a2713aSLionel Sambuc 570*f4a2713aSLionel Sambuc // Implements a BoundNodesTree::Visitor that calls a MatchCallback with 571*f4a2713aSLionel Sambuc // the aggregated bound nodes for each match. 572*f4a2713aSLionel Sambuc class MatchVisitor : public BoundNodesTreeBuilder::Visitor { 573*f4a2713aSLionel Sambuc public: 574*f4a2713aSLionel Sambuc MatchVisitor(ASTContext* Context, 575*f4a2713aSLionel Sambuc MatchFinder::MatchCallback* Callback) 576*f4a2713aSLionel Sambuc : Context(Context), 577*f4a2713aSLionel Sambuc Callback(Callback) {} 578*f4a2713aSLionel Sambuc 579*f4a2713aSLionel Sambuc virtual void visitMatch(const BoundNodes& BoundNodesView) { 580*f4a2713aSLionel Sambuc Callback->run(MatchFinder::MatchResult(BoundNodesView, Context)); 581*f4a2713aSLionel Sambuc } 582*f4a2713aSLionel Sambuc 583*f4a2713aSLionel Sambuc private: 584*f4a2713aSLionel Sambuc ASTContext* Context; 585*f4a2713aSLionel Sambuc MatchFinder::MatchCallback* Callback; 586*f4a2713aSLionel Sambuc }; 587*f4a2713aSLionel Sambuc 588*f4a2713aSLionel Sambuc // Returns true if 'TypeNode' has an alias that matches the given matcher. 589*f4a2713aSLionel Sambuc bool typeHasMatchingAlias(const Type *TypeNode, 590*f4a2713aSLionel Sambuc const Matcher<NamedDecl> Matcher, 591*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder) { 592*f4a2713aSLionel Sambuc const Type *const CanonicalType = 593*f4a2713aSLionel Sambuc ActiveASTContext->getCanonicalType(TypeNode); 594*f4a2713aSLionel Sambuc const std::set<const TypedefNameDecl *> &Aliases = 595*f4a2713aSLionel Sambuc TypeAliases[CanonicalType]; 596*f4a2713aSLionel Sambuc for (std::set<const TypedefNameDecl*>::const_iterator 597*f4a2713aSLionel Sambuc It = Aliases.begin(), End = Aliases.end(); 598*f4a2713aSLionel Sambuc It != End; ++It) { 599*f4a2713aSLionel Sambuc BoundNodesTreeBuilder Result(*Builder); 600*f4a2713aSLionel Sambuc if (Matcher.matches(**It, this, &Result)) { 601*f4a2713aSLionel Sambuc *Builder = Result; 602*f4a2713aSLionel Sambuc return true; 603*f4a2713aSLionel Sambuc } 604*f4a2713aSLionel Sambuc } 605*f4a2713aSLionel Sambuc return false; 606*f4a2713aSLionel Sambuc } 607*f4a2713aSLionel Sambuc 608*f4a2713aSLionel Sambuc std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *const 609*f4a2713aSLionel Sambuc MatcherCallbackPairs; 610*f4a2713aSLionel Sambuc ASTContext *ActiveASTContext; 611*f4a2713aSLionel Sambuc 612*f4a2713aSLionel Sambuc // Maps a canonical type to its TypedefDecls. 613*f4a2713aSLionel Sambuc llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases; 614*f4a2713aSLionel Sambuc 615*f4a2713aSLionel Sambuc // Maps (matcher, node) -> the match result for memoization. 616*f4a2713aSLionel Sambuc typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap; 617*f4a2713aSLionel Sambuc MemoizationMap ResultCache; 618*f4a2713aSLionel Sambuc }; 619*f4a2713aSLionel Sambuc 620*f4a2713aSLionel Sambuc static CXXRecordDecl *getAsCXXRecordDecl(const Type *TypeNode) { 621*f4a2713aSLionel Sambuc // Type::getAs<...>() drills through typedefs. 622*f4a2713aSLionel Sambuc if (TypeNode->getAs<DependentNameType>() != NULL || 623*f4a2713aSLionel Sambuc TypeNode->getAs<DependentTemplateSpecializationType>() != NULL || 624*f4a2713aSLionel Sambuc TypeNode->getAs<TemplateTypeParmType>() != NULL) 625*f4a2713aSLionel Sambuc // Dependent names and template TypeNode parameters will be matched when 626*f4a2713aSLionel Sambuc // the template is instantiated. 627*f4a2713aSLionel Sambuc return NULL; 628*f4a2713aSLionel Sambuc TemplateSpecializationType const *TemplateType = 629*f4a2713aSLionel Sambuc TypeNode->getAs<TemplateSpecializationType>(); 630*f4a2713aSLionel Sambuc if (TemplateType == NULL) { 631*f4a2713aSLionel Sambuc return TypeNode->getAsCXXRecordDecl(); 632*f4a2713aSLionel Sambuc } 633*f4a2713aSLionel Sambuc if (TemplateType->getTemplateName().isDependent()) 634*f4a2713aSLionel Sambuc // Dependent template specializations will be matched when the 635*f4a2713aSLionel Sambuc // template is instantiated. 636*f4a2713aSLionel Sambuc return NULL; 637*f4a2713aSLionel Sambuc 638*f4a2713aSLionel Sambuc // For template specialization types which are specializing a template 639*f4a2713aSLionel Sambuc // declaration which is an explicit or partial specialization of another 640*f4a2713aSLionel Sambuc // template declaration, getAsCXXRecordDecl() returns the corresponding 641*f4a2713aSLionel Sambuc // ClassTemplateSpecializationDecl. 642*f4a2713aSLionel Sambuc // 643*f4a2713aSLionel Sambuc // For template specialization types which are specializing a template 644*f4a2713aSLionel Sambuc // declaration which is neither an explicit nor partial specialization of 645*f4a2713aSLionel Sambuc // another template declaration, getAsCXXRecordDecl() returns NULL and 646*f4a2713aSLionel Sambuc // we get the CXXRecordDecl of the templated declaration. 647*f4a2713aSLionel Sambuc CXXRecordDecl *SpecializationDecl = TemplateType->getAsCXXRecordDecl(); 648*f4a2713aSLionel Sambuc if (SpecializationDecl != NULL) { 649*f4a2713aSLionel Sambuc return SpecializationDecl; 650*f4a2713aSLionel Sambuc } 651*f4a2713aSLionel Sambuc NamedDecl *Templated = 652*f4a2713aSLionel Sambuc TemplateType->getTemplateName().getAsTemplateDecl()->getTemplatedDecl(); 653*f4a2713aSLionel Sambuc if (CXXRecordDecl *TemplatedRecord = dyn_cast<CXXRecordDecl>(Templated)) { 654*f4a2713aSLionel Sambuc return TemplatedRecord; 655*f4a2713aSLionel Sambuc } 656*f4a2713aSLionel Sambuc // Now it can still be that we have an alias template. 657*f4a2713aSLionel Sambuc TypeAliasDecl *AliasDecl = dyn_cast<TypeAliasDecl>(Templated); 658*f4a2713aSLionel Sambuc assert(AliasDecl); 659*f4a2713aSLionel Sambuc return getAsCXXRecordDecl(AliasDecl->getUnderlyingType().getTypePtr()); 660*f4a2713aSLionel Sambuc } 661*f4a2713aSLionel Sambuc 662*f4a2713aSLionel Sambuc // Returns true if the given class is directly or indirectly derived 663*f4a2713aSLionel Sambuc // from a base type with the given name. A class is not considered to be 664*f4a2713aSLionel Sambuc // derived from itself. 665*f4a2713aSLionel Sambuc bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, 666*f4a2713aSLionel Sambuc const Matcher<NamedDecl> &Base, 667*f4a2713aSLionel Sambuc BoundNodesTreeBuilder *Builder) { 668*f4a2713aSLionel Sambuc if (!Declaration->hasDefinition()) 669*f4a2713aSLionel Sambuc return false; 670*f4a2713aSLionel Sambuc typedef CXXRecordDecl::base_class_const_iterator BaseIterator; 671*f4a2713aSLionel Sambuc for (BaseIterator It = Declaration->bases_begin(), 672*f4a2713aSLionel Sambuc End = Declaration->bases_end(); 673*f4a2713aSLionel Sambuc It != End; ++It) { 674*f4a2713aSLionel Sambuc const Type *TypeNode = It->getType().getTypePtr(); 675*f4a2713aSLionel Sambuc 676*f4a2713aSLionel Sambuc if (typeHasMatchingAlias(TypeNode, Base, Builder)) 677*f4a2713aSLionel Sambuc return true; 678*f4a2713aSLionel Sambuc 679*f4a2713aSLionel Sambuc CXXRecordDecl *ClassDecl = getAsCXXRecordDecl(TypeNode); 680*f4a2713aSLionel Sambuc if (ClassDecl == NULL) 681*f4a2713aSLionel Sambuc continue; 682*f4a2713aSLionel Sambuc if (ClassDecl == Declaration) { 683*f4a2713aSLionel Sambuc // This can happen for recursive template definitions; if the 684*f4a2713aSLionel Sambuc // current declaration did not match, we can safely return false. 685*f4a2713aSLionel Sambuc return false; 686*f4a2713aSLionel Sambuc } 687*f4a2713aSLionel Sambuc BoundNodesTreeBuilder Result(*Builder); 688*f4a2713aSLionel Sambuc if (Base.matches(*ClassDecl, this, &Result)) { 689*f4a2713aSLionel Sambuc *Builder = Result; 690*f4a2713aSLionel Sambuc return true; 691*f4a2713aSLionel Sambuc } 692*f4a2713aSLionel Sambuc if (classIsDerivedFrom(ClassDecl, Base, Builder)) 693*f4a2713aSLionel Sambuc return true; 694*f4a2713aSLionel Sambuc } 695*f4a2713aSLionel Sambuc return false; 696*f4a2713aSLionel Sambuc } 697*f4a2713aSLionel Sambuc 698*f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { 699*f4a2713aSLionel Sambuc if (DeclNode == NULL) { 700*f4a2713aSLionel Sambuc return true; 701*f4a2713aSLionel Sambuc } 702*f4a2713aSLionel Sambuc match(*DeclNode); 703*f4a2713aSLionel Sambuc return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode); 704*f4a2713aSLionel Sambuc } 705*f4a2713aSLionel Sambuc 706*f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) { 707*f4a2713aSLionel Sambuc if (StmtNode == NULL) { 708*f4a2713aSLionel Sambuc return true; 709*f4a2713aSLionel Sambuc } 710*f4a2713aSLionel Sambuc match(*StmtNode); 711*f4a2713aSLionel Sambuc return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode); 712*f4a2713aSLionel Sambuc } 713*f4a2713aSLionel Sambuc 714*f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseType(QualType TypeNode) { 715*f4a2713aSLionel Sambuc match(TypeNode); 716*f4a2713aSLionel Sambuc return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode); 717*f4a2713aSLionel Sambuc } 718*f4a2713aSLionel Sambuc 719*f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) { 720*f4a2713aSLionel Sambuc // The RecursiveASTVisitor only visits types if they're not within TypeLocs. 721*f4a2713aSLionel Sambuc // We still want to find those types via matchers, so we match them here. Note 722*f4a2713aSLionel Sambuc // that the TypeLocs are structurally a shadow-hierarchy to the expressed 723*f4a2713aSLionel Sambuc // type, so we visit all involved parts of a compound type when matching on 724*f4a2713aSLionel Sambuc // each TypeLoc. 725*f4a2713aSLionel Sambuc match(TypeLocNode); 726*f4a2713aSLionel Sambuc match(TypeLocNode.getType()); 727*f4a2713aSLionel Sambuc return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode); 728*f4a2713aSLionel Sambuc } 729*f4a2713aSLionel Sambuc 730*f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { 731*f4a2713aSLionel Sambuc match(*NNS); 732*f4a2713aSLionel Sambuc return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS); 733*f4a2713aSLionel Sambuc } 734*f4a2713aSLionel Sambuc 735*f4a2713aSLionel Sambuc bool MatchASTVisitor::TraverseNestedNameSpecifierLoc( 736*f4a2713aSLionel Sambuc NestedNameSpecifierLoc NNS) { 737*f4a2713aSLionel Sambuc match(NNS); 738*f4a2713aSLionel Sambuc // We only match the nested name specifier here (as opposed to traversing it) 739*f4a2713aSLionel Sambuc // because the traversal is already done in the parallel "Loc"-hierarchy. 740*f4a2713aSLionel Sambuc match(*NNS.getNestedNameSpecifier()); 741*f4a2713aSLionel Sambuc return 742*f4a2713aSLionel Sambuc RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS); 743*f4a2713aSLionel Sambuc } 744*f4a2713aSLionel Sambuc 745*f4a2713aSLionel Sambuc class MatchASTConsumer : public ASTConsumer { 746*f4a2713aSLionel Sambuc public: 747*f4a2713aSLionel Sambuc MatchASTConsumer(MatchFinder *Finder, 748*f4a2713aSLionel Sambuc MatchFinder::ParsingDoneTestCallback *ParsingDone) 749*f4a2713aSLionel Sambuc : Finder(Finder), ParsingDone(ParsingDone) {} 750*f4a2713aSLionel Sambuc 751*f4a2713aSLionel Sambuc private: 752*f4a2713aSLionel Sambuc virtual void HandleTranslationUnit(ASTContext &Context) { 753*f4a2713aSLionel Sambuc if (ParsingDone != NULL) { 754*f4a2713aSLionel Sambuc ParsingDone->run(); 755*f4a2713aSLionel Sambuc } 756*f4a2713aSLionel Sambuc Finder->matchAST(Context); 757*f4a2713aSLionel Sambuc } 758*f4a2713aSLionel Sambuc 759*f4a2713aSLionel Sambuc MatchFinder *Finder; 760*f4a2713aSLionel Sambuc MatchFinder::ParsingDoneTestCallback *ParsingDone; 761*f4a2713aSLionel Sambuc }; 762*f4a2713aSLionel Sambuc 763*f4a2713aSLionel Sambuc } // end namespace 764*f4a2713aSLionel Sambuc } // end namespace internal 765*f4a2713aSLionel Sambuc 766*f4a2713aSLionel Sambuc MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes, 767*f4a2713aSLionel Sambuc ASTContext *Context) 768*f4a2713aSLionel Sambuc : Nodes(Nodes), Context(Context), 769*f4a2713aSLionel Sambuc SourceManager(&Context->getSourceManager()) {} 770*f4a2713aSLionel Sambuc 771*f4a2713aSLionel Sambuc MatchFinder::MatchCallback::~MatchCallback() {} 772*f4a2713aSLionel Sambuc MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {} 773*f4a2713aSLionel Sambuc 774*f4a2713aSLionel Sambuc MatchFinder::MatchFinder() : ParsingDone(NULL) {} 775*f4a2713aSLionel Sambuc 776*f4a2713aSLionel Sambuc MatchFinder::~MatchFinder() {} 777*f4a2713aSLionel Sambuc 778*f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch, 779*f4a2713aSLionel Sambuc MatchCallback *Action) { 780*f4a2713aSLionel Sambuc MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action)); 781*f4a2713aSLionel Sambuc } 782*f4a2713aSLionel Sambuc 783*f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const TypeMatcher &NodeMatch, 784*f4a2713aSLionel Sambuc MatchCallback *Action) { 785*f4a2713aSLionel Sambuc MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action)); 786*f4a2713aSLionel Sambuc } 787*f4a2713aSLionel Sambuc 788*f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const StatementMatcher &NodeMatch, 789*f4a2713aSLionel Sambuc MatchCallback *Action) { 790*f4a2713aSLionel Sambuc MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action)); 791*f4a2713aSLionel Sambuc } 792*f4a2713aSLionel Sambuc 793*f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch, 794*f4a2713aSLionel Sambuc MatchCallback *Action) { 795*f4a2713aSLionel Sambuc MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action)); 796*f4a2713aSLionel Sambuc } 797*f4a2713aSLionel Sambuc 798*f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, 799*f4a2713aSLionel Sambuc MatchCallback *Action) { 800*f4a2713aSLionel Sambuc MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action)); 801*f4a2713aSLionel Sambuc } 802*f4a2713aSLionel Sambuc 803*f4a2713aSLionel Sambuc void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch, 804*f4a2713aSLionel Sambuc MatchCallback *Action) { 805*f4a2713aSLionel Sambuc MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action)); 806*f4a2713aSLionel Sambuc } 807*f4a2713aSLionel Sambuc 808*f4a2713aSLionel Sambuc bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, 809*f4a2713aSLionel Sambuc MatchCallback *Action) { 810*f4a2713aSLionel Sambuc if (NodeMatch.canConvertTo<Decl>()) { 811*f4a2713aSLionel Sambuc addMatcher(NodeMatch.convertTo<Decl>(), Action); 812*f4a2713aSLionel Sambuc return true; 813*f4a2713aSLionel Sambuc } else if (NodeMatch.canConvertTo<QualType>()) { 814*f4a2713aSLionel Sambuc addMatcher(NodeMatch.convertTo<QualType>(), Action); 815*f4a2713aSLionel Sambuc return true; 816*f4a2713aSLionel Sambuc } else if (NodeMatch.canConvertTo<Stmt>()) { 817*f4a2713aSLionel Sambuc addMatcher(NodeMatch.convertTo<Stmt>(), Action); 818*f4a2713aSLionel Sambuc return true; 819*f4a2713aSLionel Sambuc } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) { 820*f4a2713aSLionel Sambuc addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action); 821*f4a2713aSLionel Sambuc return true; 822*f4a2713aSLionel Sambuc } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) { 823*f4a2713aSLionel Sambuc addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action); 824*f4a2713aSLionel Sambuc return true; 825*f4a2713aSLionel Sambuc } else if (NodeMatch.canConvertTo<TypeLoc>()) { 826*f4a2713aSLionel Sambuc addMatcher(NodeMatch.convertTo<TypeLoc>(), Action); 827*f4a2713aSLionel Sambuc return true; 828*f4a2713aSLionel Sambuc } 829*f4a2713aSLionel Sambuc return false; 830*f4a2713aSLionel Sambuc } 831*f4a2713aSLionel Sambuc 832*f4a2713aSLionel Sambuc ASTConsumer *MatchFinder::newASTConsumer() { 833*f4a2713aSLionel Sambuc return new internal::MatchASTConsumer(this, ParsingDone); 834*f4a2713aSLionel Sambuc } 835*f4a2713aSLionel Sambuc 836*f4a2713aSLionel Sambuc void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node, 837*f4a2713aSLionel Sambuc ASTContext &Context) { 838*f4a2713aSLionel Sambuc internal::MatchASTVisitor Visitor(&MatcherCallbackPairs); 839*f4a2713aSLionel Sambuc Visitor.set_active_ast_context(&Context); 840*f4a2713aSLionel Sambuc Visitor.match(Node); 841*f4a2713aSLionel Sambuc } 842*f4a2713aSLionel Sambuc 843*f4a2713aSLionel Sambuc void MatchFinder::matchAST(ASTContext &Context) { 844*f4a2713aSLionel Sambuc internal::MatchASTVisitor Visitor(&MatcherCallbackPairs); 845*f4a2713aSLionel Sambuc Visitor.set_active_ast_context(&Context); 846*f4a2713aSLionel Sambuc Visitor.onStartOfTranslationUnit(); 847*f4a2713aSLionel Sambuc Visitor.TraverseDecl(Context.getTranslationUnitDecl()); 848*f4a2713aSLionel Sambuc Visitor.onEndOfTranslationUnit(); 849*f4a2713aSLionel Sambuc } 850*f4a2713aSLionel Sambuc 851*f4a2713aSLionel Sambuc void MatchFinder::registerTestCallbackAfterParsing( 852*f4a2713aSLionel Sambuc MatchFinder::ParsingDoneTestCallback *NewParsingDone) { 853*f4a2713aSLionel Sambuc ParsingDone = NewParsingDone; 854*f4a2713aSLionel Sambuc } 855*f4a2713aSLionel Sambuc 856*f4a2713aSLionel Sambuc } // end namespace ast_matchers 857*f4a2713aSLionel Sambuc } // end namespace clang 858