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