r211611 - Objective-C. When we use @selector(save:), etc. there may be more

Fariborz Jahanian fjahanian at apple.com
Tue Jun 24 10:02:20 PDT 2014


Author: fjahanian
Date: Tue Jun 24 12:02:19 2014
New Revision: 211611

URL: http://llvm.org/viewvc/llvm-project?rev=211611&view=rev
Log:
Objective-C. When we use @selector(save:), etc. there may be more 
than one method with mismatched type of same selector name. 
clang issues a warning to point this out since it may cause 
undefined behavior. There are cases though that some APIs 
don't care about user methods and such warnings are perceived as 
noise. This patch allows users to add paren delimiters around
selector name to turn off such warnings. So, @selector((save:)) will
turn off the warning. It also provides 'fixit' so user knows 
what to do. // rdar://16458579

Added:
    cfe/trunk/test/FixIt/fixit-multiple-selector-warnings.m
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/selector-1.m

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=211611&r1=211610&r2=211611&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 24 12:02:19 2014
@@ -4748,7 +4748,8 @@ public:
                                          SourceLocation AtLoc,
                                          SourceLocation SelLoc,
                                          SourceLocation LParenLoc,
-                                         SourceLocation RParenLoc);
+                                         SourceLocation RParenLoc,
+                                         bool WarnMultipleSelectors);
 
   /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
   ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=211611&r1=211610&r2=211611&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Tue Jun 24 12:02:19 2014
@@ -2839,7 +2839,7 @@ Parser::ParseObjCProtocolExpression(Sour
 }
 
 ///     objc-selector-expression
-///       @selector '(' objc-keyword-selector ')'
+///       @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')'
 ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
   SourceLocation SelectorLoc = ConsumeToken();
 
@@ -2851,7 +2851,10 @@ ExprResult Parser::ParseObjCSelectorExpr
   
   BalancedDelimiterTracker T(*this, tok::l_paren);
   T.consumeOpen();
-
+  bool HasOptionalParen = Tok.is(tok::l_paren);
+  if (HasOptionalParen)
+    ConsumeParen();
+  
   if (Tok.is(tok::code_completion)) {
     Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
     cutOffParsing();
@@ -2864,6 +2867,7 @@ ExprResult Parser::ParseObjCSelectorExpr
     return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
 
   KeyIdents.push_back(SelIdent);
+  
   unsigned nColons = 0;
   if (Tok.isNot(tok::r_paren)) {
     while (1) {
@@ -2891,11 +2895,14 @@ ExprResult Parser::ParseObjCSelectorExpr
         break;
     }
   }
+  if (HasOptionalParen && Tok.is(tok::r_paren))
+    ConsumeParen(); // ')'
   T.consumeClose();
   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
   return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
                                              T.getOpenLocation(),
-                                             T.getCloseLocation());
+                                             T.getCloseLocation(),
+                                             !HasOptionalParen);
  }
 
 void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=211611&r1=211610&r2=211611&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Jun 24 12:02:19 2014
@@ -976,6 +976,8 @@ ExprResult Sema::ParseObjCEncodeExpressi
 
 static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
                                                SourceLocation AtLoc,
+                                               SourceLocation LParenLoc,
+                                               SourceLocation RParenLoc,
                                                ObjCMethodDecl *Method,
                                                ObjCMethodList &MethList) {
   ObjCMethodList *M = &MethList;
@@ -991,7 +993,8 @@ static bool HelperToDiagnoseMismatchedMe
       if (!Warned) {
         Warned = true;
         S.Diag(AtLoc, diag::warning_multiple_selectors)
-          << Method->getSelector();
+          << Method->getSelector() << FixItHint::CreateInsertion(LParenLoc, "(")
+          << FixItHint::CreateInsertion(RParenLoc, ")");
         S.Diag(Method->getLocation(), diag::note_method_declared_at)
           << Method->getDeclName();
       }
@@ -1003,23 +1006,26 @@ static bool HelperToDiagnoseMismatchedMe
 }
 
 static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
