From 353f6a477ea2cee2e380522343e9905743a64285 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 9 Oct 2012 18:19:01 +0000 Subject: [PATCH] Move the functionality that looks for ObjC overridden methods from ASTContext to the ObjCMethodDecl, and have the more generic ASTContext::getOverriddenMethods() use the ObjCMethodDecl::getOverriddenMethods() function. llvm-svn: 165518 --- clang/include/clang/AST/DeclObjC.h | 10 +++ clang/lib/AST/ASTContext.cpp | 174 ++----------------------------------- clang/lib/AST/DeclObjC.cpp | 174 +++++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 167 deletions(-) diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 459e9b3..56418d2 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -417,6 +417,16 @@ public: /// method in the interface or its categories. bool isOverriding() const { return IsOverriding; } void setOverriding(bool isOverriding) { IsOverriding = isOverriding; } + + /// \brief Return overridden methods for the given \p Method. + /// + /// An ObjC method is considered to override any method in the class's + /// base classes, its protocols, or its categories' protocols, that has + /// the same selector and is of the same kind (class or instance). + /// A method in an implementation is not considered as overriding the same + /// method in the interface or its categories. + void getOverriddenMethods( + SmallVectorImpl &Overridden) const; // Related to protocols declared in \@protocol void setDeclImplementation(ImplementationControl ic) { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 67e89f3..0d28846 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1026,161 +1026,6 @@ void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method, OverriddenMethods[Method].push_back(Overridden); } -static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, - const ObjCMethodDecl *Method, - SmallVectorImpl &Methods, - bool MovedToSuper) { - if (!Container) - return; - - // In categories look for overriden methods from protocols. A method from - // category is not "overriden" since it is considered as the "same" method - // (same USR) as the one from the interface. - if (const ObjCCategoryDecl * - Category = dyn_cast(Container)) { - // Check whether we have a matching method at this category but only if we - // are at the super class level. - if (MovedToSuper) - if (ObjCMethodDecl * - Overridden = Container->getMethod(Method->getSelector(), - Method->isInstanceMethod())) - if (Method != Overridden) { - // We found an override at this category; there is no need to look - // into its protocols. - Methods.push_back(Overridden); - return; - } - - for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), - PEnd = Category->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); - return; - } - - // Check whether we have a matching method at this level. - if (const ObjCMethodDecl * - Overridden = Container->getMethod(Method->getSelector(), - Method->isInstanceMethod())) - if (Method != Overridden) { - // We found an override at this level; there is no need to look - // into other protocols or categories. - Methods.push_back(Overridden); - return; - } - - if (const ObjCProtocolDecl *Protocol = dyn_cast(Container)){ - for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), - PEnd = Protocol->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); - } - - if (const ObjCInterfaceDecl * - Interface = dyn_cast(Container)) { - for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), - PEnd = Interface->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); - - for (const ObjCCategoryDecl *Category = Interface->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - CollectOverriddenMethodsRecurse(Category, Method, Methods, - MovedToSuper); - - if (const ObjCInterfaceDecl *Super = Interface->getSuperClass()) - return CollectOverriddenMethodsRecurse(Super, Method, Methods, - /*MovedToSuper=*/true); - } -} - -static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container, - const ObjCMethodDecl *Method, - SmallVectorImpl &Methods) { - CollectOverriddenMethodsRecurse(Container, Method, Methods, - /*MovedToSuper=*/false); -} - -static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, - SmallVectorImpl &overridden) { - assert(Method->isOverriding()); - - if (const ObjCProtocolDecl * - ProtD = dyn_cast(Method->getDeclContext())) { - CollectOverriddenMethods(ProtD, Method, overridden); - - } else if (const ObjCImplDecl * - IMD = dyn_cast(Method->getDeclContext())) { - const ObjCInterfaceDecl *ID = IMD->getClassInterface(); - if (!ID) - return; - // Start searching for overridden methods using the method from the - // interface as starting point. - if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), - Method->isInstanceMethod())) - Method = IFaceMeth; - CollectOverriddenMethods(ID, Method, overridden); - - } else if (const ObjCCategoryDecl * - CatD = dyn_cast(Method->getDeclContext())) { - const ObjCInterfaceDecl *ID = CatD->getClassInterface(); - if (!ID) - return; - // Start searching for overridden methods using the method from the - // interface as starting point. - if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), - Method->isInstanceMethod())) - Method = IFaceMeth; - CollectOverriddenMethods(ID, Method, overridden); - - } else { - CollectOverriddenMethods( - dyn_cast_or_null(Method->getDeclContext()), - Method, overridden); - } -} - -static void collectOnCategoriesAfterLocation(SourceLocation Loc, - const ObjCInterfaceDecl *Class, - SourceManager &SM, - const ObjCMethodDecl *Method, - SmallVectorImpl &Methods) { - if (!Class) - return; - - for (const ObjCCategoryDecl *Category = Class->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (SM.isBeforeInTranslationUnit(Loc, Category->getLocation())) - CollectOverriddenMethodsRecurse(Category, Method, Methods, true); - - collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), SM, - Method, Methods); -} - -/// \brief Faster collection that is enabled when ObjCMethodDecl::isOverriding() -/// returns false. -/// You'd think that in that case there are no overrides but categories can -/// "introduce" new overridden methods that are missed by Sema because the -/// overrides lookup that it does for methods, inside implementations, will -/// stop at the interface level (if there is a method there) and not look -/// further in super classes. -static void collectOverriddenMethodsFast(SourceManager &SM, - const ObjCMethodDecl *Method, - SmallVectorImpl &Methods) { - assert(!Method->isOverriding()); - - const ObjCContainerDecl * - ContD = cast(Method->getDeclContext()); - if (isa(ContD) || isa(ContD)) - return; - const ObjCInterfaceDecl *Class = Method->getClassInterface(); - if (!Class) - return; - - collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(), - SM, Method, Methods); -} - void ASTContext::getOverriddenMethods(const NamedDecl *D, SmallVectorImpl &Overridden) { assert(D); @@ -1198,18 +1043,13 @@ void ASTContext::getOverriddenMethods(const NamedDecl *D, if (!Method) return; - if (Method->isRedeclaration()) { - Method = cast(Method->getDeclContext())-> - getMethod(Method->getSelector(), Method->isInstanceMethod()); - } - - if (!Method->isOverriding()) { - collectOverriddenMethodsFast(SourceMgr, Method, Overridden); - } else { - collectOverriddenMethodsSlow(Method, Overridden); - assert(!Overridden.empty() && - "ObjCMethodDecl's overriding bit is not as expected"); - } + SmallVector OverDecls; + Method->getOverriddenMethods(OverDecls); + for (SmallVector::iterator + M = OverDecls.begin(), + MEnd = OverDecls.end(); + M != MEnd; ++M) + Overridden.push_back(*M); } void ASTContext::addedLocalImportDecl(ImportDecl *Import) { diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 45c57d6..3958cb6 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -722,6 +722,180 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { llvm_unreachable("unknown method context"); } +static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, + const ObjCMethodDecl *Method, + SmallVectorImpl &Methods, + bool MovedToSuper) { + if (!Container) + return; + + // In categories look for overriden methods from protocols. A method from + // category is not "overriden" since it is considered as the "same" method + // (same USR) as the one from the interface. + if (const ObjCCategoryDecl * + Category = dyn_cast(Container)) { + // Check whether we have a matching method at this category but only if we + // are at the super class level. + if (MovedToSuper) + if (ObjCMethodDecl * + Overridden = Container->getMethod(Method->getSelector(), + Method->isInstanceMethod())) + if (Method != Overridden) { + // We found an override at this category; there is no need to look + // into its protocols. + Methods.push_back(Overridden); + return; + } + + for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), + PEnd = Category->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); + return; + } + + // Check whether we have a matching method at this level. + if (const ObjCMethodDecl * + Overridden = Container->getMethod(Method->getSelector(), + Method->isInstanceMethod())) + if (Method != Overridden) { + // We found an override at this level; there is no need to look + // into other protocols or categories. + Methods.push_back(Overridden); + return; + } + + if (const ObjCProtocolDecl *Protocol = dyn_cast(Container)){ + for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), + PEnd = Protocol->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); + } + + if (const ObjCInterfaceDecl * + Interface = dyn_cast(Container)) { + for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), + PEnd = Interface->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); + + for (const ObjCCategoryDecl *Category = Interface->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + CollectOverriddenMethodsRecurse(Category, Method, Methods, + MovedToSuper); + + if (const ObjCInterfaceDecl *Super = Interface->getSuperClass()) + return CollectOverriddenMethodsRecurse(Super, Method, Methods, + /*MovedToSuper=*/true); + } +} + +static inline void CollectOverriddenMethods(const ObjCContainerDecl *Container, + const ObjCMethodDecl *Method, + SmallVectorImpl &Methods) { + CollectOverriddenMethodsRecurse(Container, Method, Methods, + /*MovedToSuper=*/false); +} + +static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, + SmallVectorImpl &overridden) { + assert(Method->isOverriding()); + + if (const ObjCProtocolDecl * + ProtD = dyn_cast(Method->getDeclContext())) { + CollectOverriddenMethods(ProtD, Method, overridden); + + } else if (const ObjCImplDecl * + IMD = dyn_cast(Method->getDeclContext())) { + const ObjCInterfaceDecl *ID = IMD->getClassInterface(); + if (!ID) + return; + // Start searching for overridden methods using the method from the + // interface as starting point. + if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), + Method->isInstanceMethod())) + Method = IFaceMeth; + CollectOverriddenMethods(ID, Method, overridden); + + } else if (const ObjCCategoryDecl * + CatD = dyn_cast(Method->getDeclContext())) { + const ObjCInterfaceDecl *ID = CatD->getClassInterface(); + if (!ID) + return; + // Start searching for overridden methods using the method from the + // interface as starting point. + if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), + Method->isInstanceMethod())) + Method = IFaceMeth; + CollectOverriddenMethods(ID, Method, overridden); + + } else { + CollectOverriddenMethods( + dyn_cast_or_null(Method->getDeclContext()), + Method, overridden); + } +} + +static void collectOnCategoriesAfterLocation(SourceLocation Loc, + const ObjCInterfaceDecl *Class, + SourceManager &SM, + const ObjCMethodDecl *Method, + SmallVectorImpl &Methods) { + if (!Class) + return; + + for (const ObjCCategoryDecl *Category = Class->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + if (SM.isBeforeInTranslationUnit(Loc, Category->getLocation())) + CollectOverriddenMethodsRecurse(Category, Method, Methods, true); + + collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), SM, + Method, Methods); +} + +/// \brief Faster collection that is enabled when ObjCMethodDecl::isOverriding() +/// returns false. +/// You'd think that in that case there are no overrides but categories can +/// "introduce" new overridden methods that are missed by Sema because the +/// overrides lookup that it does for methods, inside implementations, will +/// stop at the interface level (if there is a method there) and not look +/// further in super classes. +static void collectOverriddenMethodsFast(SourceManager &SM, + const ObjCMethodDecl *Method, + SmallVectorImpl &Methods) { + assert(!Method->isOverriding()); + + const ObjCContainerDecl * + ContD = cast(Method->getDeclContext()); + if (isa(ContD) || isa(ContD)) + return; + const ObjCInterfaceDecl *Class = Method->getClassInterface(); + if (!Class) + return; + + collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(), + SM, Method, Methods); +} + +void ObjCMethodDecl::getOverriddenMethods( + SmallVectorImpl &Overridden) const { + const ObjCMethodDecl *Method = this; + + if (Method->isRedeclaration()) { + Method = cast(Method->getDeclContext())-> + getMethod(Method->getSelector(), Method->isInstanceMethod()); + } + + if (!Method->isOverriding()) { + collectOverriddenMethodsFast(getASTContext().getSourceManager(), + Method, Overridden); + } else { + collectOverriddenMethodsSlow(Method, Overridden); + assert(!Overridden.empty() && + "ObjCMethodDecl's overriding bit is not as expected"); + } +} + //===----------------------------------------------------------------------===// // ObjCInterfaceDecl //===----------------------------------------------------------------------===// -- 2.7.4