From 48f3cc2b2be1d32df14234904539b34e6e387e4a Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 22 Jan 2013 18:35:43 +0000 Subject: [PATCH] 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 --- include/clang/Parse/Parser.h | 3 +-- include/clang/Sema/Sema.h | 5 ++-- lib/Parse/ParseObjc.cpp | 29 ++++------------------ lib/Sema/SemaExprObjC.cpp | 48 ++++++++++++++++++++++-------------- test/SemaObjC/selector-3.m | 3 +++ 5 files changed, 41 insertions(+), 47 deletions(-) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index b381d5c16c..e5511a17fa 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 37de68ffd0..a3402782a9 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 47c22d9bd0..65bfd1c830 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -2419,14 +2419,12 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, // Parse objc-selector SourceLocation Loc; IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc); - + SmallVector KeyIdents; SmallVector 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) { diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 12f8d67d30..87da440191 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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::iterator Pos - = ReferencedSelectors.find(Sel); - if (Pos == ReferencedSelectors.end()) - ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); - } + if (!Method || + Method->getImplementationControl() != ObjCMethodDecl::Optional) { + llvm::DenseMap::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(Arg->IgnoreParenCasts())) { + Selector Sel = OSE->getSelector(); + SourceLocation Loc = OSE->getAtLoc(); + llvm::DenseMap::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); diff --git a/test/SemaObjC/selector-3.m b/test/SemaObjC/selector-3.m index a707276f71..f968aeb278 100644 --- a/test/SemaObjC/selector-3.m +++ b/test/SemaObjC/selector-3.m @@ -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 -- 2.40.0