objectiveC: don't warn when in -Wselector mode and
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
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index e5511a1..b381d5c 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1410,7 +1410,8 @@
   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();
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index eb561e3..37de68f 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4280,7 +4280,8 @@
                                          SourceLocation AtLoc,
                                          SourceLocation SelLoc,
                                          SourceLocation LParenLoc,
-                                         SourceLocation RParenLoc);
+                                         SourceLocation RParenLoc,
+                                         bool WarnSelector);
 
   /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
   ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index ae1e19c..47c22d9 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -2425,6 +2425,8 @@
   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 @@
         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 @@
 
 ///     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 @@
   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) {
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index bdc7266..12f8d67 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -967,24 +967,27 @@
                                              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()) {
diff --git a/test/SemaObjC/selector-3.m b/test/SemaObjC/selector-3.m
index 4c12a93..a707276 100644
--- a/test/SemaObjC/selector-3.m
+++ b/test/SemaObjC/selector-3.m
@@ -52,3 +52,29 @@
 }
 @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