diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-04-10 21:01:03 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-04-10 21:01:03 +0000 |
commit | 15f4c9819d172139c0b37e8a68767ea4fc03e5b6 (patch) | |
tree | b1a179073ae5f3b5f54fb36e5ccdb21615143c41 | |
parent | e19f86edab8fb3c2c1e99e0e9815b6058504df9b (diff) |
[libclang] For clang_getOverriddenCursors make sure to report overridden objc methods
for methods in categories of super classes. rdar://11220358
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154436 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | test/Index/overrides.m | 15 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 2 | ||||
-rw-r--r-- | tools/libclang/CXCursor.cpp | 52 |
3 files changed, 53 insertions, 16 deletions
diff --git a/test/Index/overrides.m b/test/Index/overrides.m index f7ba17c83d..6908754563 100644 --- a/test/Index/overrides.m +++ b/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/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 1896132fa0..eafb867eb2 100644 --- a/tools/libclang/CIndex.cpp +++ b/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<CXCursor, 8> Overridden; cxcursor::getOverriddenCursors(cursor, Overridden); diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 0533c84a57..8371a4f273 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -786,14 +786,11 @@ CXTranslationUnit cxcursor::getCursorTU(CXCursor Cursor) { return static_cast<CXTranslationUnit>(Cursor.data[2]); } -static void CollectOverriddenMethods(CXTranslationUnit TU, - DeclContext *Ctx, +static void CollectOverriddenMethodsRecurse(CXTranslationUnit TU, + ObjCContainerDecl *Container, ObjCMethodDecl *Method, - SmallVectorImpl<CXCursor> &Methods) { - if (!Ctx) - return; - - ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx); + SmallVectorImpl<CXCursor> &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<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) - 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<ObjCInterfaceDecl>(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<CXCursor> &Methods) { + CollectOverriddenMethodsRecurse(TU, Container, Method, Methods, + /*MovedToSuper=*/false); +} + void cxcursor::getOverriddenCursors(CXCursor cursor, SmallVectorImpl<CXCursor> &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<ObjCContainerDecl>(Method->getDeclContext()), + Method, overridden); } } |