diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp | 990 |
1 files changed, 688 insertions, 302 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index cc8eace..5002332 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -67,10 +67,14 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // Create the aggregate string with the appropriate content and location // information. - S = StringLiteral::Create(Context, StrBuf, - StringLiteral::Ascii, /*Pascal=*/false, - Context.getPointerType(Context.CharTy), - &StrLocs[0], StrLocs.size()); + const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType()); + assert(CAT && "String literal not of constant array type!"); + QualType StrTy = Context.getConstantArrayType( + CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1), + CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers()); + S = StringLiteral::Create(Context, StrBuf, StringLiteral::Ascii, + /*Pascal=*/false, StrTy, &StrLocs[0], + StrLocs.size()); } return BuildObjCStringLiteral(AtLocs[0], S); @@ -89,7 +93,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ if (!Ty.isNull()) { Ty = Context.getObjCObjectPointerType(Ty); } else if (getLangOpts().NoConstantCFStrings) { - IdentifierInfo *NSIdent=0; + IdentifierInfo *NSIdent=nullptr; std::string StringClass(getLangOpts().ObjCConstantStringClass); if (StringClass.empty()) @@ -129,7 +133,7 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ ObjCInterfaceDecl::Create (Context, Context.getTranslationUnitDecl(), SourceLocation(), NSIdent, - 0, SourceLocation()); + nullptr, SourceLocation()); Ty = Context.getObjCInterfaceType(NSStringIDecl); Context.setObjCNSStringType(Ty); } @@ -152,7 +156,7 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc, } // Make sure the return type is reasonable. - QualType ReturnType = Method->getResultType(); + QualType ReturnType = Method->getReturnType(); if (!ReturnType->isObjCObjectPointerType()) { S.Diag(Loc, diag::err_objc_literal_method_sig) << Sel; @@ -178,7 +182,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, S.Diag(Loc, diag::err_invalid_nsnumber_type) << NumberType << R; } - return 0; + return nullptr; } // If we already looked up this method, we're done. @@ -204,15 +208,15 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, S.NSNumberDecl = ObjCInterfaceDecl::Create(CX, CX.getTranslationUnitDecl(), SourceLocation(), NSNumberId, - 0, SourceLocation()); + nullptr, SourceLocation()); } else { // Otherwise, require a declaration of NSNumber. S.Diag(Loc, diag::err_undeclared_nsnumber); - return 0; + return nullptr; } } else if (!S.NSNumberDecl->hasDefinition()) { S.Diag(Loc, diag::err_undeclared_nsnumber); - return 0; + return nullptr; } // generate the pointer to NSNumber type. @@ -224,26 +228,25 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel); if (!Method && S.getLangOpts().DebuggerObjCLiteral) { // create a stub definition this NSNumber factory method. - TypeSourceInfo *ResultTInfo = 0; - Method = ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel, - S.NSNumberPointer, ResultTInfo, - S.NSNumberDecl, - /*isInstance=*/false, /*isVariadic=*/false, - /*isPropertyAccessor=*/false, - /*isImplicitlyDeclared=*/true, - /*isDefined=*/false, - ObjCMethodDecl::Required, - /*HasRelatedResultType=*/false); + TypeSourceInfo *ReturnTInfo = nullptr; + Method = + ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel, + S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl, + /*isInstance=*/false, /*isVariadic=*/false, + /*isPropertyAccessor=*/false, + /*isImplicitlyDeclared=*/true, + /*isDefined=*/false, ObjCMethodDecl::Required, + /*HasRelatedResultType=*/false); ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method, SourceLocation(), SourceLocation(), &CX.Idents.get("value"), - NumberType, /*TInfo=*/0, SC_None, - 0); + NumberType, /*TInfo=*/nullptr, + SC_None, nullptr); Method->setMethodParams(S.Context, value, None); } if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method)) - return 0; + return nullptr; // Note: if the parameter type is out-of-line, we'll catch it later in the // implicit conversion. @@ -288,12 +291,12 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { return ExprError(); // Convert the number to the type that the parameter expects. - ParmVarDecl *ParamDecl = Method->param_begin()[0]; + ParmVarDecl *ParamDecl = Method->parameters()[0]; InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, ParamDecl); ExprResult ConvertedNumber = PerformCopyInitialization(Entity, SourceLocation(), - Owned(Number)); + Number); if (ConvertedNumber.isInvalid()) return ExprError(); Number = ConvertedNumber.get(); @@ -441,10 +444,10 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { if (ValueExpr->isTypeDependent()) { ObjCBoxedExpr *BoxedExpr = - new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, NULL, SR); - return Owned(BoxedExpr); + new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR); + return BoxedExpr; } - ObjCMethodDecl *BoxingMethod = NULL; + ObjCMethodDecl *BoxingMethod = nullptr; QualType BoxedType; // Convert the expression to an RValue, so we can check for pointer types... ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr); @@ -470,7 +473,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { NSStringDecl = ObjCInterfaceDecl::Create(Context, TU, SourceLocation(), NSStringId, - 0, SourceLocation()); + nullptr, SourceLocation()); } else { Diag(SR.getBegin(), diag::err_undeclared_nsstring); return ExprError(); @@ -492,25 +495,23 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String); if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) { // Debugger needs to work even if NSString hasn't been defined. - TypeSourceInfo *ResultTInfo = 0; - ObjCMethodDecl *M = - ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(), - stringWithUTF8String, NSStringPointer, - ResultTInfo, NSStringDecl, - /*isInstance=*/false, /*isVariadic=*/false, - /*isPropertyAccessor=*/false, - /*isImplicitlyDeclared=*/true, - /*isDefined=*/false, - ObjCMethodDecl::Required, - /*HasRelatedResultType=*/false); + TypeSourceInfo *ReturnTInfo = nullptr; + ObjCMethodDecl *M = ObjCMethodDecl::Create( + Context, SourceLocation(), SourceLocation(), stringWithUTF8String, + NSStringPointer, ReturnTInfo, NSStringDecl, + /*isInstance=*/false, /*isVariadic=*/false, + /*isPropertyAccessor=*/false, + /*isImplicitlyDeclared=*/true, + /*isDefined=*/false, ObjCMethodDecl::Required, + /*HasRelatedResultType=*/false); QualType ConstCharType = Context.CharTy.withConst(); ParmVarDecl *value = ParmVarDecl::Create(Context, M, SourceLocation(), SourceLocation(), &Context.Idents.get("value"), Context.getPointerType(ConstCharType), - /*TInfo=*/0, - SC_None, 0); + /*TInfo=*/nullptr, + SC_None, nullptr); M->setMethodParams(Context, value, None); BoxingMethod = M; } @@ -554,7 +555,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { break; } } - + CheckForIntOverflow(ValueExpr); // FIXME: Do I need to do anything special with BoolTy expressions? // Look for the appropriate method within NSNumber. @@ -580,12 +581,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { } // Convert the expression to the type that the parameter requires. - ParmVarDecl *ParamDecl = BoxingMethod->param_begin()[0]; + ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0]; InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, ParamDecl); ExprResult ConvertedValueExpr = PerformCopyInitialization(Entity, SourceLocation(), - Owned(ValueExpr)); + ValueExpr); if (ConvertedValueExpr.isInvalid()) return ExprError(); ValueExpr = ConvertedValueExpr.get(); @@ -623,13 +624,9 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, BaseExpr = Result.get(); // Build the pseudo-object expression. - return Owned(ObjCSubscriptRefExpr::Create(Context, - BaseExpr, - IndexExpr, - Context.PseudoObjectTy, - getterMethod, - setterMethod, RB)); - + return ObjCSubscriptRefExpr::Create(Context, BaseExpr, IndexExpr, + Context.PseudoObjectTy, getterMethod, + setterMethod, RB); } ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { @@ -645,7 +642,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { Context.getTranslationUnitDecl(), SourceLocation(), NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), - 0, SourceLocation()); + nullptr, SourceLocation()); if (!NSArrayDecl) { Diag(SR.getBegin(), diag::err_undeclared_nsarray); @@ -660,31 +657,30 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount); ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel); if (!Method && getLangOpts().DebuggerObjCLiteral) { - TypeSourceInfo *ResultTInfo = 0; - Method = ObjCMethodDecl::Create(Context, - SourceLocation(), SourceLocation(), Sel, - IdT, - ResultTInfo, - Context.getTranslationUnitDecl(), - false /*Instance*/, false/*isVariadic*/, - /*isPropertyAccessor=*/false, - /*isImplicitlyDeclared=*/true, /*isDefined=*/false, - ObjCMethodDecl::Required, - false); + TypeSourceInfo *ReturnTInfo = nullptr; + Method = ObjCMethodDecl::Create( + Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo, + Context.getTranslationUnitDecl(), false /*Instance*/, + false /*isVariadic*/, + /*isPropertyAccessor=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, false); SmallVector<ParmVarDecl *, 2> Params; ParmVarDecl *objects = ParmVarDecl::Create(Context, Method, SourceLocation(), SourceLocation(), &Context.Idents.get("objects"), Context.getPointerType(IdT), - /*TInfo=*/0, SC_None, 0); + /*TInfo=*/nullptr, + SC_None, nullptr); Params.push_back(objects); ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, SourceLocation(), SourceLocation(), &Context.Idents.get("cnt"), Context.UnsignedLongTy, - /*TInfo=*/0, SC_None, 0); + /*TInfo=*/nullptr, SC_None, + nullptr); Params.push_back(cnt); Method->setMethodParams(Context, Params, None); } @@ -693,13 +689,13 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { return ExprError(); // Dig out the type that all elements should be converted to. - QualType T = Method->param_begin()[0]->getType(); + QualType T = Method->parameters()[0]->getType(); const PointerType *PtrT = T->getAs<PointerType>(); if (!PtrT || !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) { Diag(SR.getBegin(), diag::err_objc_literal_method_sig) << Sel; - Diag(Method->param_begin()[0]->getLocation(), + Diag(Method->parameters()[0]->getLocation(), diag::note_objc_literal_method_param) << 0 << T << Context.getPointerType(IdT.withConst()); @@ -707,13 +703,13 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { } // Check that the 'count' parameter is integral. - if (!Method->param_begin()[1]->getType()->isIntegerType()) { + if (!Method->parameters()[1]->getType()->isIntegerType()) { Diag(SR.getBegin(), diag::err_objc_literal_method_sig) << Sel; - Diag(Method->param_begin()[1]->getLocation(), + Diag(Method->parameters()[1]->getLocation(), diag::note_objc_literal_method_param) << 1 - << Method->param_begin()[1]->getType() + << Method->parameters()[1]->getType() << "integral"; return ExprError(); } @@ -722,7 +718,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { ArrayWithObjectsMethod = Method; } - QualType ObjectsType = ArrayWithObjectsMethod->param_begin()[0]->getType(); + QualType ObjectsType = ArrayWithObjectsMethod->parameters()[0]->getType(); QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType(); // Check that each of the elements provided is valid in a collection literal, @@ -761,7 +757,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, Context.getTranslationUnitDecl(), SourceLocation(), NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), - 0, SourceLocation()); + nullptr, SourceLocation()); if (!NSDictionaryDecl) { Diag(SR.getBegin(), diag::err_undeclared_nsdictionary); @@ -780,7 +776,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, Method = ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(), Sel, IdT, - 0 /*TypeSourceInfo */, + nullptr /*TypeSourceInfo */, Context.getTranslationUnitDecl(), false /*Instance*/, false/*isVariadic*/, /*isPropertyAccessor=*/false, @@ -793,21 +789,24 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, SourceLocation(), &Context.Idents.get("objects"), Context.getPointerType(IdT), - /*TInfo=*/0, SC_None, 0); + /*TInfo=*/nullptr, SC_None, + nullptr); Params.push_back(objects); ParmVarDecl *keys = ParmVarDecl::Create(Context, Method, SourceLocation(), SourceLocation(), &Context.Idents.get("keys"), Context.getPointerType(IdT), - /*TInfo=*/0, SC_None, 0); + /*TInfo=*/nullptr, SC_None, + nullptr); Params.push_back(keys); ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, SourceLocation(), SourceLocation(), &Context.Idents.get("cnt"), Context.UnsignedLongTy, - /*TInfo=*/0, SC_None, 0); + /*TInfo=*/nullptr, SC_None, + nullptr); Params.push_back(cnt); Method->setMethodParams(Context, Params, None); } @@ -817,13 +816,13 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, return ExprError(); // Dig out the type that all values should be converted to. - QualType ValueT = Method->param_begin()[0]->getType(); + QualType ValueT = Method->parameters()[0]->getType(); const PointerType *PtrValue = ValueT->getAs<PointerType>(); if (!PtrValue || !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) { Diag(SR.getBegin(), diag::err_objc_literal_method_sig) << Sel; - Diag(Method->param_begin()[0]->getLocation(), + Diag(Method->parameters()[0]->getLocation(), diag::note_objc_literal_method_param) << 0 << ValueT << Context.getPointerType(IdT.withConst()); @@ -831,7 +830,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, } // Dig out the type that all keys should be converted to. - QualType KeyT = Method->param_begin()[1]->getType(); + QualType KeyT = Method->parameters()[1]->getType(); const PointerType *PtrKey = KeyT->getAs<PointerType>(); if (!PtrKey || !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), @@ -857,7 +856,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, if (err) { Diag(SR.getBegin(), diag::err_objc_literal_method_sig) << Sel; - Diag(Method->param_begin()[1]->getLocation(), + Diag(Method->parameters()[1]->getLocation(), diag::note_objc_literal_method_param) << 1 << KeyT << Context.getPointerType(IdT.withConst()); @@ -866,11 +865,11 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, } // Check that the 'count' parameter is integral. - QualType CountType = Method->param_begin()[2]->getType(); + QualType CountType = Method->parameters()[2]->getType(); if (!CountType->isIntegerType()) { Diag(SR.getBegin(), diag::err_objc_literal_method_sig) << Sel; - Diag(Method->param_begin()[2]->getLocation(), + Diag(Method->parameters()[2]->getLocation(), diag::note_objc_literal_method_param) << 2 << CountType << "integral"; @@ -881,9 +880,9 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, DictionaryWithObjectsMethod = Method; } - QualType ValuesT = DictionaryWithObjectsMethod->param_begin()[0]->getType(); + QualType ValuesT = DictionaryWithObjectsMethod->parameters()[0]->getType(); QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType(); - QualType KeysT = DictionaryWithObjectsMethod->param_begin()[1]->getType(); + QualType KeysT = DictionaryWithObjectsMethod->parameters()[1]->getType(); QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType(); // Check that each of the keys and values provided is valid in a collection @@ -975,11 +974,68 @@ ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); } +static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S, + SourceLocation AtLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + ObjCMethodDecl *Method, + ObjCMethodList &MethList) { + ObjCMethodList *M = &MethList; + bool Warned = false; + for (M = M->getNext(); M; M=M->getNext()) { + ObjCMethodDecl *MatchingMethodDecl = M->Method; + if (MatchingMethodDecl == Method || + isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) || + MatchingMethodDecl->getSelector() != Method->getSelector()) + continue; + if (!S.MatchTwoMethodDeclarations(Method, + MatchingMethodDecl, Sema::MMS_loose)) { + if (!Warned) { + Warned = true; + S.Diag(AtLoc, diag::warning_multiple_selectors) + << Method->getSelector() << FixItHint::CreateInsertion(LParenLoc, "(") + << FixItHint::CreateInsertion(RParenLoc, ")"); + S.Diag(Method->getLocation(), diag::note_method_declared_at) + << Method->getDeclName(); + } + S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at) + << MatchingMethodDecl->getDeclName(); + } + } + return Warned; +} + +static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc, + ObjCMethodDecl *Method, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + bool WarnMultipleSelectors) { + if (!WarnMultipleSelectors || + S.Diags.isIgnored(diag::warning_multiple_selectors, SourceLocation())) + return; + bool Warned = false; + for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(), + e = S.MethodPool.end(); b != e; b++) { + // first, instance methods + ObjCMethodList &InstMethList = b->second.first; + if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc, + Method, InstMethList)) + Warned = true; + + // second, class methods + ObjCMethodList &ClsMethList = b->second.second; + if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc, + Method, ClsMethList) || Warned) + return; + } +} + ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc, SourceLocation SelLoc, SourceLocation LParenLoc, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + bool WarnMultipleSelectors) { ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LParenLoc, RParenLoc), false, false); if (!Method) @@ -996,10 +1052,13 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, } else Diag(SelLoc, diag::warn_undeclared_selector) << Sel; - } + } else + DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc, + WarnMultipleSelectors); - if (!Method || - Method->getImplementationControl() != ObjCMethodDecl::Optional) { + if (Method && + Method->getImplementationControl() != ObjCMethodDecl::Optional && + !getSourceManager().isInSystemHeader(Method->getLocation())) { llvm::DenseMap<Selector, SourceLocation>::iterator Pos = ReferencedSelectors.find(Sel); if (Pos == ReferencedSelectors.end()) @@ -1063,7 +1122,7 @@ ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) { // still have a 'self', and we really do still need to capture it! ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC); if (!method) - return 0; + return nullptr; tryCaptureVariable(method->getSelfDecl(), Loc); @@ -1120,7 +1179,8 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType, static const ObjCMethodDecl * findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD, QualType instancetype) { - if (MD->getResultType() == instancetype) return MD; + if (MD->getReturnType() == instancetype) + return MD; // For these purposes, a method in an @implementation overrides a // declaration in the @interface. @@ -1147,7 +1207,7 @@ findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD, return result; } - return 0; + return nullptr; } void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) { @@ -1155,7 +1215,7 @@ void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) { // 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())) + Context.hasSameUnqualifiedType(destType, MD->getReturnType())) return; // Look for a method overridden by this method which explicitly uses @@ -1164,7 +1224,7 @@ void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) { findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) { SourceLocation loc; SourceRange range; - if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) { + if (TypeSourceInfo *TSI = overridden->getReturnTypeSourceInfo()) { range = TSI->getTypeLoc().getSourceRange(); loc = range.getBegin(); } @@ -1195,13 +1255,12 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) { if (!Method->hasRelatedResultType()) return; - - if (Context.hasSameUnqualifiedType(Method->getResultType() - .getNonReferenceType(), - MsgSend->getType())) + + if (Context.hasSameUnqualifiedType( + Method->getReturnType().getNonReferenceType(), MsgSend->getType())) return; - - if (!Context.hasSameUnqualifiedType(Method->getResultType(), + + if (!Context.hasSameUnqualifiedType(Method->getReturnType(), Context.getObjCInstanceType())) return; @@ -1239,7 +1298,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, } if (result.isInvalid()) return true; - Args[i] = result.take(); + Args[i] = result.get(); } unsigned DiagID; @@ -1287,7 +1346,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage, isSuperMessage); - VK = Expr::getValueKindForType(Method->getResultType()); + VK = Expr::getValueKindForType(Method->getReturnType()); unsigned NumNamedArgs = Sel.getNumArgs(); // Method might have more arguments than selector indicates. This is due @@ -1309,7 +1368,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, Expr *argExpr = Args[i]; - ParmVarDecl *param = Method->param_begin()[i]; + ParmVarDecl *param = Method->parameters()[i]; assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); // Strip the unbridged-cast placeholder expression off unless it's @@ -1326,7 +1385,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, if (argE.isInvalid()) { IsError = true; } else { - Args[i] = argE.take(); + Args[i] = argE.get(); // Update the parameter type in-place. param->setType(paramType); @@ -1341,11 +1400,11 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, param); - ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, Owned(argExpr)); + ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, argExpr); if (ArgE.isInvalid()) IsError = true; else - Args[i] = ArgE.takeAs<Expr>(); + Args[i] = ArgE.getAs<Expr>(); } // Promote additional arguments to variadic methods. @@ -1355,9 +1414,9 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, continue; ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, - 0); + nullptr); IsError |= Arg.isInvalid(); - Args[i] = Arg.take(); + Args[i] = Arg.get(); } } else { // Check for extra arguments to non-variadic methods. @@ -1380,10 +1439,14 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, return IsError; } -bool Sema::isSelfExpr(Expr *receiver) { +bool Sema::isSelfExpr(Expr *RExpr) { // 'self' is objc 'self' in an objc method only. - ObjCMethodDecl *method = - dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor()); + ObjCMethodDecl *Method = + dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor()); + return isSelfExpr(RExpr, Method); +} + +bool Sema::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) { if (!method) return false; receiver = receiver->IgnoreParenLValueCasts(); @@ -1409,12 +1472,11 @@ ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, } // Check qualifiers. - for (ObjCObjectType::qual_iterator - i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i) - if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance)) + for (const auto *I : objType->quals()) + if (ObjCMethodDecl *method = I->lookupMethod(sel, isInstance)) return method; - return 0; + return nullptr; } /// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier @@ -1423,15 +1485,13 @@ ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, const ObjCObjectPointerType *OPT, bool Instance) { - ObjCMethodDecl *MD = 0; - for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), - E = OPT->qual_end(); I != E; ++I) { - ObjCProtocolDecl *PROTO = (*I); + ObjCMethodDecl *MD = nullptr; + for (const auto *PROTO : OPT->quals()) { if ((MD = PROTO->lookupMethod(Sel, Instance))) { return MD; } } - return 0; + return nullptr; } static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) { @@ -1444,15 +1504,15 @@ static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) { Expr *RExpr = Receiver->IgnoreParenImpCasts(); SourceLocation Loc = RExpr->getLocStart(); QualType T = RExpr->getType(); - const ObjCPropertyDecl *PDecl = 0; - const ObjCMethodDecl *GDecl = 0; + const ObjCPropertyDecl *PDecl = nullptr; + const ObjCMethodDecl *GDecl = nullptr; if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) { RExpr = POE->getSyntacticForm(); if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) { if (PRE->isImplicitProperty()) { GDecl = PRE->getImplicitPropertyGetter(); if (GDecl) { - T = GDecl->getResultType(); + T = GDecl->getReturnType(); } } else { @@ -1525,37 +1585,29 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); if (Super) - return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, - VK_LValue, OK_ObjCProperty, - MemberLoc, - SuperLoc, SuperType)); + return new (Context) + ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, + OK_ObjCProperty, MemberLoc, SuperLoc, SuperType); else - return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, - VK_LValue, OK_ObjCProperty, - MemberLoc, BaseExpr)); + return new (Context) + ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, + OK_ObjCProperty, MemberLoc, BaseExpr); } // Check protocols on qualified interfaces. - for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), - E = OPT->qual_end(); I != E; ++I) - if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { + for (const auto *I : OPT->quals()) + if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); if (Super) - return Owned(new (Context) ObjCPropertyRefExpr(PD, - Context.PseudoObjectTy, - VK_LValue, - OK_ObjCProperty, - MemberLoc, - SuperLoc, SuperType)); + return new (Context) ObjCPropertyRefExpr( + PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc, + SuperLoc, SuperType); else - return Owned(new (Context) ObjCPropertyRefExpr(PD, - Context.PseudoObjectTy, - VK_LValue, - OK_ObjCProperty, - MemberLoc, - BaseExpr)); + return new (Context) + ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, + OK_ObjCProperty, MemberLoc, BaseExpr); } // If that failed, look for an "implicit" property by seeing if the nullary // selector is implemented. @@ -1601,24 +1653,21 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (Getter || Setter) { if (Super) - return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - Context.PseudoObjectTy, - VK_LValue, OK_ObjCProperty, - MemberLoc, - SuperLoc, SuperType)); + return new (Context) + ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue, + OK_ObjCProperty, MemberLoc, SuperLoc, SuperType); else - return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - Context.PseudoObjectTy, - VK_LValue, OK_ObjCProperty, - MemberLoc, BaseExpr)); + return new (Context) + ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue, + OK_ObjCProperty, MemberLoc, BaseExpr); } // Attempt to correct for typos in property names. DeclFilterCCC<ObjCPropertyDecl> Validator; if (TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL, - NULL, Validator, IFace, false, OPT)) { + DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, + nullptr, nullptr, Validator, CTK_ErrorRecovery, IFace, false, OPT)) { diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest) << MemberName << QualType(OPT, 0)); DeclarationName TypoResult = Corrected.getCorrection(); @@ -1665,7 +1714,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, receiverNameLoc); bool IsSuper = false; - if (IFace == 0) { + if (!IFace) { // If the "receiver" is 'super' in a method, handle it as an expression-like // property reference. if (receiverNamePtr->isStr("super")) { @@ -1683,9 +1732,9 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, } QualType T = Context.getObjCInterfaceType(Super); T = Context.getObjCObjectPointerType(T); - + return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), - /*BaseExpr*/0, + /*BaseExpr*/nullptr, SourceLocation()/*OpLoc*/, &propertyName, propertyNameLoc, @@ -1697,9 +1746,10 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, IFace = CurMethod->getClassInterface()->getSuperClass(); } } - - if (IFace == 0) { - Diag(receiverNameLoc, diag::err_expected_ident_or_lparen); + + if (!IFace) { + Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier + << tok::l_paren; return ExprError(); } } @@ -1710,10 +1760,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, // If this reference is in an @implementation, check for 'private' methods. if (!Getter) - if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) - if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) - if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) - Getter = ImpDecl->getClassMethod(Sel); + Getter = IFace->lookupPrivateClassMethod(Sel); if (Getter) { // FIXME: refactor/share with ActOnMemberReference(). @@ -1732,10 +1779,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. - if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) - if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) - if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) - Setter = ImpDecl->getClassMethod(SetterSel); + Setter = IFace->lookupPrivateClassMethod(SetterSel); } // Look through local category implementations associated with the class. if (!Setter) @@ -1746,18 +1790,14 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, if (Getter || Setter) { if (IsSuper) - return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - Context.PseudoObjectTy, - VK_LValue, OK_ObjCProperty, - propertyNameLoc, - receiverNameLoc, - Context.getObjCInterfaceType(IFace))); - - return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - Context.PseudoObjectTy, - VK_LValue, OK_ObjCProperty, - propertyNameLoc, - receiverNameLoc, IFace)); + return new (Context) + ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue, + OK_ObjCProperty, propertyNameLoc, receiverNameLoc, + Context.getObjCInterfaceType(IFace)); + + return new (Context) ObjCPropertyRefExpr( + Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, + propertyNameLoc, receiverNameLoc, IFace); } return ExprError(Diag(propertyNameLoc, diag::err_property_not_found) << &propertyName << Context.getObjCInterfaceType(IFace)); @@ -1773,7 +1813,7 @@ class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { WantObjCSuper = Method->getClassInterface()->getSuperClass(); } - virtual bool ValidateCandidate(const TypoCorrection &candidate) { + bool ValidateCandidate(const TypoCorrection &candidate) override { return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() || candidate.isKeyword("super"); } @@ -1855,7 +1895,8 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl()); if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S, - NULL, Validator, NULL, false, NULL, false)) { + nullptr, Validator, CTK_ErrorRecovery, nullptr, false, + nullptr, false)) { if (Corrected.isKeyword()) { // If we've found the keyword "super" (the only keyword that would be // returned by CorrectTypo), this is a send to super. @@ -1918,16 +1959,16 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, // message to the superclass instance. QualType SuperTy = Context.getObjCInterfaceType(Super); SuperTy = Context.getObjCObjectPointerType(SuperTy); - return BuildInstanceMessage(0, SuperTy, SuperLoc, - Sel, /*Method=*/0, + return BuildInstanceMessage(nullptr, SuperTy, SuperLoc, + Sel, /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc, Args); } // Since we are in a class method, this is a class message to // the superclass. - return BuildClassMessage(/*ReceiverTypeInfo=*/0, + return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr, Context.getObjCInterfaceType(Super), - SuperLoc, Sel, /*Method=*/0, + SuperLoc, Sel, /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc, Args); } @@ -1938,7 +1979,7 @@ ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType, Selector Sel, ObjCMethodDecl *Method, MultiExprArg Args) { - TypeSourceInfo *receiverTypeInfo = 0; + TypeSourceInfo *receiverTypeInfo = nullptr; if (!ReceiverType.isNull()) receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType); @@ -1954,7 +1995,7 @@ static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg, bool (*refactor)(const ObjCMessageExpr *, const NSAPI &, edit::Commit &)) { SourceLocation MsgLoc = Msg->getExprLoc(); - if (S.Diags.getDiagnosticLevel(DiagID, MsgLoc) == DiagnosticsEngine::Ignored) + if (S.Diags.isIgnored(DiagID, MsgLoc)) return; SourceManager &SM = S.SourceMgr; @@ -2050,15 +2091,14 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, unsigned NumArgs = ArgsIn.size(); Expr **Args = ArgsIn.data(); assert(SuperLoc.isInvalid() && "Message to super with dependent type"); - return Owned(ObjCMessageExpr::Create(Context, ReceiverType, - VK_RValue, LBracLoc, ReceiverTypeInfo, - Sel, SelectorLocs, /*Method=*/0, - makeArrayRef(Args, NumArgs),RBracLoc, - isImplicit)); + return ObjCMessageExpr::Create( + Context, ReceiverType, VK_RValue, LBracLoc, ReceiverTypeInfo, Sel, + SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs), RBracLoc, + isImplicit); } // Find the class to which we are sending this message. - ObjCInterfaceDecl *Class = 0; + ObjCInterfaceDecl *Class = nullptr; const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>(); if (!ClassType || !(Class = ClassType->getInterface())) { Diag(Loc, diag::err_invalid_receiver_class_message) @@ -2110,8 +2150,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, ReturnType, VK)) return ExprError(); - if (Method && !Method->getResultType()->isVoidType() && - RequireCompleteType(LBracLoc, Method->getResultType(), + if (Method && !Method->getReturnType()->isVoidType() && + RequireCompleteType(LBracLoc, Method->getReturnType(), diag::err_illegal_message_expr_incomplete_type)) return ExprError(); @@ -2154,8 +2194,9 @@ ExprResult Sema::ActOnClassMessage(Scope *S, ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc); return BuildClassMessage(ReceiverTypeInfo, ReceiverType, - /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, - LBracLoc, SelectorLocs, RBracLoc, Args); + /*SuperLoc=*/SourceLocation(), Sel, + /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc, + Args); } ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver, @@ -2234,7 +2275,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, else Result = CheckPlaceholderExpr(Receiver); if (Result.isInvalid()) return ExprError(); - Receiver = Result.take(); + Receiver = Result.get(); } if (Receiver->isTypeDependent()) { @@ -2243,11 +2284,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, unsigned NumArgs = ArgsIn.size(); Expr **Args = ArgsIn.data(); assert(SuperLoc.isInvalid() && "Message to super with dependent type"); - return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy, - VK_RValue, LBracLoc, Receiver, Sel, - SelectorLocs, /*Method=*/0, - makeArrayRef(Args, NumArgs), - RBracLoc, isImplicit)); + return ObjCMessageExpr::Create( + Context, Context.DependentTy, VK_RValue, LBracLoc, Receiver, Sel, + SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs), + RBracLoc, isImplicit); } // If necessary, apply function/array conversion to the receiver. @@ -2255,7 +2295,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver); if (Result.isInvalid()) return ExprError(); - Receiver = Result.take(); + Receiver = Result.get(); ReceiverType = Receiver->getType(); // If the receiver is an ObjC pointer, a block pointer, or an @@ -2274,14 +2314,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, << Receiver->getSourceRange(); if (ReceiverType->isPointerType()) { Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), - CK_CPointerToObjCPointerCast).take(); + CK_CPointerToObjCPointerCast).get(); } else { // TODO: specialized warning on null receivers? bool IsNull = Receiver->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer; Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), - Kind).take(); + Kind).get(); } ReceiverType = Receiver->getType(); } else if (getLangOpts().CPlusPlus) { @@ -2292,7 +2332,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver); if (result.isUsable()) { - Receiver = result.take(); + Receiver = result.get(); ReceiverType = Receiver->getType(); } } @@ -2369,7 +2409,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } } else { - ObjCInterfaceDecl* ClassDecl = 0; + ObjCInterfaceDecl *ClassDecl = nullptr; // We allow sending a message to a qualified ID ("id<foo>"), which is ok as // long as one of the protocols implements the selector (if not, warn). @@ -2389,7 +2429,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // Try to complete the type. Under ARC, this is a hard error from which // we don't try to recover. - const ObjCInterfaceDecl *forwardClass = 0; + const ObjCInterfaceDecl *forwardClass = nullptr; if (RequireCompleteType(Loc, OCIType->getPointeeType(), getLangOpts().ObjCAutoRefCount ? diag::err_arc_receiver_forward_instance @@ -2402,7 +2442,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, forwardClass = OCIType->getInterfaceDecl(); Diag(Receiver ? Receiver->getLocStart() : SuperLoc, diag::note_receiver_is_id); - Method = 0; + Method = nullptr; } else { Method = ClassDecl->lookupInstanceMethod(Sel); } @@ -2447,6 +2487,52 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } + FunctionScopeInfo *DIFunctionScopeInfo = + (Method && Method->getMethodFamily() == OMF_init) + ? getEnclosingFunction() : nullptr; + + if (DIFunctionScopeInfo && + DIFunctionScopeInfo->ObjCIsDesignatedInit && + (SuperLoc.isValid() || isSelfExpr(Receiver))) { + bool isDesignatedInitChain = false; + if (SuperLoc.isValid()) { + if (const ObjCObjectPointerType * + OCIType = ReceiverType->getAsObjCInterfacePointerType()) { + if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) { + // Either we know this is a designated initializer or we + // conservatively assume it because we don't know for sure. + if (!ID->declaresOrInheritsDesignatedInitializers() || + ID->isDesignatedInitializer(Sel)) { + isDesignatedInitChain = true; + DIFunctionScopeInfo->ObjCWarnForNoDesignatedInitChain = false; + } + } + } + } + if (!isDesignatedInitChain) { + const ObjCMethodDecl *InitMethod = nullptr; + bool isDesignated = + getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod); + assert(isDesignated && InitMethod); + (void)isDesignated; + Diag(SelLoc, SuperLoc.isValid() ? + diag::warn_objc_designated_init_non_designated_init_call : + diag::warn_objc_designated_init_non_super_designated_init_call); + Diag(InitMethod->getLocation(), + diag::note_objc_designated_init_marked_here); + } + } + + if (DIFunctionScopeInfo && + DIFunctionScopeInfo->ObjCIsSecondaryInit && + (SuperLoc.isValid() || isSelfExpr(Receiver))) { + if (SuperLoc.isValid()) { + Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call); + } else { + DIFunctionScopeInfo->ObjCWarnForNoInitDelegation = false; + } + } + // Check the message arguments. unsigned NumArgs = ArgsIn.size(); Expr **Args = ArgsIn.data(); @@ -2459,9 +2545,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, ClassMessage, SuperLoc.isValid(), LBracLoc, RBracLoc, ReturnType, VK)) return ExprError(); - - if (Method && !Method->getResultType()->isVoidType() && - RequireCompleteType(LBracLoc, Method->getResultType(), + + if (Method && !Method->getReturnType()->isVoidType() && + RequireCompleteType(LBracLoc, Method->getReturnType(), diag::err_illegal_message_expr_incomplete_type)) return ExprError(); @@ -2562,7 +2648,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } if (getLangOpts().ObjCAutoRefCount) { - DiagnoseARCUseOfWeakReceiver(*this, Receiver); + // Do not warn about IBOutlet weak property receivers being set to null + // as this cannot asynchronously happen. + bool WarnWeakReceiver = true; + if (isImplicit && Method) + if (const ObjCPropertyDecl *PropertyDecl = Method->findPropertyDecl()) + WarnWeakReceiver = !PropertyDecl->hasAttr<IBOutletAttr>(); + if (WarnWeakReceiver) + DiagnoseARCUseOfWeakReceiver(*this, Receiver); // In ARC, annotate delegate init calls. if (Result->getMethodFamily() == OMF_init && @@ -2574,7 +2667,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // The implicit assignment to self means we also don't want to // consume the result. Result->setDelegateInitCall(true); - return Owned(Result); + return Result; } } @@ -2588,19 +2681,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak; if (!IsWeak && Sel.isUnarySelector()) IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak; - - if (IsWeak) { - DiagnosticsEngine::Level Level = - Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, - LBracLoc); - if (Level != DiagnosticsEngine::Ignored) - getCurFunction()->recordUseOfWeak(Result, Prop); - - } + if (IsWeak && + !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, LBracLoc)) + getCurFunction()->recordUseOfWeak(Result, Prop); } } } - + return MaybeBindToTemporary(Result); } @@ -2633,7 +2720,7 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S, if (isa<ParenListExpr>(Receiver)) { ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver); if (Result.isInvalid()) return ExprError(); - Receiver = Result.take(); + Receiver = Result.get(); } if (RespondsToSelectorSel.isNull()) { @@ -2642,10 +2729,11 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S, } if (Sel == RespondsToSelectorSel) RemoveSelectorFromWarningCache(*this, Args[0]); - + return BuildInstanceMessage(Receiver, Receiver->getType(), - /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, - LBracLoc, SelectorLocs, RBracLoc, Args); + /*SuperLoc=*/SourceLocation(), Sel, + /*Method=*/nullptr, LBracLoc, SelectorLocs, + RBracLoc, Args); } enum ARCConversionTypeClass { @@ -2859,7 +2947,7 @@ namespace { ACCResult checkCallToFunction(FunctionDecl *fn) { // Require a CF*Ref return type. - if (!isCFType(fn->getResultType())) + if (!isCFType(fn->getReturnType())) return ACC_invalid; if (!isAnyRetainable(TargetClass)) @@ -2912,7 +3000,7 @@ namespace { // Check for message sends to functions returning CF types. We // just obey the Cocoa conventions with these, even though the // return type is CF. - if (!isAnyRetainable(TargetClass) || !isCFType(method->getResultType())) + if (!isAnyRetainable(TargetClass) || !isCFType(method->getReturnType())) return ACC_invalid; // If the method is explicitly marked not-retained, it's +0. @@ -3045,6 +3133,31 @@ static void addFixitForObjCARCConversion(Sema &S, } } +template <typename T> +static inline T *getObjCBridgeAttr(const TypedefType *TD) { + TypedefNameDecl *TDNDecl = TD->getDecl(); + QualType QT = TDNDecl->getUnderlyingType(); + if (QT->isPointerType()) { + QT = QT->getPointeeType(); + if (const RecordType *RT = QT->getAs<RecordType>()) + if (RecordDecl *RD = RT->getDecl()->getMostRecentDecl()) + return RD->getAttr<T>(); + } + return nullptr; +} + +static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T, + TypedefNameDecl *&TDNDecl) { + while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) { + TDNDecl = TD->getDecl(); + if (ObjCBridgeRelatedAttr *ObjCBAttr = + getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD)) + return ObjCBAttr; + T = TDNDecl->getUnderlyingType(); + } + return nullptr; +} + static void diagnoseObjCARCConversion(Sema &S, SourceRange castRange, QualType castType, ARCConversionTypeClass castACTC, @@ -3059,6 +3172,12 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, return; QualType castExprType = castExpr->getType(); + TypedefNameDecl *TDNDecl = nullptr; + if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable && + ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) || + (exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable && + ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl))) + return; unsigned srcKind = 0; switch (exprACTC) { @@ -3099,9 +3218,10 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, DiagnosticBuilder DiagB = (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); - + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, - castType, castExpr, realCast, "__bridge ", 0); + castType, castExpr, realCast, "__bridge ", + nullptr); } if (CreateRule != ACC_plusZero) { @@ -3111,15 +3231,15 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, S.Diag(br ? castExpr->getExprLoc() : noteLoc, diag::note_arc_bridge_transfer) << castExprType << br; - + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, realCast, "__bridge_transfer ", - br ? "CFBridgingRelease" : 0); + br ? "CFBridgingRelease" : nullptr); } return; } - + // Bridge from a CF type to an ARC type. if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { bool br = S.isKnownName("CFBridgingRetain"); @@ -3140,7 +3260,8 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, - castType, castExpr, realCast, "__bridge ", 0); + castType, castExpr, realCast, "__bridge ", + nullptr); } if (CreateRule != ACC_plusZero) { @@ -3150,10 +3271,10 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, S.Diag(br ? castExpr->getExprLoc() : noteLoc, diag::note_arc_bridge_retained) << castType << br; - + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, castType, castExpr, realCast, "__bridge_retained ", - br ? "CFBridgingRetain" : 0); + br ? "CFBridgingRetain" : nullptr); } return; @@ -3165,26 +3286,17 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << castRange << castExpr->getSourceRange(); } -static inline ObjCBridgeAttr *getObjCBridgeAttr(const TypedefType *TD) { - TypedefNameDecl *TDNDecl = TD->getDecl(); - QualType QT = TDNDecl->getUnderlyingType(); - if (QT->isPointerType()) { - QT = QT->getPointeeType(); - if (const RecordType *RT = QT->getAs<RecordType>()) - if (RecordDecl *RD = RT->getDecl()) - if (RD->hasAttr<ObjCBridgeAttr>()) - return RD->getAttr<ObjCBridgeAttr>(); - } - return 0; -} - -static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) { +template <typename TB> +static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr, + bool &HadTheAttribute, bool warn) { QualType T = castExpr->getType(); + HadTheAttribute = false; while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) { TypedefNameDecl *TDNDecl = TD->getDecl(); - if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) { + if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) { if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) { - NamedDecl *Target = 0; + HadTheAttribute = true; + NamedDecl *Target = nullptr; // Check for an existing type with this name. LookupResult R(S, DeclarationName(Parm), SourceLocation(), Sema::LookupOrdinaryName); @@ -3196,39 +3308,56 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) { castType->getAsObjCInterfacePointerType()) { ObjCInterfaceDecl *CastClass = InterfacePointerType->getObjectType()->getInterface(); - if ((CastClass == ExprClass) || (CastClass && ExprClass->isSuperClassOf(CastClass))) + if ((CastClass == ExprClass) || + (CastClass && ExprClass->isSuperClassOf(CastClass))) return true; - S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) - << T << Target->getName() << castType->getPointeeType(); - return true; - } else { - S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) - << T << Target->getName() << castType; + if (warn) + S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) + << T << Target->getName() << castType->getPointeeType(); + return false; + } else if (castType->isObjCIdType() || + (S.Context.ObjCObjectAdoptsQTypeProtocols( + castType, ExprClass))) + // ok to cast to 'id'. + // casting to id<p-list> is ok if bridge type adopts all of + // p-list protocols. return true; + else { + if (warn) { + S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) + << T << Target->getName() << castType; + S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + S.Diag(Target->getLocStart(), diag::note_declared_at); + } + return false; } } } S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface) - << castExpr->getType() << Parm->getName(); + << castExpr->getType() << Parm; S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); if (Target) S.Diag(Target->getLocStart(), diag::note_declared_at); + return true; } - return true; + return false; } T = TDNDecl->getUnderlyingType(); } - return false; + return true; } -// (CFErrorRef)ns -static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) { +template <typename TB> +static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr, + bool &HadTheAttribute, bool warn) { QualType T = castType; + HadTheAttribute = false; while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) { TypedefNameDecl *TDNDecl = TD->getDecl(); - if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) { + if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) { if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) { - NamedDecl *Target = 0; + HadTheAttribute = true; + NamedDecl *Target = nullptr; // Check for an existing type with this name. LookupResult R(S, DeclarationName(Parm), SourceLocation(), Sema::LookupOrdinaryName); @@ -3240,17 +3369,30 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) { castExpr->getType()->getAsObjCInterfacePointerType()) { ObjCInterfaceDecl *ExprClass = InterfacePointerType->getObjectType()->getInterface(); - if ((CastClass == ExprClass) || (ExprClass && CastClass->isSuperClassOf(ExprClass))) + if ((CastClass == ExprClass) || + (ExprClass && CastClass->isSuperClassOf(ExprClass))) return true; - S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) - << castExpr->getType()->getPointeeType() << T; - S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); - return true; - } else { - S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) - << castExpr->getType() << castType; - S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (warn) { + S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) + << castExpr->getType()->getPointeeType() << T; + S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + } + return false; + } else if (castExpr->getType()->isObjCIdType() || + (S.Context.QIdProtocolsAdoptObjCObjectProtocols( + castExpr->getType(), CastClass))) + // ok to cast an 'id' expression to a CFtype. + // ok to cast an 'id<plist>' expression to CFtype provided plist + // adopts all of CFtype's ObjetiveC's class plist. return true; + else { + if (warn) { + S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) + << castExpr->getType() << castType; + S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + S.Diag(Target->getLocStart(), diag::note_declared_at); + } + return false; } } } @@ -3259,18 +3401,262 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) { S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); if (Target) S.Diag(Target->getLocStart(), diag::note_declared_at); + return true; } - return true; + return false; } T = TDNDecl->getUnderlyingType(); } + return true; +} + +void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) { + if (!getLangOpts().ObjC1) + return; + // warn in presence of __bridge casting to or from a toll free bridge cast. + ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType()); + ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType); + if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) { + bool HasObjCBridgeAttr; + bool ObjCBridgeAttrWillNotWarn = + CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr, + false); + if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr) + return; + bool HasObjCBridgeMutableAttr; + bool ObjCBridgeMutableAttrWillNotWarn = + CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr, + HasObjCBridgeMutableAttr, false); + if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr) + return; + + if (HasObjCBridgeAttr) + CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr, + true); + else if (HasObjCBridgeMutableAttr) + CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr, + HasObjCBridgeMutableAttr, true); + } + else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) { + bool HasObjCBridgeAttr; + bool ObjCBridgeAttrWillNotWarn = + CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr, + false); + if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr) + return; + bool HasObjCBridgeMutableAttr; + bool ObjCBridgeMutableAttrWillNotWarn = + CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr, + HasObjCBridgeMutableAttr, false); + if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr) + return; + + if (HasObjCBridgeAttr) + CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr, + true); + else if (HasObjCBridgeMutableAttr) + CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr, + HasObjCBridgeMutableAttr, true); + } +} + +void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) { + QualType SrcType = castExpr->getType(); + if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(castExpr)) { + if (PRE->isExplicitProperty()) { + if (ObjCPropertyDecl *PDecl = PRE->getExplicitProperty()) + SrcType = PDecl->getType(); + } + else if (PRE->isImplicitProperty()) { + if (ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) + SrcType = Getter->getReturnType(); + + } + } + + ARCConversionTypeClass srcExprACTC = classifyTypeForARCConversion(SrcType); + ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType); + if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation) + return; + CheckObjCBridgeRelatedConversions(castExpr->getLocStart(), + castType, SrcType, castExpr); + return; +} + +bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, + CastKind &Kind) { + if (!getLangOpts().ObjC1) + return false; + ARCConversionTypeClass exprACTC = + classifyTypeForARCConversion(castExpr->getType()); + ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType); + if ((castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) || + (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable)) { + CheckTollFreeBridgeCast(castType, castExpr); + Kind = (castACTC == ACTC_coreFoundation) ? CK_BitCast + : CK_CPointerToObjCPointerCast; + return true; + } + return false; +} + +bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, + QualType DestType, QualType SrcType, + ObjCInterfaceDecl *&RelatedClass, + ObjCMethodDecl *&ClassMethod, + ObjCMethodDecl *&InstanceMethod, + TypedefNameDecl *&TDNDecl, + bool CfToNs) { + QualType T = CfToNs ? SrcType : DestType; + ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl); + if (!ObjCBAttr) + return false; + + IdentifierInfo *RCId = ObjCBAttr->getRelatedClass(); + IdentifierInfo *CMId = ObjCBAttr->getClassMethod(); + IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod(); + if (!RCId) + return false; + NamedDecl *Target = nullptr; + // Check for an existing type with this name. + LookupResult R(*this, DeclarationName(RCId), SourceLocation(), + Sema::LookupOrdinaryName); + if (!LookupName(R, TUScope)) { + Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId + << SrcType << DestType; + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + return false; + } + Target = R.getFoundDecl(); + if (Target && isa<ObjCInterfaceDecl>(Target)) + RelatedClass = cast<ObjCInterfaceDecl>(Target); + else { + Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId + << SrcType << DestType; + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Target) + Diag(Target->getLocStart(), diag::note_declared_at); + return false; + } + + // Check for an existing class method with the given selector name. + if (CfToNs && CMId) { + Selector Sel = Context.Selectors.getUnarySelector(CMId); + ClassMethod = RelatedClass->lookupMethod(Sel, false); + if (!ClassMethod) { + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << Sel << false; + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + return false; + } + } + + // Check for an existing instance method with the given selector name. + if (!CfToNs && IMId) { + Selector Sel = Context.Selectors.getNullarySelector(IMId); + InstanceMethod = RelatedClass->lookupMethod(Sel, true); + if (!InstanceMethod) { + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << Sel << true; + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + return false; + } + } + return true; +} + +bool +Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, + QualType DestType, QualType SrcType, + Expr *&SrcExpr) { + ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType); + ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType); + bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable); + bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation); + if (!CfToNs && !NsToCf) + return false; + + ObjCInterfaceDecl *RelatedClass; + ObjCMethodDecl *ClassMethod = nullptr; + ObjCMethodDecl *InstanceMethod = nullptr; + TypedefNameDecl *TDNDecl = nullptr; + if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass, + ClassMethod, InstanceMethod, TDNDecl, CfToNs)) + return false; + + if (CfToNs) { + // Implicit conversion from CF to ObjC object is needed. + if (ClassMethod) { + std::string ExpressionString = "["; + ExpressionString += RelatedClass->getNameAsString(); + ExpressionString += " "; + ExpressionString += ClassMethod->getSelector().getAsString(); + SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd()); + // Provide a fixit: [RelatedClass ClassMethod SrcExpr] + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << ClassMethod->getSelector() << false + << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString) + << FixItHint::CreateInsertion(SrcExprEndLoc, "]"); + Diag(RelatedClass->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + + QualType receiverType = + Context.getObjCInterfaceType(RelatedClass); + // Argument. + Expr *args[] = { SrcExpr }; + ExprResult msg = BuildClassMessageImplicit(receiverType, false, + ClassMethod->getLocation(), + ClassMethod->getSelector(), ClassMethod, + MultiExprArg(args, 1)); + SrcExpr = msg.get(); + return true; + } + } + else { + // Implicit conversion from ObjC type to CF object is needed. + if (InstanceMethod) { + std::string ExpressionString; + SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd()); + if (InstanceMethod->isPropertyAccessor()) + if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) { + // fixit: ObjectExpr.propertyname when it is aproperty accessor. + ExpressionString = "."; + ExpressionString += PDecl->getNameAsString(); + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << InstanceMethod->getSelector() << true + << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); + } + if (ExpressionString.empty()) { + // Provide a fixit: [ObjectExpr InstanceMethod] + ExpressionString = " "; + ExpressionString += InstanceMethod->getSelector().getAsString(); + ExpressionString += "]"; + + Diag(Loc, diag::err_objc_bridged_related_known_method) + << SrcType << DestType << InstanceMethod->getSelector() << true + << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[") + << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); + } + Diag(RelatedClass->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + + ExprResult msg = + BuildInstanceMessageImplicit(SrcExpr, SrcType, + InstanceMethod->getLocation(), + InstanceMethod->getSelector(), + InstanceMethod, None); + SrcExpr = msg.get(); + return true; + } + } return false; } Sema::ARCConversionResult Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, Expr *&castExpr, CheckedConversionKind CCK, - bool DiagnoseCFAudited) { + bool DiagnoseCFAudited, + BinaryOperatorKind Opc) { QualType castExprType = castExpr->getType(); // For the purposes of the classification, we assume reference types @@ -3324,17 +3710,6 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr && CCK != CCK_ImplicitConversion) return ACR_okay; - - if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation && - (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast)) - if (CheckObjCBridgeNSCast(*this, castType, castExpr)) - return ACR_okay; - - if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable && - (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast)) - if (CheckObjCBridgeCFCast(*this, castType, castExpr)) - return ACR_okay; - switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) { // For invalid casts, fall through. @@ -3350,7 +3725,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, case ACC_plusOne: castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), CK_ARCConsumeObject, castExpr, - 0, VK_RValue); + nullptr, VK_RValue); ExprNeedsCleanups = true; return ACR_okay; } @@ -3362,14 +3737,23 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, CCK != CCK_ImplicitConversion) return ACR_unbridged; + // Do not issue bridge cast" diagnostic when implicit casting a cstring + // to 'NSString *'. Let caller issue a normal mismatched diagnostic with + // suitable fix-it. + if (castACTC == ACTC_retainable && exprACTC == ACTC_none && + ConversionToObjCStringLiteralCheck(castType, castExpr)) + return ACR_okay; + // Do not issue "bridge cast" diagnostic when implicit casting // a retainable object to a CF type parameter belonging to an audited // CF API function. Let caller issue a normal type mismatched diagnostic // instead. if (!DiagnoseCFAudited || exprACTC != ACTC_retainable || castACTC != ACTC_coreFoundation) - diagnoseObjCARCConversion(*this, castRange, castType, castACTC, - castExpr, castExpr, exprACTC, CCK); + if (!(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable && + (Opc == BO_NE || Opc == BO_EQ))) + diagnoseObjCARCConversion(*this, castRange, castType, castACTC, + castExpr, castExpr, exprACTC, CCK); return ACR_okay; } @@ -3486,7 +3870,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, Expr *SubExpr) { ExprResult SubResult = UsualUnaryConversions(SubExpr); if (SubResult.isInvalid()) return ExprError(); - SubExpr = SubResult.take(); + SubExpr = SubResult.get(); QualType T = TSInfo->getType(); QualType FromType = SubExpr->getType(); @@ -3545,7 +3929,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, // Produce the object before casting it. SubExpr = ImplicitCastExpr::Create(Context, FromType, CK_ARCProduceObject, - SubExpr, 0, VK_RValue); + SubExpr, nullptr, VK_RValue); break; case OBC_BridgeTransfer: { @@ -3584,7 +3968,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, if (MustConsume) { ExprNeedsCleanups = true; Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, - 0, VK_RValue); + nullptr, VK_RValue); } return Result; @@ -3597,8 +3981,10 @@ ExprResult Sema::ActOnObjCBridgedCast(Scope *S, ParsedType Type, SourceLocation RParenLoc, Expr *SubExpr) { - TypeSourceInfo *TSInfo = 0; + TypeSourceInfo *TSInfo = nullptr; QualType T = GetTypeFromParser(Type, &TSInfo); + if (Kind == OBC_Bridge) + CheckTollFreeBridgeCast(T, SubExpr); if (!TSInfo) TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc); return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo, |