diff options
Diffstat (limited to 'lib/ASTMatchers/ASTMatchFinder.cpp')
-rw-r--r-- | lib/ASTMatchers/ASTMatchFinder.cpp | 73 |
1 files changed, 68 insertions, 5 deletions
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp index f407e0875ac4..c51fd630e64b 100644 --- a/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/lib/ASTMatchers/ASTMatchFinder.cpp @@ -374,6 +374,12 @@ public: return true; } + bool VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { + const ObjCInterfaceDecl *InterfaceDecl = CAD->getClassInterface(); + CompatibleAliases[InterfaceDecl].insert(CAD); + return true; + } + bool TraverseDecl(Decl *DeclNode); bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr); bool TraverseType(QualType TypeNode); @@ -430,7 +436,13 @@ public: bool classIsDerivedFrom(const CXXRecordDecl *Declaration, const Matcher<NamedDecl> &Base, - BoundNodesTreeBuilder *Builder) override; + BoundNodesTreeBuilder *Builder, + bool Directly) override; + + bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration, + const Matcher<NamedDecl> &Base, + BoundNodesTreeBuilder *Builder, + bool Directly) override; // Implements ASTMatchFinder::matchesChildOf. bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, @@ -762,6 +774,23 @@ private: return false; } + bool + objcClassHasMatchingCompatibilityAlias(const ObjCInterfaceDecl *InterfaceDecl, + const Matcher<NamedDecl> &Matcher, + BoundNodesTreeBuilder *Builder) { + auto Aliases = CompatibleAliases.find(InterfaceDecl); + if (Aliases == CompatibleAliases.end()) + return false; + for (const ObjCCompatibleAliasDecl *Alias : Aliases->second) { + BoundNodesTreeBuilder Result(*Builder); + if (Matcher.matches(*Alias, this, &Result)) { + *Builder = std::move(Result); + return true; + } + } + return false; + } + /// Bucket to record map. /// /// Used to get the appropriate bucket for each matcher. @@ -786,6 +815,11 @@ private: // Maps a canonical type to its TypedefDecls. llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases; + // Maps an Objective-C interface to its ObjCCompatibleAliasDecls. + llvm::DenseMap<const ObjCInterfaceDecl *, + llvm::SmallPtrSet<const ObjCCompatibleAliasDecl *, 2>> + CompatibleAliases; + // Maps (matcher, node) -> the match result for memoization. typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap; MemoizationMap ResultCache; @@ -812,12 +846,13 @@ getAsCXXRecordDeclOrPrimaryTemplate(const Type *TypeNode) { return nullptr; } -// Returns true if the given class is directly or indirectly derived +// Returns true if the given C++ class is directly or indirectly derived // from a base type with the given name. A class is not considered to be // derived from itself. bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, const Matcher<NamedDecl> &Base, - BoundNodesTreeBuilder *Builder) { + BoundNodesTreeBuilder *Builder, + bool Directly) { if (!Declaration->hasDefinition()) return false; for (const auto &It : Declaration->bases()) { @@ -842,12 +877,40 @@ bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, *Builder = std::move(Result); return true; } - if (classIsDerivedFrom(ClassDecl, Base, Builder)) + if (!Directly && classIsDerivedFrom(ClassDecl, Base, Builder, Directly)) return true; } return false; } +// Returns true if the given Objective-C class is directly or indirectly +// derived from a matching base class. A class is not considered to be derived +// from itself. +bool MatchASTVisitor::objcClassIsDerivedFrom( + const ObjCInterfaceDecl *Declaration, const Matcher<NamedDecl> &Base, + BoundNodesTreeBuilder *Builder, bool Directly) { + // Check if any of the superclasses of the class match. + for (const ObjCInterfaceDecl *ClassDecl = Declaration->getSuperClass(); + ClassDecl != nullptr; ClassDecl = ClassDecl->getSuperClass()) { + // Check if there are any matching compatibility aliases. + if (objcClassHasMatchingCompatibilityAlias(ClassDecl, Base, Builder)) + return true; + + // Check if there are any matching type aliases. + const Type *TypeNode = ClassDecl->getTypeForDecl(); + if (typeHasMatchingAlias(TypeNode, Base, Builder)) + return true; + + if (Base.matches(*ClassDecl, this, Builder)) + return true; + + if (Directly) + return false; + } + + return false; +} + bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { if (!DeclNode) { return true; @@ -1015,7 +1078,7 @@ bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, } std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() { - return llvm::make_unique<internal::MatchASTConsumer>(this, ParsingDone); + return std::make_unique<internal::MatchASTConsumer>(this, ParsingDone); } void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node, |