forked from OSchip/llvm-project
objectiveC (take two): don't warn when in -Wselector mode and
an unimplemented selector is consumed by "respondsToSelector:". // rdar://12938616 llvm-svn: 173179
This commit is contained in:
parent
44c3145938
commit
02447d80e4
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue