diff options
author | Daniel Jasper <djasper@google.com> | 2012-07-17 07:39:27 +0000 |
---|---|---|
committer | Daniel Jasper <djasper@google.com> | 2012-07-17 07:39:27 +0000 |
commit | 20b802d186dfc5db9b4a9ce83e9f31fa5aa4efcc (patch) | |
tree | d0a22b3a202cc0b28f12bfff8b94588624a07f9d /lib/ASTMatchers/ASTMatchFinder.cpp | |
parent | e4ed215ccf35d4407916cd0223de26f87ccbb055 (diff) |
Make the isDerivedFrom matcher more generic.
It now accepts an arbitrary inner matcher but is fully backwards
compatible.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160348 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ASTMatchers/ASTMatchFinder.cpp')
-rw-r--r-- | lib/ASTMatchers/ASTMatchFinder.cpp | 64 |
1 files changed, 27 insertions, 37 deletions
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp index 8aad8dd834..a58d4f0fb4 100644 --- a/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/lib/ASTMatchers/ASTMatchFinder.cpp @@ -27,15 +27,6 @@ namespace ast_matchers { namespace internal { namespace { -// Returns the value that 'AMap' maps 'Key' to, or NULL if 'Key' is -// not in 'AMap'. -template <typename Map> -static const typename Map::mapped_type * -find(const Map &AMap, const typename Map::key_type &Key) { - typename Map::const_iterator It = AMap.find(Key); - return It == AMap.end() ? NULL : &It->second; -} - // We use memoization to avoid running the same matcher on the same // AST node twice. This pair is the key for looking up match // result. It consists of an ID of the MatcherInterface (for @@ -244,8 +235,7 @@ public: const Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr(); const Type *CanonicalType = // root of the typedef tree ActiveASTContext->getCanonicalType(TypeNode); - TypeToUnqualifiedAliases[CanonicalType].insert( - DeclNode->getName().str()); + TypeAliases[CanonicalType].insert(DeclNode); return true; } @@ -289,7 +279,8 @@ public: } virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration, - StringRef BaseName) const; + const Matcher<NamedDecl> &Base, + BoundNodesTreeBuilder *Builder); // Implements ASTMatchFinder::MatchesChildOf. virtual bool matchesChildOf(const Decl &DeclNode, @@ -347,16 +338,20 @@ private: MatchFinder::MatchCallback* Callback; }; - // Returns true if 'TypeNode' is also known by the name 'Name'. In other - // words, there is a type (including typedef) with the name 'Name' - // that is equal to 'TypeNode'. - bool typeHasAlias(const Type *TypeNode, - StringRef Name) const { + // Returns true if 'TypeNode' has an alias that matches the given matcher. + bool typeHasMatchingAlias(const Type *TypeNode, + const Matcher<NamedDecl> Matcher, + BoundNodesTreeBuilder *Builder) { const Type *const CanonicalType = ActiveASTContext->getCanonicalType(TypeNode); - const std::set<std::string> *UnqualifiedAlias = - find(TypeToUnqualifiedAliases, CanonicalType); - return UnqualifiedAlias != NULL && UnqualifiedAlias->count(Name) > 0; + const std::set<const TypedefDecl*> &Aliases = TypeAliases[CanonicalType]; + for (std::set<const TypedefDecl*>::const_iterator + It = Aliases.begin(), End = Aliases.end(); + It != End; ++It) { + if (Matcher.matches(**It, this, Builder)) + return true; + } + return false; } // Matches all registered matchers on the given node and calls the @@ -380,9 +375,8 @@ private: MatchFinder::MatchCallback*> > *const Triggers; ASTContext *ActiveASTContext; - // Maps a canonical type to the names of its typedefs. - llvm::DenseMap<const Type*, std::set<std::string> > - TypeToUnqualifiedAliases; + // Maps a canonical type to its TypedefDecls. + llvm::DenseMap<const Type*, std::set<const TypedefDecl*> > TypeAliases; // Maps (matcher, node) -> the match result for memoization. typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult> MemoizationMap; @@ -392,39 +386,36 @@ private: // Returns true if the given class is directly or indirectly derived // from a base type with the given name. A class is considered to be // also derived from itself. -bool -MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, - StringRef BaseName) const { - if (Declaration->getName() == BaseName) { +bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, + const Matcher<NamedDecl> &Base, + BoundNodesTreeBuilder *Builder) { + if (Base.matches(*Declaration, this, Builder)) return true; - } - if (!Declaration->hasDefinition()) { + if (!Declaration->hasDefinition()) return false; - } typedef CXXRecordDecl::base_class_const_iterator BaseIterator; for (BaseIterator It = Declaration->bases_begin(), End = Declaration->bases_end(); It != End; ++It) { const Type *TypeNode = It->getType().getTypePtr(); - if (typeHasAlias(TypeNode, BaseName)) + if (typeHasMatchingAlias(TypeNode, Base, Builder)) return true; // Type::getAs<...>() drills through typedefs. if (TypeNode->getAs<DependentNameType>() != NULL || - TypeNode->getAs<TemplateTypeParmType>() != NULL) { + TypeNode->getAs<TemplateTypeParmType>() != NULL) // Dependent names and template TypeNode parameters will be matched when // the template is instantiated. continue; - } CXXRecordDecl *ClassDecl = NULL; TemplateSpecializationType const *TemplateType = TypeNode->getAs<TemplateSpecializationType>(); if (TemplateType != NULL) { - if (TemplateType->getTemplateName().isDependent()) { + if (TemplateType->getTemplateName().isDependent()) // Dependent template specializations will be matched when the // template is instantiated. continue; - } + // For template specialization types which are specializing a template // declaration which is an explicit or partial specialization of another // template declaration, getAsCXXRecordDecl() returns the corresponding @@ -448,9 +439,8 @@ MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, } assert(ClassDecl != NULL); assert(ClassDecl != Declaration); - if (classIsDerivedFrom(ClassDecl, BaseName)) { + if (classIsDerivedFrom(ClassDecl, Base, Builder)) return true; - } } return false; } |