diff options
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 170 |
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: |