diff --git a/clang/test/Index/overrides.m b/clang/test/Index/overrides.m index f7ba17c83dee..690875456371 100644 --- a/clang/test/Index/overrides.m +++ b/clang/test/Index/overrides.m @@ -36,6 +36,20 @@ - (void)protoMethod; @end +@interface B2 +@end + +@interface B2(cat) +-(void)meth; +@end + +@interface I2 : B2 +@end + +@implementation I2 +-(void)meth { } +@end + // RUN: c-index-test -test-load-source local %s | FileCheck %s // CHECK: overrides.m:12:9: ObjCInstanceMethodDecl=protoMethod:12:9 [Overrides @3:9] // CHECK: overrides.m:22:9: ObjCInstanceMethodDecl=method:22:9 [Overrides @16:9] @@ -44,3 +58,4 @@ // CHECK: overrides.m:28:9: ObjCClassMethodDecl=methodWithParam::28:9 (Definition) [Overrides @18:9] // CHECK: overrides.m:32:9: ObjCInstanceMethodDecl=protoMethod:32:9 [Overrides @8:9] // CHECK: overrides.m:36:9: ObjCInstanceMethodDecl=protoMethod:36:9 [Overrides @12:9, @8:9, @32:9, @17:9] +// CHECK: overrides.m:50:8: ObjCInstanceMethodDecl=meth:50:8 (Definition) [Overrides @43:8] diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 1896132fa01e..eafb867eb2cf 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -5535,6 +5535,8 @@ void clang_getOverriddenCursors(CXCursor cursor, *num_overridden = 0; if (!overridden || !num_overridden) return; + if (!clang_isDeclaration(cursor.kind)) + return; SmallVector Overridden; cxcursor::getOverriddenCursors(cursor, Overridden); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 0533c84a5702..8371a4f273cf 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -786,14 +786,11 @@ CXTranslationUnit cxcursor::getCursorTU(CXCursor Cursor) { return static_cast(Cursor.data[2]); } -static void CollectOverriddenMethods(CXTranslationUnit TU, - DeclContext *Ctx, +static void CollectOverriddenMethodsRecurse(CXTranslationUnit TU, + ObjCContainerDecl *Container, ObjCMethodDecl *Method, - SmallVectorImpl &Methods) { - if (!Ctx) - return; - - ObjCContainerDecl *Container = dyn_cast(Ctx); + SmallVectorImpl &Methods, + bool MovedToSuper) { if (!Container) return; @@ -801,10 +798,23 @@ static void CollectOverriddenMethods(CXTranslationUnit TU, // 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(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) - CollectOverriddenMethods(TU, *P, Method, Methods); + CollectOverriddenMethodsRecurse(TU, *P, Method, Methods, MovedToSuper); return; } @@ -822,29 +832,37 @@ static void CollectOverriddenMethods(CXTranslationUnit TU, for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), PEnd = Protocol->protocol_end(); P != PEnd; ++P) - CollectOverriddenMethods(TU, *P, Method, Methods); + CollectOverriddenMethodsRecurse(TU, *P, Method, Methods, MovedToSuper); } if (ObjCInterfaceDecl *Interface = dyn_cast(Container)) { for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), PEnd = Interface->protocol_end(); P != PEnd; ++P) - CollectOverriddenMethods(TU, *P, Method, Methods); + CollectOverriddenMethodsRecurse(TU, *P, Method, Methods, MovedToSuper); for (ObjCCategoryDecl *Category = Interface->getCategoryList(); Category; Category = Category->getNextClassCategory()) - CollectOverriddenMethods(TU, Category, Method, Methods); + CollectOverriddenMethodsRecurse(TU, Category, Method, Methods, + MovedToSuper); if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) - return CollectOverriddenMethods(TU, Super, Method, Methods); + return CollectOverriddenMethodsRecurse(TU, Super, Method, Methods, + /*MovedToSuper=*/true); } } +static inline void CollectOverriddenMethods(CXTranslationUnit TU, + ObjCContainerDecl *Container, + ObjCMethodDecl *Method, + SmallVectorImpl &Methods) { + CollectOverriddenMethodsRecurse(TU, Container, Method, Methods, + /*MovedToSuper=*/false); +} + void cxcursor::getOverriddenCursors(CXCursor cursor, SmallVectorImpl &overridden) { - if (!clang_isDeclaration(cursor.kind)) - return; - + assert(clang_isDeclaration(cursor.kind)); Decl *D = getCursorDecl(cursor); if (!D) return; @@ -893,7 +911,9 @@ void cxcursor::getOverriddenCursors(CXCursor cursor, CollectOverriddenMethods(TU, ID, Method, overridden); } else { - CollectOverriddenMethods(TU, Method->getDeclContext(), Method, overridden); + CollectOverriddenMethods(TU, + dyn_cast_or_null(Method->getDeclContext()), + Method, overridden); } }