clang API Documentation
00001 //===--- ASTMatchFinder.cpp - Structural query framework ------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Implements an algorithm to efficiently search for matches on AST nodes. 00011 // Uses memoization to support recursive matches like HasDescendant. 00012 // 00013 // The general idea is to visit all AST nodes with a RecursiveASTVisitor, 00014 // calling the Matches(...) method of each matcher we are running on each 00015 // AST node. The matcher can recurse via the ASTMatchFinder interface. 00016 // 00017 //===----------------------------------------------------------------------===// 00018 00019 #include "clang/ASTMatchers/ASTMatchFinder.h" 00020 #include "clang/AST/ASTConsumer.h" 00021 #include "clang/AST/ASTContext.h" 00022 #include "clang/AST/RecursiveASTVisitor.h" 00023 #include "llvm/ADT/StringMap.h" 00024 #include "llvm/Support/Timer.h" 00025 #include <deque> 00026 #include <memory> 00027 #include <set> 00028 00029 namespace clang { 00030 namespace ast_matchers { 00031 namespace internal { 00032 namespace { 00033 00034 typedef MatchFinder::MatchCallback MatchCallback; 00035 00036 // The maximum number of memoization entries to store. 00037 // 10k has been experimentally found to give a good trade-off 00038 // of performance vs. memory consumption by running matcher 00039 // that match on every statement over a very large codebase. 00040 // 00041 // FIXME: Do some performance optimization in general and 00042 // revisit this number; also, put up micro-benchmarks that we can 00043 // optimize this on. 00044 static const unsigned MaxMemoizationEntries = 10000; 00045 00046 // We use memoization to avoid running the same matcher on the same 00047 // AST node twice. This struct is the key for looking up match 00048 // result. It consists of an ID of the MatcherInterface (for 00049 // identifying the matcher), a pointer to the AST node and the 00050 // bound nodes before the matcher was executed. 00051 // 00052 // We currently only memoize on nodes whose pointers identify the 00053 // nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc). 00054 // For \c QualType and \c TypeLoc it is possible to implement 00055 // generation of keys for each type. 00056 // FIXME: Benchmark whether memoization of non-pointer typed nodes 00057 // provides enough benefit for the additional amount of code. 00058 struct MatchKey { 00059 DynTypedMatcher::MatcherIDType MatcherID; 00060 ast_type_traits::DynTypedNode Node; 00061 BoundNodesTreeBuilder BoundNodes; 00062 00063 bool operator<(const MatchKey &Other) const { 00064 return std::tie(MatcherID, Node, BoundNodes) < 00065 std::tie(Other.MatcherID, Other.Node, Other.BoundNodes); 00066 } 00067 }; 00068 00069 // Used to store the result of a match and possibly bound nodes. 00070 struct MemoizedMatchResult { 00071 bool ResultOfMatch; 00072 BoundNodesTreeBuilder Nodes; 00073 }; 00074 00075 // A RecursiveASTVisitor that traverses all children or all descendants of 00076 // a node. 00077 class MatchChildASTVisitor 00078 : public RecursiveASTVisitor<MatchChildASTVisitor> { 00079 public: 00080 typedef RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase; 00081 00082 // Creates an AST visitor that matches 'matcher' on all children or 00083 // descendants of a traversed node. max_depth is the maximum depth 00084 // to traverse: use 1 for matching the children and INT_MAX for 00085 // matching the descendants. 00086 MatchChildASTVisitor(const DynTypedMatcher *Matcher, 00087 ASTMatchFinder *Finder, 00088 BoundNodesTreeBuilder *Builder, 00089 int MaxDepth, 00090 ASTMatchFinder::TraversalKind Traversal, 00091 ASTMatchFinder::BindKind Bind) 00092 : Matcher(Matcher), 00093 Finder(Finder), 00094 Builder(Builder), 00095 CurrentDepth(0), 00096 MaxDepth(MaxDepth), 00097 Traversal(Traversal), 00098 Bind(Bind), 00099 Matches(false) {} 00100 00101 // Returns true if a match is found in the subtree rooted at the 00102 // given AST node. This is done via a set of mutually recursive 00103 // functions. Here's how the recursion is done (the *wildcard can 00104 // actually be Decl, Stmt, or Type): 00105 // 00106 // - Traverse(node) calls BaseTraverse(node) when it needs 00107 // to visit the descendants of node. 00108 // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node)) 00109 // Traverse*(c) for each child c of 'node'. 00110 // - Traverse*(c) in turn calls Traverse(c), completing the 00111 // recursion. 00112 bool findMatch(const ast_type_traits::DynTypedNode &DynNode) { 00113 reset(); 00114 if (const Decl *D = DynNode.get<Decl>()) 00115 traverse(*D); 00116 else if (const Stmt *S = DynNode.get<Stmt>()) 00117 traverse(*S); 00118 else if (const NestedNameSpecifier *NNS = 00119 DynNode.get<NestedNameSpecifier>()) 00120 traverse(*NNS); 00121 else if (const NestedNameSpecifierLoc *NNSLoc = 00122 DynNode.get<NestedNameSpecifierLoc>()) 00123 traverse(*NNSLoc); 00124 else if (const QualType *Q = DynNode.get<QualType>()) 00125 traverse(*Q); 00126 else if (const TypeLoc *T = DynNode.get<TypeLoc>()) 00127 traverse(*T); 00128 // FIXME: Add other base types after adding tests. 00129 00130 // It's OK to always overwrite the bound nodes, as if there was 00131 // no match in this recursive branch, the result set is empty 00132 // anyway. 00133 *Builder = ResultBindings; 00134 00135 return Matches; 00136 } 00137 00138 // The following are overriding methods from the base visitor class. 00139 // They are public only to allow CRTP to work. They are *not *part 00140 // of the public API of this class. 00141 bool TraverseDecl(Decl *DeclNode) { 00142 ScopedIncrement ScopedDepth(&CurrentDepth); 00143 return (DeclNode == nullptr) || traverse(*DeclNode); 00144 } 00145 bool TraverseStmt(Stmt *StmtNode) { 00146 ScopedIncrement ScopedDepth(&CurrentDepth); 00147 const Stmt *StmtToTraverse = StmtNode; 00148 if (Traversal == 00149 ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) { 00150 const Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode); 00151 if (ExprNode) { 00152 StmtToTraverse = ExprNode->IgnoreParenImpCasts(); 00153 } 00154 } 00155 return (StmtToTraverse == nullptr) || traverse(*StmtToTraverse); 00156 } 00157 // We assume that the QualType and the contained type are on the same 00158 // hierarchy level. Thus, we try to match either of them. 00159 bool TraverseType(QualType TypeNode) { 00160 if (TypeNode.isNull()) 00161 return true; 00162 ScopedIncrement ScopedDepth(&CurrentDepth); 00163 // Match the Type. 00164 if (!match(*TypeNode)) 00165 return false; 00166 // The QualType is matched inside traverse. 00167 return traverse(TypeNode); 00168 } 00169 // We assume that the TypeLoc, contained QualType and contained Type all are 00170 // on the same hierarchy level. Thus, we try to match all of them. 00171 bool TraverseTypeLoc(TypeLoc TypeLocNode) { 00172 if (TypeLocNode.isNull()) 00173 return true; 00174 ScopedIncrement ScopedDepth(&CurrentDepth); 00175 // Match the Type. 00176 if (!match(*TypeLocNode.getType())) 00177 return false; 00178 // Match the QualType. 00179 if (!match(TypeLocNode.getType())) 00180 return false; 00181 // The TypeLoc is matched inside traverse. 00182 return traverse(TypeLocNode); 00183 } 00184 bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { 00185 ScopedIncrement ScopedDepth(&CurrentDepth); 00186 return (NNS == nullptr) || traverse(*NNS); 00187 } 00188 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { 00189 if (!NNS) 00190 return true; 00191 ScopedIncrement ScopedDepth(&CurrentDepth); 00192 if (!match(*NNS.getNestedNameSpecifier())) 00193 return false; 00194 return traverse(NNS); 00195 } 00196 00197 bool shouldVisitTemplateInstantiations() const { return true; } 00198 bool shouldVisitImplicitCode() const { return true; } 00199 // Disables data recursion. We intercept Traverse* methods in the RAV, which 00200 // are not triggered during data recursion. 00201 bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; } 00202 00203 private: 00204 // Used for updating the depth during traversal. 00205 struct ScopedIncrement { 00206 explicit ScopedIncrement(int *Depth) : Depth(Depth) { ++(*Depth); } 00207 ~ScopedIncrement() { --(*Depth); } 00208 00209 private: 00210 int *Depth; 00211 }; 00212 00213 // Resets the state of this object. 00214 void reset() { 00215 Matches = false; 00216 CurrentDepth = 0; 00217 } 00218 00219 // Forwards the call to the corresponding Traverse*() method in the 00220 // base visitor class. 00221 bool baseTraverse(const Decl &DeclNode) { 00222 return VisitorBase::TraverseDecl(const_cast<Decl*>(&DeclNode)); 00223 } 00224 bool baseTraverse(const Stmt &StmtNode) { 00225 return VisitorBase::TraverseStmt(const_cast<Stmt*>(&StmtNode)); 00226 } 00227 bool baseTraverse(QualType TypeNode) { 00228 return VisitorBase::TraverseType(TypeNode); 00229 } 00230 bool baseTraverse(TypeLoc TypeLocNode) { 00231 return VisitorBase::TraverseTypeLoc(TypeLocNode); 00232 } 00233 bool baseTraverse(const NestedNameSpecifier &NNS) { 00234 return VisitorBase::TraverseNestedNameSpecifier( 00235 const_cast<NestedNameSpecifier*>(&NNS)); 00236 } 00237 bool baseTraverse(NestedNameSpecifierLoc NNS) { 00238 return VisitorBase::TraverseNestedNameSpecifierLoc(NNS); 00239 } 00240 00241 // Sets 'Matched' to true if 'Matcher' matches 'Node' and: 00242 // 0 < CurrentDepth <= MaxDepth. 00243 // 00244 // Returns 'true' if traversal should continue after this function 00245 // returns, i.e. if no match is found or 'Bind' is 'BK_All'. 00246 template <typename T> 00247 bool match(const T &Node) { 00248 if (CurrentDepth == 0 || CurrentDepth > MaxDepth) { 00249 return true; 00250 } 00251 if (Bind != ASTMatchFinder::BK_All) { 00252 BoundNodesTreeBuilder RecursiveBuilder(*Builder); 00253 if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder, 00254 &RecursiveBuilder)) { 00255 Matches = true; 00256 ResultBindings.addMatch(RecursiveBuilder); 00257 return false; // Abort as soon as a match is found. 00258 } 00259 } else { 00260 BoundNodesTreeBuilder RecursiveBuilder(*Builder); 00261 if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder, 00262 &RecursiveBuilder)) { 00263 // After the first match the matcher succeeds. 00264 Matches = true; 00265 ResultBindings.addMatch(RecursiveBuilder); 00266 } 00267 } 00268 return true; 00269 } 00270 00271 // Traverses the subtree rooted at 'Node'; returns true if the 00272 // traversal should continue after this function returns. 00273 template <typename T> 00274 bool traverse(const T &Node) { 00275 static_assert(IsBaseType<T>::value, 00276 "traverse can only be instantiated with base type"); 00277 if (!match(Node)) 00278 return false; 00279 return baseTraverse(Node); 00280 } 00281 00282 const DynTypedMatcher *const Matcher; 00283 ASTMatchFinder *const Finder; 00284 BoundNodesTreeBuilder *const Builder; 00285 BoundNodesTreeBuilder ResultBindings; 00286 int CurrentDepth; 00287 const int MaxDepth; 00288 const ASTMatchFinder::TraversalKind Traversal; 00289 const ASTMatchFinder::BindKind Bind; 00290 bool Matches; 00291 }; 00292 00293 // Controls the outermost traversal of the AST and allows to match multiple 00294 // matchers. 00295 class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>, 00296 public ASTMatchFinder { 00297 public: 00298 MatchASTVisitor(const MatchFinder::MatchersByType *Matchers, 00299 const MatchFinder::MatchFinderOptions &Options) 00300 : Matchers(Matchers), Options(Options), ActiveASTContext(nullptr) {} 00301 00302 ~MatchASTVisitor() { 00303 if (Options.CheckProfiling) { 00304 Options.CheckProfiling->Records = std::move(TimeByBucket); 00305 } 00306 } 00307 00308 void onStartOfTranslationUnit() { 00309 const bool EnableCheckProfiling = Options.CheckProfiling.hasValue(); 00310 TimeBucketRegion Timer; 00311 for (MatchCallback *MC : Matchers->AllCallbacks) { 00312 if (EnableCheckProfiling) 00313 Timer.setBucket(&TimeByBucket[MC->getID()]); 00314 MC->onStartOfTranslationUnit(); 00315 } 00316 } 00317 00318 void onEndOfTranslationUnit() { 00319 const bool EnableCheckProfiling = Options.CheckProfiling.hasValue(); 00320 TimeBucketRegion Timer; 00321 for (MatchCallback *MC : Matchers->AllCallbacks) { 00322 if (EnableCheckProfiling) 00323 Timer.setBucket(&TimeByBucket[MC->getID()]); 00324 MC->onEndOfTranslationUnit(); 00325 } 00326 } 00327 00328 void set_active_ast_context(ASTContext *NewActiveASTContext) { 00329 ActiveASTContext = NewActiveASTContext; 00330 } 00331 00332 // The following Visit*() and Traverse*() functions "override" 00333 // methods in RecursiveASTVisitor. 00334 00335 bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) { 00336 // When we see 'typedef A B', we add name 'B' to the set of names 00337 // A's canonical type maps to. This is necessary for implementing 00338 // isDerivedFrom(x) properly, where x can be the name of the base 00339 // class or any of its aliases. 00340 // 00341 // In general, the is-alias-of (as defined by typedefs) relation 00342 // is tree-shaped, as you can typedef a type more than once. For 00343 // example, 00344 // 00345 // typedef A B; 00346 // typedef A C; 00347 // typedef C D; 00348 // typedef C E; 00349 // 00350 // gives you 00351 // 00352 // A 00353 // |- B 00354 // `- C 00355 // |- D 00356 // `- E 00357 // 00358 // It is wrong to assume that the relation is a chain. A correct 00359 // implementation of isDerivedFrom() needs to recognize that B and 00360 // E are aliases, even though neither is a typedef of the other. 00361 // Therefore, we cannot simply walk through one typedef chain to 00362 // find out whether the type name matches. 00363 const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr(); 00364 const Type *CanonicalType = // root of the typedef tree 00365 ActiveASTContext->getCanonicalType(TypeNode); 00366 TypeAliases[CanonicalType].insert(DeclNode); 00367 return true; 00368 } 00369 00370 bool TraverseDecl(Decl *DeclNode); 00371 bool TraverseStmt(Stmt *StmtNode); 00372 bool TraverseType(QualType TypeNode); 00373 bool TraverseTypeLoc(TypeLoc TypeNode); 00374 bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); 00375 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); 00376 00377 // Matches children or descendants of 'Node' with 'BaseMatcher'. 00378 bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node, 00379 const DynTypedMatcher &Matcher, 00380 BoundNodesTreeBuilder *Builder, int MaxDepth, 00381 TraversalKind Traversal, BindKind Bind) { 00382 // For AST-nodes that don't have an identity, we can't memoize. 00383 if (!Node.getMemoizationData() || !Builder->isComparable()) 00384 return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal, 00385 Bind); 00386 00387 MatchKey Key; 00388 Key.MatcherID = Matcher.getID(); 00389 Key.Node = Node; 00390 // Note that we key on the bindings *before* the match. 00391 Key.BoundNodes = *Builder; 00392 00393 MemoizationMap::iterator I = ResultCache.find(Key); 00394 if (I != ResultCache.end()) { 00395 *Builder = I->second.Nodes; 00396 return I->second.ResultOfMatch; 00397 } 00398 00399 MemoizedMatchResult Result; 00400 Result.Nodes = *Builder; 00401 Result.ResultOfMatch = matchesRecursively(Node, Matcher, &Result.Nodes, 00402 MaxDepth, Traversal, Bind); 00403 00404 MemoizedMatchResult &CachedResult = ResultCache[Key]; 00405 CachedResult = std::move(Result); 00406 00407 *Builder = CachedResult.Nodes; 00408 return CachedResult.ResultOfMatch; 00409 } 00410 00411 // Matches children or descendants of 'Node' with 'BaseMatcher'. 00412 bool matchesRecursively(const ast_type_traits::DynTypedNode &Node, 00413 const DynTypedMatcher &Matcher, 00414 BoundNodesTreeBuilder *Builder, int MaxDepth, 00415 TraversalKind Traversal, BindKind Bind) { 00416 MatchChildASTVisitor Visitor( 00417 &Matcher, this, Builder, MaxDepth, Traversal, Bind); 00418 return Visitor.findMatch(Node); 00419 } 00420 00421 bool classIsDerivedFrom(const CXXRecordDecl *Declaration, 00422 const Matcher<NamedDecl> &Base, 00423 BoundNodesTreeBuilder *Builder) override; 00424 00425 // Implements ASTMatchFinder::matchesChildOf. 00426 bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, 00427 const DynTypedMatcher &Matcher, 00428 BoundNodesTreeBuilder *Builder, 00429 TraversalKind Traversal, 00430 BindKind Bind) override { 00431 if (ResultCache.size() > MaxMemoizationEntries) 00432 ResultCache.clear(); 00433 return memoizedMatchesRecursively(Node, Matcher, Builder, 1, Traversal, 00434 Bind); 00435 } 00436 // Implements ASTMatchFinder::matchesDescendantOf. 00437 bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, 00438 const DynTypedMatcher &Matcher, 00439 BoundNodesTreeBuilder *Builder, 00440 BindKind Bind) override { 00441 if (ResultCache.size() > MaxMemoizationEntries) 00442 ResultCache.clear(); 00443 return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX, 00444 TK_AsIs, Bind); 00445 } 00446 // Implements ASTMatchFinder::matchesAncestorOf. 00447 bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, 00448 const DynTypedMatcher &Matcher, 00449 BoundNodesTreeBuilder *Builder, 00450 AncestorMatchMode MatchMode) override { 00451 // Reset the cache outside of the recursive call to make sure we 00452 // don't invalidate any iterators. 00453 if (ResultCache.size() > MaxMemoizationEntries) 00454 ResultCache.clear(); 00455 return memoizedMatchesAncestorOfRecursively(Node, Matcher, Builder, 00456 MatchMode); 00457 } 00458 00459 // Matches all registered matchers on the given node and calls the 00460 // result callback for every node that matches. 00461 void match(const ast_type_traits::DynTypedNode &Node) { 00462 // FIXME: Improve this with a switch or a visitor pattern. 00463 if (auto *N = Node.get<Decl>()) { 00464 match(*N); 00465 } else if (auto *N = Node.get<Stmt>()) { 00466 match(*N); 00467 } else if (auto *N = Node.get<Type>()) { 00468 match(*N); 00469 } else if (auto *N = Node.get<QualType>()) { 00470 match(*N); 00471 } else if (auto *N = Node.get<NestedNameSpecifier>()) { 00472 match(*N); 00473 } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) { 00474 match(*N); 00475 } else if (auto *N = Node.get<TypeLoc>()) { 00476 match(*N); 00477 } 00478 } 00479 00480 template <typename T> void match(const T &Node) { 00481 matchDispatch(&Node); 00482 } 00483 00484 // Implements ASTMatchFinder::getASTContext. 00485 ASTContext &getASTContext() const override { return *ActiveASTContext; } 00486 00487 bool shouldVisitTemplateInstantiations() const { return true; } 00488 bool shouldVisitImplicitCode() const { return true; } 00489 // Disables data recursion. We intercept Traverse* methods in the RAV, which 00490 // are not triggered during data recursion. 00491 bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; } 00492 00493 private: 00494 class TimeBucketRegion { 00495 public: 00496 TimeBucketRegion() : Bucket(nullptr) {} 00497 ~TimeBucketRegion() { setBucket(nullptr); } 00498 00499 /// \brief Start timing for \p NewBucket. 00500 /// 00501 /// If there was a bucket already set, it will finish the timing for that 00502 /// other bucket. 00503 /// \p NewBucket will be timed until the next call to \c setBucket() or 00504 /// until the \c TimeBucketRegion is destroyed. 00505 /// If \p NewBucket is the same as the currently timed bucket, this call 00506 /// does nothing. 00507 void setBucket(llvm::TimeRecord *NewBucket) { 00508 if (Bucket != NewBucket) { 00509 auto Now = llvm::TimeRecord::getCurrentTime(true); 00510 if (Bucket) 00511 *Bucket += Now; 00512 if (NewBucket) 00513 *NewBucket -= Now; 00514 Bucket = NewBucket; 00515 } 00516 } 00517 00518 private: 00519 llvm::TimeRecord *Bucket; 00520 }; 00521 00522 /// \brief Runs all the \p Matchers on \p Node. 00523 /// 00524 /// Used by \c matchDispatch() below. 00525 template <typename T, typename MC> 00526 void matchImpl(const T &Node, const MC &Matchers) { 00527 const bool EnableCheckProfiling = Options.CheckProfiling.hasValue(); 00528 TimeBucketRegion Timer; 00529 for (const auto &MP : Matchers) { 00530 if (EnableCheckProfiling) 00531 Timer.setBucket(&TimeByBucket[MP.second->getID()]); 00532 BoundNodesTreeBuilder Builder; 00533 if (MP.first.matches(Node, this, &Builder)) { 00534 MatchVisitor Visitor(ActiveASTContext, MP.second); 00535 Builder.visitMatches(&Visitor); 00536 } 00537 } 00538 } 00539 00540 /// @{ 00541 /// \brief Overloads to pair the different node types to their matchers. 00542 void matchDispatch(const Decl *Node) { matchImpl(*Node, Matchers->Decl); } 00543 void matchDispatch(const Stmt *Node) { matchImpl(*Node, Matchers->Stmt); } 00544 void matchDispatch(const Type *Node) { 00545 matchImpl(QualType(Node, 0), Matchers->Type); 00546 } 00547 void matchDispatch(const TypeLoc *Node) { 00548 matchImpl(*Node, Matchers->TypeLoc); 00549 } 00550 void matchDispatch(const QualType *Node) { matchImpl(*Node, Matchers->Type); } 00551 void matchDispatch(const NestedNameSpecifier *Node) { 00552 matchImpl(*Node, Matchers->NestedNameSpecifier); 00553 } 00554 void matchDispatch(const NestedNameSpecifierLoc *Node) { 00555 matchImpl(*Node, Matchers->NestedNameSpecifierLoc); 00556 } 00557 void matchDispatch(const void *) { /* Do nothing. */ } 00558 /// @} 00559 00560 // Returns whether an ancestor of \p Node matches \p Matcher. 00561 // 00562 // The order of matching ((which can lead to different nodes being bound in 00563 // case there are multiple matches) is breadth first search. 00564 // 00565 // To allow memoization in the very common case of having deeply nested 00566 // expressions inside a template function, we first walk up the AST, memoizing 00567 // the result of the match along the way, as long as there is only a single 00568 // parent. 00569 // 00570 // Once there are multiple parents, the breadth first search order does not 00571 // allow simple memoization on the ancestors. Thus, we only memoize as long 00572 // as there is a single parent. 00573 bool memoizedMatchesAncestorOfRecursively( 00574 const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher, 00575 BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) { 00576 if (Node.get<TranslationUnitDecl>() == 00577 ActiveASTContext->getTranslationUnitDecl()) 00578 return false; 00579 assert(Node.getMemoizationData() && 00580 "Invariant broken: only nodes that support memoization may be " 00581 "used in the parent map."); 00582 00583 MatchKey Key; 00584 Key.MatcherID = Matcher.getID(); 00585 Key.Node = Node; 00586 Key.BoundNodes = *Builder; 00587 00588 // Note that we cannot use insert and reuse the iterator, as recursive 00589 // calls to match might invalidate the result cache iterators. 00590 MemoizationMap::iterator I = ResultCache.find(Key); 00591 if (I != ResultCache.end()) { 00592 *Builder = I->second.Nodes; 00593 return I->second.ResultOfMatch; 00594 } 00595 00596 MemoizedMatchResult Result; 00597 Result.ResultOfMatch = false; 00598 Result.Nodes = *Builder; 00599 00600 const auto &Parents = ActiveASTContext->getParents(Node); 00601 assert(!Parents.empty() && "Found node that is not in the parent map."); 00602 if (Parents.size() == 1) { 00603 // Only one parent - do recursive memoization. 00604 const ast_type_traits::DynTypedNode Parent = Parents[0]; 00605 if (Matcher.matches(Parent, this, &Result.Nodes)) { 00606 Result.ResultOfMatch = true; 00607 } else if (MatchMode != ASTMatchFinder::AMM_ParentOnly) { 00608 // Reset the results to not include the bound nodes from the failed 00609 // match above. 00610 Result.Nodes = *Builder; 00611 Result.ResultOfMatch = memoizedMatchesAncestorOfRecursively( 00612 Parent, Matcher, &Result.Nodes, MatchMode); 00613 // Once we get back from the recursive call, the result will be the 00614 // same as the parent's result. 00615 } 00616 } else { 00617 // Multiple parents - BFS over the rest of the nodes. 00618 llvm::DenseSet<const void *> Visited; 00619 std::deque<ast_type_traits::DynTypedNode> Queue(Parents.begin(), 00620 Parents.end()); 00621 while (!Queue.empty()) { 00622 Result.Nodes = *Builder; 00623 if (Matcher.matches(Queue.front(), this, &Result.Nodes)) { 00624 Result.ResultOfMatch = true; 00625 break; 00626 } 00627 if (MatchMode != ASTMatchFinder::AMM_ParentOnly) { 00628 for (const auto &Parent : 00629 ActiveASTContext->getParents(Queue.front())) { 00630 // Make sure we do not visit the same node twice. 00631 // Otherwise, we'll visit the common ancestors as often as there 00632 // are splits on the way down. 00633 if (Visited.insert(Parent.getMemoizationData()).second) 00634 Queue.push_back(Parent); 00635 } 00636 } 00637 Queue.pop_front(); 00638 } 00639 } 00640 00641 MemoizedMatchResult &CachedResult = ResultCache[Key]; 00642 CachedResult = std::move(Result); 00643 00644 *Builder = CachedResult.Nodes; 00645 return CachedResult.ResultOfMatch; 00646 } 00647 00648 // Implements a BoundNodesTree::Visitor that calls a MatchCallback with 00649 // the aggregated bound nodes for each match. 00650 class MatchVisitor : public BoundNodesTreeBuilder::Visitor { 00651 public: 00652 MatchVisitor(ASTContext* Context, 00653 MatchFinder::MatchCallback* Callback) 00654 : Context(Context), 00655 Callback(Callback) {} 00656 00657 void visitMatch(const BoundNodes& BoundNodesView) override { 00658 Callback->run(MatchFinder::MatchResult(BoundNodesView, Context)); 00659 } 00660 00661 private: 00662 ASTContext* Context; 00663 MatchFinder::MatchCallback* Callback; 00664 }; 00665 00666 // Returns true if 'TypeNode' has an alias that matches the given matcher. 00667 bool typeHasMatchingAlias(const Type *TypeNode, 00668 const Matcher<NamedDecl> Matcher, 00669 BoundNodesTreeBuilder *Builder) { 00670 const Type *const CanonicalType = 00671 ActiveASTContext->getCanonicalType(TypeNode); 00672 for (const TypedefNameDecl *Alias : TypeAliases.lookup(CanonicalType)) { 00673 BoundNodesTreeBuilder Result(*Builder); 00674 if (Matcher.matches(*Alias, this, &Result)) { 00675 *Builder = std::move(Result); 00676 return true; 00677 } 00678 } 00679 return false; 00680 } 00681 00682 /// \brief Bucket to record map. 00683 /// 00684 /// Used to get the appropriate bucket for each matcher. 00685 llvm::StringMap<llvm::TimeRecord> TimeByBucket; 00686 00687 const MatchFinder::MatchersByType *Matchers; 00688 const MatchFinder::MatchFinderOptions &Options; 00689 ASTContext *ActiveASTContext; 00690 00691 // Maps a canonical type to its TypedefDecls. 00692 llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases; 00693 00694 // Maps (matcher, node) -> the match result for memoization. 00695 typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap; 00696 MemoizationMap ResultCache; 00697 }; 00698 00699 static CXXRecordDecl *getAsCXXRecordDecl(const Type *TypeNode) { 00700 // Type::getAs<...>() drills through typedefs. 00701 if (TypeNode->getAs<DependentNameType>() != nullptr || 00702 TypeNode->getAs<DependentTemplateSpecializationType>() != nullptr || 00703 TypeNode->getAs<TemplateTypeParmType>() != nullptr) 00704 // Dependent names and template TypeNode parameters will be matched when 00705 // the template is instantiated. 00706 return nullptr; 00707 TemplateSpecializationType const *TemplateType = 00708 TypeNode->getAs<TemplateSpecializationType>(); 00709 if (!TemplateType) { 00710 return TypeNode->getAsCXXRecordDecl(); 00711 } 00712 if (TemplateType->getTemplateName().isDependent()) 00713 // Dependent template specializations will be matched when the 00714 // template is instantiated. 00715 return nullptr; 00716 00717 // For template specialization types which are specializing a template 00718 // declaration which is an explicit or partial specialization of another 00719 // template declaration, getAsCXXRecordDecl() returns the corresponding 00720 // ClassTemplateSpecializationDecl. 00721 // 00722 // For template specialization types which are specializing a template 00723 // declaration which is neither an explicit nor partial specialization of 00724 // another template declaration, getAsCXXRecordDecl() returns NULL and 00725 // we get the CXXRecordDecl of the templated declaration. 00726 CXXRecordDecl *SpecializationDecl = TemplateType->getAsCXXRecordDecl(); 00727 if (SpecializationDecl) { 00728 return SpecializationDecl; 00729 } 00730 NamedDecl *Templated = 00731 TemplateType->getTemplateName().getAsTemplateDecl()->getTemplatedDecl(); 00732 if (CXXRecordDecl *TemplatedRecord = dyn_cast<CXXRecordDecl>(Templated)) { 00733 return TemplatedRecord; 00734 } 00735 // Now it can still be that we have an alias template. 00736 TypeAliasDecl *AliasDecl = dyn_cast<TypeAliasDecl>(Templated); 00737 assert(AliasDecl); 00738 return getAsCXXRecordDecl(AliasDecl->getUnderlyingType().getTypePtr()); 00739 } 00740 00741 // Returns true if the given class is directly or indirectly derived 00742 // from a base type with the given name. A class is not considered to be 00743 // derived from itself. 00744 bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, 00745 const Matcher<NamedDecl> &Base, 00746 BoundNodesTreeBuilder *Builder) { 00747 if (!Declaration->hasDefinition()) 00748 return false; 00749 for (const auto &It : Declaration->bases()) { 00750 const Type *TypeNode = It.getType().getTypePtr(); 00751 00752 if (typeHasMatchingAlias(TypeNode, Base, Builder)) 00753 return true; 00754 00755 CXXRecordDecl *ClassDecl = getAsCXXRecordDecl(TypeNode); 00756 if (!ClassDecl) 00757 continue; 00758 if (ClassDecl == Declaration) { 00759 // This can happen for recursive template definitions; if the 00760 // current declaration did not match, we can safely return false. 00761 return false; 00762 } 00763 BoundNodesTreeBuilder Result(*Builder); 00764 if (Base.matches(*ClassDecl, this, &Result)) { 00765 *Builder = std::move(Result); 00766 return true; 00767 } 00768 if (classIsDerivedFrom(ClassDecl, Base, Builder)) 00769 return true; 00770 } 00771 return false; 00772 } 00773 00774 bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { 00775 if (!DeclNode) { 00776 return true; 00777 } 00778 match(*DeclNode); 00779 return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode); 00780 } 00781 00782 bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) { 00783 if (!StmtNode) { 00784 return true; 00785 } 00786 match(*StmtNode); 00787 return RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode); 00788 } 00789 00790 bool MatchASTVisitor::TraverseType(QualType TypeNode) { 00791 match(TypeNode); 00792 return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode); 00793 } 00794 00795 bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) { 00796 // The RecursiveASTVisitor only visits types if they're not within TypeLocs. 00797 // We still want to find those types via matchers, so we match them here. Note 00798 // that the TypeLocs are structurally a shadow-hierarchy to the expressed 00799 // type, so we visit all involved parts of a compound type when matching on 00800 // each TypeLoc. 00801 match(TypeLocNode); 00802 match(TypeLocNode.getType()); 00803 return RecursiveASTVisitor<MatchASTVisitor>::TraverseTypeLoc(TypeLocNode); 00804 } 00805 00806 bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { 00807 match(*NNS); 00808 return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS); 00809 } 00810 00811 bool MatchASTVisitor::TraverseNestedNameSpecifierLoc( 00812 NestedNameSpecifierLoc NNS) { 00813 match(NNS); 00814 // We only match the nested name specifier here (as opposed to traversing it) 00815 // because the traversal is already done in the parallel "Loc"-hierarchy. 00816 if (NNS.hasQualifier()) 00817 match(*NNS.getNestedNameSpecifier()); 00818 return 00819 RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS); 00820 } 00821 00822 class MatchASTConsumer : public ASTConsumer { 00823 public: 00824 MatchASTConsumer(MatchFinder *Finder, 00825 MatchFinder::ParsingDoneTestCallback *ParsingDone) 00826 : Finder(Finder), ParsingDone(ParsingDone) {} 00827 00828 private: 00829 void HandleTranslationUnit(ASTContext &Context) override { 00830 if (ParsingDone != nullptr) { 00831 ParsingDone->run(); 00832 } 00833 Finder->matchAST(Context); 00834 } 00835 00836 MatchFinder *Finder; 00837 MatchFinder::ParsingDoneTestCallback *ParsingDone; 00838 }; 00839 00840 } // end namespace 00841 } // end namespace internal 00842 00843 MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes, 00844 ASTContext *Context) 00845 : Nodes(Nodes), Context(Context), 00846 SourceManager(&Context->getSourceManager()) {} 00847 00848 MatchFinder::MatchCallback::~MatchCallback() {} 00849 MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {} 00850 00851 MatchFinder::MatchFinder(MatchFinderOptions Options) 00852 : Options(std::move(Options)), ParsingDone(nullptr) {} 00853 00854 MatchFinder::~MatchFinder() {} 00855 00856 void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch, 00857 MatchCallback *Action) { 00858 Matchers.Decl.push_back(std::make_pair(NodeMatch, Action)); 00859 Matchers.AllCallbacks.push_back(Action); 00860 } 00861 00862 void MatchFinder::addMatcher(const TypeMatcher &NodeMatch, 00863 MatchCallback *Action) { 00864 Matchers.Type.push_back(std::make_pair(NodeMatch, Action)); 00865 Matchers.AllCallbacks.push_back(Action); 00866 } 00867 00868 void MatchFinder::addMatcher(const StatementMatcher &NodeMatch, 00869 MatchCallback *Action) { 00870 Matchers.Stmt.push_back(std::make_pair(NodeMatch, Action)); 00871 Matchers.AllCallbacks.push_back(Action); 00872 } 00873 00874 void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch, 00875 MatchCallback *Action) { 00876 Matchers.NestedNameSpecifier.push_back(std::make_pair(NodeMatch, Action)); 00877 Matchers.AllCallbacks.push_back(Action); 00878 } 00879 00880 void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, 00881 MatchCallback *Action) { 00882 Matchers.NestedNameSpecifierLoc.push_back(std::make_pair(NodeMatch, Action)); 00883 Matchers.AllCallbacks.push_back(Action); 00884 } 00885 00886 void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch, 00887 MatchCallback *Action) { 00888 Matchers.TypeLoc.push_back(std::make_pair(NodeMatch, Action)); 00889 Matchers.AllCallbacks.push_back(Action); 00890 } 00891 00892 bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, 00893 MatchCallback *Action) { 00894 if (NodeMatch.canConvertTo<Decl>()) { 00895 addMatcher(NodeMatch.convertTo<Decl>(), Action); 00896 return true; 00897 } else if (NodeMatch.canConvertTo<QualType>()) { 00898 addMatcher(NodeMatch.convertTo<QualType>(), Action); 00899 return true; 00900 } else if (NodeMatch.canConvertTo<Stmt>()) { 00901 addMatcher(NodeMatch.convertTo<Stmt>(), Action); 00902 return true; 00903 } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) { 00904 addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action); 00905 return true; 00906 } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) { 00907 addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action); 00908 return true; 00909 } else if (NodeMatch.canConvertTo<TypeLoc>()) { 00910 addMatcher(NodeMatch.convertTo<TypeLoc>(), Action); 00911 return true; 00912 } 00913 return false; 00914 } 00915 00916 std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() { 00917 return llvm::make_unique<internal::MatchASTConsumer>(this, ParsingDone); 00918 } 00919 00920 void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node, 00921 ASTContext &Context) { 00922 internal::MatchASTVisitor Visitor(&Matchers, Options); 00923 Visitor.set_active_ast_context(&Context); 00924 Visitor.match(Node); 00925 } 00926 00927 void MatchFinder::matchAST(ASTContext &Context) { 00928 internal::MatchASTVisitor Visitor(&Matchers, Options); 00929 Visitor.set_active_ast_context(&Context); 00930 Visitor.onStartOfTranslationUnit(); 00931 Visitor.TraverseDecl(Context.getTranslationUnitDecl()); 00932 Visitor.onEndOfTranslationUnit(); 00933 } 00934 00935 void MatchFinder::registerTestCallbackAfterParsing( 00936 MatchFinder::ParsingDoneTestCallback *NewParsingDone) { 00937 ParsingDone = NewParsingDone; 00938 } 00939 00940 StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; } 00941 00942 } // end namespace ast_matchers 00943 } // end namespace clang