r203693 - Objective-C. Issue diagnostics on mismatched methods when their selector is used

Fariborz Jahanian fjahanian at apple.com
Wed Mar 12 11:34:01 PDT 2014


Author: fjahanian
Date: Wed Mar 12 13:34:01 2014
New Revision: 203693

URL: http://llvm.org/viewvc/llvm-project?rev=203693&view=rev
Log:
Objective-C. Issue diagnostics on mismatched methods when their selector is used
in an @selector expression. // rdar://15794055

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

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=203693&r1=203692&r2=203693&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 12 13:34:01 2014
@@ -892,7 +892,9 @@ def warn_unimplemented_selector:  Warnin
   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">;

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=203693&r1=203692&r2=203693&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Mar 12 13:34:01 2014
@@ -973,6 +973,58 @@ ExprResult Sema::ParseObjCEncodeExpressi
   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::ParseObjCSelectorExpres
       
     } else
         Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
-  }
+  } else
+    DiagnoseMismatchedSelectors(*this, AtLoc, Method);
   
   if (!Method ||
       Method->getImplementationControl() != ObjCMethodDecl::Optional) {

Modified: cfe/trunk/test/SemaObjC/selector-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/selector-1.m?rev=203693&r1=203692&r2=203693&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/selector-1.m (original)
+++ cfe/trunk/test/SemaObjC/selector-1.m Wed Mar 12 13:34:01 2014
@@ -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
+ at interface NSObject @end
+
+ at class NSNumber;
+
+ at interface XBRecipe : NSObject
+ at property (nonatomic, assign) float finalVolume; // expected-note {{method 'setFinalVolume:' declared here}}
+ at end
+
+ at interface XBDocument : NSObject
+ at end
+
+ at interface XBDocument ()
+- (void)setFinalVolume:(NSNumber *)finalVolumeNumber; // expected-note {{method 'setFinalVolume:' declared here}}
+ at end
+
+ at 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}}
+}
+ at end





More information about the cfe-commits mailing list