objectiveC (take two): 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@173179 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 12f8d67..87da440 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -967,27 +967,24 @@
                                              SourceLocation AtLoc,
                                              SourceLocation SelLoc,
                                              SourceLocation LParenLoc,
-                                             SourceLocation RParenLoc,
-                                             bool WarnSelector) {
-  if (WarnSelector) {
-    ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
-                              SourceRange(LParenLoc, RParenLoc), false, false);
-    if (!Method)
-      Method = LookupFactoryMethodInGlobalPool(Sel,
+                                             SourceLocation RParenLoc) {
+  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, AtLoc));
   }
 
-  // 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()) {
@@ -2464,6 +2461,18 @@
   return MaybeBindToTemporary(Result);
 }
 
+static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) {
+  if (ObjCSelectorExpr *OSE =
+      dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) {
+    Selector Sel = OSE->getSelector();
+    SourceLocation Loc = OSE->getAtLoc();
+    llvm::DenseMap<Selector, SourceLocation>::iterator Pos
+    = S.ReferencedSelectors.find(Sel);
+    if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)
+      S.ReferencedSelectors.erase(Pos);
+  }
+}
+
 // ActOnInstanceMessage - used for both unary and keyword messages.
 // ArgExprs is optional - if it is present, the number of expressions
 // is obtained from Sel.getNumArgs().
@@ -2476,7 +2485,10 @@
                                       MultiExprArg Args) {
   if (!Receiver)
     return ExprError();
-
+  IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector");
+  if (Sel == Context.Selectors.getUnarySelector(SelectorId))
+    RemoveSelectorFromWarningCache(*this, Args[0]);
+    
   return BuildInstanceMessage(Receiver, Receiver->getType(),
                               /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, 
                               LBracLoc, SelectorLocs, RBracLoc, Args);