]> granicus.if.org Git - clang/commitdiff
Objective-C: Implements gcc's -Wselector option
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 30 May 2013 21:48:58 +0000 (21:48 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 30 May 2013 21:48:58 +0000 (21:48 +0000)
which diagnoses type mismatches of identical
selectors declared in classes throughout.
// rdar://14007194

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

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/PCH/Inputs/chain-selectors2.h
test/SemaObjC/selector-3.m

index 565a01745f11536b8a399df996aa291c796864a1..8259e2e368086a798e7f5f82e62aca75f7fb31f9 100644 (file)
@@ -338,7 +338,8 @@ def AutomaticReferenceCounting : DiagGroup<"arc",
 def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">;
 def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak",
                                      [ARCRepeatedUseOfWeakMaybe]>;
-def Selector : DiagGroup<"selector">;
+def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">;
+def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>;
 def Protocol : DiagGroup<"protocol">;
 def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
 def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
index aff02f30fc853acab50a7fd5c31f1764fbaa6714..d49457b1a5cf15294f8f6fe2e00fef0eb3dae87b 100644 (file)
@@ -824,6 +824,8 @@ def warn_auto_implicit_atomic_property : Warning<
   InGroup<ImplicitAtomic>, DefaultIgnore;
 def warn_unimplemented_selector:  Warning<
   "creating selector for nonexistent method %0">, InGroup<Selector>, DefaultIgnore;
+def warning_multiple_selectors: Warning<
+  "multiple selectors named %0 found">, InGroup<SelectorTypeMismatch>, DefaultIgnore;
 def warn_unimplemented_protocol_method : Warning<
   "method %0 in protocol not implemented">, InGroup<Protocol>;
 
index 3b4c213e94388aefde98438b8ac324cf94ffd14f..22490171c8b2794df135a7969094972256dd0326 100644 (file)
@@ -2669,6 +2669,11 @@ public:
                                     warn, /*instance*/false);
   }
 
+  /// DiagnoseMismatchedMethodsInGlobalPool - This routine goes through list of
+  /// methods in global pool and issues diagnostic on identical selectors which
+  /// have mismathched types.
+  void DiagnoseMismatchedMethodsInGlobalPool();
+  
   /// LookupImplementedMethodInGlobalPool - Returns the method which has an
   /// implementation.
   ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
index 687cdf114a6a3d6961c6f1fe7291ba7d58600c89..58ea0147849dacb4cc669ad134c17153514ddaeb 100644 (file)
@@ -2271,7 +2271,52 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
   return 0;
 }
 
-/// DiagnoseDuplicateIvars - 
+static void
+HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
+                                              ObjCMethodList &MethList) {
+  ObjCMethodList *M = &MethList;
+  ObjCMethodDecl *TargetMethod = M->Method;
+  while (TargetMethod &&
+         isa<ObjCImplDecl>(TargetMethod->getDeclContext())) {
+    M = M->getNext();
+    TargetMethod = M ? M->Method : 0;
+  }
+  if (!TargetMethod)
+    return;
+  bool FirstTime = true;
+  for (M = M->getNext(); M; M=M->getNext()) {
+    ObjCMethodDecl *MatchingMethodDecl = M->Method;
+    if (isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()))
+      continue;
+    if (!S.MatchTwoMethodDeclarations(TargetMethod,
+                                      MatchingMethodDecl, Sema::MMS_loose)) {
+      if (FirstTime) {
+        FirstTime = false;
+        S.Diag(TargetMethod->getLocation(), diag::warning_multiple_selectors)
+        << TargetMethod->getSelector();
+      }
+      S.Diag(MatchingMethodDecl->getLocation(), diag::note_also_found);
+    }
+  }
+}
+
+void Sema::DiagnoseMismatchedMethodsInGlobalPool() {
+  unsigned DIAG = diag::warning_multiple_selectors;
+  if (Diags.getDiagnosticLevel(DIAG, SourceLocation())
+      == DiagnosticsEngine::Ignored)
+    return;
+  for (GlobalMethodPool::iterator b = MethodPool.begin(),
+       e = MethodPool.end(); b != e; b++) {
+    // first, instance methods
+    ObjCMethodList &InstMethList = b->second.first;
+    HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, InstMethList);
+    // second, instance methods
+    ObjCMethodList &ClsMethList = b->second.second;
+    HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, ClsMethList);
+  }
+}
+
+/// DiagnoseDuplicateIvars -
 /// Check for duplicate ivars in the entire class at the start of 
 /// \@implementation. This becomes necesssary because class extension can
 /// add ivars to a class in random order which will not be known until
@@ -3294,6 +3339,8 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
       ReferencedSelectors[Sels[I].first] = Sels[I].second;
   }
   
+  DiagnoseMismatchedMethodsInGlobalPool();
+  
   // Warning will be issued only when selector table is
   // generated (which means there is at lease one implementation
   // in the TU). This is to match gcc's behavior.
index 973fc107e90ebe56b382ab14b5f5b220df043998..d54244de617bd97348274187a35e91f7508d7cff 100644 (file)
@@ -1,6 +1,6 @@
 @interface Y
   -(void)f;
-  -(double)f2;
+  -(void)f2;
   -(void)e;
 @end
 
index 92117db7bc21a84f75c0fba00393d1c62abb747a..d782c784f1de742d62bfe4461c4ee1916402a939 100644 (file)
@@ -81,3 +81,32 @@ extern SEL MySelector(SEL s);
   }
 }
 @end
+
+// rdar://14007194
+@interface UxTechTest : NSObject
+- (int) invalidate : (id)Arg; // expected-warning {{multiple selectors named 'invalidate:' found}}
++ (int) C_invalidate : (int)arg; // expected-warning {{multiple selectors named 'C_invalidate:' found}}
+@end
+
+@interface UxTechTest(CAT)
+- (char) invalidate : (int)arg; // expected-note {{also found}}
++ (int) C_invalidate : (char)arg; // expected-note {{also found}}
+@end
+
+@interface NSPort : NSObject
+- (double) invalidate : (void*)Arg1; // expected-note {{also found}}
++ (int) C_invalidate : (id*)arg; // expected-note {{also found}}
+@end
+
+
+@interface USEText : NSPort
+- (int) invalidate : (int)arg; // expected-note {{also found}}
+@end
+
+@implementation USEText
+- (int) invalidate :(int) arg { return 0; }
+@end
+
+@interface USETextSub : USEText
+- (int) invalidate : (id)arg;
+@end