From: Fariborz Jahanian Date: Mon, 21 Jan 2013 22:32:29 +0000 (+0000) Subject: objectiveC: don't warn when in -Wselector mode and X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f11ccc1cbb26cacac36abebe6ce9add43bf32585;p=clang 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 e5511a17fa..b381d5c16c 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index eb561e3d45..37de68ffd0 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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, diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index ae1e19cc6d..47c22d9bd0 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -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) { diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index bdc7266134..12f8d67d30 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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::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, 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 4c12a9392d..a707276f71 100644 --- a/test/SemaObjC/selector-3.m +++ b/test/SemaObjC/selector-3.m @@ -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