]> granicus.if.org Git - clang/commitdiff
[libclang] Enhance clang_getOverriddenCursors.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 8 Mar 2012 00:20:03 +0000 (00:20 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 8 Mar 2012 00:20:03 +0000 (00:20 +0000)
Basically the current design is:
-for an implementation method, show as overridden the interface method.
  This is not useful, and is inconsistent with the C++ side
-for an interface method, show as overridden the protocols methods (this is desirable)
  and the methods from the categories; methods from categories are not useful
  since they are considered the same method (same USR).
-If there is a protocol method or category method reported, it does not check the
  super class for overridden methods. This is really problematic since
  overridden methods from super class is what we want to give back.

Change clang_getOverriddenCursors to show as overridden any method in the class's
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.

rdar://10967206

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152270 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang-c/Index.h
test/Index/annotate-tokens.m
test/Index/file-refs.m
test/Index/local-symbols.m
test/Index/overrides.m
test/Index/usrs.m
tools/libclang/CXCursor.cpp

index fd7a9f3a0152d3d51529bd6b4cbe6f089b1683a0..d05510e281421b9d7f199aa612debb1815b17425 100644 (file)
@@ -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
index f9ddc655c2ff0d6fc444f4c91bda79cc36354be7..424dec8e00ef77a8b248c3526571c4adfe3ecdfa 100644 (file)
@@ -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)
index 583826700de459a5bbf241e339c96a44e4e6c2e2..684d87884e7e78803c562efa1ac0a2dd172523d3 100644 (file)
@@ -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]
 
index 01c8305c2af3d0b31a56053edab6398ae1a89210..0e70b7c89b6a6c4dc737e5099ec8adf4bac29cde 100644 (file)
@@ -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]
index 2197aaaa3672fd374115035a7ed5c3dd2f03c66b..e43d498c9a83aa90d4c405eeb37e0fe2516db7d7 100644 (file)
@@ -14,6 +14,7 @@
 
 @interface A
 - (void)method;
+- (void)protoMethod;
 + (void)methodWithParam:(int)param;
 @end
 
 + (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]
index ecf0d2302bcdb72bf50546eb3a0209e57eb5820e..cfc055626a54583302046c573bc62a4046185d47 100644 (file)
@@ -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]
index ac8cf28880353e365763e1c2ff1f48fc80818852..a141af3c2b9942f2d07106ebad3a3b2097c90924 100644 (file)
@@ -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>