diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp | 378 |
1 files changed, 269 insertions, 109 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index b56159c..4d03b06 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -14,6 +14,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Initialization.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -23,6 +24,7 @@ #include "clang/Lex/Preprocessor.h" using namespace clang; +using namespace sema; ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, Expr **strings, @@ -77,7 +79,14 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, if (!Ty.isNull()) { Ty = Context.getObjCObjectPointerType(Ty); } else if (getLangOptions().NoConstantCFStrings) { - IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString"); + IdentifierInfo *NSIdent=0; + std::string StringClass(getLangOptions().ObjCConstantStringClass); + + if (StringClass.empty()) + NSIdent = &Context.Idents.get("NSConstantString"); + else + NSIdent = &Context.Idents.get(StringClass); + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0], LookupOrdinaryName); if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { @@ -188,11 +197,49 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc); } +/// Try to capture an implicit reference to 'self'. +ObjCMethodDecl *Sema::tryCaptureObjCSelf() { + // Ignore block scopes: we can capture through them. + DeclContext *DC = CurContext; + while (true) { + if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext(); + else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext(); + else break; + } + + // If we're not in an ObjC method, error out. Note that, unlike the + // C++ case, we don't require an instance method --- class methods + // still have a 'self', and we really do still need to capture it! + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC); + if (!method) + return 0; + + ImplicitParamDecl *self = method->getSelfDecl(); + assert(self && "capturing 'self' in non-definition?"); + + // Mark that we're closing on 'this' in all the block scopes, if applicable. + for (unsigned idx = FunctionScopes.size() - 1; + isa<BlockScopeInfo>(FunctionScopes[idx]); + --idx) { + BlockScopeInfo *blockScope = cast<BlockScopeInfo>(FunctionScopes[idx]); + unsigned &captureIndex = blockScope->CaptureMap[self]; + if (captureIndex) break; + + bool nested = isa<BlockScopeInfo>(FunctionScopes[idx-1]); + blockScope->Captures.push_back( + BlockDecl::Capture(self, /*byref*/ false, nested, /*copy*/ 0)); + captureIndex = blockScope->Captures.size(); // +1 + } + + return method; +} + + bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel, ObjCMethodDecl *Method, bool isClassMessage, SourceLocation lbrac, SourceLocation rbrac, - QualType &ReturnType) { + QualType &ReturnType, ExprValueKind &VK) { if (!Method) { // Apply default argument promotion as for (C99 6.5.2.2p6). for (unsigned i = 0; i != NumArgs; i++) { @@ -207,10 +254,12 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Diag(lbrac, DiagID) << Sel << isClassMessage << SourceRange(lbrac, rbrac); ReturnType = Context.getObjCIdType(); + VK = VK_RValue; return false; } ReturnType = Method->getSendResultType(); + VK = Expr::getValueKindForType(Method->getResultType()); unsigned NumNamedArgs = Sel.getNumArgs(); // Method might have more arguments than selector indicates. This is due @@ -219,8 +268,8 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, NumNamedArgs = Method->param_size(); // FIXME. This need be cleaned up. if (NumArgs < NumNamedArgs) { - Diag(lbrac, diag::err_typecheck_call_too_few_args) << 2 - << NumNamedArgs << NumArgs; + Diag(lbrac, diag::err_typecheck_call_too_few_args) + << 2 << NumNamedArgs << NumArgs; return false; } @@ -241,10 +290,9 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, << argExpr->getSourceRange())) return true; - InitializedEntity Entity = InitializedEntity::InitializeParameter(Param); - ExprResult ArgE = PerformCopyInitialization(Entity, - SourceLocation(), - Owned(argExpr->Retain())); + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + Param); + ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr)); if (ArgE.isInvalid()) IsError = true; else @@ -276,6 +324,9 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, } bool Sema::isSelfExpr(Expr *RExpr) { + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RExpr)) + if (ICE->getCastKind() == CK_LValueToRValue) + RExpr = ICE->getSubExpr(); if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr)) if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self")) return true; @@ -335,11 +386,19 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, ExprResult Sema:: HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Expr *BaseExpr, DeclarationName MemberName, - SourceLocation MemberLoc) { + SourceLocation MemberLoc, + SourceLocation SuperLoc, QualType SuperType, + bool Super) { const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); ObjCInterfaceDecl *IFace = IFaceT->getDecl(); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + if (IFace->isForwardDecl()) { + Diag(MemberLoc, diag::err_property_not_found_forward_class) + << MemberName << QualType(OPT, 0); + Diag(IFace->getLocation(), diag::note_forward_class); + return ExprError(); + } // Search for a declared property first. if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. @@ -349,9 +408,17 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) - ResTy = Getter->getSendResultType(); - return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, - MemberLoc, BaseExpr)); + ResTy = Getter->getResultType(); + + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, BaseExpr)); } // Check protocols on qualified interfaces. for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), @@ -360,9 +427,18 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); - - return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), - MemberLoc, BaseExpr)); + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), + VK_LValue, + OK_ObjCProperty, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), + VK_LValue, + OK_ObjCProperty, + MemberLoc, + BaseExpr)); } // If that failed, look for an "implicit" property by seeing if the nullary // selector is implemented. @@ -375,7 +451,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // If this reference is in an @implementation, check for 'private' methods. if (!Getter) - Getter = IFace->lookupPrivateInstanceMethod(Sel); + Getter = IFace->lookupPrivateMethod(Sel); // Look through local category implementations associated with the class. if (!Getter) @@ -394,7 +470,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. - Setter = IFace->lookupPrivateInstanceMethod(SetterSel); + Setter = IFace->lookupPrivateMethod(SetterSel); } // Look through local category implementations associated with the class. if (!Setter) @@ -403,11 +479,31 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); - if (Getter) { + if (Getter || Setter) { QualType PType; - PType = Getter->getSendResultType(); - return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType, - Setter, MemberLoc, BaseExpr)); + if (Getter) + PType = Getter->getSendResultType(); + else { + ParmVarDecl *ArgDecl = *Setter->param_begin(); + PType = ArgDecl->getType(); + } + + ExprValueKind VK = VK_LValue; + ExprObjectKind OK = OK_ObjCProperty; + if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() && + PType->isVoidType()) + VK = VK_RValue, OK = OK_Ordinary; + + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + PType, VK, OK, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + PType, VK, OK, + MemberLoc, BaseExpr)); + } // Attempt to correct for typos in property names. @@ -421,14 +517,31 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>(); Diag(Property->getLocation(), diag::note_previous_decl) << Property->getDeclName(); - return HandleExprPropertyRefExpr(OPT, BaseExpr, TypoResult, MemberLoc); + return HandleExprPropertyRefExpr(OPT, BaseExpr, TypoResult, MemberLoc, + SuperLoc, SuperType, Super); + } + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *Ivar = + IFace->lookupInstanceVariable(Member, ClassDeclared)) { + QualType T = Ivar->getType(); + if (const ObjCObjectPointerType * OBJPT = + T->getAsObjCInterfacePointerType()) { + const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); + if (ObjCInterfaceDecl *IFace = IFaceT->getDecl()) + if (IFace->isForwardDecl()) { + Diag(MemberLoc, diag::err_property_not_as_forward_class) + << MemberName << IFace; + Diag(IFace->getLocation(), diag::note_forward_class); + return ExprError(); + } + } } Diag(MemberLoc, diag::err_property_not_found) << MemberName << QualType(OPT, 0); - if (Setter && !Getter) + if (Setter) Diag(Setter->getLocation(), diag::note_getter_unavailable) - << MemberName << BaseExpr->getSourceRange(); + << MemberName << BaseExpr->getSourceRange(); return ExprError(); } @@ -446,23 +559,24 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, if (IFace == 0) { // If the "receiver" is 'super' in a method, handle it as an expression-like // property reference. - if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) - if (receiverNamePtr->isStr("super")) { + if (receiverNamePtr->isStr("super")) { + if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf()) { if (CurMethod->isInstanceMethod()) { QualType T = Context.getObjCInterfaceType(CurMethod->getClassInterface()); T = Context.getObjCObjectPointerType(T); - Expr *SuperExpr = new (Context) ObjCSuperExpr(receiverNameLoc, T); return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), - SuperExpr, &propertyName, - propertyNameLoc); + /*BaseExpr*/0, &propertyName, + propertyNameLoc, + receiverNameLoc, T, true); } // Otherwise, if this is a class method, try dispatching to our // superclass. IFace = CurMethod->getClassInterface()->getSuperClass(); } + } if (IFace == 0) { Diag(receiverNameLoc, diag::err_expected_ident_or_lparen); @@ -512,16 +626,25 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, if (Getter || Setter) { QualType PType; - if (Getter) + ExprValueKind VK = VK_LValue; + if (Getter) { PType = Getter->getSendResultType(); - else { + if (!getLangOptions().CPlusPlus && + !PType.hasQualifiers() && PType->isVoidType()) + VK = VK_RValue; + } else { for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(), E = Setter->param_end(); PI != E; ++PI) PType = (*PI)->getType(); + VK = VK_LValue; } - return Owned(new (Context) ObjCImplicitSetterGetterRefExpr( - Getter, PType, Setter, - propertyNameLoc, IFace, receiverNameLoc)); + + ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); + + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + PType, VK, OK, + propertyNameLoc, + receiverNameLoc, IFace)); } return ExprError(Diag(propertyNameLoc, diag::err_property_not_found) << &propertyName << Context.getObjCInterfaceType(IFace)); @@ -536,9 +659,10 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, ReceiverType = ParsedType(); // If the identifier is "super" and there is no trailing dot, we're - // messaging super. - if (IsSuper && !HasTrailingDot && S->isInObjcMethodScope()) - return ObjCSuperMessage; + // messaging super. If the identifier is "super" and there is a + // trailing dot, it's an instance message. + if (IsSuper && S->isInObjcMethodScope()) + return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage; LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); LookupName(Result, S); @@ -547,14 +671,15 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, case LookupResult::NotFound: // Normal name lookup didn't find anything. If we're in an // Objective-C method, look for ivars. If we find one, we're done! - // FIXME: This is a hack. Ivar lookup should be part of normal lookup. + // FIXME: This is a hack. Ivar lookup should be part of normal + // lookup. if (ObjCMethodDecl *Method = getCurMethodDecl()) { ObjCInterfaceDecl *ClassDeclared; if (Method->getClassInterface()->lookupInstanceVariable(Name, ClassDeclared)) return ObjCInstanceMessage; } - + // Break out; we'll perform typo correction below. break; @@ -566,6 +691,10 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, return ObjCInstanceMessage; case LookupResult::Found: { + // If the identifier is a class or not, and there is a trailing dot, + // it's an instance message. + if (HasTrailingDot) + return ObjCInstanceMessage; // We found something. If it's a type, then we have a class // message. Otherwise, it's an instance message. NamedDecl *ND = Result.getFoundDecl(); @@ -616,7 +745,6 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, Diag(NameLoc, diag::err_unknown_receiver_suggest) << Name << Corrected << FixItHint::CreateReplacement(SourceRange(NameLoc), "super"); - Name = Corrected.getAsIdentifierInfo(); return ObjCSuperMessage; } } @@ -626,14 +754,14 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, } ExprResult Sema::ActOnSuperMessage(Scope *S, - SourceLocation SuperLoc, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args) { + SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { // Determine whether we are inside a method or not. - ObjCMethodDecl *Method = getCurMethodDecl(); + ObjCMethodDecl *Method = tryCaptureObjCSelf(); if (!Method) { Diag(SuperLoc, diag::err_invalid_receiver_to_message_super); return ExprError(); @@ -649,7 +777,8 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, ObjCInterfaceDecl *Super = Class->getSuperClass(); if (!Super) { // The current class does not have a superclass. - Diag(SuperLoc, diag::error_no_super_class) << Class->getIdentifier(); + Diag(SuperLoc, diag::error_root_class_cannot_use_super) + << Class->getIdentifier(); return ExprError(); } @@ -661,16 +790,16 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, QualType SuperTy = Context.getObjCInterfaceType(Super); SuperTy = Context.getObjCObjectPointerType(SuperTy); return BuildInstanceMessage(0, SuperTy, SuperLoc, - Sel, /*Method=*/0, LBracLoc, RBracLoc, - move(Args)); + Sel, /*Method=*/0, + LBracLoc, SelectorLoc, RBracLoc, move(Args)); } // Since we are in a class method, this is a class message to // the superclass. return BuildClassMessage(/*ReceiverTypeInfo=*/0, Context.getObjCInterfaceType(Super), - SuperLoc, Sel, /*Method=*/0, LBracLoc, RBracLoc, - move(Args)); + SuperLoc, Sel, /*Method=*/0, + LBracLoc, SelectorLoc, RBracLoc, move(Args)); } /// \brief Build an Objective-C class message expression. @@ -702,27 +831,34 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, /// /// \param Args The message arguments. ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, - QualType ReceiverType, - SourceLocation SuperLoc, - Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - SourceLocation RBracLoc, - MultiExprArg ArgsIn) { + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg ArgsIn) { + SourceLocation Loc = SuperLoc.isValid()? SuperLoc + : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin(); + if (LBracLoc.isInvalid()) { + Diag(Loc, diag::err_missing_open_square_message_send) + << FixItHint::CreateInsertion(Loc, "["); + LBracLoc = Loc; + } + if (ReceiverType->isDependentType()) { // If the receiver type is dependent, we can't type-check anything // at this point. Build a dependent expression. unsigned NumArgs = ArgsIn.size(); Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); assert(SuperLoc.isInvalid() && "Message to super with dependent type"); - return Owned(ObjCMessageExpr::Create(Context, ReceiverType, LBracLoc, - ReceiverTypeInfo, Sel, /*Method=*/0, + return Owned(ObjCMessageExpr::Create(Context, ReceiverType, + VK_RValue, LBracLoc, ReceiverTypeInfo, + Sel, SelectorLoc, /*Method=*/0, Args, NumArgs, RBracLoc)); } - SourceLocation Loc = SuperLoc.isValid()? SuperLoc - : ReceiverTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(); - // Find the class to which we are sending this message. ObjCInterfaceDecl *Class = 0; const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>(); @@ -757,23 +893,30 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, // Check the argument types and determine the result type. QualType ReturnType; + ExprValueKind VK = VK_RValue; + unsigned NumArgs = ArgsIn.size(); Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true, - LBracLoc, RBracLoc, ReturnType)) + LBracLoc, RBracLoc, ReturnType, VK)) + return ExprError(); + + if (Method && !Method->getResultType()->isVoidType() && + RequireCompleteType(LBracLoc, Method->getResultType(), + diag::err_illegal_message_expr_incomplete_type)) return ExprError(); // Construct the appropriate ObjCMessageExpr. Expr *Result; if (SuperLoc.isValid()) - Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/false, - ReceiverType, Sel, Method, Args, - NumArgs, RBracLoc); + ReceiverType, Sel, SelectorLoc, + Method, Args, NumArgs, RBracLoc); else - Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, - ReceiverTypeInfo, Sel, Method, Args, - NumArgs, RBracLoc); + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + ReceiverTypeInfo, Sel, SelectorLoc, + Method, Args, NumArgs, RBracLoc); return MaybeBindToTemporary(Result); } @@ -781,12 +924,12 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). ExprResult Sema::ActOnClassMessage(Scope *S, - ParsedType Receiver, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args) { + ParsedType Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { TypeSourceInfo *ReceiverTypeInfo; QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo); if (ReceiverType.isNull()) @@ -798,7 +941,7 @@ ExprResult Sema::ActOnClassMessage(Scope *S, return BuildClassMessage(ReceiverTypeInfo, ReceiverType, /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, - LBracLoc, RBracLoc, move(Args)); + LBracLoc, SelectorLoc, RBracLoc, move(Args)); } /// \brief Build an Objective-C instance message expression. @@ -830,13 +973,23 @@ ExprResult Sema::ActOnClassMessage(Scope *S, /// /// \param Args The message arguments. ExprResult Sema::BuildInstanceMessage(Expr *Receiver, - QualType ReceiverType, - SourceLocation SuperLoc, - Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - SourceLocation RBracLoc, - MultiExprArg ArgsIn) { + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg ArgsIn) { + // The location of the receiver. + SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); + + if (LBracLoc.isInvalid()) { + Diag(Loc, diag::err_missing_open_square_message_send) + << FixItHint::CreateInsertion(Loc, "["); + LBracLoc = Loc; + } + // If we have a receiver expression, perform appropriate promotions // and determine receiver type. if (Receiver) { @@ -847,9 +1000,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); assert(SuperLoc.isInvalid() && "Message to super with dependent type"); return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy, - LBracLoc, Receiver, Sel, - /*Method=*/0, Args, NumArgs, - RBracLoc)); + VK_RValue, LBracLoc, Receiver, Sel, + SelectorLoc, /*Method=*/0, + Args, NumArgs, RBracLoc)); } // If necessary, apply function/array conversion to the receiver. @@ -858,9 +1011,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, ReceiverType = Receiver->getType(); } - // The location of the receiver. - SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); - if (!Method) { // Handle messages to id. bool receiverIsId = ReceiverType->isObjCIdType(); @@ -946,6 +1096,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, break; } } + bool forwardClass = false; if (!Method) { // If we have implementations in scope, check "private" methods. Method = LookupPrivateInstanceMethod(Sel, ClassDecl); @@ -956,14 +1107,15 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // compatibility. FIXME: should we deviate?? if (OCIType->qual_empty()) { Method = LookupInstanceMethodInGlobalPool(Sel, - SourceRange(LBracLoc, RBracLoc)); - if (Method && !OCIType->getInterfaceDecl()->isForwardDecl()) + SourceRange(LBracLoc, RBracLoc)); + forwardClass = OCIType->getInterfaceDecl()->isForwardDecl(); + if (Method && !forwardClass) Diag(Loc, diag::warn_maynot_respond) << OCIType->getInterfaceDecl()->getIdentifier() << Sel; } } } - if (Method && DiagnoseUseOfDecl(Method, Loc)) + if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass)) return ExprError(); } else if (!Context.getObjCIdType().isNull() && (ReceiverType->isPointerType() || @@ -975,9 +1127,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (ReceiverType->isPointerType()) ImpCastExprToType(Receiver, Context.getObjCIdType(), CK_BitCast); - else + else { + // TODO: specialized warning on null receivers? + bool IsNull = Receiver->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); ImpCastExprToType(Receiver, Context.getObjCIdType(), - CK_IntegralToPointer); + IsNull ? CK_NullToPointer : CK_IntegralToPointer); + } ReceiverType = Receiver->getType(); } else if (getLangOptions().CPlusPlus && @@ -991,7 +1147,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, SuperLoc, Sel, Method, - LBracLoc, + LBracLoc, + SelectorLoc, RBracLoc, move(ArgsIn)); } else { @@ -1007,26 +1164,29 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, unsigned NumArgs = ArgsIn.size(); Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); QualType ReturnType; - if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, false, - LBracLoc, RBracLoc, ReturnType)) + ExprValueKind VK = VK_RValue; + bool ClassMessage = (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()); + if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, ClassMessage, + LBracLoc, RBracLoc, ReturnType, VK)) return ExprError(); - if (!ReturnType->isVoidType()) { - if (RequireCompleteType(LBracLoc, ReturnType, - diag::err_illegal_message_expr_incomplete_type)) - return ExprError(); - } + if (Method && !Method->getResultType()->isVoidType() && + RequireCompleteType(LBracLoc, Method->getResultType(), + diag::err_illegal_message_expr_incomplete_type)) + return ExprError(); // Construct the appropriate ObjCMessageExpr instance. Expr *Result; if (SuperLoc.isValid()) - Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/true, - ReceiverType, Sel, Method, + ReceiverType, Sel, SelectorLoc, Method, Args, NumArgs, RBracLoc); else - Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, Receiver, - Sel, Method, Args, NumArgs, RBracLoc); + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + Receiver, Sel, SelectorLoc, Method, + Args, NumArgs, RBracLoc); return MaybeBindToTemporary(Result); } @@ -1045,6 +1205,6 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S, return BuildInstanceMessage(Receiver, Receiver->getType(), /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, - LBracLoc, RBracLoc, move(Args)); + LBracLoc, SelectorLoc, RBracLoc, move(Args)); } |