]> granicus.if.org Git - clang/commitdiff
Objective-C. Issue diagnostics on mismatched methods when their selector is used
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 12 Mar 2014 18:34:01 +0000 (18:34 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 12 Mar 2014 18:34:01 +0000 (18:34 +0000)
in an @selector expression. // rdar://15794055

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/selector-1.m

index 49d1d676faf83397f3ddd230a5de97f65a32c698..727e229644fd6ed2fe3f16b47a51df6186ed726b 100644 (file)
@@ -892,7 +892,9 @@ def warn_unimplemented_selector:  Warning<
   InGroup<Selector>, DefaultIgnore;
 def warn_unimplemented_protocol_method : Warning<
   "method %0 in protocol %1 not implemented">, InGroup<Protocol>;
-
+def warning_multiple_selectors: Warning<
+  "several methods with selector %0 of mismatched types are found for the @selector expression">,
+  InGroup<SelectorTypeMismatch>;
 // C++ declarations
 def err_static_assert_expression_is_not_constant : Error<
   "static_assert expression is not an integral constant expression">;
index 0d41d2ef81d7c9fc0b2564539348435e4ada8c9c..2e5c132a4d6765105e2c5a39570c0ccbc2fb38d8 100644 (file)
@@ -973,6 +973,58 @@ ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
   return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
 }
 
+static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
+                                               SourceLocation AtLoc,
+                                               ObjCMethodDecl *Method,
+                                               ObjCMethodList &MethList) {
+  ObjCMethodList *M = &MethList;
+  bool Warned = false;
+  for (M = M->getNext(); M; M=M->getNext()) {
+    ObjCMethodDecl *MatchingMethodDecl = M->Method;
+    if (MatchingMethodDecl == Method ||
+        isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) ||
+        MatchingMethodDecl->getSelector() != Method->getSelector())
+      continue;
+    if (!S.MatchTwoMethodDeclarations(Method,
+                                      MatchingMethodDecl, Sema::MMS_loose)) {
+      if (!Warned) {
+        Warned = true;
+        S.Diag(AtLoc, diag::warning_multiple_selectors)
+          << Method->getSelector();
+        S.Diag(Method->getLocation(), diag::note_method_declared_at)
+          << Method->getDeclName();
+      }
+      S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at)
+        << MatchingMethodDecl->getDeclName();
+    }
+  }
+  return Warned;
+}
+
+static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
+                                        ObjCMethodDecl *Method) {
+  unsigned DIAG = diag::warning_multiple_selectors;
+  if (S.Diags.getDiagnosticLevel(DIAG, SourceLocation())
+        == DiagnosticsEngine::Ignored)
+    return;
+  bool Warned = false;
+  for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(),
+       e = S.MethodPool.end(); b != e; b++) {
+    // first, instance methods
+    ObjCMethodList &InstMethList = b->second.first;
+    if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc,
+                                                      Method, InstMethList))
+      Warned = true;
+        
+    // second, class methods
+    ObjCMethodList &ClsMethList = b->second.second;
+    if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc,
+                                                      Method, ClsMethList) ||
+        Warned)
+      return;
+  }
+}
+
 ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
                                              SourceLocation AtLoc,
                                              SourceLocation SelLoc,
@@ -994,7 +1046,8 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
       
     } else
         Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
-  }
+  } else
+    DiagnoseMismatchedSelectors(*this, AtLoc, Method);
   
   if (!Method ||
       Method->getImplementationControl() != ObjCMethodDecl::Optional) {
index 33f8a8d36c20a38c332ca6df963f7e7f13b912b9..faa742616d5c35711babe30e86f0c4f14dddf0ee 100644 (file)
@@ -1,18 +1,17 @@
 // RUN: %clang_cc1 -verify %s 
-// expected-no-diagnostics
 
 @interface I
-- (id) compare: (char) arg1;
+- (id) compare: (char) arg1; // expected-note {{method 'compare:' declared here}}
 - length;
 @end
 
 @interface J
-- (id) compare: (id) arg1;
+- (id) compare: (id) arg1; // expected-note {{method 'compare:' declared here}}
 @end
 
 SEL func()
 {
-       return @selector(compare:);     // no warning on multiple selector found.
+       return @selector(compare:);     // expected-warning {{several methods with selector 'compare:' of mismatched types are found for the @selector expression}}
 }
 
 int main() {
@@ -27,3 +26,26 @@ int main() {
 
  SEL s9 = @selector(:enum:bool:);
 }
+
+// rdar://15794055
+@interface NSObject @end
+
+@class NSNumber;
+
+@interface XBRecipe : NSObject
+@property (nonatomic, assign) float finalVolume; // expected-note {{method 'setFinalVolume:' declared here}}
+@end
+
+@interface XBDocument : NSObject
+@end
+
+@interface XBDocument ()
+- (void)setFinalVolume:(NSNumber *)finalVolumeNumber; // expected-note {{method 'setFinalVolume:' declared here}}
+@end
+
+@implementation XBDocument
+- (void)setFinalVolume:(NSNumber *)finalVolumeNumber
+{
+    (void)@selector(setFinalVolume:); // expected-warning {{several methods with selector 'setFinalVolume:' of mismatched types are found for the @selector expression}}
+}
+@end