]> granicus.if.org Git - clang/commitdiff
objectiveC: don't warn when in -Wselector mode and
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 21 Jan 2013 22:32:29 +0000 (22:32 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 21 Jan 2013 22:32:29 +0000 (22:32 +0000)
an unimplemented selector is consumed by
"respondsToSelector:". // rdar://12938616

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

include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
lib/Parse/ParseObjc.cpp
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/selector-3.m

index e5511a17fa27b34bd4a5ac680e9b6a78dd058aa9..b381d5c16c5bec5983ef9802b0db90c9985467cb 100644 (file)
@@ -1410,7 +1410,8 @@ private:
   ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc);
   ExprResult ParseObjCBoxedExpr(SourceLocation AtLoc);
   ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
-  ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
+  ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc,
+                                         bool WarnSelector=true);
   ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
   bool isSimpleObjCMessageExpression();
   ExprResult ParseObjCMessageExpression();
index eb561e3d451f03d620094c9e592d64dadf97745e..37de68ffd029b7011a9207b85e0e8c90a9d7d1bc 100644 (file)
@@ -4280,7 +4280,8 @@ public:
                                          SourceLocation AtLoc,
                                          SourceLocation SelLoc,
                                          SourceLocation LParenLoc,
-                                         SourceLocation RParenLoc);
+                                         SourceLocation RParenLoc,
+                                         bool WarnSelector);
 
   /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
   ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
index ae1e19cc6d8a2341bbc9b7542f9b603b5e80c99a..47c22d9bd00e0d2958c99856a3054a5ec4ad8b95 100644 (file)
@@ -2425,6 +2425,8 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
   ExprVector KeyExprs;
 
   if (Tok.is(tok::colon)) {
+    bool RespondsToSelector =
+           selIdent && selIdent->isStr("respondsToSelector");
     while (1) {
       // Each iteration parses a single keyword argument.
       KeyIdents.push_back(selIdent);
@@ -2463,7 +2465,22 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
         return ExprError();
       }
       
-      ExprResult Res(ParseAssignmentExpression());
+      ExprResult Res;
+      if (RespondsToSelector) {
+        if (Tok.is(tok::at)) {
+          // Special handling for 'respondsToSelector:' which must not warn
+          // on use of @selector expression as its sole argument.
+          Token AfterAt = GetLookAheadToken(1);
+          if (AfterAt.isObjCAtKeyword(tok::objc_selector)) {
+            SourceLocation AtLoc = ConsumeToken();
+            Res = ParseObjCSelectorExpression(AtLoc, false);
+          }
+        }
+        RespondsToSelector = false;
+      }
+      if (!Res.get())
+        Res = ParseAssignmentExpression();
+      
       if (Res.isInvalid()) {
         // We must manually skip to a ']', otherwise the expression skipper will
         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
@@ -2797,7 +2814,8 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
 
 ///     objc-selector-expression
 ///       @selector '(' objc-keyword-selector ')'
-ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
+ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc,
+                                               bool WarnSelector) {
   SourceLocation SelectorLoc = ConsumeToken();
 
   if (Tok.isNot(tok::l_paren))
@@ -2855,7 +2873,8 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
   return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
                                              T.getOpenLocation(),
-                                             T.getCloseLocation());
+                                             T.getCloseLocation(),
+                                             WarnSelector);
  }
 
 void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
index bdc72661344ac63132aae6e6d89305685e6949f8..12f8d67d30fdf97223a2b737f196cf6c600d0493 100644 (file)
@@ -967,24 +967,27 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
                                              SourceLocation AtLoc,
                                              SourceLocation SelLoc,
                                              SourceLocation LParenLoc,
-                                             SourceLocation RParenLoc) {
-  ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
-                             SourceRange(LParenLoc, RParenLoc), false, false);
-  if (!Method)
-    Method = LookupFactoryMethodInGlobalPool(Sel,
+                                             SourceLocation RParenLoc,
+                                             bool WarnSelector) {
+  if (WarnSelector) {
+    ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
+                              SourceRange(LParenLoc, RParenLoc), false, false);
+    if (!Method)
+      Method = LookupFactoryMethodInGlobalPool(Sel,
                                           SourceRange(LParenLoc, RParenLoc));
-  if (!Method)
-    Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+    if (!Method)
+      Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
   
-  if (!Method ||
-      Method->getImplementationControl() != ObjCMethodDecl::Optional) {
-    llvm::DenseMap<Selector, SourceLocation>::iterator Pos
-      = ReferencedSelectors.find(Sel);
-    if (Pos == ReferencedSelectors.end())
-      ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
+    if (!Method ||
+        Method->getImplementationControl() != ObjCMethodDecl::Optional) {
+            llvm::DenseMap<Selector, SourceLocation>::iterator Pos
+          = ReferencedSelectors.find(Sel);
+          if (Pos == ReferencedSelectors.end())
+            ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
+    }
   }
 
-  // In ARC, forbid the user from using @selector for 
+  // In ARC, forbid the user from using @selector for
   // retain/release/autorelease/dealloc/retainCount.
   if (getLangOpts().ObjCAutoRefCount) {
     switch (Sel.getMethodFamily()) {
index 4c12a9392dc14843bb3e20b2842ed2c624f18695..a707276f714606ef5fc3f63e7c145340c0c004ec 100644 (file)
@@ -52,3 +52,29 @@ SEL func()
 }
 @end
 
+// rdar://12938616
+@class NSXPCConnection;
+
+@interface NSObject
+@end
+
+@interface INTF : NSObject
+{
+  NSXPCConnection *cnx; // Comes in as a parameter.
+}
+- (void) Meth;
+@end
+
+extern SEL MySelector(SEL s);
+
+@implementation INTF
+- (void) Meth {
+  if( [cnx respondsToSelector:MySelector(@selector( _setQueue: ))] ) // expected-warning {{unimplemented selector '_setQueue:'}} 
+  {
+  }
+
+  if( [cnx respondsToSelector:@selector( _setQueueXX: )] ) // No warning here.
+  {
+  }
+}
+@end