aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang-c/Index.h11
-rw-r--r--test/Index/annotate-tokens.m2
-rw-r--r--test/Index/file-refs.m10
-rw-r--r--test/Index/local-symbols.m2
-rw-r--r--test/Index/overrides.m21
-rw-r--r--test/Index/usrs.m12
-rw-r--r--tools/libclang/CXCursor.cpp63
7 files changed, 79 insertions, 42 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index fd7a9f3a01..d05510e281 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -2219,11 +2219,12 @@ CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor);
* In both Objective-C and C++, a method (aka virtual member function,
* in C++) can override a virtual method in a base class. For
* Objective-C, a method is said to override any method in the class's
- * interface (if we're coming from an implementation), its protocols,
- * or its categories, that has the same selector and is of the same
- * kind (class or instance). If no such method exists, the search
- * continues to the class's superclass, its protocols, and its
- * categories, and so on.
+ * base class, its protocols, or its categories' protocols, that has the same
+ * selector and is of the same kind (class or instance).
+ * If no such method exists, the search continues to the class's superclass,
+ * its protocols, and its categories, and so on. A method from an Objective-C
+ * implementation is considered to override the same methods as its
+ * corresponding method in the interface.
*
* For C++, a virtual member function overrides any virtual member
* function with the same signature that occurs in its base
diff --git a/test/Index/annotate-tokens.m b/test/Index/annotate-tokens.m
index f9ddc655c2..424dec8e00 100644
--- a/test/Index/annotate-tokens.m
+++ b/test/Index/annotate-tokens.m
@@ -271,7 +271,7 @@ static Rdar8595462_A * Rdar8595462_staticVar;
// CHECK: Punctuation: ")" [38:12 - 38:13] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition)
// CHECK: Identifier: "actionMethod" [38:14 - 38:26] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition)
// CHECK: Punctuation: ":" [38:26 - 38:27] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition)
-// CHECK: Keyword: "in" [38:28 - 38:30] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition) [Overrides @33:1]
+// CHECK: Keyword: "in" [38:28 - 38:30] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition)
// CHECK: Identifier: "id" [38:31 - 38:33] TypeRef=id:0:0
// CHECK: Punctuation: ")" [38:33 - 38:34] ParmDecl=arg:38:34 (Definition)
// CHECK: Identifier: "arg" [38:34 - 38:37] ParmDecl=arg:38:34 (Definition)
diff --git a/test/Index/file-refs.m b/test/Index/file-refs.m
index 583826700d..684d87884e 100644
--- a/test/Index/file-refs.m
+++ b/test/Index/file-refs.m
@@ -55,14 +55,14 @@ void test2(Sub *s, id<Prot1> p) {
// RUN: -file-refs-at=%s:4:10 \
// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::4:1
// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::4:1 =[4:6 - 4:16]
-// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::8:1 (Definition) [Overrides @4:1] =[8:6 - 8:16]
+// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::8:1 (Definition) =[8:6 - 8:16]
// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1 =[14:8 - 14:18]
// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1 =[15:8 - 15:18]
// RUN: -file-refs-at=%s:15:27 \
// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1
// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::4:1 =[4:24 - 4:32]
-// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::8:1 (Definition) [Overrides @4:1] =[8:24 - 8:32]
+// CHECK-NEXT: ObjCInstanceMethodDecl=setWithInt:andFloat::8:1 (Definition) =[8:24 - 8:32]
// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1 =[14:21 - 14:29]
// CHECK-NEXT: ObjCMessageExpr=setWithInt:andFloat::4:1 =[15:22 - 15:30]
@@ -76,15 +76,15 @@ void test2(Sub *s, id<Prot1> p) {
// CHECK-NEXT: ObjCMessageExpr=protMeth:19:1
// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:19:1 =[19:8 - 19:16]
// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:29:1 [Overrides @19:1] =[29:8 - 29:16]
-// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @29:1] =[33:8 - 33:16]
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @19:1] =[33:8 - 33:16]
// CHECK-NEXT: ObjCMessageExpr=protMeth:29:1 =[37:6 - 37:14]
// CHECK-NEXT: ObjCMessageExpr=protMeth:19:1 =[38:6 - 38:14]
// RUN: -file-refs-at=%s:33:12 \
-// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @29:1]
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @19:1]
// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:19:1 =[19:8 - 19:16]
// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:29:1 [Overrides @19:1] =[29:8 - 29:16]
-// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @29:1] =[33:8 - 33:16]
+// CHECK-NEXT: ObjCInstanceMethodDecl=protMeth:33:1 (Definition) [Overrides @19:1] =[33:8 - 33:16]
// CHECK-NEXT: ObjCMessageExpr=protMeth:29:1 =[37:6 - 37:14]
// CHECK-NEXT: ObjCMessageExpr=protMeth:19:1 =[38:6 - 38:14]
diff --git a/test/Index/local-symbols.m b/test/Index/local-symbols.m
index 01c8305c2a..0e70b7c89b 100644
--- a/test/Index/local-symbols.m
+++ b/test/Index/local-symbols.m
@@ -32,7 +32,7 @@
// CHECK: local-symbols.m:9:1: ObjCInstanceMethodDecl=bar:9:1 Extent=[9:1 - 9:12]
// CHECK: local-symbols.m:9:4: TypeRef=id:0:0 Extent=[9:4 - 9:6]
// CHECK: local-symbols.m:12:17: ObjCImplementationDecl=Foo:12:17 (Definition) Extent=[12:1 - 16:2]
-// CHECK: local-symbols.m:13:1: ObjCInstanceMethodDecl=bar:13:1 (Definition) [Overrides @9:1] Extent=[13:1 - 15:2]
+// CHECK: local-symbols.m:13:1: ObjCInstanceMethodDecl=bar:13:1 (Definition) Extent=[13:1 - 15:2]
// CHECK: local-symbols.m:13:4: TypeRef=id:0:0 Extent=[13:4 - 13:6]
// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
// CHECK: local-symbols.m:14:10: IntegerLiteral= Extent=[14:10 - 14:11]
diff --git a/test/Index/overrides.m b/test/Index/overrides.m
index 2197aaaa36..e43d498c9a 100644
--- a/test/Index/overrides.m
+++ b/test/Index/overrides.m
@@ -14,6 +14,7 @@
@interface A
- (void)method;
+- (void)protoMethod;
+ (void)methodWithParam:(int)param;
@end
@@ -27,9 +28,19 @@
+ (void)methodWithParam:(int)param { }
@end
+@protocol P4 <P3>
+- (void)protoMethod;
+@end
+
+@interface B(cat) <P4>
+- (void)protoMethod;
+@end
+
// RUN: c-index-test -test-load-source local %s | FileCheck %s
-// CHECK: overrides.m:12:1: ObjCInstanceMethodDecl=protoMethod:12:1 [Overrides @3:1] Extent=[12:1 - 12:21]
-// CHECK: overrides.m:21:1: ObjCInstanceMethodDecl=method:21:1 [Overrides @16:1] Extent=[21:1 - 21:16]
-// CHECK: overrides.m:22:1: ObjCInstanceMethodDecl=protoMethod:22:1 [Overrides @12:1, @8:1] Extent=[22:1 - 22:21]
-// CHECK: overrides.m:26:1: ObjCInstanceMethodDecl=method:26:1 (Definition) [Overrides @21:1] Extent=[26:1 - 26:19]
-// CHECK: overrides.m:27:1: ObjCClassMethodDecl=methodWithParam::27:1 (Definition) [Overrides @17:1] Extent=[27:1 - 27:39]
+// CHECK: overrides.m:12:1: ObjCInstanceMethodDecl=protoMethod:12:1 [Overrides @3:1]
+// CHECK: overrides.m:22:1: ObjCInstanceMethodDecl=method:22:1 [Overrides @16:1]
+// CHECK: overrides.m:23:1: ObjCInstanceMethodDecl=protoMethod:23:1 [Overrides @12:1, @8:1, @32:1, @17:1]
+// CHECK: overrides.m:27:1: ObjCInstanceMethodDecl=method:27:1 (Definition) [Overrides @16:1]
+// CHECK: overrides.m:28:1: ObjCClassMethodDecl=methodWithParam::28:1 (Definition) [Overrides @18:1]
+// CHECK: overrides.m:32:1: ObjCInstanceMethodDecl=protoMethod:32:1 [Overrides @8:1]
+// CHECK: overrides.m:36:1: ObjCInstanceMethodDecl=protoMethod:36:1 [Overrides @12:1, @8:1, @32:1, @17:1]
diff --git a/test/Index/usrs.m b/test/Index/usrs.m
index ecf0d2302b..cfc055626a 100644
--- a/test/Index/usrs.m
+++ b/test/Index/usrs.m
@@ -189,7 +189,7 @@ int test_multi_declaration(void) {
// CHECK-source: usrs.m:31:15: ObjCInstanceMethodDecl=setD1::31:15 Extent=[31:15 - 31:17]
// CHECK-source: usrs.m:31:15: ParmDecl=d1:31:15 (Definition) Extent=[31:15 - 31:17]
// CHECK-source: usrs.m:34:17: ObjCImplementationDecl=Foo:34:17 (Definition) Extent=[34:1 - 45:2]
-// CHECK-source: usrs.m:35:1: ObjCInstanceMethodDecl=godzilla:35:1 (Definition) [Overrides @29:1] Extent=[35:1 - 39:2]
+// CHECK-source: usrs.m:35:1: ObjCInstanceMethodDecl=godzilla:35:1 (Definition) Extent=[35:1 - 39:2]
// CHECK-source: usrs.m:35:4: TypeRef=id:0:0 Extent=[35:4 - 35:6]
// CHECK-source: usrs.m:35:17: CompoundStmt= Extent=[35:17 - 39:2]
// CHECK-source: usrs.m:36:3: DeclStmt= Extent=[36:3 - 36:20]
@@ -200,7 +200,7 @@ int test_multi_declaration(void) {
// CHECK-source: usrs.m:38:3: ReturnStmt= Extent=[38:3 - 38:11]
// CHECK-source: usrs.m:38:10: UnexposedExpr= Extent=[38:10 - 38:11]
// CHECK-source: usrs.m:38:10: IntegerLiteral= Extent=[38:10 - 38:11]
-// CHECK-source: usrs.m:40:1: ObjCClassMethodDecl=kingkong:40:1 (Definition) [Overrides @30:1] Extent=[40:1 - 43:2]
+// CHECK-source: usrs.m:40:1: ObjCClassMethodDecl=kingkong:40:1 (Definition) Extent=[40:1 - 43:2]
// CHECK-source: usrs.m:40:4: TypeRef=id:0:0 Extent=[40:4 - 40:6]
// CHECK-source: usrs.m:40:17: CompoundStmt= Extent=[40:17 - 43:2]
// CHECK-source: usrs.m:41:3: DeclStmt= Extent=[41:3 - 41:17]
@@ -232,19 +232,19 @@ int test_multi_declaration(void) {
// CHECK-source: usrs.m:61:1: ObjCInstanceMethodDecl=meth4:61:1 Extent=[61:1 - 61:14]
// CHECK-source: usrs.m:61:4: TypeRef=id:0:0 Extent=[61:4 - 61:6]
// CHECK-source: usrs.m:63:17: ObjCImplementationDecl=CWithExt:63:17 (Definition) Extent=[63:1 - 67:2]
-// CHECK-source: usrs.m:64:1: ObjCInstanceMethodDecl=meth1:64:1 (Definition) [Overrides @52:1] Extent=[64:1 - 64:27]
+// CHECK-source: usrs.m:64:1: ObjCInstanceMethodDecl=meth1:64:1 (Definition) Extent=[64:1 - 64:27]
// CHECK-source: usrs.m:64:4: TypeRef=id:0:0 Extent=[64:4 - 64:6]
// CHECK-source: usrs.m:64:14: CompoundStmt= Extent=[64:14 - 64:27]
// CHECK-source: usrs.m:64:16: ReturnStmt= Extent=[64:16 - 64:24]
// CHECK-source: usrs.m:64:23: UnexposedExpr= Extent=[64:23 - 64:24]
// CHECK-source: usrs.m:64:23: IntegerLiteral= Extent=[64:23 - 64:24]
-// CHECK-source: usrs.m:65:1: ObjCInstanceMethodDecl=meth2:65:1 (Definition) [Overrides @55:1] Extent=[65:1 - 65:27]
+// CHECK-source: usrs.m:65:1: ObjCInstanceMethodDecl=meth2:65:1 (Definition) Extent=[65:1 - 65:27]
// CHECK-source: usrs.m:65:4: TypeRef=id:0:0 Extent=[65:4 - 65:6]
// CHECK-source: usrs.m:65:14: CompoundStmt= Extent=[65:14 - 65:27]
// CHECK-source: usrs.m:65:16: ReturnStmt= Extent=[65:16 - 65:24]
// CHECK-source: usrs.m:65:23: UnexposedExpr= Extent=[65:23 - 65:24]
// CHECK-source: usrs.m:65:23: IntegerLiteral= Extent=[65:23 - 65:24]
-// CHECK-source: usrs.m:66:1: ObjCInstanceMethodDecl=meth3:66:1 (Definition) [Overrides @58:1] Extent=[66:1 - 66:27]
+// CHECK-source: usrs.m:66:1: ObjCInstanceMethodDecl=meth3:66:1 (Definition) Extent=[66:1 - 66:27]
// CHECK-source: usrs.m:66:4: TypeRef=id:0:0 Extent=[66:4 - 66:6]
// CHECK-source: usrs.m:66:14: CompoundStmt= Extent=[66:14 - 66:27]
// CHECK-source: usrs.m:66:16: ReturnStmt= Extent=[66:16 - 66:24]
@@ -252,7 +252,7 @@ int test_multi_declaration(void) {
// CHECK-source: usrs.m:66:23: IntegerLiteral= Extent=[66:23 - 66:24]
// CHECK-source: usrs.m:68:17: ObjCCategoryImplDecl=Bar:68:17 (Definition) Extent=[68:1 - 70:2]
// CHECK-source: usrs.m:68:17: ObjCClassRef=CWithExt:51:12 Extent=[68:17 - 68:25]
-// CHECK-source: usrs.m:69:1: ObjCInstanceMethodDecl=meth4:69:1 (Definition) [Overrides @61:1] Extent=[69:1 - 69:27]
+// CHECK-source: usrs.m:69:1: ObjCInstanceMethodDecl=meth4:69:1 (Definition) Extent=[69:1 - 69:27]
// CHECK-source: usrs.m:69:4: TypeRef=id:0:0 Extent=[69:4 - 69:6]
// CHECK-source: usrs.m:69:14: CompoundStmt= Extent=[69:14 - 69:27]
// CHECK-source: usrs.m:69:16: ReturnStmt= Extent=[69:16 - 69:24]
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index ac8cf28880..a141af3c2b 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -794,16 +794,21 @@ static void CollectOverriddenMethods(CXTranslationUnit TU,
if (!Ctx)
return;
- // If we have a class or category implementation, jump straight to the
- // interface.
- if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(Ctx))
- return CollectOverriddenMethods(TU, Impl->getClassInterface(),
- Method, Methods);
-
ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx);
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)) {
+ for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
+ PEnd = Category->protocol_end();
+ P != PEnd; ++P)
+ CollectOverriddenMethods(TU, *P, Method, Methods);
+ return;
+ }
+
// Check whether we have a matching method at this level.
if (ObjCMethodDecl *Overridden = Container->getMethod(Method->getSelector(),
Method->isInstanceMethod()))
@@ -821,13 +826,6 @@ static void CollectOverriddenMethods(CXTranslationUnit TU,
CollectOverriddenMethods(TU, *P, Method, Methods);
}
- if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
- for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
- PEnd = Category->protocol_end();
- P != PEnd; ++P)
- CollectOverriddenMethods(TU, *P, Method, Methods);
- }
-
if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(),
PEnd = Interface->protocol_end();
@@ -838,10 +836,8 @@ static void CollectOverriddenMethods(CXTranslationUnit TU,
Category; Category = Category->getNextClassCategory())
CollectOverriddenMethods(TU, Category, Method, Methods);
- // We only look into the superclass if we haven't found anything yet.
- if (Methods.empty())
- if (ObjCInterfaceDecl *Super = Interface->getSuperClass())
- return CollectOverriddenMethods(TU, Super, Method, Methods);
+ if (ObjCInterfaceDecl *Super = Interface->getSuperClass())
+ return CollectOverriddenMethods(TU, Super, Method, Methods);
}
}
@@ -869,8 +865,37 @@ void cxcursor::getOverriddenCursors(CXCursor cursor,
if (!Method)
return;
- // Handle Objective-C methods.
- CollectOverriddenMethods(TU, Method->getDeclContext(), Method, overridden);
+ 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, Method->getDeclContext(), Method, overridden);
+ }
}
std::pair<int, SourceLocation>