aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r--lib/Sema/SemaExprObjC.cpp170
1 files changed, 126 insertions, 44 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index b0d5453808..cf77896cb8 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -238,8 +238,8 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
SourceLocation(), SourceLocation(),
&CX.Idents.get("value"),
NumberType, /*TInfo=*/0, SC_None,
- SC_None, 0);
- Method->setMethodParams(S.Context, value, ArrayRef<SourceLocation>());
+ 0);
+ Method->setMethodParams(S.Context, value, None);
}
if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method))
@@ -343,7 +343,7 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
InitializationKind Kind
= InitializationKind::CreateCopy(Element->getLocStart(),
SourceLocation());
- InitializationSequence Seq(S, Entity, Kind, &Element, 1);
+ InitializationSequence Seq(S, Entity, Kind, Element);
if (!Seq.Failed())
return Seq.Perform(S, Entity, Kind, Element);
}
@@ -489,8 +489,8 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
&Context.Idents.get("value"),
Context.getPointerType(ConstCharType),
/*TInfo=*/0,
- SC_None, SC_None, 0);
- M->setMethodParams(Context, value, ArrayRef<SourceLocation>());
+ SC_None, 0);
+ M->setMethodParams(Context, value, None);
BoxingMethod = M;
}
@@ -656,18 +656,16 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(objects);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(cnt);
- Method->setMethodParams(Context, Params, ArrayRef<SourceLocation>());
+ Method->setMethodParams(Context, Params, None);
}
if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method))
@@ -774,26 +772,23 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
SourceLocation(),
&Context.Idents.get("objects"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(objects);
ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("keys"),
Context.getPointerType(IdT),
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(keys);
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
SourceLocation(),
SourceLocation(),
&Context.Idents.get("cnt"),
Context.UnsignedLongTy,
- /*TInfo=*/0, SC_None, SC_None,
- 0);
+ /*TInfo=*/0, SC_None, 0);
Params.push_back(cnt);
- Method->setMethodParams(Context, Params, ArrayRef<SourceLocation>());
+ Method->setMethodParams(Context, Params, None);
}
if (!validateBoxingMethod(*this, SR.getBegin(), NSDictionaryDecl, Sel,
@@ -1094,6 +1089,73 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType,
return ReceiverType;
}
+/// Look for an ObjC method whose result type exactly matches the given type.
+static const ObjCMethodDecl *
+findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
+ QualType instancetype) {
+ if (MD->getResultType() == instancetype) return MD;
+
+ // For these purposes, a method in an @implementation overrides a
+ // declaration in the @interface.
+ if (const ObjCImplDecl *impl =
+ dyn_cast<ObjCImplDecl>(MD->getDeclContext())) {
+ const ObjCContainerDecl *iface;
+ if (const ObjCCategoryImplDecl *catImpl =
+ dyn_cast<ObjCCategoryImplDecl>(impl)) {
+ iface = catImpl->getCategoryDecl();
+ } else {
+ iface = impl->getClassInterface();
+ }
+
+ const ObjCMethodDecl *ifaceMD =
+ iface->getMethod(MD->getSelector(), MD->isInstanceMethod());
+ if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype);
+ }
+
+ SmallVector<const ObjCMethodDecl *, 4> overrides;
+ MD->getOverriddenMethods(overrides);
+ for (unsigned i = 0, e = overrides.size(); i != e; ++i) {
+ if (const ObjCMethodDecl *result =
+ findExplicitInstancetypeDeclarer(overrides[i], instancetype))
+ return result;
+ }
+
+ return 0;
+}
+
+void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
+ // Only complain if we're in an ObjC method and the required return
+ // type doesn't match the method's declared return type.
+ ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext);
+ if (!MD || !MD->hasRelatedResultType() ||
+ Context.hasSameUnqualifiedType(destType, MD->getResultType()))
+ return;
+
+ // Look for a method overridden by this method which explicitly uses
+ // 'instancetype'.
+ if (const ObjCMethodDecl *overridden =
+ findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {
+ SourceLocation loc;
+ SourceRange range;
+ if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) {
+ range = TSI->getTypeLoc().getSourceRange();
+ loc = range.getBegin();
+ }
+ if (loc.isInvalid())
+ loc = overridden->getLocation();
+ Diag(loc, diag::note_related_result_type_explicit)
+ << /*current method*/ 1 << range;
+ return;
+ }
+
+ // Otherwise, if we have an interesting method family, note that.
+ // This should always trigger if the above didn't.
+ if (ObjCMethodFamily family = MD->getMethodFamily())
+ Diag(MD->getLocation(), diag::note_related_result_type_family)
+ << /*current method*/ 1
+ << family;
+}
+
void Sema::EmitRelatedResultTypeNote(const Expr *E) {
E = E->IgnoreParenImpCasts();
const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);
@@ -1129,6 +1191,12 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
bool isClassMessage, bool isSuperMessage,
SourceLocation lbrac, SourceLocation rbrac,
QualType &ReturnType, ExprValueKind &VK) {
+ SourceLocation SelLoc;
+ if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
+ SelLoc = SelectorLocs.front();
+ else
+ SelLoc = lbrac;
+
if (!Method) {
// Apply default argument promotion as for (C99 6.5.2.2p6).
for (unsigned i = 0; i != NumArgs; i++) {
@@ -1138,7 +1206,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
ExprResult result;
if (getLangOpts().DebuggerSupport) {
QualType paramTy; // ignored
- result = checkUnknownAnyArg(lbrac, Args[i], paramTy);
+ result = checkUnknownAnyArg(SelLoc, Args[i], paramTy);
} else {
result = DefaultArgumentPromotion(Args[i]);
}
@@ -1154,7 +1222,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
DiagID = isClassMessage ? diag::warn_class_method_not_found
: diag::warn_inst_method_not_found;
if (!getLangOpts().DebuggerSupport)
- Diag(lbrac, DiagID)
+ Diag(SelLoc, DiagID)
<< Sel << isClassMessage << SourceRange(SelectorLocs.front(),
SelectorLocs.back());
@@ -1180,7 +1248,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
NumNamedArgs = Method->param_size();
// FIXME. This need be cleaned up.
if (NumArgs < NumNamedArgs) {
- Diag(lbrac, diag::err_typecheck_call_too_few_args)
+ Diag(SelLoc, diag::err_typecheck_call_too_few_args)
<< 2 << NumNamedArgs << NumArgs;
return false;
}
@@ -1206,7 +1274,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
// from the argument.
if (param->getType() == Context.UnknownAnyTy) {
QualType paramType;
- ExprResult argE = checkUnknownAnyArg(lbrac, argExpr, paramType);
+ ExprResult argE = checkUnknownAnyArg(SelLoc, argExpr, paramType);
if (argE.isInvalid()) {
IsError = true;
} else {
@@ -1225,7 +1293,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
param);
- ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr));
+ ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, Owned(argExpr));
if (ArgE.isInvalid())
IsError = true;
else
@@ -1255,10 +1323,11 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
}
}
- DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
+ DiagnoseSentinelCalls(Method, SelLoc, Args, NumArgs);
// Do additional checkings on method.
- IsError |= CheckObjCMethodCall(Method, lbrac, Args, NumArgs);
+ IsError |= CheckObjCMethodCall(Method, SelLoc,
+ llvm::makeArrayRef<const Expr *>(Args, NumArgs));
return IsError;
}
@@ -1266,7 +1335,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
bool Sema::isSelfExpr(Expr *receiver) {
// 'self' is objc 'self' in an objc method only.
ObjCMethodDecl *method =
- dyn_cast<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
+ dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
if (!method) return false;
receiver = receiver->IgnoreParenLValueCasts();
@@ -1724,9 +1793,11 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
QualType T;
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))
T = Context.getObjCInterfaceType(Class);
- else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+ else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) {
T = Context.getTypeDeclType(Type);
- else
+ DiagnoseUseOfDecl(Type, NameLoc);
+ }
+ else
return ObjCInstanceMessage;
// We have a class message, and T is the type we're
@@ -1929,7 +2000,12 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
<< FixItHint::CreateInsertion(Loc, "[");
LBracLoc = Loc;
}
-
+ SourceLocation SelLoc;
+ if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
+ SelLoc = SelectorLocs.front();
+ else
+ SelLoc = Loc;
+
if (ReceiverType->isDependentType()) {
// If the receiver type is dependent, we can't type-check anything
// at this point. Build a dependent expression.
@@ -1954,7 +2030,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
assert(Class && "We don't know which class we're messaging?");
// objc++ diagnoses during typename annotation.
if (!getLangOpts().CPlusPlus)
- (void)DiagnoseUseOfDecl(Class, Loc);
+ (void)DiagnoseUseOfDecl(Class, SelLoc);
// Find the method we are messaging.
if (!Method) {
SourceRange TypeRange
@@ -1979,7 +2055,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
if (!Method)
Method = Class->lookupPrivateClassMethod(Sel);
- if (Method && DiagnoseUseOfDecl(Method, Loc))
+ if (Method && DiagnoseUseOfDecl(Method, SelLoc))
return ExprError();
}
@@ -2095,7 +2171,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
bool isImplicit) {
// The location of the receiver.
SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
-
+ SourceRange RecRange =
+ SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
+ SourceLocation SelLoc;
+ if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
+ SelLoc = SelectorLocs.front();
+ else
+ SelLoc = Loc;
+
if (LBracLoc.isInvalid()) {
Diag(Loc, diag::err_missing_open_square_message_send)
<< FixItHint::CreateInsertion(Loc, "[");
@@ -2200,7 +2283,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Method = LookupMethodInQualifiedType(Sel, QClassTy, true);
// warn if instance method found for a Class message.
if (Method) {
- Diag(Loc, diag::warn_instance_method_on_class_found)
+ Diag(SelLoc, diag::warn_instance_method_on_class_found)
<< Method->getSelector() << Sel;
Diag(Method->getLocation(), diag::note_method_declared_at)
<< Method->getDeclName();
@@ -2215,7 +2298,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (!Method)
Method = ClassDecl->lookupPrivateClassMethod(Sel);
}
- if (Method && DiagnoseUseOfDecl(Method, Loc))
+ if (Method && DiagnoseUseOfDecl(Method, SelLoc))
return ExprError();
}
if (!Method) {
@@ -2234,7 +2317,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (const ObjCInterfaceDecl *ID =
dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
if (ID->getSuperClass())
- Diag(Loc, diag::warn_root_inst_method_not_found)
+ Diag(SelLoc, diag::warn_root_inst_method_not_found)
<< Sel << SourceRange(LBracLoc, RBracLoc);
}
}
@@ -2253,7 +2336,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
if (!Method)
Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
- if (Method && DiagnoseUseOfDecl(Method, Loc))
+ if (Method && DiagnoseUseOfDecl(Method, SelLoc))
return ExprError();
} else if (const ObjCObjectPointerType *OCIType
= ReceiverType->getAsObjCInterfacePointerType()) {
@@ -2289,8 +2372,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Method = ClassDecl->lookupPrivateMethod(Sel);
if (!Method && getLangOpts().ObjCAutoRefCount) {
- Diag(Loc, diag::err_arc_may_not_respond)
- << OCIType->getPointeeType() << Sel
+ Diag(SelLoc, diag::err_arc_may_not_respond)
+ << OCIType->getPointeeType() << Sel << RecRange
<< SourceRange(SelectorLocs.front(), SelectorLocs.back());
return ExprError();
}
@@ -2303,12 +2386,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc));
if (Method && !forwardClass)
- Diag(Loc, diag::warn_maynot_respond)
- << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
+ Diag(SelLoc, diag::warn_maynot_respond)
+ << OCIType->getInterfaceDecl()->getIdentifier()
+ << Sel << RecRange;
}
}
}
- if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass))
+ if (Method && DiagnoseUseOfDecl(Method, SelLoc, forwardClass))
return ExprError();
} else {
// Reject other random receiver types (e.g. structs).
@@ -2337,8 +2421,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
diag::err_illegal_message_expr_incomplete_type))
return ExprError();
- SourceLocation SelLoc = SelectorLocs.front();
-
// In ARC, forbid the user from sending messages to
// retain/release/autorelease/dealloc/retainCount explicitly.
if (getLangOpts().ObjCAutoRefCount) {
@@ -2363,8 +2445,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
case OMF_release:
case OMF_autorelease:
case OMF_retainCount:
- Diag(Loc, diag::err_arc_illegal_explicit_message)
- << Sel << SelLoc;
+ Diag(SelLoc, diag::err_arc_illegal_explicit_message)
+ << Sel << RecRange;
break;
case OMF_performSelector: