objectiveC (take two): don't warn when in -Wselector mode and
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 22 Jan 2013 18:35:43 +0000 (18:35 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 22 Jan 2013 18:35:43 +0000 (18:35 +0000)
an unimplemented selector is consumed by
"respondsToSelector:". // rdar://12938616

llvm-svn: 173179

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

index b381d5c16c5bec5983ef9802b0db90c9985467cb..e5511a17fa27b34bd4a5ac680e9b6a78dd058aa9 100644 (file)
@@ -1410,8 +1410,7 @@ private:
   ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc);
   ExprResult ParseObjCBoxedExpr(SourceLocation AtLoc);
   ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
-  ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc,
-                                         bool WarnSelector=true);
+  ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
   ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
   bool isSimpleObjCMessageExpression();
   ExprResult ParseObjCMessageExpression();
index 37de68ffd029b7011a9207b85e0e8c90a9d7d1bc..a3402782a9c82c1d9210ce1f7455efcfdf57d926 100644 (file)
@@ -4280,8 +4280,7 @@ public:
                                          SourceLocation AtLoc,
                                          SourceLocation SelLoc,
                                          SourceLocation LParenLoc,
-                                         SourceLocation RParenLoc,
-                                         bool WarnSelector);
+                                         SourceLocation RParenLoc);
 
   /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
   ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
@@ -6392,7 +6391,7 @@ public:
                                   ParsedType Type,
                                   SourceLocation RParenLoc,
                                   Expr *SubExpr);
-
+  
   bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
 
   /// \brief Check whether the given new method is a valid override of the
index 47c22d9bd00e0d2958c99856a3054a5ec4ad8b95..65bfd1c830ea2516fe590edc8c7eaf1cf55752c5 100644 (file)
@@ -2419,14 +2419,12 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
   // Parse objc-selector
   SourceLocation Loc;
   IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
-
+  
   SmallVector<IdentifierInfo *, 12> KeyIdents;
   SmallVector<SourceLocation, 12> KeyLocs;
   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);
@@ -2465,22 +2463,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
         return ExprError();
       }
       
-      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();
-      
+      ExprResult 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
@@ -2560,7 +2543,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
     SkipUntil(tok::r_square);
     return ExprError();
   }
-
+  
   SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
 
   unsigned nKeys = KeyIdents.size();
@@ -2814,8 +2797,7 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
 
 ///     objc-selector-expression
 ///       @selector '(' objc-keyword-selector ')'
-ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc,
-                                               bool WarnSelector) {
+ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
   SourceLocation SelectorLoc = ConsumeToken();
 
   if (Tok.isNot(tok::l_paren))
@@ -2873,8 +2855,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc,
   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
   return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
                                              T.getOpenLocation(),
-                                             T.getCloseLocation(),
-                                             WarnSelector);
+                                             T.getCloseLocation());
  }
 
 void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
index 12f8d67d30fdf97223a2b737f196cf6c600d0493..87da44019169ca90e3a45e9b0cf6d09a0c91f17f 100644 (file)
@@ -967,27 +967,24 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
                                              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 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
   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 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S,
                                       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);
index a707276f714606ef5fc3f63e7c145340c0c004ec..f968aeb278c28df48aff114747fec54831562f41 100644 (file)
@@ -76,5 +76,8 @@ extern SEL MySelector(SEL s);
   if( [cnx respondsToSelector:@selector( _setQueueXX: )] ) // No warning here.
   {
   }
+  if( [cnx respondsToSelector:(@selector( _setQueueXX: ))] ) // No warning here.
+  {
+  }
 }
 @end