5247 lines · cpp
1//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements semantic analysis for Objective-C expressions.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/Availability.h"15#include "clang/AST/DeclObjC.h"16#include "clang/AST/ExprObjC.h"17#include "clang/AST/StmtVisitor.h"18#include "clang/AST/TypeLoc.h"19#include "clang/Analysis/DomainSpecific/CocoaConventions.h"20#include "clang/Basic/Builtins.h"21#include "clang/Basic/TargetInfo.h"22#include "clang/Edit/Commit.h"23#include "clang/Edit/Rewriters.h"24#include "clang/Lex/Preprocessor.h"25#include "clang/Sema/Initialization.h"26#include "clang/Sema/Lookup.h"27#include "clang/Sema/Scope.h"28#include "clang/Sema/ScopeInfo.h"29#include "clang/Sema/SemaObjC.h"30#include "llvm/Support/ConvertUTF.h"31#include <optional>32 33using namespace clang;34using namespace sema;35using llvm::ArrayRef;36 37ExprResult SemaObjC::ParseObjCStringLiteral(SourceLocation *AtLocs,38 ArrayRef<Expr *> Strings) {39 ASTContext &Context = getASTContext();40 // Most ObjC strings are formed out of a single piece. However, we *can*41 // have strings formed out of multiple @ strings with multiple pptokens in42 // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one43 // StringLiteral for ObjCStringLiteral to hold onto.44 StringLiteral *S = cast<StringLiteral>(Strings[0]);45 46 // If we have a multi-part string, merge it all together.47 if (Strings.size() != 1) {48 // Concatenate objc strings.49 SmallString<128> StrBuf;50 SmallVector<SourceLocation, 8> StrLocs;51 52 for (Expr *E : Strings) {53 S = cast<StringLiteral>(E);54 55 // ObjC strings can't be wide or UTF.56 if (!S->isOrdinary()) {57 Diag(S->getBeginLoc(), diag::err_cfstring_literal_not_string_constant)58 << S->getSourceRange();59 return true;60 }61 62 // Append the string.63 StrBuf += S->getString();64 65 // Get the locations of the string tokens.66 StrLocs.append(S->tokloc_begin(), S->tokloc_end());67 }68 69 // Create the aggregate string with the appropriate content and location70 // information.71 const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType());72 assert(CAT && "String literal not of constant array type!");73 QualType StrTy = Context.getConstantArrayType(74 CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1), nullptr,75 CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());76 S = StringLiteral::Create(Context, StrBuf, StringLiteralKind::Ordinary,77 /*Pascal=*/false, StrTy, StrLocs);78 }79 80 return BuildObjCStringLiteral(AtLocs[0], S);81}82 83ExprResult SemaObjC::BuildObjCStringLiteral(SourceLocation AtLoc,84 StringLiteral *S) {85 ASTContext &Context = getASTContext();86 // Verify that this composite string is acceptable for ObjC strings.87 if (CheckObjCString(S))88 return true;89 90 // Initialize the constant string interface lazily. This assumes91 // the NSString interface is seen in this translation unit. Note: We92 // don't use NSConstantString, since the runtime team considers this93 // interface private (even though it appears in the header files).94 QualType Ty = Context.getObjCConstantStringInterface();95 if (!Ty.isNull()) {96 Ty = Context.getObjCObjectPointerType(Ty);97 } else if (getLangOpts().NoConstantCFStrings) {98 IdentifierInfo *NSIdent=nullptr;99 std::string StringClass(getLangOpts().ObjCConstantStringClass);100 101 if (StringClass.empty())102 NSIdent = &Context.Idents.get("NSConstantString");103 else104 NSIdent = &Context.Idents.get(StringClass);105 106 NamedDecl *IF = SemaRef.LookupSingleName(SemaRef.TUScope, NSIdent, AtLoc,107 Sema::LookupOrdinaryName);108 if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {109 Context.setObjCConstantStringInterface(StrIF);110 Ty = Context.getObjCConstantStringInterface();111 Ty = Context.getObjCObjectPointerType(Ty);112 } else {113 // If there is no NSConstantString interface defined then treat this114 // as error and recover from it.115 Diag(S->getBeginLoc(), diag::err_no_nsconstant_string_class)116 << NSIdent << S->getSourceRange();117 Ty = Context.getObjCIdType();118 }119 } else {120 IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);121 NamedDecl *IF = SemaRef.LookupSingleName(SemaRef.TUScope, NSIdent, AtLoc,122 Sema::LookupOrdinaryName);123 if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {124 Context.setObjCConstantStringInterface(StrIF);125 Ty = Context.getObjCConstantStringInterface();126 Ty = Context.getObjCObjectPointerType(Ty);127 } else {128 // If there is no NSString interface defined, implicitly declare129 // a @class NSString; and use that instead. This is to make sure130 // type of an NSString literal is represented correctly, instead of131 // being an 'id' type.132 Ty = Context.getObjCNSStringType();133 if (Ty.isNull()) {134 ObjCInterfaceDecl *NSStringIDecl =135 ObjCInterfaceDecl::Create (Context,136 Context.getTranslationUnitDecl(),137 SourceLocation(), NSIdent,138 nullptr, nullptr, SourceLocation());139 Ty = Context.getObjCInterfaceType(NSStringIDecl);140 Context.setObjCNSStringType(Ty);141 }142 Ty = Context.getObjCObjectPointerType(Ty);143 }144 }145 146 return new (Context) ObjCStringLiteral(S, Ty, AtLoc);147}148 149/// Emits an error if the given method does not exist, or if the return150/// type is not an Objective-C object.151static bool validateBoxingMethod(Sema &S, SourceLocation Loc,152 const ObjCInterfaceDecl *Class,153 Selector Sel, const ObjCMethodDecl *Method) {154 if (!Method) {155 // FIXME: Is there a better way to avoid quotes than using getName()?156 S.Diag(Loc, diag::err_undeclared_boxing_method) << Sel << Class->getName();157 return false;158 }159 160 // Make sure the return type is reasonable.161 QualType ReturnType = Method->getReturnType();162 if (!ReturnType->isObjCObjectPointerType()) {163 S.Diag(Loc, diag::err_objc_literal_method_sig)164 << Sel;165 S.Diag(Method->getLocation(), diag::note_objc_literal_method_return)166 << ReturnType;167 return false;168 }169 170 return true;171}172 173/// Maps ObjCLiteralKind to NSClassIdKindKind174static NSAPI::NSClassIdKindKind175ClassKindFromLiteralKind(SemaObjC::ObjCLiteralKind LiteralKind) {176 switch (LiteralKind) {177 case SemaObjC::LK_Array:178 return NSAPI::ClassId_NSArray;179 case SemaObjC::LK_Dictionary:180 return NSAPI::ClassId_NSDictionary;181 case SemaObjC::LK_Numeric:182 return NSAPI::ClassId_NSNumber;183 case SemaObjC::LK_String:184 return NSAPI::ClassId_NSString;185 case SemaObjC::LK_Boxed:186 return NSAPI::ClassId_NSValue;187 188 // there is no corresponding matching189 // between LK_None/LK_Block and NSClassIdKindKind190 case SemaObjC::LK_Block:191 case SemaObjC::LK_None:192 break;193 }194 llvm_unreachable("LiteralKind can't be converted into a ClassKind");195}196 197/// Validates ObjCInterfaceDecl availability.198/// ObjCInterfaceDecl, used to create ObjC literals, should be defined199/// if clang not in a debugger mode.200static bool201ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,202 SourceLocation Loc,203 SemaObjC::ObjCLiteralKind LiteralKind) {204 if (!Decl) {205 NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind);206 IdentifierInfo *II = S.ObjC().NSAPIObj->getNSClassId(Kind);207 S.Diag(Loc, diag::err_undeclared_objc_literal_class)208 << II->getName() << LiteralKind;209 return false;210 } else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) {211 S.Diag(Loc, diag::err_undeclared_objc_literal_class)212 << Decl->getName() << LiteralKind;213 S.Diag(Decl->getLocation(), diag::note_forward_class);214 return false;215 }216 217 return true;218}219 220/// Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.221/// Used to create ObjC literals, such as NSDictionary (@{}),222/// NSArray (@[]) and Boxed Expressions (@())223static ObjCInterfaceDecl *224LookupObjCInterfaceDeclForLiteral(Sema &S, SourceLocation Loc,225 SemaObjC::ObjCLiteralKind LiteralKind) {226 NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind);227 IdentifierInfo *II = S.ObjC().NSAPIObj->getNSClassId(ClassKind);228 NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc,229 Sema::LookupOrdinaryName);230 ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF);231 if (!ID && S.getLangOpts().DebuggerObjCLiteral) {232 ASTContext &Context = S.Context;233 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();234 ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II,235 nullptr, nullptr, SourceLocation());236 }237 238 if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) {239 ID = nullptr;240 }241 242 return ID;243}244 245/// Retrieve the NSNumber factory method that should be used to create246/// an Objective-C literal for the given type.247static ObjCMethodDecl *getNSNumberFactoryMethod(SemaObjC &S, SourceLocation Loc,248 QualType NumberType,249 bool isLiteral = false,250 SourceRange R = SourceRange()) {251 std::optional<NSAPI::NSNumberLiteralMethodKind> Kind =252 S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType);253 254 if (!Kind) {255 if (isLiteral) {256 S.Diag(Loc, diag::err_invalid_nsnumber_type)257 << NumberType << R;258 }259 return nullptr;260 }261 262 // If we already looked up this method, we're done.263 if (S.NSNumberLiteralMethods[*Kind])264 return S.NSNumberLiteralMethods[*Kind];265 266 Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind,267 /*Instance=*/false);268 269 ASTContext &CX = S.SemaRef.Context;270 271 // Look up the NSNumber class, if we haven't done so already. It's cached272 // in the Sema instance.273 if (!S.NSNumberDecl) {274 S.NSNumberDecl =275 LookupObjCInterfaceDeclForLiteral(S.SemaRef, Loc, SemaObjC::LK_Numeric);276 if (!S.NSNumberDecl) {277 return nullptr;278 }279 }280 281 if (S.NSNumberPointer.isNull()) {282 // generate the pointer to NSNumber type.283 QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl);284 S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject);285 }286 287 // Look for the appropriate method within NSNumber.288 ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);289 if (!Method && S.getLangOpts().DebuggerObjCLiteral) {290 // create a stub definition this NSNumber factory method.291 TypeSourceInfo *ReturnTInfo = nullptr;292 Method = ObjCMethodDecl::Create(293 CX, SourceLocation(), SourceLocation(), Sel, S.NSNumberPointer,294 ReturnTInfo, S.NSNumberDecl,295 /*isInstance=*/false, /*isVariadic=*/false,296 /*isPropertyAccessor=*/false,297 /*isSynthesizedAccessorStub=*/false,298 /*isImplicitlyDeclared=*/true,299 /*isDefined=*/false, ObjCImplementationControl::Required,300 /*HasRelatedResultType=*/false);301 ParmVarDecl *value =302 ParmVarDecl::Create(S.SemaRef.Context, Method, SourceLocation(),303 SourceLocation(), &CX.Idents.get("value"),304 NumberType, /*TInfo=*/nullptr, SC_None, nullptr);305 Method->setMethodParams(S.SemaRef.Context, value, {});306 }307 308 if (!validateBoxingMethod(S.SemaRef, Loc, S.NSNumberDecl, Sel, Method))309 return nullptr;310 311 // Note: if the parameter type is out-of-line, we'll catch it later in the312 // implicit conversion.313 314 S.NSNumberLiteralMethods[*Kind] = Method;315 return Method;316}317 318/// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the319/// numeric literal expression. Type of the expression will be "NSNumber *".320ExprResult SemaObjC::BuildObjCNumericLiteral(SourceLocation AtLoc,321 Expr *Number) {322 ASTContext &Context = getASTContext();323 // Determine the type of the literal.324 QualType NumberType = Number->getType();325 if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) {326 // In C, character literals have type 'int'. That's not the type we want327 // to use to determine the Objective-c literal kind.328 switch (Char->getKind()) {329 case CharacterLiteralKind::Ascii:330 case CharacterLiteralKind::UTF8:331 NumberType = Context.CharTy;332 break;333 334 case CharacterLiteralKind::Wide:335 NumberType = Context.getWideCharType();336 break;337 338 case CharacterLiteralKind::UTF16:339 NumberType = Context.Char16Ty;340 break;341 342 case CharacterLiteralKind::UTF32:343 NumberType = Context.Char32Ty;344 break;345 }346 }347 348 // Look for the appropriate method within NSNumber.349 // Construct the literal.350 SourceRange NR(Number->getSourceRange());351 ObjCMethodDecl *Method = getNSNumberFactoryMethod(*this, AtLoc, NumberType,352 true, NR);353 if (!Method)354 return ExprError();355 356 // Convert the number to the type that the parameter expects.357 ParmVarDecl *ParamDecl = Method->parameters()[0];358 InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,359 ParamDecl);360 ExprResult ConvertedNumber =361 SemaRef.PerformCopyInitialization(Entity, SourceLocation(), Number);362 if (ConvertedNumber.isInvalid())363 return ExprError();364 Number = ConvertedNumber.get();365 366 // Use the effective source range of the literal, including the leading '@'.367 return SemaRef.MaybeBindToTemporary(new (Context) ObjCBoxedExpr(368 Number, NSNumberPointer, Method, SourceRange(AtLoc, NR.getEnd())));369}370 371ExprResult SemaObjC::ActOnObjCBoolLiteral(SourceLocation AtLoc,372 SourceLocation ValueLoc, bool Value) {373 ASTContext &Context = getASTContext();374 ExprResult Inner;375 if (getLangOpts().CPlusPlus) {376 Inner = SemaRef.ActOnCXXBoolLiteral(ValueLoc,377 Value ? tok::kw_true : tok::kw_false);378 } else {379 // C doesn't actually have a way to represent literal values of type380 // _Bool. So, we'll use 0/1 and implicit cast to _Bool.381 Inner = SemaRef.ActOnIntegerConstant(ValueLoc, Value ? 1 : 0);382 Inner = SemaRef.ImpCastExprToType(Inner.get(), Context.BoolTy,383 CK_IntegralToBoolean);384 }385 386 return BuildObjCNumericLiteral(AtLoc, Inner.get());387}388 389/// Check that the given expression is a valid element of an Objective-C390/// collection literal.391static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,392 QualType T,393 bool ArrayLiteral = false) {394 // If the expression is type-dependent, there's nothing for us to do.395 if (Element->isTypeDependent())396 return Element;397 398 ExprResult Result = S.CheckPlaceholderExpr(Element);399 if (Result.isInvalid())400 return ExprError();401 Element = Result.get();402 403 // In C++, check for an implicit conversion to an Objective-C object pointer404 // type.405 if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) {406 InitializedEntity Entity407 = InitializedEntity::InitializeParameter(S.Context, T,408 /*Consumed=*/false);409 InitializationKind Kind = InitializationKind::CreateCopy(410 Element->getBeginLoc(), SourceLocation());411 InitializationSequence Seq(S, Entity, Kind, Element);412 if (!Seq.Failed())413 return Seq.Perform(S, Entity, Kind, Element);414 }415 416 Expr *OrigElement = Element;417 418 // Perform lvalue-to-rvalue conversion.419 Result = S.DefaultLvalueConversion(Element);420 if (Result.isInvalid())421 return ExprError();422 Element = Result.get();423 424 // Make sure that we have an Objective-C pointer type or block.425 if (!Element->getType()->isObjCObjectPointerType() &&426 !Element->getType()->isBlockPointerType()) {427 bool Recovered = false;428 429 // If this is potentially an Objective-C numeric literal, add the '@'.430 if (isa<IntegerLiteral>(OrigElement) ||431 isa<CharacterLiteral>(OrigElement) ||432 isa<FloatingLiteral>(OrigElement) ||433 isa<ObjCBoolLiteralExpr>(OrigElement) ||434 isa<CXXBoolLiteralExpr>(OrigElement)) {435 if (S.ObjC().NSAPIObj->getNSNumberFactoryMethodKind(436 OrigElement->getType())) {437 int Which = isa<CharacterLiteral>(OrigElement) ? 1438 : (isa<CXXBoolLiteralExpr>(OrigElement) ||439 isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2440 : 3;441 442 S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection)443 << Which << OrigElement->getSourceRange()444 << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@");445 446 Result = S.ObjC().BuildObjCNumericLiteral(OrigElement->getBeginLoc(),447 OrigElement);448 if (Result.isInvalid())449 return ExprError();450 451 Element = Result.get();452 Recovered = true;453 }454 }455 // If this is potentially an Objective-C string literal, add the '@'.456 else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) {457 if (String->isOrdinary()) {458 S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection)459 << 0 << OrigElement->getSourceRange()460 << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@");461 462 Result =463 S.ObjC().BuildObjCStringLiteral(OrigElement->getBeginLoc(), String);464 if (Result.isInvalid())465 return ExprError();466 467 Element = Result.get();468 Recovered = true;469 }470 }471 472 if (!Recovered) {473 S.Diag(Element->getBeginLoc(), diag::err_invalid_collection_element)474 << Element->getType();475 return ExprError();476 }477 }478 if (ArrayLiteral)479 if (ObjCStringLiteral *getString =480 dyn_cast<ObjCStringLiteral>(OrigElement)) {481 if (StringLiteral *SL = getString->getString()) {482 unsigned numConcat = SL->getNumConcatenated();483 if (numConcat > 1) {484 // Only warn if the concatenated string doesn't come from a macro.485 bool hasMacro = false;486 for (unsigned i = 0; i < numConcat ; ++i)487 if (SL->getStrTokenLoc(i).isMacroID()) {488 hasMacro = true;489 break;490 }491 if (!hasMacro)492 S.Diag(Element->getBeginLoc(),493 diag::warn_concatenated_nsarray_literal)494 << Element->getType();495 }496 }497 }498 499 // Make sure that the element has the type that the container factory500 // function expects.501 return S.PerformCopyInitialization(502 InitializedEntity::InitializeParameter(S.Context, T,503 /*Consumed=*/false),504 Element->getBeginLoc(), Element);505}506 507ExprResult SemaObjC::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {508 ASTContext &Context = getASTContext();509 if (ValueExpr->isTypeDependent()) {510 ObjCBoxedExpr *BoxedExpr =511 new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR);512 return BoxedExpr;513 }514 ObjCMethodDecl *BoxingMethod = nullptr;515 QualType BoxedType;516 // Convert the expression to an RValue, so we can check for pointer types...517 ExprResult RValue = SemaRef.DefaultFunctionArrayLvalueConversion(ValueExpr);518 if (RValue.isInvalid()) {519 return ExprError();520 }521 SourceLocation Loc = SR.getBegin();522 ValueExpr = RValue.get();523 QualType ValueType(ValueExpr->getType());524 if (const PointerType *PT = ValueType->getAs<PointerType>()) {525 QualType PointeeType = PT->getPointeeType();526 if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {527 528 if (!NSStringDecl) {529 NSStringDecl =530 LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, LK_String);531 if (!NSStringDecl) {532 return ExprError();533 }534 QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl);535 NSStringPointer = Context.getObjCObjectPointerType(NSStringObject);536 }537 538 // The boxed expression can be emitted as a compile time constant if it is539 // a string literal whose character encoding is compatible with UTF-8.540 if (auto *CE = dyn_cast<ImplicitCastExpr>(ValueExpr))541 if (CE->getCastKind() == CK_ArrayToPointerDecay)542 if (auto *SL =543 dyn_cast<StringLiteral>(CE->getSubExpr()->IgnoreParens())) {544 assert((SL->isOrdinary() || SL->isUTF8()) &&545 "unexpected character encoding");546 StringRef Str = SL->getString();547 const llvm::UTF8 *StrBegin = Str.bytes_begin();548 const llvm::UTF8 *StrEnd = Str.bytes_end();549 // Check that this is a valid UTF-8 string.550 if (llvm::isLegalUTF8String(&StrBegin, StrEnd)) {551 BoxedType = Context.getAttributedType(NullabilityKind::NonNull,552 NSStringPointer, NSStringPointer);553 return new (Context) ObjCBoxedExpr(CE, BoxedType, nullptr, SR);554 }555 556 Diag(SL->getBeginLoc(), diag::warn_objc_boxing_invalid_utf8_string)557 << NSStringPointer << SL->getSourceRange();558 }559 560 if (!StringWithUTF8StringMethod) {561 IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String");562 Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II);563 564 // Look for the appropriate method within NSString.565 BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);566 if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {567 // Debugger needs to work even if NSString hasn't been defined.568 TypeSourceInfo *ReturnTInfo = nullptr;569 ObjCMethodDecl *M = ObjCMethodDecl::Create(570 Context, SourceLocation(), SourceLocation(), stringWithUTF8String,571 NSStringPointer, ReturnTInfo, NSStringDecl,572 /*isInstance=*/false, /*isVariadic=*/false,573 /*isPropertyAccessor=*/false,574 /*isSynthesizedAccessorStub=*/false,575 /*isImplicitlyDeclared=*/true,576 /*isDefined=*/false, ObjCImplementationControl::Required,577 /*HasRelatedResultType=*/false);578 QualType ConstCharType = Context.CharTy.withConst();579 ParmVarDecl *value =580 ParmVarDecl::Create(Context, M,581 SourceLocation(), SourceLocation(),582 &Context.Idents.get("value"),583 Context.getPointerType(ConstCharType),584 /*TInfo=*/nullptr,585 SC_None, nullptr);586 M->setMethodParams(Context, value, {});587 BoxingMethod = M;588 }589 590 if (!validateBoxingMethod(SemaRef, Loc, NSStringDecl,591 stringWithUTF8String, BoxingMethod))592 return ExprError();593 594 StringWithUTF8StringMethod = BoxingMethod;595 }596 597 BoxingMethod = StringWithUTF8StringMethod;598 BoxedType = NSStringPointer;599 // Transfer the nullability from method's return type.600 std::optional<NullabilityKind> Nullability =601 BoxingMethod->getReturnType()->getNullability();602 if (Nullability)603 BoxedType =604 Context.getAttributedType(*Nullability, BoxedType, BoxedType);605 }606 } else if (ValueType->isBuiltinType()) {607 // The other types we support are numeric, char and BOOL/bool. We could also608 // provide limited support for structure types, such as NSRange, NSRect, and609 // NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h>610 // for more details.611 612 // Check for a top-level character literal.613 if (const CharacterLiteral *Char =614 dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) {615 // In C, character literals have type 'int'. That's not the type we want616 // to use to determine the Objective-c literal kind.617 switch (Char->getKind()) {618 case CharacterLiteralKind::Ascii:619 case CharacterLiteralKind::UTF8:620 ValueType = Context.CharTy;621 break;622 623 case CharacterLiteralKind::Wide:624 ValueType = Context.getWideCharType();625 break;626 627 case CharacterLiteralKind::UTF16:628 ValueType = Context.Char16Ty;629 break;630 631 case CharacterLiteralKind::UTF32:632 ValueType = Context.Char32Ty;633 break;634 }635 }636 // FIXME: Do I need to do anything special with BoolTy expressions?637 638 // Look for the appropriate method within NSNumber.639 BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType);640 BoxedType = NSNumberPointer;641 } else if (const auto *ED = ValueType->getAsEnumDecl()) {642 if (!ED->isComplete()) {643 Diag(Loc, diag::err_objc_incomplete_boxed_expression_type)644 << ValueType << ValueExpr->getSourceRange();645 return ExprError();646 }647 648 BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ED->getIntegerType());649 BoxedType = NSNumberPointer;650 } else if (ValueType->isObjCBoxableRecordType()) {651 // Support for structure types, that marked as objc_boxable652 // struct __attribute__((objc_boxable)) s { ... };653 654 // Look up the NSValue class, if we haven't done so already. It's cached655 // in the Sema instance.656 if (!NSValueDecl) {657 NSValueDecl = LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, LK_Boxed);658 if (!NSValueDecl) {659 return ExprError();660 }661 662 // generate the pointer to NSValue type.663 QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);664 NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);665 }666 667 if (!ValueWithBytesObjCTypeMethod) {668 const IdentifierInfo *II[] = {&Context.Idents.get("valueWithBytes"),669 &Context.Idents.get("objCType")};670 Selector ValueWithBytesObjCType = Context.Selectors.getSelector(2, II);671 672 // Look for the appropriate method within NSValue.673 BoxingMethod = NSValueDecl->lookupClassMethod(ValueWithBytesObjCType);674 if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {675 // Debugger needs to work even if NSValue hasn't been defined.676 TypeSourceInfo *ReturnTInfo = nullptr;677 ObjCMethodDecl *M = ObjCMethodDecl::Create(678 Context, SourceLocation(), SourceLocation(), ValueWithBytesObjCType,679 NSValuePointer, ReturnTInfo, NSValueDecl,680 /*isInstance=*/false,681 /*isVariadic=*/false,682 /*isPropertyAccessor=*/false,683 /*isSynthesizedAccessorStub=*/false,684 /*isImplicitlyDeclared=*/true,685 /*isDefined=*/false, ObjCImplementationControl::Required,686 /*HasRelatedResultType=*/false);687 688 SmallVector<ParmVarDecl *, 2> Params;689 690 ParmVarDecl *bytes =691 ParmVarDecl::Create(Context, M,692 SourceLocation(), SourceLocation(),693 &Context.Idents.get("bytes"),694 Context.VoidPtrTy.withConst(),695 /*TInfo=*/nullptr,696 SC_None, nullptr);697 Params.push_back(bytes);698 699 QualType ConstCharType = Context.CharTy.withConst();700 ParmVarDecl *type =701 ParmVarDecl::Create(Context, M,702 SourceLocation(), SourceLocation(),703 &Context.Idents.get("type"),704 Context.getPointerType(ConstCharType),705 /*TInfo=*/nullptr,706 SC_None, nullptr);707 Params.push_back(type);708 709 M->setMethodParams(Context, Params, {});710 BoxingMethod = M;711 }712 713 if (!validateBoxingMethod(SemaRef, Loc, NSValueDecl,714 ValueWithBytesObjCType, BoxingMethod))715 return ExprError();716 717 ValueWithBytesObjCTypeMethod = BoxingMethod;718 }719 720 if (!ValueType.isTriviallyCopyableType(Context)) {721 Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type)722 << ValueType << ValueExpr->getSourceRange();723 return ExprError();724 }725 726 BoxingMethod = ValueWithBytesObjCTypeMethod;727 BoxedType = NSValuePointer;728 }729 730 if (!BoxingMethod) {731 Diag(Loc, diag::err_objc_illegal_boxed_expression_type)732 << ValueType << ValueExpr->getSourceRange();733 return ExprError();734 }735 736 SemaRef.DiagnoseUseOfDecl(BoxingMethod, Loc);737 738 ExprResult ConvertedValueExpr;739 if (ValueType->isObjCBoxableRecordType()) {740 InitializedEntity IE = InitializedEntity::InitializeTemporary(ValueType);741 ConvertedValueExpr = SemaRef.PerformCopyInitialization(742 IE, ValueExpr->getExprLoc(), ValueExpr);743 } else {744 // Convert the expression to the type that the parameter requires.745 ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];746 InitializedEntity IE = InitializedEntity::InitializeParameter(Context,747 ParamDecl);748 ConvertedValueExpr =749 SemaRef.PerformCopyInitialization(IE, SourceLocation(), ValueExpr);750 }751 752 if (ConvertedValueExpr.isInvalid())753 return ExprError();754 ValueExpr = ConvertedValueExpr.get();755 756 ObjCBoxedExpr *BoxedExpr =757 new (Context) ObjCBoxedExpr(ValueExpr, BoxedType,758 BoxingMethod, SR);759 return SemaRef.MaybeBindToTemporary(BoxedExpr);760}761 762/// Build an ObjC subscript pseudo-object expression, given that763/// that's supported by the runtime.764ExprResult SemaObjC::BuildObjCSubscriptExpression(765 SourceLocation RB, Expr *BaseExpr, Expr *IndexExpr,766 ObjCMethodDecl *getterMethod, ObjCMethodDecl *setterMethod) {767 assert(!getLangOpts().isSubscriptPointerArithmetic());768 ASTContext &Context = getASTContext();769 770 // We can't get dependent types here; our callers should have771 // filtered them out.772 assert((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) &&773 "base or index cannot have dependent type here");774 775 // Filter out placeholders in the index. In theory, overloads could776 // be preserved here, although that might not actually work correctly.777 ExprResult Result = SemaRef.CheckPlaceholderExpr(IndexExpr);778 if (Result.isInvalid())779 return ExprError();780 IndexExpr = Result.get();781 782 // Perform lvalue-to-rvalue conversion on the base.783 Result = SemaRef.DefaultLvalueConversion(BaseExpr);784 if (Result.isInvalid())785 return ExprError();786 BaseExpr = Result.get();787 788 // Build the pseudo-object expression.789 return new (Context) ObjCSubscriptRefExpr(790 BaseExpr, IndexExpr, Context.PseudoObjectTy, VK_LValue, OK_ObjCSubscript,791 getterMethod, setterMethod, RB);792}793 794ExprResult SemaObjC::BuildObjCArrayLiteral(SourceRange SR,795 MultiExprArg Elements) {796 ASTContext &Context = getASTContext();797 SourceLocation Loc = SR.getBegin();798 799 if (!NSArrayDecl) {800 NSArrayDecl =801 LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, SemaObjC::LK_Array);802 if (!NSArrayDecl) {803 return ExprError();804 }805 }806 807 // Find the arrayWithObjects:count: method, if we haven't done so already.808 QualType IdT = Context.getObjCIdType();809 if (!ArrayWithObjectsMethod) {810 Selector811 Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);812 ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);813 if (!Method && getLangOpts().DebuggerObjCLiteral) {814 TypeSourceInfo *ReturnTInfo = nullptr;815 Method = ObjCMethodDecl::Create(816 Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,817 Context.getTranslationUnitDecl(), false /*Instance*/,818 false /*isVariadic*/,819 /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,820 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,821 ObjCImplementationControl::Required, false);822 SmallVector<ParmVarDecl *, 2> Params;823 ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,824 SourceLocation(),825 SourceLocation(),826 &Context.Idents.get("objects"),827 Context.getPointerType(IdT),828 /*TInfo=*/nullptr,829 SC_None, nullptr);830 Params.push_back(objects);831 ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,832 SourceLocation(),833 SourceLocation(),834 &Context.Idents.get("cnt"),835 Context.UnsignedLongTy,836 /*TInfo=*/nullptr, SC_None,837 nullptr);838 Params.push_back(cnt);839 Method->setMethodParams(Context, Params, {});840 }841 842 if (!validateBoxingMethod(SemaRef, Loc, NSArrayDecl, Sel, Method))843 return ExprError();844 845 // Dig out the type that all elements should be converted to.846 QualType T = Method->parameters()[0]->getType();847 const PointerType *PtrT = T->getAs<PointerType>();848 if (!PtrT ||849 !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {850 Diag(SR.getBegin(), diag::err_objc_literal_method_sig)851 << Sel;852 Diag(Method->parameters()[0]->getLocation(),853 diag::note_objc_literal_method_param)854 << 0 << T855 << Context.getPointerType(IdT.withConst());856 return ExprError();857 }858 859 // Check that the 'count' parameter is integral.860 if (!Method->parameters()[1]->getType()->isIntegerType()) {861 Diag(SR.getBegin(), diag::err_objc_literal_method_sig)862 << Sel;863 Diag(Method->parameters()[1]->getLocation(),864 diag::note_objc_literal_method_param)865 << 1866 << Method->parameters()[1]->getType()867 << "integral";868 return ExprError();869 }870 871 // We've found a good +arrayWithObjects:count: method. Save it!872 ArrayWithObjectsMethod = Method;873 }874 875 QualType ObjectsType = ArrayWithObjectsMethod->parameters()[0]->getType();876 QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType();877 878 // Check that each of the elements provided is valid in a collection literal,879 // performing conversions as necessary.880 Expr **ElementsBuffer = Elements.data();881 for (unsigned I = 0, N = Elements.size(); I != N; ++I) {882 ExprResult Converted = CheckObjCCollectionLiteralElement(883 SemaRef, ElementsBuffer[I], RequiredType, true);884 if (Converted.isInvalid())885 return ExprError();886 887 ElementsBuffer[I] = Converted.get();888 }889 890 QualType Ty891 = Context.getObjCObjectPointerType(892 Context.getObjCInterfaceType(NSArrayDecl));893 894 return SemaRef.MaybeBindToTemporary(ObjCArrayLiteral::Create(895 Context, Elements, Ty, ArrayWithObjectsMethod, SR));896}897 898/// Check for duplicate keys in an ObjC dictionary literal. For instance:899/// NSDictionary *nd = @{ @"foo" : @"bar", @"foo" : @"baz" };900static void901CheckObjCDictionaryLiteralDuplicateKeys(Sema &S,902 ObjCDictionaryLiteral *Literal) {903 if (Literal->isValueDependent() || Literal->isTypeDependent())904 return;905 906 // NSNumber has quite relaxed equality semantics (for instance, @YES is907 // considered equal to @1.0). For now, ignore floating points and just do a908 // bit-width and sign agnostic integer compare.909 struct APSIntCompare {910 bool operator()(const llvm::APSInt &LHS, const llvm::APSInt &RHS) const {911 return llvm::APSInt::compareValues(LHS, RHS) < 0;912 }913 };914 915 llvm::DenseMap<StringRef, SourceLocation> StringKeys;916 std::map<llvm::APSInt, SourceLocation, APSIntCompare> IntegralKeys;917 918 auto checkOneKey = [&](auto &Map, const auto &Key, SourceLocation Loc) {919 auto Pair = Map.insert({Key, Loc});920 if (!Pair.second) {921 S.Diag(Loc, diag::warn_nsdictionary_duplicate_key);922 S.Diag(Pair.first->second, diag::note_nsdictionary_duplicate_key_here);923 }924 };925 926 for (unsigned Idx = 0, End = Literal->getNumElements(); Idx != End; ++Idx) {927 Expr *Key = Literal->getKeyValueElement(Idx).Key->IgnoreParenImpCasts();928 929 if (auto *StrLit = dyn_cast<ObjCStringLiteral>(Key)) {930 StringRef Bytes = StrLit->getString()->getBytes();931 SourceLocation Loc = StrLit->getExprLoc();932 checkOneKey(StringKeys, Bytes, Loc);933 }934 935 if (auto *BE = dyn_cast<ObjCBoxedExpr>(Key)) {936 Expr *Boxed = BE->getSubExpr();937 SourceLocation Loc = BE->getExprLoc();938 939 // Check for @("foo").940 if (auto *Str = dyn_cast<StringLiteral>(Boxed->IgnoreParenImpCasts())) {941 checkOneKey(StringKeys, Str->getBytes(), Loc);942 continue;943 }944 945 Expr::EvalResult Result;946 if (Boxed->EvaluateAsInt(Result, S.getASTContext(),947 Expr::SE_AllowSideEffects)) {948 checkOneKey(IntegralKeys, Result.Val.getInt(), Loc);949 }950 }951 }952}953 954ExprResult SemaObjC::BuildObjCDictionaryLiteral(955 SourceRange SR, MutableArrayRef<ObjCDictionaryElement> Elements) {956 ASTContext &Context = getASTContext();957 SourceLocation Loc = SR.getBegin();958 959 if (!NSDictionaryDecl) {960 NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(961 SemaRef, Loc, SemaObjC::LK_Dictionary);962 if (!NSDictionaryDecl) {963 return ExprError();964 }965 }966 967 // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done968 // so already.969 QualType IdT = Context.getObjCIdType();970 if (!DictionaryWithObjectsMethod) {971 Selector Sel = NSAPIObj->getNSDictionarySelector(972 NSAPI::NSDict_dictionaryWithObjectsForKeysCount);973 ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);974 if (!Method && getLangOpts().DebuggerObjCLiteral) {975 Method = ObjCMethodDecl::Create(976 Context, SourceLocation(), SourceLocation(), Sel, IdT,977 nullptr /*TypeSourceInfo */, Context.getTranslationUnitDecl(),978 false /*Instance*/, false /*isVariadic*/,979 /*isPropertyAccessor=*/false,980 /*isSynthesizedAccessorStub=*/false,981 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,982 ObjCImplementationControl::Required, false);983 SmallVector<ParmVarDecl *, 3> Params;984 ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,985 SourceLocation(),986 SourceLocation(),987 &Context.Idents.get("objects"),988 Context.getPointerType(IdT),989 /*TInfo=*/nullptr, SC_None,990 nullptr);991 Params.push_back(objects);992 ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,993 SourceLocation(),994 SourceLocation(),995 &Context.Idents.get("keys"),996 Context.getPointerType(IdT),997 /*TInfo=*/nullptr, SC_None,998 nullptr);999 Params.push_back(keys);1000 ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,1001 SourceLocation(),1002 SourceLocation(),1003 &Context.Idents.get("cnt"),1004 Context.UnsignedLongTy,1005 /*TInfo=*/nullptr, SC_None,1006 nullptr);1007 Params.push_back(cnt);1008 Method->setMethodParams(Context, Params, {});1009 }1010 1011 if (!validateBoxingMethod(SemaRef, SR.getBegin(), NSDictionaryDecl, Sel,1012 Method))1013 return ExprError();1014 1015 // Dig out the type that all values should be converted to.1016 QualType ValueT = Method->parameters()[0]->getType();1017 const PointerType *PtrValue = ValueT->getAs<PointerType>();1018 if (!PtrValue ||1019 !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {1020 Diag(SR.getBegin(), diag::err_objc_literal_method_sig)1021 << Sel;1022 Diag(Method->parameters()[0]->getLocation(),1023 diag::note_objc_literal_method_param)1024 << 0 << ValueT1025 << Context.getPointerType(IdT.withConst());1026 return ExprError();1027 }1028 1029 // Dig out the type that all keys should be converted to.1030 QualType KeyT = Method->parameters()[1]->getType();1031 const PointerType *PtrKey = KeyT->getAs<PointerType>();1032 if (!PtrKey ||1033 !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),1034 IdT)) {1035 bool err = true;1036 if (PtrKey) {1037 if (QIDNSCopying.isNull()) {1038 // key argument of selector is id<NSCopying>?1039 if (ObjCProtocolDecl *NSCopyingPDecl =1040 LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {1041 ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};1042 QIDNSCopying = Context.getObjCObjectType(1043 Context.ObjCBuiltinIdTy, {},1044 llvm::ArrayRef((ObjCProtocolDecl **)PQ, 1), false);1045 QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);1046 }1047 }1048 if (!QIDNSCopying.isNull())1049 err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),1050 QIDNSCopying);1051 }1052 1053 if (err) {1054 Diag(SR.getBegin(), diag::err_objc_literal_method_sig)1055 << Sel;1056 Diag(Method->parameters()[1]->getLocation(),1057 diag::note_objc_literal_method_param)1058 << 1 << KeyT1059 << Context.getPointerType(IdT.withConst());1060 return ExprError();1061 }1062 }1063 1064 // Check that the 'count' parameter is integral.1065 QualType CountType = Method->parameters()[2]->getType();1066 if (!CountType->isIntegerType()) {1067 Diag(SR.getBegin(), diag::err_objc_literal_method_sig)1068 << Sel;1069 Diag(Method->parameters()[2]->getLocation(),1070 diag::note_objc_literal_method_param)1071 << 2 << CountType1072 << "integral";1073 return ExprError();1074 }1075 1076 // We've found a good +dictionaryWithObjects:keys:count: method; save it!1077 DictionaryWithObjectsMethod = Method;1078 }1079 1080 QualType ValuesT = DictionaryWithObjectsMethod->parameters()[0]->getType();1081 QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType();1082 QualType KeysT = DictionaryWithObjectsMethod->parameters()[1]->getType();1083 QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType();1084 1085 // Check that each of the keys and values provided is valid in a collection1086 // literal, performing conversions as necessary.1087 bool HasPackExpansions = false;1088 for (ObjCDictionaryElement &Element : Elements) {1089 // Check the key.1090 ExprResult Key =1091 CheckObjCCollectionLiteralElement(SemaRef, Element.Key, KeyT);1092 if (Key.isInvalid())1093 return ExprError();1094 1095 // Check the value.1096 ExprResult Value =1097 CheckObjCCollectionLiteralElement(SemaRef, Element.Value, ValueT);1098 if (Value.isInvalid())1099 return ExprError();1100 1101 Element.Key = Key.get();1102 Element.Value = Value.get();1103 1104 if (Element.EllipsisLoc.isInvalid())1105 continue;1106 1107 if (!Element.Key->containsUnexpandedParameterPack() &&1108 !Element.Value->containsUnexpandedParameterPack()) {1109 Diag(Element.EllipsisLoc,1110 diag::err_pack_expansion_without_parameter_packs)1111 << SourceRange(Element.Key->getBeginLoc(),1112 Element.Value->getEndLoc());1113 return ExprError();1114 }1115 1116 HasPackExpansions = true;1117 }1118 1119 QualType Ty = Context.getObjCObjectPointerType(1120 Context.getObjCInterfaceType(NSDictionaryDecl));1121 1122 auto *Literal =1123 ObjCDictionaryLiteral::Create(Context, Elements, HasPackExpansions, Ty,1124 DictionaryWithObjectsMethod, SR);1125 CheckObjCDictionaryLiteralDuplicateKeys(SemaRef, Literal);1126 return SemaRef.MaybeBindToTemporary(Literal);1127}1128 1129ExprResult SemaObjC::BuildObjCEncodeExpression(SourceLocation AtLoc,1130 TypeSourceInfo *EncodedTypeInfo,1131 SourceLocation RParenLoc) {1132 ASTContext &Context = getASTContext();1133 QualType EncodedType = EncodedTypeInfo->getType();1134 QualType StrTy;1135 if (EncodedType->isDependentType())1136 StrTy = Context.DependentTy;1137 else {1138 if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled.1139 !EncodedType->isVoidType()) // void is handled too.1140 if (SemaRef.RequireCompleteType(AtLoc, EncodedType,1141 diag::err_incomplete_type_objc_at_encode,1142 EncodedTypeInfo->getTypeLoc()))1143 return ExprError();1144 1145 std::string Str;1146 QualType NotEncodedT;1147 Context.getObjCEncodingForType(EncodedType, Str, nullptr, &NotEncodedT);1148 if (!NotEncodedT.isNull())1149 Diag(AtLoc, diag::warn_incomplete_encoded_type)1150 << EncodedType << NotEncodedT;1151 1152 // The type of @encode is the same as the type of the corresponding string,1153 // which is an array type.1154 StrTy = Context.getStringLiteralArrayType(Context.CharTy, Str.size());1155 }1156 1157 return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);1158}1159 1160ExprResult SemaObjC::ParseObjCEncodeExpression(SourceLocation AtLoc,1161 SourceLocation EncodeLoc,1162 SourceLocation LParenLoc,1163 ParsedType ty,1164 SourceLocation RParenLoc) {1165 ASTContext &Context = getASTContext();1166 // FIXME: Preserve type source info ?1167 TypeSourceInfo *TInfo;1168 QualType EncodedType = SemaRef.GetTypeFromParser(ty, &TInfo);1169 if (!TInfo)1170 TInfo = Context.getTrivialTypeSourceInfo(1171 EncodedType, SemaRef.getLocForEndOfToken(LParenLoc));1172 1173 return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);1174}1175 1176static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,1177 SourceLocation AtLoc,1178 SourceLocation LParenLoc,1179 SourceLocation RParenLoc,1180 ObjCMethodDecl *Method,1181 ObjCMethodList &MethList) {1182 ObjCMethodList *M = &MethList;1183 bool Warned = false;1184 for (M = M->getNext(); M; M=M->getNext()) {1185 ObjCMethodDecl *MatchingMethodDecl = M->getMethod();1186 if (MatchingMethodDecl == Method ||1187 isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) ||1188 MatchingMethodDecl->getSelector() != Method->getSelector())1189 continue;1190 if (!S.ObjC().MatchTwoMethodDeclarations(Method, MatchingMethodDecl,1191 SemaObjC::MMS_loose)) {1192 if (!Warned) {1193 Warned = true;1194 S.Diag(AtLoc, diag::warn_multiple_selectors)1195 << Method->getSelector() << FixItHint::CreateInsertion(LParenLoc, "(")1196 << FixItHint::CreateInsertion(RParenLoc, ")");1197 S.Diag(Method->getLocation(), diag::note_method_declared_at)1198 << Method->getDeclName();1199 }1200 S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at)1201 << MatchingMethodDecl->getDeclName();1202 }1203 }1204 return Warned;1205}1206 1207static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,1208 ObjCMethodDecl *Method,1209 SourceLocation LParenLoc,1210 SourceLocation RParenLoc,1211 bool WarnMultipleSelectors) {1212 if (!WarnMultipleSelectors ||1213 S.Diags.isIgnored(diag::warn_multiple_selectors, SourceLocation()))1214 return;1215 bool Warned = false;1216 for (SemaObjC::GlobalMethodPool::iterator b = S.ObjC().MethodPool.begin(),1217 e = S.ObjC().MethodPool.end();1218 b != e; b++) {1219 // first, instance methods1220 ObjCMethodList &InstMethList = b->second.first;1221 if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,1222 Method, InstMethList))1223 Warned = true;1224 1225 // second, class methods1226 ObjCMethodList &ClsMethList = b->second.second;1227 if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,1228 Method, ClsMethList) || Warned)1229 return;1230 }1231}1232 1233static ObjCMethodDecl *LookupDirectMethodInMethodList(Sema &S, Selector Sel,1234 ObjCMethodList &MethList,1235 bool &onlyDirect,1236 bool &anyDirect) {1237 (void)Sel;1238 ObjCMethodList *M = &MethList;1239 ObjCMethodDecl *DirectMethod = nullptr;1240 for (; M; M = M->getNext()) {1241 ObjCMethodDecl *Method = M->getMethod();1242 if (!Method)1243 continue;1244 assert(Method->getSelector() == Sel && "Method with wrong selector in method list");1245 if (Method->isDirectMethod()) {1246 anyDirect = true;1247 DirectMethod = Method;1248 } else1249 onlyDirect = false;1250 }1251 1252 return DirectMethod;1253}1254 1255// Search the global pool for (potentially) direct methods matching the given1256// selector. If a non-direct method is found, set \param onlyDirect to false. If1257// a direct method is found, set \param anyDirect to true. Returns a direct1258// method, if any.1259static ObjCMethodDecl *LookupDirectMethodInGlobalPool(Sema &S, Selector Sel,1260 bool &onlyDirect,1261 bool &anyDirect) {1262 auto Iter = S.ObjC().MethodPool.find(Sel);1263 if (Iter == S.ObjC().MethodPool.end())1264 return nullptr;1265 1266 ObjCMethodDecl *DirectInstance = LookupDirectMethodInMethodList(1267 S, Sel, Iter->second.first, onlyDirect, anyDirect);1268 ObjCMethodDecl *DirectClass = LookupDirectMethodInMethodList(1269 S, Sel, Iter->second.second, onlyDirect, anyDirect);1270 1271 return DirectInstance ? DirectInstance : DirectClass;1272}1273 1274static ObjCMethodDecl *findMethodInCurrentClass(Sema &S, Selector Sel) {1275 auto *CurMD = S.getCurMethodDecl();1276 if (!CurMD)1277 return nullptr;1278 ObjCInterfaceDecl *IFace = CurMD->getClassInterface();1279 1280 // The language enforce that only one direct method is present in a given1281 // class, so we just need to find one method in the current class to know1282 // whether Sel is potentially direct in this context.1283 if (ObjCMethodDecl *MD = IFace->lookupMethod(Sel, /*isInstance=*/true))1284 return MD;1285 if (ObjCMethodDecl *MD = IFace->lookupPrivateMethod(Sel, /*Instance=*/true))1286 return MD;1287 if (ObjCMethodDecl *MD = IFace->lookupMethod(Sel, /*isInstance=*/false))1288 return MD;1289 if (ObjCMethodDecl *MD = IFace->lookupPrivateMethod(Sel, /*Instance=*/false))1290 return MD;1291 1292 return nullptr;1293}1294 1295ExprResult SemaObjC::ParseObjCSelectorExpression(Selector Sel,1296 SourceLocation AtLoc,1297 SourceLocation SelLoc,1298 SourceLocation LParenLoc,1299 SourceLocation RParenLoc,1300 bool WarnMultipleSelectors) {1301 ASTContext &Context = getASTContext();1302 ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,1303 SourceRange(LParenLoc, RParenLoc));1304 if (!Method)1305 Method = LookupFactoryMethodInGlobalPool(Sel,1306 SourceRange(LParenLoc, RParenLoc));1307 if (!Method) {1308 if (const ObjCMethodDecl *OM = SelectorsForTypoCorrection(Sel)) {1309 Selector MatchedSel = OM->getSelector();1310 SourceRange SelectorRange(LParenLoc.getLocWithOffset(1),1311 RParenLoc.getLocWithOffset(-1));1312 Diag(SelLoc, diag::warn_undeclared_selector_with_typo)1313 << Sel << MatchedSel1314 << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());1315 1316 } else1317 Diag(SelLoc, diag::warn_undeclared_selector) << Sel;1318 } else {1319 DiagnoseMismatchedSelectors(SemaRef, AtLoc, Method, LParenLoc, RParenLoc,1320 WarnMultipleSelectors);1321 1322 bool onlyDirect = true;1323 bool anyDirect = false;1324 ObjCMethodDecl *GlobalDirectMethod =1325 LookupDirectMethodInGlobalPool(SemaRef, Sel, onlyDirect, anyDirect);1326 1327 if (onlyDirect) {1328 Diag(AtLoc, diag::err_direct_selector_expression)1329 << Method->getSelector();1330 Diag(Method->getLocation(), diag::note_direct_method_declared_at)1331 << Method->getDeclName();1332 } else if (anyDirect) {1333 // If we saw any direct methods, see if we see a direct member of the1334 // current class. If so, the @selector will likely be used to refer to1335 // this direct method.1336 ObjCMethodDecl *LikelyTargetMethod =1337 findMethodInCurrentClass(SemaRef, Sel);1338 if (LikelyTargetMethod && LikelyTargetMethod->isDirectMethod()) {1339 Diag(AtLoc, diag::warn_potentially_direct_selector_expression) << Sel;1340 Diag(LikelyTargetMethod->getLocation(),1341 diag::note_direct_method_declared_at)1342 << LikelyTargetMethod->getDeclName();1343 } else if (!LikelyTargetMethod) {1344 // Otherwise, emit the "strict" variant of this diagnostic, unless1345 // LikelyTargetMethod is non-direct.1346 Diag(AtLoc, diag::warn_strict_potentially_direct_selector_expression)1347 << Sel;1348 Diag(GlobalDirectMethod->getLocation(),1349 diag::note_direct_method_declared_at)1350 << GlobalDirectMethod->getDeclName();1351 }1352 }1353 }1354 1355 if (Method &&1356 Method->getImplementationControl() !=1357 ObjCImplementationControl::Optional &&1358 !SemaRef.getSourceManager().isInSystemHeader(Method->getLocation()))1359 ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));1360 1361 // In ARC, forbid the user from using @selector for1362 // retain/release/autorelease/dealloc/retainCount.1363 if (getLangOpts().ObjCAutoRefCount) {1364 switch (Sel.getMethodFamily()) {1365 case OMF_retain:1366 case OMF_release:1367 case OMF_autorelease:1368 case OMF_retainCount:1369 case OMF_dealloc:1370 Diag(AtLoc, diag::err_arc_illegal_selector) <<1371 Sel << SourceRange(LParenLoc, RParenLoc);1372 break;1373 1374 case OMF_None:1375 case OMF_alloc:1376 case OMF_copy:1377 case OMF_finalize:1378 case OMF_init:1379 case OMF_mutableCopy:1380 case OMF_new:1381 case OMF_self:1382 case OMF_initialize:1383 case OMF_performSelector:1384 break;1385 }1386 }1387 QualType Ty = Context.getObjCSelType();1388 return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);1389}1390 1391ExprResult SemaObjC::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,1392 SourceLocation AtLoc,1393 SourceLocation ProtoLoc,1394 SourceLocation LParenLoc,1395 SourceLocation ProtoIdLoc,1396 SourceLocation RParenLoc) {1397 ASTContext &Context = getASTContext();1398 ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoIdLoc);1399 if (!PDecl) {1400 Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;1401 return true;1402 }1403 if (PDecl->isNonRuntimeProtocol())1404 Diag(ProtoLoc, diag::err_objc_non_runtime_protocol_in_protocol_expr)1405 << PDecl;1406 if (!PDecl->hasDefinition()) {1407 Diag(ProtoLoc, diag::err_atprotocol_protocol) << PDecl;1408 Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;1409 } else {1410 PDecl = PDecl->getDefinition();1411 }1412 1413 QualType Ty = Context.getObjCProtoType();1414 if (Ty.isNull())1415 return true;1416 Ty = Context.getObjCObjectPointerType(Ty);1417 return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, ProtoIdLoc, RParenLoc);1418}1419 1420/// Try to capture an implicit reference to 'self'.1421ObjCMethodDecl *SemaObjC::tryCaptureObjCSelf(SourceLocation Loc) {1422 DeclContext *DC = SemaRef.getFunctionLevelDeclContext();1423 1424 // If we're not in an ObjC method, error out. Note that, unlike the1425 // C++ case, we don't require an instance method --- class methods1426 // still have a 'self', and we really do still need to capture it!1427 ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC);1428 if (!method)1429 return nullptr;1430 1431 SemaRef.tryCaptureVariable(method->getSelfDecl(), Loc);1432 1433 return method;1434}1435 1436static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {1437 QualType origType = T;1438 if (auto nullability = AttributedType::stripOuterNullability(T)) {1439 if (T == Context.getObjCInstanceType()) {1440 return Context.getAttributedType(*nullability, Context.getObjCIdType(),1441 Context.getObjCIdType());1442 }1443 1444 return origType;1445 }1446 1447 if (T == Context.getObjCInstanceType())1448 return Context.getObjCIdType();1449 1450 return origType;1451}1452 1453/// Determine the result type of a message send based on the receiver type,1454/// method, and the kind of message send.1455///1456/// This is the "base" result type, which will still need to be adjusted1457/// to account for nullability.1458static QualType getBaseMessageSendResultType(Sema &S,1459 QualType ReceiverType,1460 ObjCMethodDecl *Method,1461 bool isClassMessage,1462 bool isSuperMessage) {1463 assert(Method && "Must have a method");1464 if (!Method->hasRelatedResultType())1465 return Method->getSendResultType(ReceiverType);1466 1467 ASTContext &Context = S.Context;1468 1469 // Local function that transfers the nullability of the method's1470 // result type to the returned result.1471 auto transferNullability = [&](QualType type) -> QualType {1472 // If the method's result type has nullability, extract it.1473 if (auto nullability =1474 Method->getSendResultType(ReceiverType)->getNullability()) {1475 // Strip off any outer nullability sugar from the provided type.1476 (void)AttributedType::stripOuterNullability(type);1477 1478 // Form a new attributed type using the method result type's nullability.1479 return Context.getAttributedType(*nullability, type, type);1480 }1481 1482 return type;1483 };1484 1485 // If a method has a related return type:1486 // - if the method found is an instance method, but the message send1487 // was a class message send, T is the declared return type of the method1488 // found1489 if (Method->isInstanceMethod() && isClassMessage)1490 return stripObjCInstanceType(Context,1491 Method->getSendResultType(ReceiverType));1492 1493 // - if the receiver is super, T is a pointer to the class of the1494 // enclosing method definition1495 if (isSuperMessage) {1496 if (ObjCMethodDecl *CurMethod = S.getCurMethodDecl())1497 if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) {1498 return transferNullability(1499 Context.getObjCObjectPointerType(1500 Context.getObjCInterfaceType(Class)));1501 }1502 }1503 1504 // - if the receiver is the name of a class U, T is a pointer to U1505 if (ReceiverType->getAsObjCInterfaceType())1506 return transferNullability(Context.getObjCObjectPointerType(ReceiverType));1507 // - if the receiver is of type Class or qualified Class type,1508 // T is the declared return type of the method.1509 if (ReceiverType->isObjCClassType() ||1510 ReceiverType->isObjCQualifiedClassType())1511 return stripObjCInstanceType(Context,1512 Method->getSendResultType(ReceiverType));1513 1514 // - if the receiver is id, qualified id, Class, or qualified Class, T1515 // is the receiver type, otherwise1516 // - T is the type of the receiver expression.1517 return transferNullability(ReceiverType);1518}1519 1520QualType SemaObjC::getMessageSendResultType(const Expr *Receiver,1521 QualType ReceiverType,1522 ObjCMethodDecl *Method,1523 bool isClassMessage,1524 bool isSuperMessage) {1525 ASTContext &Context = getASTContext();1526 // Produce the result type.1527 QualType resultType = getBaseMessageSendResultType(1528 SemaRef, ReceiverType, Method, isClassMessage, isSuperMessage);1529 1530 // If this is a class message, ignore the nullability of the receiver.1531 if (isClassMessage) {1532 // In a class method, class messages to 'self' that return instancetype can1533 // be typed as the current class. We can safely do this in ARC because self1534 // can't be reassigned, and we do it unsafely outside of ARC because in1535 // practice people never reassign self in class methods and there's some1536 // virtue in not being aggressively pedantic.1537 if (Receiver && Receiver->isObjCSelfExpr()) {1538 assert(ReceiverType->isObjCClassType() && "expected a Class self");1539 QualType T = Method->getSendResultType(ReceiverType);1540 AttributedType::stripOuterNullability(T);1541 if (T == Context.getObjCInstanceType()) {1542 const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(1543 cast<ImplicitParamDecl>(1544 cast<DeclRefExpr>(Receiver->IgnoreParenImpCasts())->getDecl())1545 ->getDeclContext());1546 assert(MD->isClassMethod() && "expected a class method");1547 QualType NewResultType = Context.getObjCObjectPointerType(1548 Context.getObjCInterfaceType(MD->getClassInterface()));1549 if (auto Nullability = resultType->getNullability())1550 NewResultType = Context.getAttributedType(*Nullability, NewResultType,1551 NewResultType);1552 return NewResultType;1553 }1554 }1555 return resultType;1556 }1557 1558 // There is nothing left to do if the result type cannot have a nullability1559 // specifier.1560 if (!resultType->canHaveNullability())1561 return resultType;1562 1563 // Map the nullability of the result into a table index.1564 unsigned receiverNullabilityIdx = 0;1565 if (std::optional<NullabilityKind> nullability =1566 ReceiverType->getNullability()) {1567 if (*nullability == NullabilityKind::NullableResult)1568 nullability = NullabilityKind::Nullable;1569 receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);1570 }1571 1572 unsigned resultNullabilityIdx = 0;1573 if (std::optional<NullabilityKind> nullability =1574 resultType->getNullability()) {1575 if (*nullability == NullabilityKind::NullableResult)1576 nullability = NullabilityKind::Nullable;1577 resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability);1578 }1579 1580 // The table of nullability mappings, indexed by the receiver's nullability1581 // and then the result type's nullability.1582 static const uint8_t None = 0;1583 static const uint8_t NonNull = 1;1584 static const uint8_t Nullable = 2;1585 static const uint8_t Unspecified = 3;1586 static const uint8_t nullabilityMap[4][4] = {1587 // None NonNull Nullable Unspecified1588 /* None */ { None, None, Nullable, None },1589 /* NonNull */ { None, NonNull, Nullable, Unspecified },1590 /* Nullable */ { Nullable, Nullable, Nullable, Nullable },1591 /* Unspecified */ { None, Unspecified, Nullable, Unspecified }1592 };1593 1594 unsigned newResultNullabilityIdx1595 = nullabilityMap[receiverNullabilityIdx][resultNullabilityIdx];1596 if (newResultNullabilityIdx == resultNullabilityIdx)1597 return resultType;1598 1599 // Strip off the existing nullability. This removes as little type sugar as1600 // possible.1601 do {1602 if (auto attributed = dyn_cast<AttributedType>(resultType.getTypePtr())) {1603 resultType = attributed->getModifiedType();1604 } else {1605 resultType = resultType.getDesugaredType(Context);1606 }1607 } while (resultType->getNullability());1608 1609 // Add nullability back if needed.1610 if (newResultNullabilityIdx > 0) {1611 auto newNullability1612 = static_cast<NullabilityKind>(newResultNullabilityIdx-1);1613 return Context.getAttributedType(newNullability, resultType, resultType);1614 }1615 1616 return resultType;1617}1618 1619/// Look for an ObjC method whose result type exactly matches the given type.1620static const ObjCMethodDecl *1621findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,1622 QualType instancetype) {1623 if (MD->getReturnType() == instancetype)1624 return MD;1625 1626 // For these purposes, a method in an @implementation overrides a1627 // declaration in the @interface.1628 if (const ObjCImplDecl *impl =1629 dyn_cast<ObjCImplDecl>(MD->getDeclContext())) {1630 const ObjCContainerDecl *iface;1631 if (const ObjCCategoryImplDecl *catImpl =1632 dyn_cast<ObjCCategoryImplDecl>(impl)) {1633 iface = catImpl->getCategoryDecl();1634 } else {1635 iface = impl->getClassInterface();1636 }1637 1638 const ObjCMethodDecl *ifaceMD =1639 iface->getMethod(MD->getSelector(), MD->isInstanceMethod());1640 if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype);1641 }1642 1643 SmallVector<const ObjCMethodDecl *, 4> overrides;1644 MD->getOverriddenMethods(overrides);1645 for (unsigned i = 0, e = overrides.size(); i != e; ++i) {1646 if (const ObjCMethodDecl *result =1647 findExplicitInstancetypeDeclarer(overrides[i], instancetype))1648 return result;1649 }1650 1651 return nullptr;1652}1653 1654void SemaObjC::EmitRelatedResultTypeNoteForReturn(QualType destType) {1655 ASTContext &Context = getASTContext();1656 // Only complain if we're in an ObjC method and the required return1657 // type doesn't match the method's declared return type.1658 ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext);1659 if (!MD || !MD->hasRelatedResultType() ||1660 Context.hasSameUnqualifiedType(destType, MD->getReturnType()))1661 return;1662 1663 // Look for a method overridden by this method which explicitly uses1664 // 'instancetype'.1665 if (const ObjCMethodDecl *overridden =1666 findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {1667 SourceRange range = overridden->getReturnTypeSourceRange();1668 SourceLocation loc = range.getBegin();1669 if (loc.isInvalid())1670 loc = overridden->getLocation();1671 Diag(loc, diag::note_related_result_type_explicit)1672 << /*current method*/ 1 << range;1673 return;1674 }1675 1676 // Otherwise, if we have an interesting method family, note that.1677 // This should always trigger if the above didn't.1678 if (ObjCMethodFamily family = MD->getMethodFamily())1679 Diag(MD->getLocation(), diag::note_related_result_type_family)1680 << /*current method*/ 11681 << family;1682}1683 1684void SemaObjC::EmitRelatedResultTypeNote(const Expr *E) {1685 ASTContext &Context = getASTContext();1686 E = E->IgnoreParenImpCasts();1687 const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);1688 if (!MsgSend)1689 return;1690 1691 const ObjCMethodDecl *Method = MsgSend->getMethodDecl();1692 if (!Method)1693 return;1694 1695 if (!Method->hasRelatedResultType())1696 return;1697 1698 if (Context.hasSameUnqualifiedType(1699 Method->getReturnType().getNonReferenceType(), MsgSend->getType()))1700 return;1701 1702 if (!Context.hasSameUnqualifiedType(Method->getReturnType(),1703 Context.getObjCInstanceType()))1704 return;1705 1706 Diag(Method->getLocation(), diag::note_related_result_type_inferred)1707 << Method->isInstanceMethod() << Method->getSelector()1708 << MsgSend->getType();1709}1710 1711bool SemaObjC::CheckMessageArgumentTypes(1712 const Expr *Receiver, QualType ReceiverType, MultiExprArg Args,1713 Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method,1714 bool isClassMessage, bool isSuperMessage, SourceLocation lbrac,1715 SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType,1716 ExprValueKind &VK) {1717 ASTContext &Context = getASTContext();1718 SourceLocation SelLoc;1719 if (!SelectorLocs.empty() && SelectorLocs.front().isValid())1720 SelLoc = SelectorLocs.front();1721 else1722 SelLoc = lbrac;1723 1724 if (!Method) {1725 // Apply default argument promotion as for (C99 6.5.2.2p6).1726 for (unsigned i = 0, e = Args.size(); i != e; i++) {1727 if (Args[i]->isTypeDependent())1728 continue;1729 1730 ExprResult result;1731 if (getLangOpts().DebuggerSupport) {1732 QualType paramTy; // ignored1733 result = SemaRef.checkUnknownAnyArg(SelLoc, Args[i], paramTy);1734 } else {1735 result = SemaRef.DefaultArgumentPromotion(Args[i]);1736 }1737 if (result.isInvalid())1738 return true;1739 Args[i] = result.get();1740 }1741 1742 unsigned DiagID;1743 if (getLangOpts().ObjCAutoRefCount)1744 DiagID = diag::err_arc_method_not_found;1745 else1746 DiagID = isClassMessage ? diag::warn_class_method_not_found1747 : diag::warn_inst_method_not_found;1748 if (!getLangOpts().DebuggerSupport) {1749 const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType);1750 if (OMD && !OMD->isInvalidDecl()) {1751 if (getLangOpts().ObjCAutoRefCount)1752 DiagID = diag::err_method_not_found_with_typo;1753 else1754 DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo1755 : diag::warn_instance_method_not_found_with_typo;1756 Selector MatchedSel = OMD->getSelector();1757 SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back());1758 if (MatchedSel.isUnarySelector())1759 Diag(SelLoc, DiagID)1760 << Sel<< isClassMessage << MatchedSel1761 << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());1762 else1763 Diag(SelLoc, DiagID) << Sel<< isClassMessage << MatchedSel;1764 }1765 else1766 Diag(SelLoc, DiagID)1767 << Sel << isClassMessage << SourceRange(SelectorLocs.front(),1768 SelectorLocs.back());1769 // Find the class to which we are sending this message.1770 if (auto *ObjPT = ReceiverType->getAs<ObjCObjectPointerType>()) {1771 if (ObjCInterfaceDecl *ThisClass = ObjPT->getInterfaceDecl()) {1772 Diag(ThisClass->getLocation(), diag::note_receiver_class_declared);1773 if (!RecRange.isInvalid())1774 if (ThisClass->lookupClassMethod(Sel))1775 Diag(RecRange.getBegin(), diag::note_receiver_expr_here)1776 << FixItHint::CreateReplacement(RecRange,1777 ThisClass->getNameAsString());1778 }1779 }1780 }1781 1782 // In debuggers, we want to use __unknown_anytype for these1783 // results so that clients can cast them.1784 if (getLangOpts().DebuggerSupport) {1785 ReturnType = Context.UnknownAnyTy;1786 } else {1787 ReturnType = Context.getObjCIdType();1788 }1789 VK = VK_PRValue;1790 return false;1791 }1792 1793 ReturnType = getMessageSendResultType(Receiver, ReceiverType, Method,1794 isClassMessage, isSuperMessage);1795 VK = Expr::getValueKindForType(Method->getReturnType());1796 1797 unsigned NumNamedArgs = Sel.getNumArgs();1798 // Method might have more arguments than selector indicates. This is due1799 // to addition of c-style arguments in method.1800 if (Method->param_size() > Sel.getNumArgs())1801 NumNamedArgs = Method->param_size();1802 // FIXME. This need be cleaned up.1803 if (Args.size() < NumNamedArgs) {1804 Diag(SelLoc, diag::err_typecheck_call_too_few_args)1805 << 2 << NumNamedArgs << static_cast<unsigned>(Args.size())1806 << /*is non object*/ 0;1807 return false;1808 }1809 1810 // Compute the set of type arguments to be substituted into each parameter1811 // type.1812 std::optional<ArrayRef<QualType>> typeArgs =1813 ReceiverType->getObjCSubstitutions(Method->getDeclContext());1814 bool IsError = false;1815 for (unsigned i = 0; i < NumNamedArgs; i++) {1816 // We can't do any type-checking on a type-dependent argument.1817 if (Args[i]->isTypeDependent())1818 continue;1819 1820 Expr *argExpr = Args[i];1821 1822 ParmVarDecl *param = Method->parameters()[i];1823 assert(argExpr && "CheckMessageArgumentTypes(): missing expression");1824 1825 if (param->hasAttr<NoEscapeAttr>() &&1826 param->getType()->isBlockPointerType())1827 if (auto *BE = dyn_cast<BlockExpr>(1828 argExpr->IgnoreParenNoopCasts(Context)))1829 BE->getBlockDecl()->setDoesNotEscape();1830 1831 // Strip the unbridged-cast placeholder expression off unless it's1832 // a consumed argument.1833 if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&1834 !param->hasAttr<CFConsumedAttr>())1835 argExpr = stripARCUnbridgedCast(argExpr);1836 1837 // If the parameter is __unknown_anytype, infer its type1838 // from the argument.1839 if (param->getType() == Context.UnknownAnyTy) {1840 QualType paramType;1841 ExprResult argE = SemaRef.checkUnknownAnyArg(SelLoc, argExpr, paramType);1842 if (argE.isInvalid()) {1843 IsError = true;1844 } else {1845 Args[i] = argE.get();1846 1847 // Update the parameter type in-place.1848 param->setType(paramType);1849 }1850 continue;1851 }1852 1853 QualType origParamType = param->getType();1854 QualType paramType = param->getType();1855 if (typeArgs)1856 paramType = paramType.substObjCTypeArgs(1857 Context,1858 *typeArgs,1859 ObjCSubstitutionContext::Parameter);1860 1861 if (SemaRef.RequireCompleteType(1862 argExpr->getSourceRange().getBegin(), paramType,1863 diag::err_call_incomplete_argument, argExpr))1864 return true;1865 1866 InitializedEntity Entity1867 = InitializedEntity::InitializeParameter(Context, param, paramType);1868 ExprResult ArgE =1869 SemaRef.PerformCopyInitialization(Entity, SourceLocation(), argExpr);1870 if (ArgE.isInvalid())1871 IsError = true;1872 else {1873 Args[i] = ArgE.getAs<Expr>();1874 1875 // If we are type-erasing a block to a block-compatible1876 // Objective-C pointer type, we may need to extend the lifetime1877 // of the block object.1878 if (typeArgs && Args[i]->isPRValue() && paramType->isBlockPointerType() &&1879 Args[i]->getType()->isBlockPointerType() &&1880 origParamType->isObjCObjectPointerType()) {1881 ExprResult arg = Args[i];1882 SemaRef.maybeExtendBlockObject(arg);1883 Args[i] = arg.get();1884 }1885 }1886 }1887 1888 // Promote additional arguments to variadic methods.1889 if (Method->isVariadic()) {1890 for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {1891 if (Args[i]->isTypeDependent())1892 continue;1893 1894 ExprResult Arg = SemaRef.DefaultVariadicArgumentPromotion(1895 Args[i], VariadicCallType::Method, nullptr);1896 IsError |= Arg.isInvalid();1897 Args[i] = Arg.get();1898 }1899 } else {1900 // Check for extra arguments to non-variadic methods.1901 if (Args.size() != NumNamedArgs) {1902 Diag(Args[NumNamedArgs]->getBeginLoc(),1903 diag::err_typecheck_call_too_many_args)1904 << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size())1905 << Method->getSourceRange() << /*is non object*/ 01906 << SourceRange(Args[NumNamedArgs]->getBeginLoc(),1907 Args.back()->getEndLoc());1908 }1909 }1910 1911 SemaRef.DiagnoseSentinelCalls(Method, SelLoc, Args);1912 1913 // Do additional checkings on method.1914 IsError |=1915 CheckObjCMethodCall(Method, SelLoc, ArrayRef(Args.data(), Args.size()));1916 1917 return IsError;1918}1919 1920bool SemaObjC::isSelfExpr(Expr *RExpr) {1921 // 'self' is objc 'self' in an objc method only.1922 ObjCMethodDecl *Method = dyn_cast_or_null<ObjCMethodDecl>(1923 SemaRef.CurContext->getNonClosureAncestor());1924 return isSelfExpr(RExpr, Method);1925}1926 1927bool SemaObjC::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) {1928 if (!method) return false;1929 1930 receiver = receiver->IgnoreParenLValueCasts();1931 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver))1932 if (DRE->getDecl() == method->getSelfDecl())1933 return true;1934 return false;1935}1936 1937/// LookupMethodInType - Look up a method in an ObjCObjectType.1938ObjCMethodDecl *SemaObjC::LookupMethodInObjectType(Selector sel, QualType type,1939 bool isInstance) {1940 const ObjCObjectType *objType = type->castAs<ObjCObjectType>();1941 if (ObjCInterfaceDecl *iface = objType->getInterface()) {1942 // Look it up in the main interface (and categories, etc.)1943 if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance))1944 return method;1945 1946 // Okay, look for "private" methods declared in any1947 // @implementations we've seen.1948 if (ObjCMethodDecl *method = iface->lookupPrivateMethod(sel, isInstance))1949 return method;1950 }1951 1952 // Check qualifiers.1953 for (const auto *I : objType->quals())1954 if (ObjCMethodDecl *method = I->lookupMethod(sel, isInstance))1955 return method;1956 1957 return nullptr;1958}1959 1960/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier1961/// list of a qualified objective pointer type.1962ObjCMethodDecl *SemaObjC::LookupMethodInQualifiedType(1963 Selector Sel, const ObjCObjectPointerType *OPT, bool Instance) {1964 ObjCMethodDecl *MD = nullptr;1965 for (const auto *PROTO : OPT->quals()) {1966 if ((MD = PROTO->lookupMethod(Sel, Instance))) {1967 return MD;1968 }1969 }1970 return nullptr;1971}1972 1973/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an1974/// objective C interface. This is a property reference expression.1975ExprResult SemaObjC::HandleExprPropertyRefExpr(1976 const ObjCObjectPointerType *OPT, Expr *BaseExpr, SourceLocation OpLoc,1977 DeclarationName MemberName, SourceLocation MemberLoc,1978 SourceLocation SuperLoc, QualType SuperType, bool Super) {1979 ASTContext &Context = getASTContext();1980 const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();1981 assert(IFaceT && "Expected an Interface");1982 ObjCInterfaceDecl *IFace = IFaceT->getDecl();1983 1984 if (!MemberName.isIdentifier()) {1985 Diag(MemberLoc, diag::err_invalid_property_name)1986 << MemberName << QualType(OPT, 0);1987 return ExprError();1988 }1989 1990 IdentifierInfo *Member = MemberName.getAsIdentifierInfo();1991 1992 SourceRange BaseRange = Super? SourceRange(SuperLoc)1993 : BaseExpr->getSourceRange();1994 if (SemaRef.RequireCompleteType(MemberLoc, OPT->getPointeeType(),1995 diag::err_property_not_found_forward_class,1996 MemberName, BaseRange))1997 return ExprError();1998 1999 if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(2000 Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {2001 // Check whether we can reference this property.2002 if (SemaRef.DiagnoseUseOfDecl(PD, MemberLoc))2003 return ExprError();2004 if (Super)2005 return new (Context)2006 ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,2007 OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);2008 else2009 return new (Context)2010 ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,2011 OK_ObjCProperty, MemberLoc, BaseExpr);2012 }2013 // Check protocols on qualified interfaces.2014 for (const auto *I : OPT->quals())2015 if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(2016 Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {2017 // Check whether we can reference this property.2018 if (SemaRef.DiagnoseUseOfDecl(PD, MemberLoc))2019 return ExprError();2020 2021 if (Super)2022 return new (Context) ObjCPropertyRefExpr(2023 PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc,2024 SuperLoc, SuperType);2025 else2026 return new (Context)2027 ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,2028 OK_ObjCProperty, MemberLoc, BaseExpr);2029 }2030 // If that failed, look for an "implicit" property by seeing if the nullary2031 // selector is implemented.2032 2033 // FIXME: The logic for looking up nullary and unary selectors should be2034 // shared with the code in ActOnInstanceMessage.2035 2036 Selector Sel = SemaRef.PP.getSelectorTable().getNullarySelector(Member);2037 ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);2038 2039 // May be found in property's qualified list.2040 if (!Getter)2041 Getter = LookupMethodInQualifiedType(Sel, OPT, true);2042 2043 // If this reference is in an @implementation, check for 'private' methods.2044 if (!Getter)2045 Getter = IFace->lookupPrivateMethod(Sel);2046 2047 if (Getter) {2048 // Check if we can reference this property.2049 if (SemaRef.DiagnoseUseOfDecl(Getter, MemberLoc))2050 return ExprError();2051 }2052 // If we found a getter then this may be a valid dot-reference, we2053 // will look for the matching setter, in case it is needed.2054 Selector SetterSel = SelectorTable::constructSetterSelector(2055 SemaRef.PP.getIdentifierTable(), SemaRef.PP.getSelectorTable(), Member);2056 ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);2057 2058 // May be found in property's qualified list.2059 if (!Setter)2060 Setter = LookupMethodInQualifiedType(SetterSel, OPT, true);2061 2062 if (!Setter) {2063 // If this reference is in an @implementation, also check for 'private'2064 // methods.2065 Setter = IFace->lookupPrivateMethod(SetterSel);2066 }2067 2068 if (Setter && SemaRef.DiagnoseUseOfDecl(Setter, MemberLoc))2069 return ExprError();2070 2071 // Special warning if member name used in a property-dot for a setter accessor2072 // does not use a property with same name; e.g. obj.X = ... for a property with2073 // name 'x'.2074 if (Setter && Setter->isImplicit() && Setter->isPropertyAccessor() &&2075 !IFace->FindPropertyDeclaration(2076 Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {2077 if (const ObjCPropertyDecl *PDecl = Setter->findPropertyDecl()) {2078 // Do not warn if user is using property-dot syntax to make call to2079 // user named setter.2080 if (!(PDecl->getPropertyAttributes() &2081 ObjCPropertyAttribute::kind_setter))2082 Diag(MemberLoc,2083 diag::warn_property_access_suggest)2084 << MemberName << QualType(OPT, 0) << PDecl->getName()2085 << FixItHint::CreateReplacement(MemberLoc, PDecl->getName());2086 }2087 }2088 2089 if (Getter || Setter) {2090 if (Super)2091 return new (Context)2092 ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,2093 OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);2094 else2095 return new (Context)2096 ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,2097 OK_ObjCProperty, MemberLoc, BaseExpr);2098 2099 }2100 2101 // Attempt to correct for typos in property names.2102 DeclFilterCCC<ObjCPropertyDecl> CCC{};2103 if (TypoCorrection Corrected = SemaRef.CorrectTypo(2104 DeclarationNameInfo(MemberName, MemberLoc), Sema::LookupOrdinaryName,2105 nullptr, nullptr, CCC, CorrectTypoKind::ErrorRecovery, IFace, false,2106 OPT)) {2107 DeclarationName TypoResult = Corrected.getCorrection();2108 if (TypoResult.isIdentifier() &&2109 TypoResult.getAsIdentifierInfo() == Member) {2110 // There is no need to try the correction if it is the same.2111 NamedDecl *ChosenDecl =2112 Corrected.isKeyword() ? nullptr : Corrected.getFoundDecl();2113 if (ChosenDecl && isa<ObjCPropertyDecl>(ChosenDecl))2114 if (cast<ObjCPropertyDecl>(ChosenDecl)->isClassProperty()) {2115 // This is a class property, we should not use the instance to2116 // access it.2117 Diag(MemberLoc, diag::err_class_property_found) << MemberName2118 << OPT->getInterfaceDecl()->getName()2119 << FixItHint::CreateReplacement(BaseExpr->getSourceRange(),2120 OPT->getInterfaceDecl()->getName());2121 return ExprError();2122 }2123 } else {2124 SemaRef.diagnoseTypo(Corrected,2125 PDiag(diag::err_property_not_found_suggest)2126 << MemberName << QualType(OPT, 0));2127 return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,2128 TypoResult, MemberLoc,2129 SuperLoc, SuperType, Super);2130 }2131 }2132 ObjCInterfaceDecl *ClassDeclared;2133 if (ObjCIvarDecl *Ivar =2134 IFace->lookupInstanceVariable(Member, ClassDeclared)) {2135 QualType T = Ivar->getType();2136 if (const ObjCObjectPointerType * OBJPT =2137 T->getAsObjCInterfacePointerType()) {2138 if (SemaRef.RequireCompleteType(MemberLoc, OBJPT->getPointeeType(),2139 diag::err_property_not_as_forward_class,2140 MemberName, BaseExpr))2141 return ExprError();2142 }2143 Diag(MemberLoc,2144 diag::err_ivar_access_using_property_syntax_suggest)2145 << MemberName << QualType(OPT, 0) << Ivar->getDeclName()2146 << FixItHint::CreateReplacement(OpLoc, "->");2147 return ExprError();2148 }2149 2150 Diag(MemberLoc, diag::err_property_not_found)2151 << MemberName << QualType(OPT, 0);2152 if (Setter)2153 Diag(Setter->getLocation(), diag::note_getter_unavailable)2154 << MemberName << BaseExpr->getSourceRange();2155 return ExprError();2156}2157 2158ExprResult SemaObjC::ActOnClassPropertyRefExpr(2159 const IdentifierInfo &receiverName, const IdentifierInfo &propertyName,2160 SourceLocation receiverNameLoc, SourceLocation propertyNameLoc) {2161 ASTContext &Context = getASTContext();2162 const IdentifierInfo *receiverNamePtr = &receiverName;2163 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,2164 receiverNameLoc);2165 2166 QualType SuperType;2167 if (!IFace) {2168 // If the "receiver" is 'super' in a method, handle it as an expression-like2169 // property reference.2170 if (receiverNamePtr->isStr("super")) {2171 if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) {2172 if (auto classDecl = CurMethod->getClassInterface()) {2173 SuperType = QualType(classDecl->getSuperClassType(), 0);2174 if (CurMethod->isInstanceMethod()) {2175 if (SuperType.isNull()) {2176 // The current class does not have a superclass.2177 Diag(receiverNameLoc, diag::err_root_class_cannot_use_super)2178 << CurMethod->getClassInterface()->getIdentifier();2179 return ExprError();2180 }2181 QualType T = Context.getObjCObjectPointerType(SuperType);2182 2183 return HandleExprPropertyRefExpr(T->castAs<ObjCObjectPointerType>(),2184 /*BaseExpr*/nullptr,2185 SourceLocation()/*OpLoc*/,2186 &propertyName,2187 propertyNameLoc,2188 receiverNameLoc, T, true);2189 }2190 2191 // Otherwise, if this is a class method, try dispatching to our2192 // superclass.2193 IFace = CurMethod->getClassInterface()->getSuperClass();2194 }2195 }2196 }2197 2198 if (!IFace) {2199 Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier2200 << tok::l_paren;2201 return ExprError();2202 }2203 }2204 2205 Selector GetterSel;2206 Selector SetterSel;2207 if (auto PD = IFace->FindPropertyDeclaration(2208 &propertyName, ObjCPropertyQueryKind::OBJC_PR_query_class)) {2209 GetterSel = PD->getGetterName();2210 SetterSel = PD->getSetterName();2211 } else {2212 GetterSel = SemaRef.PP.getSelectorTable().getNullarySelector(&propertyName);2213 SetterSel = SelectorTable::constructSetterSelector(2214 SemaRef.PP.getIdentifierTable(), SemaRef.PP.getSelectorTable(),2215 &propertyName);2216 }2217 2218 // Search for a declared property first.2219 ObjCMethodDecl *Getter = IFace->lookupClassMethod(GetterSel);2220 2221 // If this reference is in an @implementation, check for 'private' methods.2222 if (!Getter)2223 Getter = IFace->lookupPrivateClassMethod(GetterSel);2224 2225 if (Getter) {2226 // FIXME: refactor/share with ActOnMemberReference().2227 // Check if we can reference this property.2228 if (SemaRef.DiagnoseUseOfDecl(Getter, propertyNameLoc))2229 return ExprError();2230 }2231 2232 // Look for the matching setter, in case it is needed.2233 ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);2234 if (!Setter) {2235 // If this reference is in an @implementation, also check for 'private'2236 // methods.2237 Setter = IFace->lookupPrivateClassMethod(SetterSel);2238 }2239 // Look through local category implementations associated with the class.2240 if (!Setter)2241 Setter = IFace->getCategoryClassMethod(SetterSel);2242 2243 if (Setter && SemaRef.DiagnoseUseOfDecl(Setter, propertyNameLoc))2244 return ExprError();2245 2246 if (Getter || Setter) {2247 if (!SuperType.isNull())2248 return new (Context)2249 ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,2250 OK_ObjCProperty, propertyNameLoc, receiverNameLoc,2251 SuperType);2252 2253 return new (Context) ObjCPropertyRefExpr(2254 Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty,2255 propertyNameLoc, receiverNameLoc, IFace);2256 }2257 return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)2258 << &propertyName << Context.getObjCInterfaceType(IFace));2259}2260 2261namespace {2262 2263class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback {2264 public:2265 ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {2266 // Determine whether "super" is acceptable in the current context.2267 if (Method && Method->getClassInterface())2268 WantObjCSuper = Method->getClassInterface()->getSuperClass();2269 }2270 2271 bool ValidateCandidate(const TypoCorrection &candidate) override {2272 return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||2273 candidate.isKeyword("super");2274 }2275 2276 std::unique_ptr<CorrectionCandidateCallback> clone() override {2277 return std::make_unique<ObjCInterfaceOrSuperCCC>(*this);2278 }2279};2280 2281} // end anonymous namespace2282 2283SemaObjC::ObjCMessageKind2284SemaObjC::getObjCMessageKind(Scope *S, IdentifierInfo *Name,2285 SourceLocation NameLoc, bool IsSuper,2286 bool HasTrailingDot, ParsedType &ReceiverType) {2287 ASTContext &Context = getASTContext();2288 ReceiverType = nullptr;2289 2290 // If the identifier is "super" and there is no trailing dot, we're2291 // messaging super. If the identifier is "super" and there is a2292 // trailing dot, it's an instance message.2293 if (IsSuper && S->isInObjcMethodScope())2294 return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage;2295 2296 LookupResult Result(SemaRef, Name, NameLoc, Sema::LookupOrdinaryName);2297 SemaRef.LookupName(Result, S);2298 2299 switch (Result.getResultKind()) {2300 case LookupResultKind::NotFound:2301 // Normal name lookup didn't find anything. If we're in an2302 // Objective-C method, look for ivars. If we find one, we're done!2303 // FIXME: This is a hack. Ivar lookup should be part of normal2304 // lookup.2305 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {2306 if (!Method->getClassInterface()) {2307 // Fall back: let the parser try to parse it as an instance message.2308 return ObjCInstanceMessage;2309 }2310 2311 ObjCInterfaceDecl *ClassDeclared;2312 if (Method->getClassInterface()->lookupInstanceVariable(Name,2313 ClassDeclared))2314 return ObjCInstanceMessage;2315 }2316 2317 // Break out; we'll perform typo correction below.2318 break;2319 2320 case LookupResultKind::NotFoundInCurrentInstantiation:2321 case LookupResultKind::FoundOverloaded:2322 case LookupResultKind::FoundUnresolvedValue:2323 case LookupResultKind::Ambiguous:2324 Result.suppressDiagnostics();2325 return ObjCInstanceMessage;2326 2327 case LookupResultKind::Found: {2328 // If the identifier is a class or not, and there is a trailing dot,2329 // it's an instance message.2330 if (HasTrailingDot)2331 return ObjCInstanceMessage;2332 // We found something. If it's a type, then we have a class2333 // message. Otherwise, it's an instance message.2334 NamedDecl *ND = Result.getFoundDecl();2335 QualType T;2336 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))2337 T = Context.getObjCInterfaceType(Class);2338 else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) {2339 SemaRef.DiagnoseUseOfDecl(Type, NameLoc);2340 T = Context.getTypeDeclType(ElaboratedTypeKeyword::None,2341 /*Qualifier=*/std::nullopt, Type);2342 } else2343 return ObjCInstanceMessage;2344 2345 // We have a class message, and T is the type we're2346 // messaging. Build source-location information for it.2347 TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);2348 ReceiverType = SemaRef.CreateParsedType(T, TSInfo);2349 return ObjCClassMessage;2350 }2351 }2352 2353 ObjCInterfaceOrSuperCCC CCC(SemaRef.getCurMethodDecl());2354 if (TypoCorrection Corrected = SemaRef.CorrectTypo(2355 Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, CCC,2356 CorrectTypoKind::ErrorRecovery, nullptr, false, nullptr, false)) {2357 if (Corrected.isKeyword()) {2358 // If we've found the keyword "super" (the only keyword that would be2359 // returned by CorrectTypo), this is a send to super.2360 SemaRef.diagnoseTypo(Corrected, PDiag(diag::err_unknown_receiver_suggest)2361 << Name);2362 return ObjCSuperMessage;2363 } else if (ObjCInterfaceDecl *Class =2364 Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {2365 // If we found a declaration, correct when it refers to an Objective-C2366 // class.2367 SemaRef.diagnoseTypo(Corrected, PDiag(diag::err_unknown_receiver_suggest)2368 << Name);2369 QualType T = Context.getObjCInterfaceType(Class);2370 TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);2371 ReceiverType = SemaRef.CreateParsedType(T, TSInfo);2372 return ObjCClassMessage;2373 }2374 }2375 2376 // Fall back: let the parser try to parse it as an instance message.2377 return ObjCInstanceMessage;2378}2379 2380ExprResult SemaObjC::ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,2381 Selector Sel, SourceLocation LBracLoc,2382 ArrayRef<SourceLocation> SelectorLocs,2383 SourceLocation RBracLoc,2384 MultiExprArg Args) {2385 ASTContext &Context = getASTContext();2386 // Determine whether we are inside a method or not.2387 ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc);2388 if (!Method) {2389 Diag(SuperLoc, diag::err_invalid_receiver_to_message_super);2390 return ExprError();2391 }2392 2393 ObjCInterfaceDecl *Class = Method->getClassInterface();2394 if (!Class) {2395 Diag(SuperLoc, diag::err_no_super_class_message)2396 << Method->getDeclName();2397 return ExprError();2398 }2399 2400 QualType SuperTy(Class->getSuperClassType(), 0);2401 if (SuperTy.isNull()) {2402 // The current class does not have a superclass.2403 Diag(SuperLoc, diag::err_root_class_cannot_use_super)2404 << Class->getIdentifier();2405 return ExprError();2406 }2407 2408 // We are in a method whose class has a superclass, so 'super'2409 // is acting as a keyword.2410 if (Method->getSelector() == Sel)2411 SemaRef.getCurFunction()->ObjCShouldCallSuper = false;2412 2413 if (Method->isInstanceMethod()) {2414 // Since we are in an instance method, this is an instance2415 // message to the superclass instance.2416 SuperTy = Context.getObjCObjectPointerType(SuperTy);2417 return BuildInstanceMessage(nullptr, SuperTy, SuperLoc,2418 Sel, /*Method=*/nullptr,2419 LBracLoc, SelectorLocs, RBracLoc, Args);2420 }2421 2422 // Since we are in a class method, this is a class message to2423 // the superclass.2424 return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,2425 SuperTy,2426 SuperLoc, Sel, /*Method=*/nullptr,2427 LBracLoc, SelectorLocs, RBracLoc, Args);2428}2429 2430ExprResult SemaObjC::BuildClassMessageImplicit(QualType ReceiverType,2431 bool isSuperReceiver,2432 SourceLocation Loc, Selector Sel,2433 ObjCMethodDecl *Method,2434 MultiExprArg Args) {2435 ASTContext &Context = getASTContext();2436 TypeSourceInfo *receiverTypeInfo = nullptr;2437 if (!ReceiverType.isNull())2438 receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType);2439 2440 assert(((isSuperReceiver && Loc.isValid()) || receiverTypeInfo) &&2441 "Either the super receiver location needs to be valid or the receiver "2442 "needs valid type source information");2443 return BuildClassMessage(receiverTypeInfo, ReceiverType,2444 /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(),2445 Sel, Method, Loc, Loc, Loc, Args,2446 /*isImplicit=*/true);2447}2448 2449static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,2450 unsigned DiagID,2451 bool (*refactor)(const ObjCMessageExpr *,2452 const NSAPI &, edit::Commit &)) {2453 SourceLocation MsgLoc = Msg->getExprLoc();2454 if (S.Diags.isIgnored(DiagID, MsgLoc))2455 return;2456 2457 SourceManager &SM = S.SourceMgr;2458 edit::Commit ECommit(SM, S.LangOpts);2459 if (refactor(Msg, *S.ObjC().NSAPIObj, ECommit)) {2460 auto Builder = S.Diag(MsgLoc, DiagID)2461 << Msg->getSelector() << Msg->getSourceRange();2462 // FIXME: Don't emit diagnostic at all if fixits are non-commitable.2463 if (!ECommit.isCommitable())2464 return;2465 for (edit::Commit::edit_iterator2466 I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) {2467 const edit::Commit::Edit &Edit = *I;2468 switch (Edit.Kind) {2469 case edit::Commit::Act_Insert:2470 Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc,2471 Edit.Text,2472 Edit.BeforePrev));2473 break;2474 case edit::Commit::Act_InsertFromRange:2475 Builder.AddFixItHint(2476 FixItHint::CreateInsertionFromRange(Edit.OrigLoc,2477 Edit.getInsertFromRange(SM),2478 Edit.BeforePrev));2479 break;2480 case edit::Commit::Act_Remove:2481 Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM)));2482 break;2483 }2484 }2485 }2486}2487 2488static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) {2489 applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use,2490 edit::rewriteObjCRedundantCallWithLiteral);2491}2492 2493static void checkFoundationAPI(Sema &S, SourceLocation Loc,2494 const ObjCMethodDecl *Method,2495 ArrayRef<Expr *> Args, QualType ReceiverType,2496 bool IsClassObjectCall) {2497 // Check if this is a performSelector method that uses a selector that returns2498 // a record or a vector type.2499 if (Method->getSelector().getMethodFamily() != OMF_performSelector ||2500 Args.empty())2501 return;2502 const auto *SE = dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens());2503 if (!SE)2504 return;2505 ObjCMethodDecl *ImpliedMethod;2506 if (!IsClassObjectCall) {2507 const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>();2508 if (!OPT || !OPT->getInterfaceDecl())2509 return;2510 ImpliedMethod =2511 OPT->getInterfaceDecl()->lookupInstanceMethod(SE->getSelector());2512 if (!ImpliedMethod)2513 ImpliedMethod =2514 OPT->getInterfaceDecl()->lookupPrivateMethod(SE->getSelector());2515 } else {2516 const auto *IT = ReceiverType->getAs<ObjCInterfaceType>();2517 if (!IT)2518 return;2519 ImpliedMethod = IT->getDecl()->lookupClassMethod(SE->getSelector());2520 if (!ImpliedMethod)2521 ImpliedMethod =2522 IT->getDecl()->lookupPrivateClassMethod(SE->getSelector());2523 }2524 if (!ImpliedMethod)2525 return;2526 QualType Ret = ImpliedMethod->getReturnType();2527 if (Ret->isRecordType() || Ret->isVectorType() || Ret->isExtVectorType()) {2528 S.Diag(Loc, diag::warn_objc_unsafe_perform_selector)2529 << Method->getSelector()2530 << (!Ret->isRecordType()2531 ? /*Vector*/ 22532 : Ret->isUnionType() ? /*Union*/ 1 : /*Struct*/ 0);2533 S.Diag(ImpliedMethod->getBeginLoc(),2534 diag::note_objc_unsafe_perform_selector_method_declared_here)2535 << ImpliedMethod->getSelector() << Ret;2536 }2537}2538 2539/// Diagnose use of %s directive in an NSString which is being passed2540/// as formatting string to formatting method.2541static void2542DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,2543 ObjCMethodDecl *Method,2544 Selector Sel,2545 Expr **Args, unsigned NumArgs) {2546 unsigned Idx = 0;2547 bool Format = false;2548 ObjCStringFormatFamily SFFamily = Sel.getStringFormatFamily();2549 if (SFFamily == ObjCStringFormatFamily::SFF_NSString) {2550 Idx = 0;2551 Format = true;2552 }2553 else if (Method) {2554 for (const auto *I : Method->specific_attrs<FormatAttr>()) {2555 if (S.ObjC().GetFormatNSStringIdx(I, Idx)) {2556 Format = true;2557 break;2558 }2559 }2560 }2561 if (!Format || NumArgs <= Idx)2562 return;2563 2564 Expr *FormatExpr = Args[Idx];2565 if (ObjCStringLiteral *OSL =2566 dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts())) {2567 StringLiteral *FormatString = OSL->getString();2568 if (S.FormatStringHasSArg(FormatString)) {2569 S.Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string)2570 << "%s" << 0 << 0;2571 if (Method)2572 S.Diag(Method->getLocation(), diag::note_method_declared_at)2573 << Method->getDeclName();2574 }2575 }2576}2577 2578/// Build an Objective-C class message expression.2579///2580/// This routine takes care of both normal class messages and2581/// class messages to the superclass.2582///2583/// \param ReceiverTypeInfo Type source information that describes the2584/// receiver of this message. This may be NULL, in which case we are2585/// sending to the superclass and \p SuperLoc must be a valid source2586/// location.2587 2588/// \param ReceiverType The type of the object receiving the2589/// message. When \p ReceiverTypeInfo is non-NULL, this is the same2590/// type as that refers to. For a superclass send, this is the type of2591/// the superclass.2592///2593/// \param SuperLoc The location of the "super" keyword in a2594/// superclass message.2595///2596/// \param Sel The selector to which the message is being sent.2597///2598/// \param Method The method that this class message is invoking, if2599/// already known.2600///2601/// \param LBracLoc The location of the opening square bracket ']'.2602///2603/// \param RBracLoc The location of the closing square bracket ']'.2604///2605/// \param ArgsIn The message arguments.2606ExprResult SemaObjC::BuildClassMessage(2607 TypeSourceInfo *ReceiverTypeInfo, QualType ReceiverType,2608 SourceLocation SuperLoc, Selector Sel, ObjCMethodDecl *Method,2609 SourceLocation LBracLoc, ArrayRef<SourceLocation> SelectorLocs,2610 SourceLocation RBracLoc, MultiExprArg ArgsIn, bool isImplicit) {2611 ASTContext &Context = getASTContext();2612 SourceLocation Loc = SuperLoc.isValid()? SuperLoc2613 : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();2614 if (LBracLoc.isInvalid()) {2615 Diag(Loc, diag::err_missing_open_square_message_send)2616 << FixItHint::CreateInsertion(Loc, "[");2617 LBracLoc = Loc;2618 }2619 ArrayRef<SourceLocation> SelectorSlotLocs;2620 if (!SelectorLocs.empty() && SelectorLocs.front().isValid())2621 SelectorSlotLocs = SelectorLocs;2622 else2623 SelectorSlotLocs = Loc;2624 SourceLocation SelLoc = SelectorSlotLocs.front();2625 2626 if (ReceiverType->isDependentType()) {2627 // If the receiver type is dependent, we can't type-check anything2628 // at this point. Build a dependent expression.2629 unsigned NumArgs = ArgsIn.size();2630 Expr **Args = ArgsIn.data();2631 assert(SuperLoc.isInvalid() && "Message to super with dependent type");2632 return ObjCMessageExpr::Create(Context, ReceiverType, VK_PRValue, LBracLoc,2633 ReceiverTypeInfo, Sel, SelectorLocs,2634 /*Method=*/nullptr, ArrayRef(Args, NumArgs),2635 RBracLoc, isImplicit);2636 }2637 2638 // Find the class to which we are sending this message.2639 ObjCInterfaceDecl *Class = nullptr;2640 const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();2641 if (!ClassType || !(Class = ClassType->getInterface())) {2642 Diag(Loc, diag::err_invalid_receiver_class_message)2643 << ReceiverType;2644 return ExprError();2645 }2646 assert(Class && "We don't know which class we're messaging?");2647 // objc++ diagnoses during typename annotation.2648 if (!getLangOpts().CPlusPlus)2649 (void)SemaRef.DiagnoseUseOfDecl(Class, SelectorSlotLocs);2650 // Find the method we are messaging.2651 if (!Method) {2652 SourceRange TypeRange2653 = SuperLoc.isValid()? SourceRange(SuperLoc)2654 : ReceiverTypeInfo->getTypeLoc().getSourceRange();2655 if (SemaRef.RequireCompleteType(Loc, Context.getObjCInterfaceType(Class),2656 (getLangOpts().ObjCAutoRefCount2657 ? diag::err_arc_receiver_forward_class2658 : diag::warn_receiver_forward_class),2659 TypeRange)) {2660 // A forward class used in messaging is treated as a 'Class'2661 Method = LookupFactoryMethodInGlobalPool(Sel,2662 SourceRange(LBracLoc, RBracLoc));2663 if (Method && !getLangOpts().ObjCAutoRefCount)2664 Diag(Method->getLocation(), diag::note_method_sent_forward_class)2665 << Method->getDeclName();2666 }2667 if (!Method)2668 Method = Class->lookupClassMethod(Sel);2669 2670 // If we have an implementation in scope, check "private" methods.2671 if (!Method)2672 Method = Class->lookupPrivateClassMethod(Sel);2673 2674 if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs, nullptr,2675 false, false, Class))2676 return ExprError();2677 }2678 2679 // Check the argument types and determine the result type.2680 QualType ReturnType;2681 ExprValueKind VK = VK_PRValue;2682 2683 unsigned NumArgs = ArgsIn.size();2684 Expr **Args = ArgsIn.data();2685 if (CheckMessageArgumentTypes(/*Receiver=*/nullptr, ReceiverType,2686 MultiExprArg(Args, NumArgs), Sel, SelectorLocs,2687 Method, true, SuperLoc.isValid(), LBracLoc,2688 RBracLoc, SourceRange(), ReturnType, VK))2689 return ExprError();2690 2691 if (Method && !Method->getReturnType()->isVoidType() &&2692 SemaRef.RequireCompleteType(2693 LBracLoc, Method->getReturnType(),2694 diag::err_illegal_message_expr_incomplete_type))2695 return ExprError();2696 2697 if (Method && Method->isDirectMethod() && SuperLoc.isValid()) {2698 Diag(SuperLoc, diag::err_messaging_super_with_direct_method)2699 << FixItHint::CreateReplacement(2700 SuperLoc, getLangOpts().ObjCAutoRefCount2701 ? "self"2702 : Method->getClassInterface()->getName());2703 Diag(Method->getLocation(), diag::note_direct_method_declared_at)2704 << Method->getDeclName();2705 }2706 2707 // Warn about explicit call of +initialize on its own class. But not on 'super'.2708 if (Method && Method->getMethodFamily() == OMF_initialize) {2709 if (!SuperLoc.isValid()) {2710 const ObjCInterfaceDecl *ID =2711 dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext());2712 if (ID == Class) {2713 Diag(Loc, diag::warn_direct_initialize_call);2714 Diag(Method->getLocation(), diag::note_method_declared_at)2715 << Method->getDeclName();2716 }2717 } else if (ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl()) {2718 // [super initialize] is allowed only within an +initialize implementation2719 if (CurMeth->getMethodFamily() != OMF_initialize) {2720 Diag(Loc, diag::warn_direct_super_initialize_call);2721 Diag(Method->getLocation(), diag::note_method_declared_at)2722 << Method->getDeclName();2723 Diag(CurMeth->getLocation(), diag::note_method_declared_at)2724 << CurMeth->getDeclName();2725 }2726 }2727 }2728 2729 DiagnoseCStringFormatDirectiveInObjCAPI(SemaRef, Method, Sel, Args, NumArgs);2730 2731 // Construct the appropriate ObjCMessageExpr.2732 ObjCMessageExpr *Result;2733 if (SuperLoc.isValid())2734 Result = ObjCMessageExpr::Create(2735 Context, ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/false,2736 ReceiverType, Sel, SelectorLocs, Method, ArrayRef(Args, NumArgs),2737 RBracLoc, isImplicit);2738 else {2739 Result = ObjCMessageExpr::Create(2740 Context, ReturnType, VK, LBracLoc, ReceiverTypeInfo, Sel, SelectorLocs,2741 Method, ArrayRef(Args, NumArgs), RBracLoc, isImplicit);2742 if (!isImplicit)2743 checkCocoaAPI(SemaRef, Result);2744 }2745 if (Method)2746 checkFoundationAPI(SemaRef, SelLoc, Method, ArrayRef(Args, NumArgs),2747 ReceiverType, /*IsClassObjectCall=*/true);2748 return SemaRef.MaybeBindToTemporary(Result);2749}2750 2751// ActOnClassMessage - used for both unary and keyword messages.2752// ArgExprs is optional - if it is present, the number of expressions2753// is obtained from Sel.getNumArgs().2754ExprResult SemaObjC::ActOnClassMessage(Scope *S, ParsedType Receiver,2755 Selector Sel, SourceLocation LBracLoc,2756 ArrayRef<SourceLocation> SelectorLocs,2757 SourceLocation RBracLoc,2758 MultiExprArg Args) {2759 ASTContext &Context = getASTContext();2760 TypeSourceInfo *ReceiverTypeInfo;2761 QualType ReceiverType =2762 SemaRef.GetTypeFromParser(Receiver, &ReceiverTypeInfo);2763 if (ReceiverType.isNull())2764 return ExprError();2765 2766 if (!ReceiverTypeInfo)2767 ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);2768 2769 return BuildClassMessage(ReceiverTypeInfo, ReceiverType,2770 /*SuperLoc=*/SourceLocation(), Sel,2771 /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc,2772 Args);2773}2774 2775ExprResult SemaObjC::BuildInstanceMessageImplicit(2776 Expr *Receiver, QualType ReceiverType, SourceLocation Loc, Selector Sel,2777 ObjCMethodDecl *Method, MultiExprArg Args) {2778 return BuildInstanceMessage(Receiver, ReceiverType,2779 /*SuperLoc=*/!Receiver ? Loc : SourceLocation(),2780 Sel, Method, Loc, Loc, Loc, Args,2781 /*isImplicit=*/true);2782}2783 2784static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) {2785 if (!S.ObjC().NSAPIObj)2786 return false;2787 const auto *Protocol = dyn_cast<ObjCProtocolDecl>(M->getDeclContext());2788 if (!Protocol)2789 return false;2790 const IdentifierInfo *II =2791 S.ObjC().NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);2792 if (const auto *RootClass = dyn_cast_or_null<ObjCInterfaceDecl>(2793 S.LookupSingleName(S.TUScope, II, Protocol->getBeginLoc(),2794 Sema::LookupOrdinaryName))) {2795 for (const ObjCProtocolDecl *P : RootClass->all_referenced_protocols()) {2796 if (P->getCanonicalDecl() == Protocol->getCanonicalDecl())2797 return true;2798 }2799 }2800 return false;2801}2802 2803/// Build an Objective-C instance message expression.2804///2805/// This routine takes care of both normal instance messages and2806/// instance messages to the superclass instance.2807///2808/// \param Receiver The expression that computes the object that will2809/// receive this message. This may be empty, in which case we are2810/// sending to the superclass instance and \p SuperLoc must be a valid2811/// source location.2812///2813/// \param ReceiverType The (static) type of the object receiving the2814/// message. When a \p Receiver expression is provided, this is the2815/// same type as that expression. For a superclass instance send, this2816/// is a pointer to the type of the superclass.2817///2818/// \param SuperLoc The location of the "super" keyword in a2819/// superclass instance message.2820///2821/// \param Sel The selector to which the message is being sent.2822///2823/// \param Method The method that this instance message is invoking, if2824/// already known.2825///2826/// \param LBracLoc The location of the opening square bracket ']'.2827///2828/// \param RBracLoc The location of the closing square bracket ']'.2829///2830/// \param ArgsIn The message arguments.2831ExprResult SemaObjC::BuildInstanceMessage(2832 Expr *Receiver, QualType ReceiverType, SourceLocation SuperLoc,2833 Selector Sel, ObjCMethodDecl *Method, SourceLocation LBracLoc,2834 ArrayRef<SourceLocation> SelectorLocs, SourceLocation RBracLoc,2835 MultiExprArg ArgsIn, bool isImplicit) {2836 assert((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the "2837 "SuperLoc must be valid so we can "2838 "use it instead.");2839 ASTContext &Context = getASTContext();2840 2841 // The location of the receiver.2842 SourceLocation Loc = SuperLoc.isValid() ? SuperLoc : Receiver->getBeginLoc();2843 SourceRange RecRange =2844 SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();2845 ArrayRef<SourceLocation> SelectorSlotLocs;2846 if (!SelectorLocs.empty() && SelectorLocs.front().isValid())2847 SelectorSlotLocs = SelectorLocs;2848 else2849 SelectorSlotLocs = Loc;2850 SourceLocation SelLoc = SelectorSlotLocs.front();2851 2852 if (LBracLoc.isInvalid()) {2853 Diag(Loc, diag::err_missing_open_square_message_send)2854 << FixItHint::CreateInsertion(Loc, "[");2855 LBracLoc = Loc;2856 }2857 2858 // If we have a receiver expression, perform appropriate promotions2859 // and determine receiver type.2860 if (Receiver) {2861 if (Receiver->hasPlaceholderType()) {2862 ExprResult Result;2863 if (Receiver->getType() == Context.UnknownAnyTy)2864 Result =2865 SemaRef.forceUnknownAnyToType(Receiver, Context.getObjCIdType());2866 else2867 Result = SemaRef.CheckPlaceholderExpr(Receiver);2868 if (Result.isInvalid()) return ExprError();2869 Receiver = Result.get();2870 }2871 2872 if (Receiver->isTypeDependent()) {2873 // If the receiver is type-dependent, we can't type-check anything2874 // at this point. Build a dependent expression.2875 unsigned NumArgs = ArgsIn.size();2876 Expr **Args = ArgsIn.data();2877 assert(SuperLoc.isInvalid() && "Message to super with dependent type");2878 return ObjCMessageExpr::Create(2879 Context, Context.DependentTy, VK_PRValue, LBracLoc, Receiver, Sel,2880 SelectorLocs, /*Method=*/nullptr, ArrayRef(Args, NumArgs), RBracLoc,2881 isImplicit);2882 }2883 2884 // If necessary, apply function/array conversion to the receiver.2885 // C99 6.7.5.3p[7,8].2886 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Receiver);2887 if (Result.isInvalid())2888 return ExprError();2889 Receiver = Result.get();2890 ReceiverType = Receiver->getType();2891 2892 // If the receiver is an ObjC pointer, a block pointer, or an2893 // __attribute__((NSObject)) pointer, we don't need to do any2894 // special conversion in order to look up a receiver.2895 if (ReceiverType->isObjCRetainableType()) {2896 // do nothing2897 } else if (!getLangOpts().ObjCAutoRefCount &&2898 !Context.getObjCIdType().isNull() &&2899 (ReceiverType->isPointerType() ||2900 ReceiverType->isIntegerType())) {2901 // Implicitly convert integers and pointers to 'id' but emit a warning.2902 // But not in ARC.2903 Diag(Loc, diag::warn_bad_receiver_type) << ReceiverType << RecRange;2904 if (ReceiverType->isPointerType()) {2905 Receiver = SemaRef2906 .ImpCastExprToType(Receiver, Context.getObjCIdType(),2907 CK_CPointerToObjCPointerCast)2908 .get();2909 } else {2910 // TODO: specialized warning on null receivers?2911 bool IsNull = Receiver->isNullPointerConstant(Context,2912 Expr::NPC_ValueDependentIsNull);2913 CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;2914 Receiver =2915 SemaRef.ImpCastExprToType(Receiver, Context.getObjCIdType(), Kind)2916 .get();2917 }2918 ReceiverType = Receiver->getType();2919 } else if (getLangOpts().CPlusPlus) {2920 // The receiver must be a complete type.2921 if (SemaRef.RequireCompleteType(Loc, Receiver->getType(),2922 diag::err_incomplete_receiver_type))2923 return ExprError();2924 2925 ExprResult result =2926 SemaRef.PerformContextuallyConvertToObjCPointer(Receiver);2927 if (result.isUsable()) {2928 Receiver = result.get();2929 ReceiverType = Receiver->getType();2930 }2931 }2932 }2933 2934 // There's a somewhat weird interaction here where we assume that we2935 // won't actually have a method unless we also don't need to do some2936 // of the more detailed type-checking on the receiver.2937 2938 if (!Method) {2939 // Handle messages to id and __kindof types (where we use the2940 // global method pool).2941 const ObjCObjectType *typeBound = nullptr;2942 bool receiverIsIdLike = ReceiverType->isObjCIdOrObjectKindOfType(Context,2943 typeBound);2944 if (receiverIsIdLike || ReceiverType->isBlockPointerType() ||2945 (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {2946 SmallVector<ObjCMethodDecl*, 4> Methods;2947 // If we have a type bound, further filter the methods.2948 CollectMultipleMethodsInGlobalPool(Sel, Methods, true/*InstanceFirst*/,2949 true/*CheckTheOther*/, typeBound);2950 if (!Methods.empty()) {2951 // We choose the first method as the initial candidate, then try to2952 // select a better one.2953 Method = Methods[0];2954 2955 if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(2956 Sel, ArgsIn, Method->isInstanceMethod(), Methods))2957 Method = BestMethod;2958 2959 if (!AreMultipleMethodsInGlobalPool(Sel, Method,2960 SourceRange(LBracLoc, RBracLoc),2961 receiverIsIdLike, Methods))2962 SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs);2963 }2964 } else if (ReceiverType->isObjCClassOrClassKindOfType() ||2965 ReceiverType->isObjCQualifiedClassType()) {2966 // Handle messages to Class.2967 // We allow sending a message to a qualified Class ("Class<foo>"), which2968 // is ok as long as one of the protocols implements the selector (if not,2969 // warn).2970 if (!ReceiverType->isObjCClassOrClassKindOfType()) {2971 const ObjCObjectPointerType *QClassTy2972 = ReceiverType->getAsObjCQualifiedClassType();2973 // Search protocols for class methods.2974 Method = LookupMethodInQualifiedType(Sel, QClassTy, false);2975 if (!Method) {2976 Method = LookupMethodInQualifiedType(Sel, QClassTy, true);2977 // warn if instance method found for a Class message.2978 if (Method && !isMethodDeclaredInRootProtocol(SemaRef, Method)) {2979 Diag(SelLoc, diag::warn_instance_method_on_class_found)2980 << Method->getSelector() << Sel;2981 Diag(Method->getLocation(), diag::note_method_declared_at)2982 << Method->getDeclName();2983 }2984 }2985 } else {2986 if (ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl()) {2987 if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {2988 // As a guess, try looking for the method in the current interface.2989 // This very well may not produce the "right" method.2990 2991 // First check the public methods in the class interface.2992 Method = ClassDecl->lookupClassMethod(Sel);2993 2994 if (!Method)2995 Method = ClassDecl->lookupPrivateClassMethod(Sel);2996 2997 if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs))2998 return ExprError();2999 }3000 }3001 if (!Method) {3002 // If not messaging 'self', look for any factory method named 'Sel'.3003 if (!Receiver || !isSelfExpr(Receiver)) {3004 // If no class (factory) method was found, check if an _instance_3005 // method of the same name exists in the root class only.3006 SmallVector<ObjCMethodDecl*, 4> Methods;3007 CollectMultipleMethodsInGlobalPool(Sel, Methods,3008 false/*InstanceFirst*/,3009 true/*CheckTheOther*/);3010 if (!Methods.empty()) {3011 // We choose the first method as the initial candidate, then try3012 // to select a better one.3013 Method = Methods[0];3014 3015 // If we find an instance method, emit warning.3016 if (Method->isInstanceMethod()) {3017 if (const ObjCInterfaceDecl *ID =3018 dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {3019 if (ID->getSuperClass())3020 Diag(SelLoc, diag::warn_root_inst_method_not_found)3021 << Sel << SourceRange(LBracLoc, RBracLoc);3022 }3023 }3024 3025 if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(3026 Sel, ArgsIn, Method->isInstanceMethod(), Methods))3027 Method = BestMethod;3028 }3029 }3030 }3031 }3032 } else {3033 ObjCInterfaceDecl *ClassDecl = nullptr;3034 3035 // We allow sending a message to a qualified ID ("id<foo>"), which is ok as3036 // long as one of the protocols implements the selector (if not, warn).3037 // And as long as message is not deprecated/unavailable (warn if it is).3038 if (const ObjCObjectPointerType *QIdTy3039 = ReceiverType->getAsObjCQualifiedIdType()) {3040 // Search protocols for instance methods.3041 Method = LookupMethodInQualifiedType(Sel, QIdTy, true);3042 if (!Method)3043 Method = LookupMethodInQualifiedType(Sel, QIdTy, false);3044 if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs))3045 return ExprError();3046 } else if (const ObjCObjectPointerType *OCIType3047 = ReceiverType->getAsObjCInterfacePointerType()) {3048 // We allow sending a message to a pointer to an interface (an object).3049 ClassDecl = OCIType->getInterfaceDecl();3050 3051 // Try to complete the type. Under ARC, this is a hard error from which3052 // we don't try to recover.3053 // FIXME: In the non-ARC case, this will still be a hard error if the3054 // definition is found in a module that's not visible.3055 const ObjCInterfaceDecl *forwardClass = nullptr;3056 if (SemaRef.RequireCompleteType(3057 Loc, OCIType->getPointeeType(),3058 getLangOpts().ObjCAutoRefCount3059 ? diag::err_arc_receiver_forward_instance3060 : diag::warn_receiver_forward_instance,3061 RecRange)) {3062 if (getLangOpts().ObjCAutoRefCount)3063 return ExprError();3064 3065 forwardClass = OCIType->getInterfaceDecl();3066 Diag(Receiver ? Receiver->getBeginLoc() : SuperLoc,3067 diag::note_receiver_is_id);3068 Method = nullptr;3069 } else {3070 Method = ClassDecl->lookupInstanceMethod(Sel);3071 }3072 3073 if (!Method)3074 // Search protocol qualifiers.3075 Method = LookupMethodInQualifiedType(Sel, OCIType, true);3076 3077 if (!Method) {3078 // If we have implementations in scope, check "private" methods.3079 Method = ClassDecl->lookupPrivateMethod(Sel);3080 3081 if (!Method && getLangOpts().ObjCAutoRefCount) {3082 Diag(SelLoc, diag::err_arc_may_not_respond)3083 << OCIType->getPointeeType() << Sel << RecRange3084 << SourceRange(SelectorLocs.front(), SelectorLocs.back());3085 return ExprError();3086 }3087 3088 if (!Method && (!Receiver || !isSelfExpr(Receiver))) {3089 // If we still haven't found a method, look in the global pool. This3090 // behavior isn't very desirable, however we need it for GCC3091 // compatibility. FIXME: should we deviate??3092 if (OCIType->qual_empty()) {3093 SmallVector<ObjCMethodDecl*, 4> Methods;3094 CollectMultipleMethodsInGlobalPool(Sel, Methods,3095 true/*InstanceFirst*/,3096 false/*CheckTheOther*/);3097 if (!Methods.empty()) {3098 // We choose the first method as the initial candidate, then try3099 // to select a better one.3100 Method = Methods[0];3101 3102 if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(3103 Sel, ArgsIn, Method->isInstanceMethod(), Methods))3104 Method = BestMethod;3105 3106 AreMultipleMethodsInGlobalPool(Sel, Method,3107 SourceRange(LBracLoc, RBracLoc),3108 true/*receiverIdOrClass*/,3109 Methods);3110 }3111 if (Method && !forwardClass)3112 Diag(SelLoc, diag::warn_maynot_respond)3113 << OCIType->getInterfaceDecl()->getIdentifier()3114 << Sel << RecRange;3115 }3116 }3117 }3118 if (Method &&3119 SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs, forwardClass))3120 return ExprError();3121 } else {3122 // Reject other random receiver types (e.g. structs).3123 Diag(Loc, diag::err_bad_receiver_type) << ReceiverType << RecRange;3124 return ExprError();3125 }3126 }3127 }3128 3129 FunctionScopeInfo *DIFunctionScopeInfo =3130 (Method && Method->getMethodFamily() == OMF_init)3131 ? SemaRef.getEnclosingFunction()3132 : nullptr;3133 3134 if (Method && Method->isDirectMethod()) {3135 if (ReceiverType->isObjCIdType() && !isImplicit) {3136 Diag(Receiver->getExprLoc(),3137 diag::err_messaging_unqualified_id_with_direct_method);3138 Diag(Method->getLocation(), diag::note_direct_method_declared_at)3139 << Method->getDeclName();3140 }3141 3142 // Under ARC, self can't be assigned, and doing a direct call to `self`3143 // when it's a Class is hence safe. For other cases, we can't trust `self`3144 // is what we think it is, so we reject it.3145 if (ReceiverType->isObjCClassType() && !isImplicit &&3146 !(Receiver->isObjCSelfExpr() && getLangOpts().ObjCAutoRefCount)) {3147 {3148 auto Builder = Diag(Receiver->getExprLoc(),3149 diag::err_messaging_class_with_direct_method);3150 if (Receiver->isObjCSelfExpr()) {3151 Builder.AddFixItHint(FixItHint::CreateReplacement(3152 RecRange, Method->getClassInterface()->getName()));3153 }3154 }3155 Diag(Method->getLocation(), diag::note_direct_method_declared_at)3156 << Method->getDeclName();3157 }3158 3159 if (SuperLoc.isValid()) {3160 {3161 auto Builder =3162 Diag(SuperLoc, diag::err_messaging_super_with_direct_method);3163 if (ReceiverType->isObjCClassType()) {3164 Builder.AddFixItHint(FixItHint::CreateReplacement(3165 SuperLoc, Method->getClassInterface()->getName()));3166 } else {3167 Builder.AddFixItHint(FixItHint::CreateReplacement(SuperLoc, "self"));3168 }3169 }3170 Diag(Method->getLocation(), diag::note_direct_method_declared_at)3171 << Method->getDeclName();3172 }3173 } else if (ReceiverType->isObjCIdType() && !isImplicit) {3174 Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id);3175 }3176 3177 if (DIFunctionScopeInfo &&3178 DIFunctionScopeInfo->ObjCIsDesignatedInit &&3179 (SuperLoc.isValid() || isSelfExpr(Receiver))) {3180 bool isDesignatedInitChain = false;3181 if (SuperLoc.isValid()) {3182 if (const ObjCObjectPointerType *3183 OCIType = ReceiverType->getAsObjCInterfacePointerType()) {3184 if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {3185 // Either we know this is a designated initializer or we3186 // conservatively assume it because we don't know for sure.3187 if (!ID->declaresOrInheritsDesignatedInitializers() ||3188 ID->isDesignatedInitializer(Sel)) {3189 isDesignatedInitChain = true;3190 DIFunctionScopeInfo->ObjCWarnForNoDesignatedInitChain = false;3191 }3192 }3193 }3194 }3195 if (!isDesignatedInitChain) {3196 const ObjCMethodDecl *InitMethod = nullptr;3197 auto *CurMD = SemaRef.getCurMethodDecl();3198 assert(CurMD && "Current method declaration should not be null");3199 bool isDesignated =3200 CurMD->isDesignatedInitializerForTheInterface(&InitMethod);3201 assert(isDesignated && InitMethod);3202 (void)isDesignated;3203 Diag(SelLoc, SuperLoc.isValid() ?3204 diag::warn_objc_designated_init_non_designated_init_call :3205 diag::warn_objc_designated_init_non_super_designated_init_call);3206 Diag(InitMethod->getLocation(),3207 diag::note_objc_designated_init_marked_here);3208 }3209 }3210 3211 if (DIFunctionScopeInfo &&3212 DIFunctionScopeInfo->ObjCIsSecondaryInit &&3213 (SuperLoc.isValid() || isSelfExpr(Receiver))) {3214 if (SuperLoc.isValid()) {3215 Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call);3216 } else {3217 DIFunctionScopeInfo->ObjCWarnForNoInitDelegation = false;3218 }3219 }3220 3221 // Check the message arguments.3222 unsigned NumArgs = ArgsIn.size();3223 Expr **Args = ArgsIn.data();3224 QualType ReturnType;3225 ExprValueKind VK = VK_PRValue;3226 bool ClassMessage = (ReceiverType->isObjCClassType() ||3227 ReceiverType->isObjCQualifiedClassType());3228 if (CheckMessageArgumentTypes(Receiver, ReceiverType,3229 MultiExprArg(Args, NumArgs), Sel, SelectorLocs,3230 Method, ClassMessage, SuperLoc.isValid(),3231 LBracLoc, RBracLoc, RecRange, ReturnType, VK))3232 return ExprError();3233 3234 if (Method && !Method->getReturnType()->isVoidType() &&3235 SemaRef.RequireCompleteType(3236 LBracLoc, Method->getReturnType(),3237 diag::err_illegal_message_expr_incomplete_type))3238 return ExprError();3239 3240 // In ARC, forbid the user from sending messages to3241 // retain/release/autorelease/dealloc/retainCount explicitly.3242 if (getLangOpts().ObjCAutoRefCount) {3243 ObjCMethodFamily family =3244 (Method ? Method->getMethodFamily() : Sel.getMethodFamily());3245 switch (family) {3246 case OMF_init:3247 if (Method)3248 checkInitMethod(Method, ReceiverType);3249 break;3250 3251 case OMF_None:3252 case OMF_alloc:3253 case OMF_copy:3254 case OMF_finalize:3255 case OMF_mutableCopy:3256 case OMF_new:3257 case OMF_self:3258 case OMF_initialize:3259 break;3260 3261 case OMF_dealloc:3262 case OMF_retain:3263 case OMF_release:3264 case OMF_autorelease:3265 case OMF_retainCount:3266 Diag(SelLoc, diag::err_arc_illegal_explicit_message)3267 << Sel << RecRange;3268 break;3269 3270 case OMF_performSelector:3271 if (Method && NumArgs >= 1) {3272 if (const auto *SelExp =3273 dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens())) {3274 Selector ArgSel = SelExp->getSelector();3275 ObjCMethodDecl *SelMethod =3276 LookupInstanceMethodInGlobalPool(ArgSel,3277 SelExp->getSourceRange());3278 if (!SelMethod)3279 SelMethod =3280 LookupFactoryMethodInGlobalPool(ArgSel,3281 SelExp->getSourceRange());3282 if (SelMethod) {3283 ObjCMethodFamily SelFamily = SelMethod->getMethodFamily();3284 switch (SelFamily) {3285 case OMF_alloc:3286 case OMF_copy:3287 case OMF_mutableCopy:3288 case OMF_new:3289 case OMF_init:3290 // Issue error, unless ns_returns_not_retained.3291 if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) {3292 // selector names a +1 method3293 Diag(SelLoc,3294 diag::err_arc_perform_selector_retains);3295 Diag(SelMethod->getLocation(), diag::note_method_declared_at)3296 << SelMethod->getDeclName();3297 }3298 break;3299 default:3300 // +0 call. OK. unless ns_returns_retained.3301 if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) {3302 // selector names a +1 method3303 Diag(SelLoc,3304 diag::err_arc_perform_selector_retains);3305 Diag(SelMethod->getLocation(), diag::note_method_declared_at)3306 << SelMethod->getDeclName();3307 }3308 break;3309 }3310 }3311 } else {3312 // error (may leak).3313 Diag(SelLoc, diag::warn_arc_perform_selector_leaks);3314 Diag(Args[0]->getExprLoc(), diag::note_used_here);3315 }3316 }3317 break;3318 }3319 }3320 3321 DiagnoseCStringFormatDirectiveInObjCAPI(SemaRef, Method, Sel, Args, NumArgs);3322 3323 // Construct the appropriate ObjCMessageExpr instance.3324 ObjCMessageExpr *Result;3325 if (SuperLoc.isValid())3326 Result = ObjCMessageExpr::Create(3327 Context, ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/true,3328 ReceiverType, Sel, SelectorLocs, Method, ArrayRef(Args, NumArgs),3329 RBracLoc, isImplicit);3330 else {3331 Result = ObjCMessageExpr::Create(3332 Context, ReturnType, VK, LBracLoc, Receiver, Sel, SelectorLocs, Method,3333 ArrayRef(Args, NumArgs), RBracLoc, isImplicit);3334 if (!isImplicit)3335 checkCocoaAPI(SemaRef, Result);3336 }3337 if (Method) {3338 bool IsClassObjectCall = ClassMessage;3339 // 'self' message receivers in class methods should be treated as message3340 // sends to the class object in order for the semantic checks to be3341 // performed correctly. Messages to 'super' already count as class messages,3342 // so they don't need to be handled here.3343 if (Receiver && isSelfExpr(Receiver)) {3344 if (const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>()) {3345 if (OPT->getObjectType()->isObjCClass()) {3346 if (const auto *CurMeth = SemaRef.getCurMethodDecl()) {3347 IsClassObjectCall = true;3348 ReceiverType =3349 Context.getObjCInterfaceType(CurMeth->getClassInterface());3350 }3351 }3352 }3353 }3354 checkFoundationAPI(SemaRef, SelLoc, Method, ArrayRef(Args, NumArgs),3355 ReceiverType, IsClassObjectCall);3356 }3357 3358 if (getLangOpts().ObjCAutoRefCount) {3359 // In ARC, annotate delegate init calls.3360 if (Result->getMethodFamily() == OMF_init &&3361 (SuperLoc.isValid() || isSelfExpr(Receiver))) {3362 // Only consider init calls *directly* in init implementations,3363 // not within blocks.3364 ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext);3365 if (method && method->getMethodFamily() == OMF_init) {3366 // The implicit assignment to self means we also don't want to3367 // consume the result.3368 Result->setDelegateInitCall(true);3369 return Result;3370 }3371 }3372 3373 // In ARC, check for message sends which are likely to introduce3374 // retain cycles.3375 checkRetainCycles(Result);3376 }3377 3378 if (getLangOpts().ObjCWeak) {3379 if (!isImplicit && Method) {3380 if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) {3381 bool IsWeak =3382 Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak;3383 if (!IsWeak && Sel.isUnarySelector())3384 IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;3385 if (IsWeak && !SemaRef.isUnevaluatedContext() &&3386 !getDiagnostics().isIgnored(diag::warn_arc_repeated_use_of_weak,3387 LBracLoc))3388 SemaRef.getCurFunction()->recordUseOfWeak(Result, Prop);3389 }3390 }3391 }3392 3393 CheckObjCCircularContainer(Result);3394 3395 return SemaRef.MaybeBindToTemporary(Result);3396}3397 3398static void RemoveSelectorFromWarningCache(SemaObjC &S, Expr *Arg) {3399 if (ObjCSelectorExpr *OSE =3400 dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) {3401 Selector Sel = OSE->getSelector();3402 SourceLocation Loc = OSE->getAtLoc();3403 auto Pos = S.ReferencedSelectors.find(Sel);3404 if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)3405 S.ReferencedSelectors.erase(Pos);3406 }3407}3408 3409// ActOnInstanceMessage - used for both unary and keyword messages.3410// ArgExprs is optional - if it is present, the number of expressions3411// is obtained from Sel.getNumArgs().3412ExprResult SemaObjC::ActOnInstanceMessage(Scope *S, Expr *Receiver,3413 Selector Sel, SourceLocation LBracLoc,3414 ArrayRef<SourceLocation> SelectorLocs,3415 SourceLocation RBracLoc,3416 MultiExprArg Args) {3417 ASTContext &Context = getASTContext();3418 if (!Receiver)3419 return ExprError();3420 3421 // A ParenListExpr can show up while doing error recovery with invalid code.3422 if (isa<ParenListExpr>(Receiver)) {3423 ExprResult Result =3424 SemaRef.MaybeConvertParenListExprToParenExpr(S, Receiver);3425 if (Result.isInvalid()) return ExprError();3426 Receiver = Result.get();3427 }3428 3429 if (RespondsToSelectorSel.isNull()) {3430 IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector");3431 RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId);3432 }3433 if (Sel == RespondsToSelectorSel)3434 RemoveSelectorFromWarningCache(*this, Args[0]);3435 3436 return BuildInstanceMessage(Receiver, Receiver->getType(),3437 /*SuperLoc=*/SourceLocation(), Sel,3438 /*Method=*/nullptr, LBracLoc, SelectorLocs,3439 RBracLoc, Args);3440}3441 3442enum ARCConversionTypeClass {3443 /// int, void, struct A3444 ACTC_none,3445 3446 /// id, void (^)()3447 ACTC_retainable,3448 3449 /// id*, id***, void (^*)(),3450 ACTC_indirectRetainable,3451 3452 /// void* might be a normal C type, or it might a CF type.3453 ACTC_voidPtr,3454 3455 /// struct A*3456 ACTC_coreFoundation3457};3458 3459static bool isAnyRetainable(ARCConversionTypeClass ACTC) {3460 return (ACTC == ACTC_retainable ||3461 ACTC == ACTC_coreFoundation ||3462 ACTC == ACTC_voidPtr);3463}3464 3465static bool isAnyCLike(ARCConversionTypeClass ACTC) {3466 return ACTC == ACTC_none ||3467 ACTC == ACTC_voidPtr ||3468 ACTC == ACTC_coreFoundation;3469}3470 3471static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) {3472 bool isIndirect = false;3473 3474 // Ignore an outermost reference type.3475 if (const ReferenceType *ref = type->getAs<ReferenceType>()) {3476 type = ref->getPointeeType();3477 isIndirect = true;3478 }3479 3480 // Drill through pointers and arrays recursively.3481 while (true) {3482 if (const PointerType *ptr = type->getAs<PointerType>()) {3483 type = ptr->getPointeeType();3484 3485 // The first level of pointer may be the innermost pointer on a CF type.3486 if (!isIndirect) {3487 if (type->isVoidType()) return ACTC_voidPtr;3488 if (type->isRecordType()) return ACTC_coreFoundation;3489 }3490 } else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) {3491 type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0);3492 } else {3493 break;3494 }3495 isIndirect = true;3496 }3497 3498 if (isIndirect) {3499 if (type->isObjCARCBridgableType())3500 return ACTC_indirectRetainable;3501 return ACTC_none;3502 }3503 3504 if (type->isObjCARCBridgableType())3505 return ACTC_retainable;3506 3507 return ACTC_none;3508}3509 3510namespace {3511 /// A result from the cast checker.3512 enum ACCResult {3513 /// Cannot be casted.3514 ACC_invalid,3515 3516 /// Can be safely retained or not retained.3517 ACC_bottom,3518 3519 /// Can be casted at +0.3520 ACC_plusZero,3521 3522 /// Can be casted at +1.3523 ACC_plusOne3524 };3525 ACCResult merge(ACCResult left, ACCResult right) {3526 if (left == right) return left;3527 if (left == ACC_bottom) return right;3528 if (right == ACC_bottom) return left;3529 return ACC_invalid;3530 }3531 3532 /// A checker which white-lists certain expressions whose conversion3533 /// to or from retainable type would otherwise be forbidden in ARC.3534 class ARCCastChecker : public StmtVisitor<ARCCastChecker, ACCResult> {3535 typedef StmtVisitor<ARCCastChecker, ACCResult> super;3536 3537 ASTContext &Context;3538 ARCConversionTypeClass SourceClass;3539 ARCConversionTypeClass TargetClass;3540 bool Diagnose;3541 3542 static bool isCFType(QualType type) {3543 // Someday this can use ns_bridged. For now, it has to do this.3544 return type->isCARCBridgableType();3545 }3546 3547 public:3548 ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source,3549 ARCConversionTypeClass target, bool diagnose)3550 : Context(Context), SourceClass(source), TargetClass(target),3551 Diagnose(diagnose) {}3552 3553 using super::Visit;3554 ACCResult Visit(Expr *e) {3555 return super::Visit(e->IgnoreParens());3556 }3557 3558 ACCResult VisitStmt(Stmt *s) {3559 return ACC_invalid;3560 }3561 3562 /// Null pointer constants can be casted however you please.3563 ACCResult VisitExpr(Expr *e) {3564 if (e->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))3565 return ACC_bottom;3566 return ACC_invalid;3567 }3568 3569 /// Objective-C string literals can be safely casted.3570 ACCResult VisitObjCStringLiteral(ObjCStringLiteral *e) {3571 // If we're casting to any retainable type, go ahead. Global3572 // strings are immune to retains, so this is bottom.3573 if (isAnyRetainable(TargetClass)) return ACC_bottom;3574 3575 return ACC_invalid;3576 }3577 3578 /// Look through certain implicit and explicit casts.3579 ACCResult VisitCastExpr(CastExpr *e) {3580 switch (e->getCastKind()) {3581 case CK_NullToPointer:3582 return ACC_bottom;3583 3584 case CK_NoOp:3585 case CK_LValueToRValue:3586 case CK_BitCast:3587 case CK_CPointerToObjCPointerCast:3588 case CK_BlockPointerToObjCPointerCast:3589 case CK_AnyPointerToBlockPointerCast:3590 return Visit(e->getSubExpr());3591 3592 default:3593 return ACC_invalid;3594 }3595 }3596 3597 /// Look through unary extension.3598 ACCResult VisitUnaryExtension(UnaryOperator *e) {3599 return Visit(e->getSubExpr());3600 }3601 3602 /// Ignore the LHS of a comma operator.3603 ACCResult VisitBinComma(BinaryOperator *e) {3604 return Visit(e->getRHS());3605 }3606 3607 /// Conditional operators are okay if both sides are okay.3608 ACCResult VisitConditionalOperator(ConditionalOperator *e) {3609 ACCResult left = Visit(e->getTrueExpr());3610 if (left == ACC_invalid) return ACC_invalid;3611 return merge(left, Visit(e->getFalseExpr()));3612 }3613 3614 /// Look through pseudo-objects.3615 ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) {3616 // If we're getting here, we should always have a result.3617 return Visit(e->getResultExpr());3618 }3619 3620 /// Statement expressions are okay if their result expression is okay.3621 ACCResult VisitStmtExpr(StmtExpr *e) {3622 return Visit(e->getSubStmt()->body_back());3623 }3624 3625 /// Some declaration references are okay.3626 ACCResult VisitDeclRefExpr(DeclRefExpr *e) {3627 VarDecl *var = dyn_cast<VarDecl>(e->getDecl());3628 // References to global constants are okay.3629 if (isAnyRetainable(TargetClass) &&3630 isAnyRetainable(SourceClass) &&3631 var &&3632 !var->hasDefinition(Context) &&3633 var->getType().isConstQualified()) {3634 3635 // In system headers, they can also be assumed to be immune to retains.3636 // These are things like 'kCFStringTransformToLatin'.3637 if (Context.getSourceManager().isInSystemHeader(var->getLocation()))3638 return ACC_bottom;3639 3640 return ACC_plusZero;3641 }3642 3643 // Nothing else.3644 return ACC_invalid;3645 }3646 3647 /// Some calls are okay.3648 ACCResult VisitCallExpr(CallExpr *e) {3649 if (FunctionDecl *fn = e->getDirectCallee())3650 if (ACCResult result = checkCallToFunction(fn))3651 return result;3652 3653 return super::VisitCallExpr(e);3654 }3655 3656 ACCResult checkCallToFunction(FunctionDecl *fn) {3657 // Require a CF*Ref return type.3658 if (!isCFType(fn->getReturnType()))3659 return ACC_invalid;3660 3661 if (!isAnyRetainable(TargetClass))3662 return ACC_invalid;3663 3664 // Honor an explicit 'not retained' attribute.3665 if (fn->hasAttr<CFReturnsNotRetainedAttr>())3666 return ACC_plusZero;3667 3668 // Honor an explicit 'retained' attribute, except that for3669 // now we're not going to permit implicit handling of +1 results,3670 // because it's a bit frightening.3671 if (fn->hasAttr<CFReturnsRetainedAttr>())3672 return Diagnose ? ACC_plusOne3673 : ACC_invalid; // ACC_plusOne if we start accepting this3674 3675 // Recognize this specific builtin function, which is used by CFSTR.3676 unsigned builtinID = fn->getBuiltinID();3677 if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString)3678 return ACC_bottom;3679 3680 // Otherwise, don't do anything implicit with an unaudited function.3681 if (!fn->hasAttr<CFAuditedTransferAttr>())3682 return ACC_invalid;3683 3684 // Otherwise, it's +0 unless it follows the create convention.3685 if (ento::coreFoundation::followsCreateRule(fn))3686 return Diagnose ? ACC_plusOne3687 : ACC_invalid; // ACC_plusOne if we start accepting this3688 3689 return ACC_plusZero;3690 }3691 3692 ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) {3693 return checkCallToMethod(e->getMethodDecl());3694 }3695 3696 ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) {3697 ObjCMethodDecl *method;3698 if (e->isExplicitProperty())3699 method = e->getExplicitProperty()->getGetterMethodDecl();3700 else3701 method = e->getImplicitPropertyGetter();3702 return checkCallToMethod(method);3703 }3704 3705 ACCResult checkCallToMethod(ObjCMethodDecl *method) {3706 if (!method) return ACC_invalid;3707 3708 // Check for message sends to functions returning CF types. We3709 // just obey the Cocoa conventions with these, even though the3710 // return type is CF.3711 if (!isAnyRetainable(TargetClass) || !isCFType(method->getReturnType()))3712 return ACC_invalid;3713 3714 // If the method is explicitly marked not-retained, it's +0.3715 if (method->hasAttr<CFReturnsNotRetainedAttr>())3716 return ACC_plusZero;3717 3718 // If the method is explicitly marked as returning retained, or its3719 // selector follows a +1 Cocoa convention, treat it as +1.3720 if (method->hasAttr<CFReturnsRetainedAttr>())3721 return ACC_plusOne;3722 3723 switch (method->getSelector().getMethodFamily()) {3724 case OMF_alloc:3725 case OMF_copy:3726 case OMF_mutableCopy:3727 case OMF_new:3728 return ACC_plusOne;3729 3730 default:3731 // Otherwise, treat it as +0.3732 return ACC_plusZero;3733 }3734 }3735 };3736} // end anonymous namespace3737 3738bool SemaObjC::isKnownName(StringRef name) {3739 ASTContext &Context = getASTContext();3740 if (name.empty())3741 return false;3742 LookupResult R(SemaRef, &Context.Idents.get(name), SourceLocation(),3743 Sema::LookupOrdinaryName);3744 return SemaRef.LookupName(R, SemaRef.TUScope, false);3745}3746 3747template <typename DiagBuilderT>3748static void addFixitForObjCARCConversion(3749 Sema &S, DiagBuilderT &DiagB, CheckedConversionKind CCK,3750 SourceLocation afterLParen, QualType castType, Expr *castExpr,3751 Expr *realCast, const char *bridgeKeyword, const char *CFBridgeName) {3752 // We handle C-style and implicit casts here.3753 switch (CCK) {3754 case CheckedConversionKind::Implicit:3755 case CheckedConversionKind::ForBuiltinOverloadedOp:3756 case CheckedConversionKind::CStyleCast:3757 case CheckedConversionKind::OtherCast:3758 break;3759 case CheckedConversionKind::FunctionalCast:3760 return;3761 }3762 3763 if (CFBridgeName) {3764 if (CCK == CheckedConversionKind::OtherCast) {3765 if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {3766 SourceRange range(NCE->getOperatorLoc(),3767 NCE->getAngleBrackets().getEnd());3768 SmallString<32> BridgeCall;3769 3770 SourceManager &SM = S.getSourceManager();3771 char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));3772 if (Lexer::isAsciiIdentifierContinueChar(PrevChar, S.getLangOpts()))3773 BridgeCall += ' ';3774 3775 BridgeCall += CFBridgeName;3776 DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall));3777 }3778 return;3779 }3780 Expr *castedE = castExpr;3781 if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE))3782 castedE = CCE->getSubExpr();3783 castedE = castedE->IgnoreImpCasts();3784 SourceRange range = castedE->getSourceRange();3785 3786 SmallString<32> BridgeCall;3787 3788 SourceManager &SM = S.getSourceManager();3789 char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));3790 if (Lexer::isAsciiIdentifierContinueChar(PrevChar, S.getLangOpts()))3791 BridgeCall += ' ';3792 3793 BridgeCall += CFBridgeName;3794 3795 if (isa<ParenExpr>(castedE)) {3796 DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),3797 BridgeCall));3798 } else {3799 BridgeCall += '(';3800 DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),3801 BridgeCall));3802 DiagB.AddFixItHint(FixItHint::CreateInsertion(3803 S.getLocForEndOfToken(range.getEnd()),3804 ")"));3805 }3806 return;3807 }3808 3809 if (CCK == CheckedConversionKind::CStyleCast) {3810 DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword));3811 } else if (CCK == CheckedConversionKind::OtherCast) {3812 if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {3813 std::string castCode = "(";3814 castCode += bridgeKeyword;3815 castCode += castType.getAsString();3816 castCode += ")";3817 SourceRange Range(NCE->getOperatorLoc(),3818 NCE->getAngleBrackets().getEnd());3819 DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode));3820 }3821 } else {3822 std::string castCode = "(";3823 castCode += bridgeKeyword;3824 castCode += castType.getAsString();3825 castCode += ")";3826 Expr *castedE = castExpr->IgnoreImpCasts();3827 SourceRange range = castedE->getSourceRange();3828 if (isa<ParenExpr>(castedE)) {3829 DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),3830 castCode));3831 } else {3832 castCode += "(";3833 DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),3834 castCode));3835 DiagB.AddFixItHint(FixItHint::CreateInsertion(3836 S.getLocForEndOfToken(range.getEnd()),3837 ")"));3838 }3839 }3840}3841 3842template <typename T>3843static inline T *getObjCBridgeAttr(const TypedefType *TD) {3844 TypedefNameDecl *TDNDecl = TD->getDecl();3845 QualType QT = TDNDecl->getUnderlyingType();3846 if (QT->isPointerType()) {3847 QT = QT->getPointeeType();3848 if (const RecordType *RT = QT->getAsCanonical<RecordType>()) {3849 for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {3850 if (auto *attr = Redecl->getAttr<T>())3851 return attr;3852 }3853 }3854 }3855 return nullptr;3856}3857 3858static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T,3859 TypedefNameDecl *&TDNDecl) {3860 while (const auto *TD = T->getAs<TypedefType>()) {3861 TDNDecl = TD->getDecl();3862 if (ObjCBridgeRelatedAttr *ObjCBAttr =3863 getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD))3864 return ObjCBAttr;3865 T = TDNDecl->getUnderlyingType();3866 }3867 return nullptr;3868}3869 3870static void diagnoseObjCARCConversion(Sema &S, SourceRange castRange,3871 QualType castType,3872 ARCConversionTypeClass castACTC,3873 Expr *castExpr, Expr *realCast,3874 ARCConversionTypeClass exprACTC,3875 CheckedConversionKind CCK) {3876 SourceLocation loc =3877 (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());3878 3879 if (S.makeUnavailableInSystemHeader(loc,3880 UnavailableAttr::IR_ARCForbiddenConversion))3881 return;3882 3883 QualType castExprType = castExpr->getType();3884 // Defer emitting a diagnostic for bridge-related casts; that will be3885 // handled by CheckObjCBridgeRelatedConversions.3886 TypedefNameDecl *TDNDecl = nullptr;3887 if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&3888 ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) ||3889 (exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&3890 ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl)))3891 return;3892 3893 unsigned srcKind = 0;3894 switch (exprACTC) {3895 case ACTC_none:3896 case ACTC_coreFoundation:3897 case ACTC_voidPtr:3898 srcKind = (castExprType->isPointerType() ? 1 : 0);3899 break;3900 case ACTC_retainable:3901 srcKind = (castExprType->isBlockPointerType() ? 2 : 3);3902 break;3903 case ACTC_indirectRetainable:3904 srcKind = 4;3905 break;3906 }3907 3908 // Check whether this could be fixed with a bridge cast.3909 SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin());3910 SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;3911 3912 unsigned convKindForDiag = Sema::isCast(CCK) ? 0 : 1;3913 3914 // Bridge from an ARC type to a CF type.3915 if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {3916 3917 S.Diag(loc, diag::err_arc_cast_requires_bridge)3918 << convKindForDiag3919 << 2 // of C pointer type3920 << castExprType3921 << unsigned(castType->isBlockPointerType()) // to ObjC|block type3922 << castType3923 << castRange3924 << castExpr->getSourceRange();3925 bool br = S.ObjC().isKnownName("CFBridgingRelease");3926 ACCResult CreateRule =3927 ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);3928 assert(CreateRule != ACC_bottom && "This cast should already be accepted.");3929 if (CreateRule != ACC_plusOne)3930 {3931 auto DiagB = (CCK != CheckedConversionKind::OtherCast)3932 ? S.Diag(noteLoc, diag::note_arc_bridge)3933 : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);3934 3935 addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,3936 castType, castExpr, realCast, "__bridge ",3937 nullptr);3938 }3939 if (CreateRule != ACC_plusZero)3940 {3941 auto DiagB = (CCK == CheckedConversionKind::OtherCast && !br)3942 ? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer)3943 << castExprType3944 : S.Diag(br ? castExpr->getExprLoc() : noteLoc,3945 diag::note_arc_bridge_transfer)3946 << castExprType << br;3947 3948 addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,3949 castType, castExpr, realCast, "__bridge_transfer ",3950 br ? "CFBridgingRelease" : nullptr);3951 }3952 3953 return;3954 }3955 3956 // Bridge from a CF type to an ARC type.3957 if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {3958 bool br = S.ObjC().isKnownName("CFBridgingRetain");3959 S.Diag(loc, diag::err_arc_cast_requires_bridge)3960 << convKindForDiag3961 << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type3962 << castExprType3963 << 2 // to C pointer type3964 << castType3965 << castRange3966 << castExpr->getSourceRange();3967 ACCResult CreateRule =3968 ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);3969 assert(CreateRule != ACC_bottom && "This cast should already be accepted.");3970 if (CreateRule != ACC_plusOne)3971 {3972 auto DiagB = (CCK != CheckedConversionKind::OtherCast)3973 ? S.Diag(noteLoc, diag::note_arc_bridge)3974 : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);3975 addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,3976 castType, castExpr, realCast, "__bridge ",3977 nullptr);3978 }3979 if (CreateRule != ACC_plusZero)3980 {3981 auto DiagB = (CCK == CheckedConversionKind::OtherCast && !br)3982 ? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained)3983 << castType3984 : S.Diag(br ? castExpr->getExprLoc() : noteLoc,3985 diag::note_arc_bridge_retained)3986 << castType << br;3987 3988 addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,3989 castType, castExpr, realCast, "__bridge_retained ",3990 br ? "CFBridgingRetain" : nullptr);3991 }3992 3993 return;3994 }3995 3996 S.Diag(loc, diag::err_arc_mismatched_cast)3997 << !convKindForDiag3998 << srcKind << castExprType << castType3999 << castRange << castExpr->getSourceRange();4000}4001 4002template <typename TB>4003static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,4004 bool &HadTheAttribute, bool warn) {4005 QualType T = castExpr->getType();4006 HadTheAttribute = false;4007 while (const auto *TD = T->getAs<TypedefType>()) {4008 TypedefNameDecl *TDNDecl = TD->getDecl();4009 if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {4010 if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {4011 HadTheAttribute = true;4012 if (Parm->isStr("id"))4013 return true;4014 4015 // Check for an existing type with this name.4016 LookupResult R(S, DeclarationName(Parm), SourceLocation(),4017 Sema::LookupOrdinaryName);4018 if (S.LookupName(R, S.TUScope)) {4019 NamedDecl *Target = R.getFoundDecl();4020 if (Target && isa<ObjCInterfaceDecl>(Target)) {4021 ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Target);4022 if (const ObjCObjectPointerType *InterfacePointerType =4023 castType->getAsObjCInterfacePointerType()) {4024 ObjCInterfaceDecl *CastClass4025 = InterfacePointerType->getObjectType()->getInterface();4026 if ((CastClass == ExprClass) ||4027 (CastClass && CastClass->isSuperClassOf(ExprClass)))4028 return true;4029 if (warn)4030 S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge)4031 << T << Target->getName() << castType->getPointeeType();4032 return false;4033 } else if (castType->isObjCIdType() ||4034 (S.Context.ObjCObjectAdoptsQTypeProtocols(4035 castType, ExprClass)))4036 // ok to cast to 'id'.4037 // casting to id<p-list> is ok if bridge type adopts all of4038 // p-list protocols.4039 return true;4040 else {4041 if (warn) {4042 S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge)4043 << T << Target->getName() << castType;4044 S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4045 S.Diag(Target->getBeginLoc(), diag::note_declared_at);4046 }4047 return false;4048 }4049 }4050 } else if (!castType->isObjCIdType()) {4051 S.Diag(castExpr->getBeginLoc(),4052 diag::err_objc_cf_bridged_not_interface)4053 << castExpr->getType() << Parm;4054 S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4055 }4056 return true;4057 }4058 return false;4059 }4060 T = TDNDecl->getUnderlyingType();4061 }4062 return true;4063}4064 4065template <typename TB>4066static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,4067 bool &HadTheAttribute, bool warn) {4068 QualType T = castType;4069 HadTheAttribute = false;4070 while (const auto *TD = T->getAs<TypedefType>()) {4071 TypedefNameDecl *TDNDecl = TD->getDecl();4072 if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {4073 if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {4074 HadTheAttribute = true;4075 if (Parm->isStr("id"))4076 return true;4077 4078 NamedDecl *Target = nullptr;4079 // Check for an existing type with this name.4080 LookupResult R(S, DeclarationName(Parm), SourceLocation(),4081 Sema::LookupOrdinaryName);4082 if (S.LookupName(R, S.TUScope)) {4083 Target = R.getFoundDecl();4084 if (Target && isa<ObjCInterfaceDecl>(Target)) {4085 ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target);4086 if (const ObjCObjectPointerType *InterfacePointerType =4087 castExpr->getType()->getAsObjCInterfacePointerType()) {4088 ObjCInterfaceDecl *ExprClass4089 = InterfacePointerType->getObjectType()->getInterface();4090 if ((CastClass == ExprClass) ||4091 (ExprClass && CastClass->isSuperClassOf(ExprClass)))4092 return true;4093 if (warn) {4094 S.Diag(castExpr->getBeginLoc(),4095 diag::warn_objc_invalid_bridge_to_cf)4096 << castExpr->getType()->getPointeeType() << T;4097 S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4098 }4099 return false;4100 } else if (castExpr->getType()->isObjCIdType() ||4101 (S.Context.QIdProtocolsAdoptObjCObjectProtocols(4102 castExpr->getType(), CastClass)))4103 // ok to cast an 'id' expression to a CFtype.4104 // ok to cast an 'id<plist>' expression to CFtype provided plist4105 // adopts all of CFtype's ObjetiveC's class plist.4106 return true;4107 else {4108 if (warn) {4109 S.Diag(castExpr->getBeginLoc(),4110 diag::warn_objc_invalid_bridge_to_cf)4111 << castExpr->getType() << castType;4112 S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4113 S.Diag(Target->getBeginLoc(), diag::note_declared_at);4114 }4115 return false;4116 }4117 }4118 }4119 S.Diag(castExpr->getBeginLoc(),4120 diag::err_objc_ns_bridged_invalid_cfobject)4121 << castExpr->getType() << castType;4122 S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4123 if (Target)4124 S.Diag(Target->getBeginLoc(), diag::note_declared_at);4125 return true;4126 }4127 return false;4128 }4129 T = TDNDecl->getUnderlyingType();4130 }4131 return true;4132}4133 4134void SemaObjC::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {4135 if (!getLangOpts().ObjC)4136 return;4137 // warn in presence of __bridge casting to or from a toll free bridge cast.4138 ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType());4139 ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);4140 if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) {4141 bool HasObjCBridgeAttr;4142 bool ObjCBridgeAttrWillNotWarn = CheckObjCBridgeNSCast<ObjCBridgeAttr>(4143 SemaRef, castType, castExpr, HasObjCBridgeAttr, false);4144 if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)4145 return;4146 bool HasObjCBridgeMutableAttr;4147 bool ObjCBridgeMutableAttrWillNotWarn =4148 CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(4149 SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, false);4150 if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)4151 return;4152 4153 if (HasObjCBridgeAttr)4154 CheckObjCBridgeNSCast<ObjCBridgeAttr>(SemaRef, castType, castExpr,4155 HasObjCBridgeAttr, true);4156 else if (HasObjCBridgeMutableAttr)4157 CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(4158 SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, true);4159 }4160 else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) {4161 bool HasObjCBridgeAttr;4162 bool ObjCBridgeAttrWillNotWarn = CheckObjCBridgeCFCast<ObjCBridgeAttr>(4163 SemaRef, castType, castExpr, HasObjCBridgeAttr, false);4164 if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)4165 return;4166 bool HasObjCBridgeMutableAttr;4167 bool ObjCBridgeMutableAttrWillNotWarn =4168 CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(4169 SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, false);4170 if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)4171 return;4172 4173 if (HasObjCBridgeAttr)4174 CheckObjCBridgeCFCast<ObjCBridgeAttr>(SemaRef, castType, castExpr,4175 HasObjCBridgeAttr, true);4176 else if (HasObjCBridgeMutableAttr)4177 CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(4178 SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, true);4179 }4180}4181 4182void SemaObjC::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) {4183 QualType SrcType = castExpr->getType();4184 if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(castExpr)) {4185 if (PRE->isExplicitProperty()) {4186 if (ObjCPropertyDecl *PDecl = PRE->getExplicitProperty())4187 SrcType = PDecl->getType();4188 }4189 else if (PRE->isImplicitProperty()) {4190 if (ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter())4191 SrcType = Getter->getReturnType();4192 }4193 }4194 4195 ARCConversionTypeClass srcExprACTC = classifyTypeForARCConversion(SrcType);4196 ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType);4197 if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation)4198 return;4199 CheckObjCBridgeRelatedConversions(castExpr->getBeginLoc(), castType, SrcType,4200 castExpr);4201}4202 4203bool SemaObjC::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,4204 CastKind &Kind) {4205 if (!getLangOpts().ObjC)4206 return false;4207 ARCConversionTypeClass exprACTC =4208 classifyTypeForARCConversion(castExpr->getType());4209 ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);4210 if ((castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) ||4211 (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable)) {4212 CheckTollFreeBridgeCast(castType, castExpr);4213 Kind = (castACTC == ACTC_coreFoundation) ? CK_BitCast4214 : CK_CPointerToObjCPointerCast;4215 return true;4216 }4217 return false;4218}4219 4220bool SemaObjC::checkObjCBridgeRelatedComponents(4221 SourceLocation Loc, QualType DestType, QualType SrcType,4222 ObjCInterfaceDecl *&RelatedClass, ObjCMethodDecl *&ClassMethod,4223 ObjCMethodDecl *&InstanceMethod, TypedefNameDecl *&TDNDecl, bool CfToNs,4224 bool Diagnose) {4225 ASTContext &Context = getASTContext();4226 QualType T = CfToNs ? SrcType : DestType;4227 ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl);4228 if (!ObjCBAttr)4229 return false;4230 4231 IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();4232 IdentifierInfo *CMId = ObjCBAttr->getClassMethod();4233 IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();4234 if (!RCId)4235 return false;4236 NamedDecl *Target = nullptr;4237 // Check for an existing type with this name.4238 LookupResult R(SemaRef, DeclarationName(RCId), SourceLocation(),4239 Sema::LookupOrdinaryName);4240 if (!SemaRef.LookupName(R, SemaRef.TUScope)) {4241 if (Diagnose) {4242 Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId4243 << SrcType << DestType;4244 Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4245 }4246 return false;4247 }4248 Target = R.getFoundDecl();4249 if (Target && isa<ObjCInterfaceDecl>(Target))4250 RelatedClass = cast<ObjCInterfaceDecl>(Target);4251 else {4252 if (Diagnose) {4253 Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId4254 << SrcType << DestType;4255 Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4256 if (Target)4257 Diag(Target->getBeginLoc(), diag::note_declared_at);4258 }4259 return false;4260 }4261 4262 // Check for an existing class method with the given selector name.4263 if (CfToNs && CMId) {4264 Selector Sel = Context.Selectors.getUnarySelector(CMId);4265 ClassMethod = RelatedClass->lookupMethod(Sel, false);4266 if (!ClassMethod) {4267 if (Diagnose) {4268 Diag(Loc, diag::err_objc_bridged_related_known_method)4269 << SrcType << DestType << Sel << false;4270 Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4271 }4272 return false;4273 }4274 }4275 4276 // Check for an existing instance method with the given selector name.4277 if (!CfToNs && IMId) {4278 Selector Sel = Context.Selectors.getNullarySelector(IMId);4279 InstanceMethod = RelatedClass->lookupMethod(Sel, true);4280 if (!InstanceMethod) {4281 if (Diagnose) {4282 Diag(Loc, diag::err_objc_bridged_related_known_method)4283 << SrcType << DestType << Sel << true;4284 Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4285 }4286 return false;4287 }4288 }4289 return true;4290}4291 4292bool SemaObjC::CheckObjCBridgeRelatedConversions(SourceLocation Loc,4293 QualType DestType,4294 QualType SrcType,4295 Expr *&SrcExpr,4296 bool Diagnose) {4297 ASTContext &Context = getASTContext();4298 ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType);4299 ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType);4300 bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);4301 bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);4302 if (!CfToNs && !NsToCf)4303 return false;4304 4305 ObjCInterfaceDecl *RelatedClass;4306 ObjCMethodDecl *ClassMethod = nullptr;4307 ObjCMethodDecl *InstanceMethod = nullptr;4308 TypedefNameDecl *TDNDecl = nullptr;4309 if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,4310 ClassMethod, InstanceMethod, TDNDecl,4311 CfToNs, Diagnose))4312 return false;4313 4314 if (CfToNs) {4315 // Implicit conversion from CF to ObjC object is needed.4316 if (ClassMethod) {4317 if (Diagnose) {4318 std::string ExpressionString = "[";4319 ExpressionString += RelatedClass->getNameAsString();4320 ExpressionString += " ";4321 ExpressionString += ClassMethod->getSelector().getAsString();4322 SourceLocation SrcExprEndLoc =4323 SemaRef.getLocForEndOfToken(SrcExpr->getEndLoc());4324 // Provide a fixit: [RelatedClass ClassMethod SrcExpr]4325 Diag(Loc, diag::err_objc_bridged_related_known_method)4326 << SrcType << DestType << ClassMethod->getSelector() << false4327 << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(),4328 ExpressionString)4329 << FixItHint::CreateInsertion(SrcExprEndLoc, "]");4330 Diag(RelatedClass->getBeginLoc(), diag::note_declared_at);4331 Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4332 4333 QualType receiverType = Context.getObjCInterfaceType(RelatedClass);4334 // Argument.4335 Expr *args[] = { SrcExpr };4336 ExprResult msg = BuildClassMessageImplicit(receiverType, false,4337 ClassMethod->getLocation(),4338 ClassMethod->getSelector(), ClassMethod,4339 MultiExprArg(args, 1));4340 SrcExpr = msg.get();4341 }4342 return true;4343 }4344 }4345 else {4346 // Implicit conversion from ObjC type to CF object is needed.4347 if (InstanceMethod) {4348 if (Diagnose) {4349 std::string ExpressionString;4350 SourceLocation SrcExprEndLoc =4351 SemaRef.getLocForEndOfToken(SrcExpr->getEndLoc());4352 if (InstanceMethod->isPropertyAccessor())4353 if (const ObjCPropertyDecl *PDecl =4354 InstanceMethod->findPropertyDecl()) {4355 // fixit: ObjectExpr.propertyname when it is aproperty accessor.4356 ExpressionString = ".";4357 ExpressionString += PDecl->getNameAsString();4358 Diag(Loc, diag::err_objc_bridged_related_known_method)4359 << SrcType << DestType << InstanceMethod->getSelector() << true4360 << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);4361 }4362 if (ExpressionString.empty()) {4363 // Provide a fixit: [ObjectExpr InstanceMethod]4364 ExpressionString = " ";4365 ExpressionString += InstanceMethod->getSelector().getAsString();4366 ExpressionString += "]";4367 4368 Diag(Loc, diag::err_objc_bridged_related_known_method)4369 << SrcType << DestType << InstanceMethod->getSelector() << true4370 << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "[")4371 << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);4372 }4373 Diag(RelatedClass->getBeginLoc(), diag::note_declared_at);4374 Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4375 4376 ExprResult msg = BuildInstanceMessageImplicit(4377 SrcExpr, SrcType, InstanceMethod->getLocation(),4378 InstanceMethod->getSelector(), InstanceMethod, {});4379 SrcExpr = msg.get();4380 }4381 return true;4382 }4383 }4384 return false;4385}4386 4387SemaObjC::ARCConversionResult4388SemaObjC::CheckObjCConversion(SourceRange castRange, QualType castType,4389 Expr *&castExpr, CheckedConversionKind CCK,4390 bool Diagnose, bool DiagnoseCFAudited,4391 BinaryOperatorKind Opc, bool IsReinterpretCast) {4392 ASTContext &Context = getASTContext();4393 QualType castExprType = castExpr->getType();4394 4395 // For the purposes of the classification, we assume reference types4396 // will bind to temporaries.4397 QualType effCastType = castType;4398 if (const ReferenceType *ref = castType->getAs<ReferenceType>())4399 effCastType = ref->getPointeeType();4400 4401 ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType);4402 ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType);4403 if (exprACTC == castACTC) {4404 // Check for viability and report error if casting an rvalue to a4405 // life-time qualifier.4406 if (castACTC == ACTC_retainable &&4407 (CCK == CheckedConversionKind::CStyleCast ||4408 CCK == CheckedConversionKind::OtherCast) &&4409 castType != castExprType) {4410 const Type *DT = castType.getTypePtr();4411 QualType QDT = castType;4412 // We desugar some types but not others. We ignore those4413 // that cannot happen in a cast; i.e. auto, and those which4414 // should not be de-sugared; i.e typedef.4415 if (const ParenType *PT = dyn_cast<ParenType>(DT))4416 QDT = PT->desugar();4417 else if (const TypeOfType *TP = dyn_cast<TypeOfType>(DT))4418 QDT = TP->desugar();4419 else if (const AttributedType *AT = dyn_cast<AttributedType>(DT))4420 QDT = AT->desugar();4421 if (QDT != castType &&4422 QDT.getObjCLifetime() != Qualifiers::OCL_None) {4423 if (Diagnose) {4424 SourceLocation loc = (castRange.isValid() ? castRange.getBegin()4425 : castExpr->getExprLoc());4426 Diag(loc, diag::err_arc_nolifetime_behavior);4427 }4428 return ACR_error;4429 }4430 }4431 return ACR_okay;4432 }4433 4434 // The life-time qualifier cast check above is all we need for ObjCWeak.4435 // ObjCAutoRefCount has more restrictions on what is legal.4436 if (!getLangOpts().ObjCAutoRefCount)4437 return ACR_okay;4438 4439 if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay;4440 4441 // Allow all of these types to be cast to integer types (but not4442 // vice-versa).4443 if (castACTC == ACTC_none && castType->isIntegralType(Context))4444 return ACR_okay;4445 4446 // Allow casts between pointers to lifetime types (e.g., __strong id*)4447 // and pointers to void (e.g., cv void *). Casting from void* to lifetime*4448 // must be explicit.4449 // Allow conversions between pointers to lifetime types and coreFoundation4450 // pointers too, but only when the conversions are explicit.4451 // Allow conversions requested with a reinterpret_cast that converts an4452 // expression of type T* to type U*.4453 if (exprACTC == ACTC_indirectRetainable &&4454 (castACTC == ACTC_voidPtr ||4455 (castACTC == ACTC_coreFoundation && SemaRef.isCast(CCK)) ||4456 (IsReinterpretCast && effCastType->isAnyPointerType())))4457 return ACR_okay;4458 if (castACTC == ACTC_indirectRetainable &&4459 (((exprACTC == ACTC_voidPtr || exprACTC == ACTC_coreFoundation) &&4460 SemaRef.isCast(CCK)) ||4461 (IsReinterpretCast && castExprType->isAnyPointerType())))4462 return ACR_okay;4463 4464 switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {4465 // For invalid casts, fall through.4466 case ACC_invalid:4467 break;4468 4469 // Do nothing for both bottom and +0.4470 case ACC_bottom:4471 case ACC_plusZero:4472 return ACR_okay;4473 4474 // If the result is +1, consume it here.4475 case ACC_plusOne:4476 castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),4477 CK_ARCConsumeObject, castExpr, nullptr,4478 VK_PRValue, FPOptionsOverride());4479 SemaRef.Cleanup.setExprNeedsCleanups(true);4480 return ACR_okay;4481 }4482 4483 // If this is a non-implicit cast from id or block type to a4484 // CoreFoundation type, delay complaining in case the cast is used4485 // in an acceptable context.4486 if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) &&4487 SemaRef.isCast(CCK))4488 return ACR_unbridged;4489 4490 // Issue a diagnostic about a missing @-sign when implicit casting a cstring4491 // to 'NSString *', instead of falling through to report a "bridge cast"4492 // diagnostic.4493 if (castACTC == ACTC_retainable && exprACTC == ACTC_none &&4494 CheckConversionToObjCLiteral(castType, castExpr, Diagnose))4495 return ACR_error;4496 4497 // Do not issue "bridge cast" diagnostic when implicit casting4498 // a retainable object to a CF type parameter belonging to an audited4499 // CF API function. Let caller issue a normal type mismatched diagnostic4500 // instead.4501 if ((!DiagnoseCFAudited || exprACTC != ACTC_retainable ||4502 castACTC != ACTC_coreFoundation) &&4503 !(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable &&4504 (Opc == BO_NE || Opc == BO_EQ))) {4505 if (Diagnose)4506 diagnoseObjCARCConversion(SemaRef, castRange, castType, castACTC,4507 castExpr, castExpr, exprACTC, CCK);4508 return ACR_error;4509 }4510 return ACR_okay;4511}4512 4513/// Given that we saw an expression with the ARCUnbridgedCastTy4514/// placeholder type, complain bitterly.4515void SemaObjC::diagnoseARCUnbridgedCast(Expr *e) {4516 // We expect the spurious ImplicitCastExpr to already have been stripped.4517 assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));4518 CastExpr *realCast = cast<CastExpr>(e->IgnoreParens());4519 4520 SourceRange castRange;4521 QualType castType;4522 CheckedConversionKind CCK;4523 4524 if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) {4525 castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc());4526 castType = cast->getTypeAsWritten();4527 CCK = CheckedConversionKind::CStyleCast;4528 } else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) {4529 castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange();4530 castType = cast->getTypeAsWritten();4531 CCK = CheckedConversionKind::OtherCast;4532 } else {4533 llvm_unreachable("Unexpected ImplicitCastExpr");4534 }4535 4536 ARCConversionTypeClass castACTC =4537 classifyTypeForARCConversion(castType.getNonReferenceType());4538 4539 Expr *castExpr = realCast->getSubExpr();4540 assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);4541 4542 diagnoseObjCARCConversion(SemaRef, castRange, castType, castACTC, castExpr,4543 realCast, ACTC_retainable, CCK);4544}4545 4546/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast4547/// type, remove the placeholder cast.4548Expr *SemaObjC::stripARCUnbridgedCast(Expr *e) {4549 assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));4550 ASTContext &Context = getASTContext();4551 4552 if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) {4553 Expr *sub = stripARCUnbridgedCast(pe->getSubExpr());4554 return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub);4555 } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {4556 assert(uo->getOpcode() == UO_Extension);4557 Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());4558 return UnaryOperator::Create(Context, sub, UO_Extension, sub->getType(),4559 sub->getValueKind(), sub->getObjectKind(),4560 uo->getOperatorLoc(), false,4561 SemaRef.CurFPFeatureOverrides());4562 } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {4563 assert(!gse->isResultDependent());4564 assert(!gse->isTypePredicate());4565 4566 unsigned n = gse->getNumAssocs();4567 SmallVector<Expr *, 4> subExprs;4568 SmallVector<TypeSourceInfo *, 4> subTypes;4569 subExprs.reserve(n);4570 subTypes.reserve(n);4571 for (const GenericSelectionExpr::Association assoc : gse->associations()) {4572 subTypes.push_back(assoc.getTypeSourceInfo());4573 Expr *sub = assoc.getAssociationExpr();4574 if (assoc.isSelected())4575 sub = stripARCUnbridgedCast(sub);4576 subExprs.push_back(sub);4577 }4578 4579 return GenericSelectionExpr::Create(4580 Context, gse->getGenericLoc(), gse->getControllingExpr(), subTypes,4581 subExprs, gse->getDefaultLoc(), gse->getRParenLoc(),4582 gse->containsUnexpandedParameterPack(), gse->getResultIndex());4583 } else {4584 assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!");4585 return cast<ImplicitCastExpr>(e)->getSubExpr();4586 }4587}4588 4589bool SemaObjC::CheckObjCARCUnavailableWeakConversion(QualType castType,4590 QualType exprType) {4591 ASTContext &Context = getASTContext();4592 QualType canCastType =4593 Context.getCanonicalType(castType).getUnqualifiedType();4594 QualType canExprType =4595 Context.getCanonicalType(exprType).getUnqualifiedType();4596 if (isa<ObjCObjectPointerType>(canCastType) &&4597 castType.getObjCLifetime() == Qualifiers::OCL_Weak &&4598 canExprType->isObjCObjectPointerType()) {4599 if (const ObjCObjectPointerType *ObjT =4600 canExprType->getAs<ObjCObjectPointerType>())4601 if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl())4602 return !ObjI->isArcWeakrefUnavailable();4603 }4604 return true;4605}4606 4607/// Look for an ObjCReclaimReturnedObject cast and destroy it.4608static Expr *maybeUndoReclaimObject(Expr *e) {4609 Expr *curExpr = e, *prevExpr = nullptr;4610 4611 // Walk down the expression until we hit an implicit cast of kind4612 // ARCReclaimReturnedObject or an Expr that is neither a Paren nor a Cast.4613 while (true) {4614 if (auto *pe = dyn_cast<ParenExpr>(curExpr)) {4615 prevExpr = curExpr;4616 curExpr = pe->getSubExpr();4617 continue;4618 }4619 4620 if (auto *ce = dyn_cast<CastExpr>(curExpr)) {4621 if (auto *ice = dyn_cast<ImplicitCastExpr>(ce))4622 if (ice->getCastKind() == CK_ARCReclaimReturnedObject) {4623 if (!prevExpr)4624 return ice->getSubExpr();4625 if (auto *pe = dyn_cast<ParenExpr>(prevExpr))4626 pe->setSubExpr(ice->getSubExpr());4627 else4628 cast<CastExpr>(prevExpr)->setSubExpr(ice->getSubExpr());4629 return e;4630 }4631 4632 prevExpr = curExpr;4633 curExpr = ce->getSubExpr();4634 continue;4635 }4636 4637 // Break out of the loop if curExpr is neither a Paren nor a Cast.4638 break;4639 }4640 4641 return e;4642}4643 4644ExprResult SemaObjC::BuildObjCBridgedCast(SourceLocation LParenLoc,4645 ObjCBridgeCastKind Kind,4646 SourceLocation BridgeKeywordLoc,4647 TypeSourceInfo *TSInfo,4648 Expr *SubExpr) {4649 ASTContext &Context = getASTContext();4650 ExprResult SubResult = SemaRef.UsualUnaryConversions(SubExpr);4651 if (SubResult.isInvalid()) return ExprError();4652 SubExpr = SubResult.get();4653 4654 QualType T = TSInfo->getType();4655 QualType FromType = SubExpr->getType();4656 4657 CastKind CK;4658 4659 bool MustConsume = false;4660 if (T->isDependentType() || SubExpr->isTypeDependent()) {4661 // Okay: we'll build a dependent expression type.4662 CK = CK_Dependent;4663 } else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) {4664 // Casting CF -> id4665 CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast4666 : CK_CPointerToObjCPointerCast);4667 switch (Kind) {4668 case OBC_Bridge:4669 break;4670 4671 case OBC_BridgeRetained: {4672 bool br = isKnownName("CFBridgingRelease");4673 Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)4674 << 24675 << FromType4676 << (T->isBlockPointerType()? 1 : 0)4677 << T4678 << SubExpr->getSourceRange()4679 << Kind;4680 Diag(BridgeKeywordLoc, diag::note_arc_bridge)4681 << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge");4682 Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer)4683 << FromType << br4684 << FixItHint::CreateReplacement(BridgeKeywordLoc,4685 br ? "CFBridgingRelease "4686 : "__bridge_transfer ");4687 4688 Kind = OBC_Bridge;4689 break;4690 }4691 4692 case OBC_BridgeTransfer:4693 // We must consume the Objective-C object produced by the cast.4694 MustConsume = true;4695 break;4696 }4697 } else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) {4698 // Okay: id -> CF4699 CK = CK_BitCast;4700 switch (Kind) {4701 case OBC_Bridge:4702 // Reclaiming a value that's going to be __bridge-casted to CF4703 // is very dangerous, so we don't do it.4704 SubExpr = maybeUndoReclaimObject(SubExpr);4705 break;4706 4707 case OBC_BridgeRetained:4708 // Produce the object before casting it.4709 SubExpr = ImplicitCastExpr::Create(Context, FromType, CK_ARCProduceObject,4710 SubExpr, nullptr, VK_PRValue,4711 FPOptionsOverride());4712 break;4713 4714 case OBC_BridgeTransfer: {4715 bool br = isKnownName("CFBridgingRetain");4716 Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)4717 << (FromType->isBlockPointerType()? 1 : 0)4718 << FromType4719 << 24720 << T4721 << SubExpr->getSourceRange()4722 << Kind;4723 4724 Diag(BridgeKeywordLoc, diag::note_arc_bridge)4725 << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge ");4726 Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained)4727 << T << br4728 << FixItHint::CreateReplacement(BridgeKeywordLoc,4729 br ? "CFBridgingRetain " : "__bridge_retained");4730 4731 Kind = OBC_Bridge;4732 break;4733 }4734 }4735 } else {4736 Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible)4737 << FromType << T << Kind4738 << SubExpr->getSourceRange()4739 << TSInfo->getTypeLoc().getSourceRange();4740 return ExprError();4741 }4742 4743 Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK,4744 BridgeKeywordLoc,4745 TSInfo, SubExpr);4746 4747 if (MustConsume) {4748 SemaRef.Cleanup.setExprNeedsCleanups(true);4749 Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,4750 nullptr, VK_PRValue, FPOptionsOverride());4751 }4752 4753 return Result;4754}4755 4756ExprResult SemaObjC::ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc,4757 ObjCBridgeCastKind Kind,4758 SourceLocation BridgeKeywordLoc,4759 ParsedType Type,4760 SourceLocation RParenLoc,4761 Expr *SubExpr) {4762 ASTContext &Context = getASTContext();4763 TypeSourceInfo *TSInfo = nullptr;4764 QualType T = SemaRef.GetTypeFromParser(Type, &TSInfo);4765 if (Kind == OBC_Bridge)4766 CheckTollFreeBridgeCast(T, SubExpr);4767 if (!TSInfo)4768 TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc);4769 return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,4770 SubExpr);4771}4772 4773DeclResult SemaObjC::LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,4774 IdentifierInfo *II) {4775 SourceLocation Loc = Lookup.getNameLoc();4776 ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl();4777 4778 // Check for error condition which is already reported.4779 if (!CurMethod)4780 return DeclResult(true);4781 4782 // There are two cases to handle here. 1) scoped lookup could have failed,4783 // in which case we should look for an ivar. 2) scoped lookup could have4784 // found a decl, but that decl is outside the current instance method (i.e.4785 // a global variable). In these two cases, we do a lookup for an ivar with4786 // this name, if the lookup sucedes, we replace it our current decl.4787 4788 // If we're in a class method, we don't normally want to look for4789 // ivars. But if we don't find anything else, and there's an4790 // ivar, that's an error.4791 bool IsClassMethod = CurMethod->isClassMethod();4792 4793 bool LookForIvars;4794 if (Lookup.empty())4795 LookForIvars = true;4796 else if (IsClassMethod)4797 LookForIvars = false;4798 else4799 LookForIvars = (Lookup.isSingleResult() &&4800 Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());4801 ObjCInterfaceDecl *IFace = nullptr;4802 if (LookForIvars) {4803 IFace = CurMethod->getClassInterface();4804 ObjCInterfaceDecl *ClassDeclared;4805 ObjCIvarDecl *IV = nullptr;4806 if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {4807 // Diagnose using an ivar in a class method.4808 if (IsClassMethod) {4809 Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName();4810 return DeclResult(true);4811 }4812 4813 // Diagnose the use of an ivar outside of the declaring class.4814 if (IV->getAccessControl() == ObjCIvarDecl::Private &&4815 !declaresSameEntity(ClassDeclared, IFace) &&4816 !getLangOpts().DebuggerSupport)4817 Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName();4818 4819 // Success.4820 return IV;4821 }4822 } else if (CurMethod->isInstanceMethod()) {4823 // We should warn if a local variable hides an ivar.4824 if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) {4825 ObjCInterfaceDecl *ClassDeclared;4826 if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {4827 if (IV->getAccessControl() != ObjCIvarDecl::Private ||4828 declaresSameEntity(IFace, ClassDeclared))4829 Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();4830 }4831 }4832 } else if (Lookup.isSingleResult() &&4833 Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {4834 // If accessing a stand-alone ivar in a class method, this is an error.4835 if (const ObjCIvarDecl *IV =4836 dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl())) {4837 Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName();4838 return DeclResult(true);4839 }4840 }4841 4842 // Didn't encounter an error, didn't find an ivar.4843 return DeclResult(false);4844}4845 4846ExprResult SemaObjC::LookupInObjCMethod(LookupResult &Lookup, Scope *S,4847 IdentifierInfo *II,4848 bool AllowBuiltinCreation) {4849 // FIXME: Integrate this lookup step into LookupParsedName.4850 DeclResult Ivar = LookupIvarInObjCMethod(Lookup, S, II);4851 if (Ivar.isInvalid())4852 return ExprError();4853 if (Ivar.isUsable())4854 return BuildIvarRefExpr(S, Lookup.getNameLoc(),4855 cast<ObjCIvarDecl>(Ivar.get()));4856 4857 if (Lookup.empty() && II && AllowBuiltinCreation)4858 SemaRef.LookupBuiltin(Lookup);4859 4860 // Sentinel value saying that we didn't do anything special.4861 return ExprResult(false);4862}4863 4864ExprResult SemaObjC::BuildIvarRefExpr(Scope *S, SourceLocation Loc,4865 ObjCIvarDecl *IV) {4866 ASTContext &Context = getASTContext();4867 ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl();4868 assert(CurMethod && CurMethod->isInstanceMethod() &&4869 "should not reference ivar from this context");4870 4871 ObjCInterfaceDecl *IFace = CurMethod->getClassInterface();4872 assert(IFace && "should not reference ivar from this context");4873 4874 // If we're referencing an invalid decl, just return this as a silent4875 // error node. The error diagnostic was already emitted on the decl.4876 if (IV->isInvalidDecl())4877 return ExprError();4878 4879 // Check if referencing a field with __attribute__((deprecated)).4880 if (SemaRef.DiagnoseUseOfDecl(IV, Loc))4881 return ExprError();4882 4883 // FIXME: This should use a new expr for a direct reference, don't4884 // turn this into Self->ivar, just return a BareIVarExpr or something.4885 IdentifierInfo &II = Context.Idents.get("self");4886 UnqualifiedId SelfName;4887 SelfName.setImplicitSelfParam(&II);4888 CXXScopeSpec SelfScopeSpec;4889 SourceLocation TemplateKWLoc;4890 ExprResult SelfExpr =4891 SemaRef.ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName,4892 /*HasTrailingLParen=*/false,4893 /*IsAddressOfOperand=*/false);4894 if (SelfExpr.isInvalid())4895 return ExprError();4896 4897 SelfExpr = SemaRef.DefaultLvalueConversion(SelfExpr.get());4898 if (SelfExpr.isInvalid())4899 return ExprError();4900 4901 SemaRef.MarkAnyDeclReferenced(Loc, IV, true);4902 4903 ObjCMethodFamily MF = CurMethod->getMethodFamily();4904 if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&4905 !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))4906 Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();4907 4908 ObjCIvarRefExpr *Result = new (Context)4909 ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc,4910 IV->getLocation(), SelfExpr.get(), true, true);4911 4912 if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {4913 if (!SemaRef.isUnevaluatedContext() &&4914 !getDiagnostics().isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))4915 SemaRef.getCurFunction()->recordUseOfWeak(Result);4916 }4917 if (getLangOpts().ObjCAutoRefCount && !SemaRef.isUnevaluatedContext())4918 if (const BlockDecl *BD = SemaRef.CurContext->getInnermostBlockDecl())4919 SemaRef.ImplicitlyRetainedSelfLocs.push_back({Loc, BD});4920 4921 return Result;4922}4923 4924QualType SemaObjC::FindCompositeObjCPointerType(ExprResult &LHS,4925 ExprResult &RHS,4926 SourceLocation QuestionLoc) {4927 ASTContext &Context = getASTContext();4928 QualType LHSTy = LHS.get()->getType();4929 QualType RHSTy = RHS.get()->getType();4930 4931 // Handle things like Class and struct objc_class*. Here we case the result4932 // to the pseudo-builtin, because that will be implicitly cast back to the4933 // redefinition type if an attempt is made to access its fields.4934 if (LHSTy->isObjCClassType() &&4935 (Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) {4936 RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy,4937 CK_CPointerToObjCPointerCast);4938 return LHSTy;4939 }4940 if (RHSTy->isObjCClassType() &&4941 (Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) {4942 LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy,4943 CK_CPointerToObjCPointerCast);4944 return RHSTy;4945 }4946 // And the same for struct objc_object* / id4947 if (LHSTy->isObjCIdType() &&4948 (Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) {4949 RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy,4950 CK_CPointerToObjCPointerCast);4951 return LHSTy;4952 }4953 if (RHSTy->isObjCIdType() &&4954 (Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) {4955 LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy,4956 CK_CPointerToObjCPointerCast);4957 return RHSTy;4958 }4959 // And the same for struct objc_selector* / SEL4960 if (Context.isObjCSelType(LHSTy) &&4961 (Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) {4962 RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy, CK_BitCast);4963 return LHSTy;4964 }4965 if (Context.isObjCSelType(RHSTy) &&4966 (Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) {4967 LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy, CK_BitCast);4968 return RHSTy;4969 }4970 // Check constraints for Objective-C object pointers types.4971 if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {4972 4973 if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {4974 // Two identical object pointer types are always compatible.4975 return LHSTy;4976 }4977 const ObjCObjectPointerType *LHSOPT =4978 LHSTy->castAs<ObjCObjectPointerType>();4979 const ObjCObjectPointerType *RHSOPT =4980 RHSTy->castAs<ObjCObjectPointerType>();4981 QualType compositeType = LHSTy;4982 4983 // If both operands are interfaces and either operand can be4984 // assigned to the other, use that type as the composite4985 // type. This allows4986 // xxx ? (A*) a : (B*) b4987 // where B is a subclass of A.4988 //4989 // Additionally, as for assignment, if either type is 'id'4990 // allow silent coercion. Finally, if the types are4991 // incompatible then make sure to use 'id' as the composite4992 // type so the result is acceptable for sending messages to.4993 4994 // FIXME: Consider unifying with 'areComparableObjCPointerTypes'.4995 // It could return the composite type.4996 if (!(compositeType = Context.areCommonBaseCompatible(LHSOPT, RHSOPT))4997 .isNull()) {4998 // Nothing more to do.4999 } else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {5000 compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;5001 } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {5002 compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;5003 } else if ((LHSOPT->isObjCQualifiedIdType() ||5004 RHSOPT->isObjCQualifiedIdType()) &&5005 Context.ObjCQualifiedIdTypesAreCompatible(LHSOPT, RHSOPT,5006 true)) {5007 // Need to handle "id<xx>" explicitly.5008 // GCC allows qualified id and any Objective-C type to devolve to5009 // id. Currently localizing to here until clear this should be5010 // part of ObjCQualifiedIdTypesAreCompatible.5011 compositeType = Context.getObjCIdType();5012 } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {5013 compositeType = Context.getObjCIdType();5014 } else {5015 Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)5016 << LHSTy << RHSTy << LHS.get()->getSourceRange()5017 << RHS.get()->getSourceRange();5018 QualType incompatTy = Context.getObjCIdType();5019 LHS = SemaRef.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast);5020 RHS = SemaRef.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast);5021 return incompatTy;5022 }5023 // The object pointer types are compatible.5024 LHS = SemaRef.ImpCastExprToType(LHS.get(), compositeType, CK_BitCast);5025 RHS = SemaRef.ImpCastExprToType(RHS.get(), compositeType, CK_BitCast);5026 return compositeType;5027 }5028 // Check Objective-C object pointer types and 'void *'5029 if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {5030 if (getLangOpts().ObjCAutoRefCount) {5031 // ARC forbids the implicit conversion of object pointers to 'void *',5032 // so these types are not compatible.5033 Diag(QuestionLoc, diag::err_cond_voidptr_arc)5034 << LHSTy << RHSTy << LHS.get()->getSourceRange()5035 << RHS.get()->getSourceRange();5036 LHS = RHS = true;5037 return QualType();5038 }5039 QualType lhptee = LHSTy->castAs<PointerType>()->getPointeeType();5040 QualType rhptee = RHSTy->castAs<ObjCObjectPointerType>()->getPointeeType();5041 QualType destPointee =5042 Context.getQualifiedType(lhptee, rhptee.getQualifiers());5043 QualType destType = Context.getPointerType(destPointee);5044 // Add qualifiers if necessary.5045 LHS = SemaRef.ImpCastExprToType(LHS.get(), destType, CK_NoOp);5046 // Promote to void*.5047 RHS = SemaRef.ImpCastExprToType(RHS.get(), destType, CK_BitCast);5048 return destType;5049 }5050 if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {5051 if (getLangOpts().ObjCAutoRefCount) {5052 // ARC forbids the implicit conversion of object pointers to 'void *',5053 // so these types are not compatible.5054 Diag(QuestionLoc, diag::err_cond_voidptr_arc)5055 << LHSTy << RHSTy << LHS.get()->getSourceRange()5056 << RHS.get()->getSourceRange();5057 LHS = RHS = true;5058 return QualType();5059 }5060 QualType lhptee = LHSTy->castAs<ObjCObjectPointerType>()->getPointeeType();5061 QualType rhptee = RHSTy->castAs<PointerType>()->getPointeeType();5062 QualType destPointee =5063 Context.getQualifiedType(rhptee, lhptee.getQualifiers());5064 QualType destType = Context.getPointerType(destPointee);5065 // Add qualifiers if necessary.5066 RHS = SemaRef.ImpCastExprToType(RHS.get(), destType, CK_NoOp);5067 // Promote to void*.5068 LHS = SemaRef.ImpCastExprToType(LHS.get(), destType, CK_BitCast);5069 return destType;5070 }5071 return QualType();5072}5073 5074bool SemaObjC::CheckConversionToObjCLiteral(QualType DstType, Expr *&Exp,5075 bool Diagnose) {5076 if (!getLangOpts().ObjC)5077 return false;5078 5079 const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();5080 if (!PT)5081 return false;5082 const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();5083 5084 // Ignore any parens, implicit casts (should only be5085 // array-to-pointer decays), and not-so-opaque values. The last is5086 // important for making this trigger for property assignments.5087 Expr *SrcExpr = Exp->IgnoreParenImpCasts();5088 if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr))5089 if (OV->getSourceExpr())5090 SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();5091 5092 if (auto *SL = dyn_cast<StringLiteral>(SrcExpr)) {5093 if (!PT->isObjCIdType() && !(ID && ID->getIdentifier()->isStr("NSString")))5094 return false;5095 if (!SL->isOrdinary())5096 return false;5097 5098 if (Diagnose) {5099 Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix)5100 << /*string*/ 0 << FixItHint::CreateInsertion(SL->getBeginLoc(), "@");5101 Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get();5102 }5103 return true;5104 }5105 5106 if ((isa<IntegerLiteral>(SrcExpr) || isa<CharacterLiteral>(SrcExpr) ||5107 isa<FloatingLiteral>(SrcExpr) || isa<ObjCBoolLiteralExpr>(SrcExpr) ||5108 isa<CXXBoolLiteralExpr>(SrcExpr)) &&5109 !SrcExpr->isNullPointerConstant(getASTContext(),5110 Expr::NPC_NeverValueDependent)) {5111 if (!ID || !ID->getIdentifier()->isStr("NSNumber"))5112 return false;5113 if (Diagnose) {5114 Diag(SrcExpr->getBeginLoc(), diag::err_missing_atsign_prefix)5115 << /*number*/ 15116 << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "@");5117 Expr *NumLit =5118 BuildObjCNumericLiteral(SrcExpr->getBeginLoc(), SrcExpr).get();5119 if (NumLit)5120 Exp = NumLit;5121 }5122 return true;5123 }5124 5125 return false;5126}5127 5128/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.5129ExprResult SemaObjC::ActOnObjCBoolLiteral(SourceLocation OpLoc,5130 tok::TokenKind Kind) {5131 assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) &&5132 "Unknown Objective-C Boolean value!");5133 ASTContext &Context = getASTContext();5134 QualType BoolT = Context.ObjCBuiltinBoolTy;5135 if (!Context.getBOOLDecl()) {5136 LookupResult Result(SemaRef, &Context.Idents.get("BOOL"), OpLoc,5137 Sema::LookupOrdinaryName);5138 if (SemaRef.LookupName(Result, SemaRef.getCurScope()) &&5139 Result.isSingleResult()) {5140 NamedDecl *ND = Result.getFoundDecl();5141 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND))5142 Context.setBOOLDecl(TD);5143 }5144 }5145 if (Context.getBOOLDecl())5146 BoolT = Context.getBOOLType();5147 return new (Context)5148 ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, BoolT, OpLoc);5149}5150 5151ExprResult SemaObjC::ActOnObjCAvailabilityCheckExpr(5152 llvm::ArrayRef<AvailabilitySpec> AvailSpecs, SourceLocation AtLoc,5153 SourceLocation RParen) {5154 ASTContext &Context = getASTContext();5155 auto FindSpecVersion =5156 [&](StringRef Platform,5157 const llvm::Triple::OSType &OS) -> std::optional<VersionTuple> {5158 auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) {5159 return Spec.getPlatform() == Platform;5160 });5161 // Transcribe the "ios" availability check to "maccatalyst" when compiling5162 // for "maccatalyst" if "maccatalyst" is not specified.5163 if (Spec == AvailSpecs.end() && Platform == "maccatalyst") {5164 Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) {5165 return Spec.getPlatform() == "ios";5166 });5167 }5168 if (Spec == AvailSpecs.end())5169 return std::nullopt;5170 5171 return llvm::Triple::getCanonicalVersionForOS(5172 OS, Spec->getVersion(),5173 llvm::Triple::isValidVersionForOS(OS, Spec->getVersion()));5174 };5175 5176 VersionTuple Version;5177 if (auto MaybeVersion =5178 FindSpecVersion(Context.getTargetInfo().getPlatformName(),5179 Context.getTargetInfo().getTriple().getOS()))5180 Version = *MaybeVersion;5181 5182 // The use of `@available` in the enclosing context should be analyzed to5183 // warn when it's used inappropriately (i.e. not if(@available)).5184 if (FunctionScopeInfo *Context = SemaRef.getCurFunctionAvailabilityContext())5185 Context->HasPotentialAvailabilityViolations = true;5186 5187 return new (Context)5188 ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);5189}5190 5191/// Prepare a conversion of the given expression to an ObjC object5192/// pointer type.5193CastKind SemaObjC::PrepareCastToObjCObjectPointer(ExprResult &E) {5194 QualType type = E.get()->getType();5195 if (type->isObjCObjectPointerType()) {5196 return CK_BitCast;5197 } else if (type->isBlockPointerType()) {5198 SemaRef.maybeExtendBlockObject(E);5199 return CK_BlockPointerToObjCPointerCast;5200 } else {5201 assert(type->isPointerType());5202 return CK_CPointerToObjCPointerCast;5203 }5204}5205 5206SemaObjC::ObjCLiteralKind SemaObjC::CheckLiteralKind(Expr *FromE) {5207 FromE = FromE->IgnoreParenImpCasts();5208 switch (FromE->getStmtClass()) {5209 default:5210 break;5211 case Stmt::ObjCStringLiteralClass:5212 // "string literal"5213 return LK_String;5214 case Stmt::ObjCArrayLiteralClass:5215 // "array literal"5216 return LK_Array;5217 case Stmt::ObjCDictionaryLiteralClass:5218 // "dictionary literal"5219 return LK_Dictionary;5220 case Stmt::BlockExprClass:5221 return LK_Block;5222 case Stmt::ObjCBoxedExprClass: {5223 Expr *Inner = cast<ObjCBoxedExpr>(FromE)->getSubExpr()->IgnoreParens();5224 switch (Inner->getStmtClass()) {5225 case Stmt::IntegerLiteralClass:5226 case Stmt::FloatingLiteralClass:5227 case Stmt::CharacterLiteralClass:5228 case Stmt::ObjCBoolLiteralExprClass:5229 case Stmt::CXXBoolLiteralExprClass:5230 // "numeric literal"5231 return LK_Numeric;5232 case Stmt::ImplicitCastExprClass: {5233 CastKind CK = cast<CastExpr>(Inner)->getCastKind();5234 // Boolean literals can be represented by implicit casts.5235 if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast)5236 return LK_Numeric;5237 break;5238 }5239 default:5240 break;5241 }5242 return LK_Boxed;5243 }5244 }5245 return LK_None;5246}5247