-                                        ObjCMethodDecl *Method) {
-  if (S.Diags.isIgnored(diag::warning_multiple_selectors, SourceLocation()))
+                                        ObjCMethodDecl *Method,
+                                        SourceLocation LParenLoc,
+                                        SourceLocation RParenLoc,
+                                        bool WarnMultipleSelectors) {
+  if (!WarnMultipleSelectors ||
+      S.Diags.isIgnored(diag::warning_multiple_selectors, SourceLocation()))
     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,
+    if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
                                                       Method, InstMethList))
       Warned = true;
         
     // second, class methods
     ObjCMethodList &ClsMethList = b->second.second;
-    if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc,
-                                                      Method, ClsMethList) ||
-        Warned)
+    if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
+                                                      Method, ClsMethList) || Warned)
       return;
   }
 }
@@ -1028,7 +1034,8 @@ ExprResult Sema::ParseObjCSelectorExpres
                                              SourceLocation AtLoc,
                                              SourceLocation SelLoc,
                                              SourceLocation LParenLoc,
-                                             SourceLocation RParenLoc) {
+                                             SourceLocation RParenLoc,
+                                             bool WarnMultipleSelectors) {
   ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
                              SourceRange(LParenLoc, RParenLoc), false, false);
   if (!Method)
@@ -1046,7 +1053,8 @@ ExprResult Sema::ParseObjCSelectorExpres
     } else
         Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
   } else
-    DiagnoseMismatchedSelectors(*this, AtLoc, Method);
+    DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc,
+                                WarnMultipleSelectors);
   
   if (Method &&
       Method->getImplementationControl() != ObjCMethodDecl::Optional &&

Added: cfe/trunk/test/FixIt/fixit-multiple-selector-warnings.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-multiple-selector-warnings.m?rev=211611&view=auto
==============================================================================
--- cfe/trunk/test/FixIt/fixit-multiple-selector-warnings.m (added)
+++ cfe/trunk/test/FixIt/fixit-multiple-selector-warnings.m Tue Jun 24 12:02:19 2014
@@ -0,0 +1,26 @@
+/* RUN: cp %s %t
+   RUN: %clang_cc1 -x objective-c -Wselector-type-mismatch -fixit %t
+   RUN: %clang_cc1 -x objective-c -Wselector-type-mismatch -Werror %t
+*/
+// rdar://16458579
+
+ at interface I
+- (id) compare: (char) arg1;
+- length;
+ at end
+
+ at interface J
+- (id) compare: (id) arg1;
+ at end
+
+SEL func()
+{
+        (void)@selector( compare: );
+        (void)@selector (compare:);
+        (void)@selector( compare:);
+        (void)@selector(compare: );
+        (void)@selector ( compare: );
+	return @selector(compare:);
+}
+
+

Modified: cfe/trunk/test/SemaObjC/selector-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/selector-1.m?rev=211611&r1=211610&r2=211611&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/selector-1.m (original)
+++ cfe/trunk/test/SemaObjC/selector-1.m Tue Jun 24 12:02:19 2014
@@ -14,6 +14,18 @@ SEL func()
 	return @selector(compare:);	// expected-warning {{several methods with selector 'compare:' of mismatched types are found for the @selector expression}}
 }
 
+// rdar://16458579
+void Test16458579() {
+ SEL s = @selector((retain));
+ SEL s1 = @selector((meth1:));
+ SEL s2 = @selector((retainArgument::));
+ SEL s3 = @selector((retainArgument:::::));
+ SEL s4 = @selector((retainArgument:with:));
+ SEL s5 = @selector((meth1:with:with:));
+ SEL s6 = @selector((getEnum:enum:bool:));
+ SEL s7 = @selector((char:float:double:unsigned:short:long:));
+ SEL s9 = @selector((:enum:bool:));
+}
 int main() {
  SEL s = @selector(retain);
  SEL s1 = @selector(meth1:);





More information about the cfe-commits mailing list