diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-10-09 01:23:50 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-10-09 01:23:50 +0000 |
commit | 21c3607282550779c9ae5fe784928597807fd110 (patch) | |
tree | ef43f21703c37939b96be9d2d578c45ce79f1d24 /tools/libclang/CXCursor.cpp | |
parent | 38eb1e161f602ee810dfb8a5a0d8462572f22689 (diff) |
Move the logic that searches for overridden methods from libclang to
ASTContext so that it can be widely available.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165473 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/libclang/CXCursor.cpp')
-rw-r--r-- | tools/libclang/CXCursor.cpp | 186 |
1 files changed, 6 insertions, 180 deletions
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index a8cb1f96d4..ce517023f4 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -795,194 +795,20 @@ CXTranslationUnit cxcursor::getCursorTU(CXCursor Cursor) { return static_cast<CXTranslationUnit>(Cursor.data[2]); } -static void CollectOverriddenMethodsRecurse(CXTranslationUnit TU, - ObjCContainerDecl *Container, - ObjCMethodDecl *Method, - SmallVectorImpl<CXCursor> &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 (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(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(MakeCXCursor(Overridden, TU)); - return; - } - - for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), - PEnd = Category->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(TU, *P, Method, Methods, MovedToSuper); - return; - } - - // Check whether we have a matching method at this level. - if (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(MakeCXCursor(Overridden, TU)); - return; - } - - if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { - for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), - PEnd = Protocol->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(TU, *P, Method, Methods, MovedToSuper); - } - - if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { - for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), - PEnd = Interface->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(TU, *P, Method, Methods, MovedToSuper); - - for (ObjCCategoryDecl *Category = Interface->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - CollectOverriddenMethodsRecurse(TU, Category, Method, Methods, - MovedToSuper); - - if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) - return CollectOverriddenMethodsRecurse(TU, Super, Method, Methods, - /*MovedToSuper=*/true); - } -} - -static inline void CollectOverriddenMethods(CXTranslationUnit TU, - ObjCContainerDecl *Container, - ObjCMethodDecl *Method, - SmallVectorImpl<CXCursor> &Methods) { - CollectOverriddenMethodsRecurse(TU, Container, Method, Methods, - /*MovedToSuper=*/false); -} - -static void collectOverriddenMethodsSlow(CXTranslationUnit TU, - ObjCMethodDecl *Method, - SmallVectorImpl<CXCursor> &overridden) { - assert(Method->isOverriding()); - - if (ObjCProtocolDecl * - ProtD = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) { - CollectOverriddenMethods(TU, ProtD, Method, overridden); - - } else if (ObjCImplDecl * - IMD = dyn_cast<ObjCImplDecl>(Method->getDeclContext())) { - ObjCInterfaceDecl *ID = IMD->getClassInterface(); - if (!ID) - return; - // Start searching for overridden methods using the method from the - // interface as starting point. - if (ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), - Method->isInstanceMethod())) - Method = IFaceMeth; - CollectOverriddenMethods(TU, ID, Method, overridden); - - } else if (ObjCCategoryDecl * - CatD = dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) { - ObjCInterfaceDecl *ID = CatD->getClassInterface(); - if (!ID) - return; - // Start searching for overridden methods using the method from the - // interface as starting point. - if (ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), - Method->isInstanceMethod())) - Method = IFaceMeth; - CollectOverriddenMethods(TU, ID, Method, overridden); - - } else { - CollectOverriddenMethods(TU, - dyn_cast_or_null<ObjCContainerDecl>(Method->getDeclContext()), - Method, overridden); - } -} - -static void collectOnCategoriesAfterLocation(SourceLocation Loc, - ObjCInterfaceDecl *Class, - CXTranslationUnit TU, - ObjCMethodDecl *Method, - SmallVectorImpl<CXCursor> &Methods) { - if (!Class) - return; - - SourceManager &SM = static_cast<ASTUnit *>(TU->TUData)->getSourceManager(); - for (ObjCCategoryDecl *Category = Class->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (SM.isBeforeInTranslationUnit(Loc, Category->getLocation())) - CollectOverriddenMethodsRecurse(TU, Category, Method, Methods, true); - - collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), TU, - 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(CXTranslationUnit TU, - ObjCMethodDecl *Method, - SmallVectorImpl<CXCursor> &Methods) { - assert(!Method->isOverriding()); - - ObjCContainerDecl *ContD = cast<ObjCContainerDecl>(Method->getDeclContext()); - if (isa<ObjCInterfaceDecl>(ContD) || isa<ObjCProtocolDecl>(ContD)) - return; - ObjCInterfaceDecl *Class = Method->getClassInterface(); - if (!Class) - return; - - collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(), - TU, Method, Methods); -} - void cxcursor::getOverriddenCursors(CXCursor cursor, SmallVectorImpl<CXCursor> &overridden) { assert(clang_isDeclaration(cursor.kind)); - Decl *D = getCursorDecl(cursor); + const NamedDecl *D = dyn_cast_or_null<NamedDecl>(getCursorDecl(cursor)); if (!D) return; - // Handle C++ member functions. CXTranslationUnit TU = getCursorTU(cursor); - if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { - for (CXXMethodDecl::method_iterator - M = CXXMethod->begin_overridden_methods(), - MEnd = CXXMethod->end_overridden_methods(); - M != MEnd; ++M) - overridden.push_back(MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU)); - return; - } - - ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D); - if (!Method) - return; - - if (Method->isRedeclaration()) { - Method = cast<ObjCContainerDecl>(Method->getDeclContext())-> - getMethod(Method->getSelector(), Method->isInstanceMethod()); - } + SmallVector<const NamedDecl *, 8> OverDecls; + D->getASTContext().getOverriddenMethods(D, OverDecls); - if (!Method->isOverriding()) { - collectOverriddenMethodsFast(TU, Method, overridden); - } else { - collectOverriddenMethodsSlow(TU, Method, overridden); - assert(!overridden.empty() && - "ObjCMethodDecl's overriding bit is not as expected"); + for (SmallVector<const NamedDecl *, 8>::iterator + I = OverDecls.begin(), E = OverDecls.end(); I != E; ++I) { + overridden.push_back(MakeCXCursor(const_cast<NamedDecl*>(*I), TU)); } } |