Path: blob/main/contrib/llvm-project/clang/lib/Sema/SemaExprObjC.cpp
35233 views
//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements semantic analysis for Objective-C expressions.9//10//===----------------------------------------------------------------------===//1112#include "clang/AST/ASTContext.h"13#include "clang/AST/DeclObjC.h"14#include "clang/AST/ExprObjC.h"15#include "clang/AST/StmtVisitor.h"16#include "clang/AST/TypeLoc.h"17#include "clang/Analysis/DomainSpecific/CocoaConventions.h"18#include "clang/Basic/Builtins.h"19#include "clang/Basic/TargetInfo.h"20#include "clang/Edit/Commit.h"21#include "clang/Edit/Rewriters.h"22#include "clang/Lex/Preprocessor.h"23#include "clang/Sema/Initialization.h"24#include "clang/Sema/Lookup.h"25#include "clang/Sema/Scope.h"26#include "clang/Sema/ScopeInfo.h"27#include "clang/Sema/SemaInternal.h"28#include "clang/Sema/SemaObjC.h"29#include "llvm/ADT/SmallString.h"30#include "llvm/Support/ConvertUTF.h"31#include <optional>3233using namespace clang;34using namespace sema;35using llvm::ArrayRef;3637ExprResult SemaObjC::ParseObjCStringLiteral(SourceLocation *AtLocs,38ArrayRef<Expr *> Strings) {39ASTContext &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.44StringLiteral *S = cast<StringLiteral>(Strings[0]);4546// If we have a multi-part string, merge it all together.47if (Strings.size() != 1) {48// Concatenate objc strings.49SmallString<128> StrBuf;50SmallVector<SourceLocation, 8> StrLocs;5152for (Expr *E : Strings) {53S = cast<StringLiteral>(E);5455// ObjC strings can't be wide or UTF.56if (!S->isOrdinary()) {57Diag(S->getBeginLoc(), diag::err_cfstring_literal_not_string_constant)58<< S->getSourceRange();59return true;60}6162// Append the string.63StrBuf += S->getString();6465// Get the locations of the string tokens.66StrLocs.append(S->tokloc_begin(), S->tokloc_end());67}6869// Create the aggregate string with the appropriate content and location70// information.71const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType());72assert(CAT && "String literal not of constant array type!");73QualType StrTy = Context.getConstantArrayType(74CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1), nullptr,75CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());76S = StringLiteral::Create(Context, StrBuf, StringLiteralKind::Ordinary,77/*Pascal=*/false, StrTy, &StrLocs[0],78StrLocs.size());79}8081return BuildObjCStringLiteral(AtLocs[0], S);82}8384ExprResult SemaObjC::BuildObjCStringLiteral(SourceLocation AtLoc,85StringLiteral *S) {86ASTContext &Context = getASTContext();87// Verify that this composite string is acceptable for ObjC strings.88if (CheckObjCString(S))89return true;9091// Initialize the constant string interface lazily. This assumes92// the NSString interface is seen in this translation unit. Note: We93// don't use NSConstantString, since the runtime team considers this94// interface private (even though it appears in the header files).95QualType Ty = Context.getObjCConstantStringInterface();96if (!Ty.isNull()) {97Ty = Context.getObjCObjectPointerType(Ty);98} else if (getLangOpts().NoConstantCFStrings) {99IdentifierInfo *NSIdent=nullptr;100std::string StringClass(getLangOpts().ObjCConstantStringClass);101102if (StringClass.empty())103NSIdent = &Context.Idents.get("NSConstantString");104else105NSIdent = &Context.Idents.get(StringClass);106107NamedDecl *IF = SemaRef.LookupSingleName(SemaRef.TUScope, NSIdent, AtLoc,108Sema::LookupOrdinaryName);109if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {110Context.setObjCConstantStringInterface(StrIF);111Ty = Context.getObjCConstantStringInterface();112Ty = Context.getObjCObjectPointerType(Ty);113} else {114// If there is no NSConstantString interface defined then treat this115// as error and recover from it.116Diag(S->getBeginLoc(), diag::err_no_nsconstant_string_class)117<< NSIdent << S->getSourceRange();118Ty = Context.getObjCIdType();119}120} else {121IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);122NamedDecl *IF = SemaRef.LookupSingleName(SemaRef.TUScope, NSIdent, AtLoc,123Sema::LookupOrdinaryName);124if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {125Context.setObjCConstantStringInterface(StrIF);126Ty = Context.getObjCConstantStringInterface();127Ty = Context.getObjCObjectPointerType(Ty);128} else {129// If there is no NSString interface defined, implicitly declare130// a @class NSString; and use that instead. This is to make sure131// type of an NSString literal is represented correctly, instead of132// being an 'id' type.133Ty = Context.getObjCNSStringType();134if (Ty.isNull()) {135ObjCInterfaceDecl *NSStringIDecl =136ObjCInterfaceDecl::Create (Context,137Context.getTranslationUnitDecl(),138SourceLocation(), NSIdent,139nullptr, nullptr, SourceLocation());140Ty = Context.getObjCInterfaceType(NSStringIDecl);141Context.setObjCNSStringType(Ty);142}143Ty = Context.getObjCObjectPointerType(Ty);144}145}146147return new (Context) ObjCStringLiteral(S, Ty, AtLoc);148}149150/// Emits an error if the given method does not exist, or if the return151/// type is not an Objective-C object.152static bool validateBoxingMethod(Sema &S, SourceLocation Loc,153const ObjCInterfaceDecl *Class,154Selector Sel, const ObjCMethodDecl *Method) {155if (!Method) {156// FIXME: Is there a better way to avoid quotes than using getName()?157S.Diag(Loc, diag::err_undeclared_boxing_method) << Sel << Class->getName();158return false;159}160161// Make sure the return type is reasonable.162QualType ReturnType = Method->getReturnType();163if (!ReturnType->isObjCObjectPointerType()) {164S.Diag(Loc, diag::err_objc_literal_method_sig)165<< Sel;166S.Diag(Method->getLocation(), diag::note_objc_literal_method_return)167<< ReturnType;168return false;169}170171return true;172}173174/// Maps ObjCLiteralKind to NSClassIdKindKind175static NSAPI::NSClassIdKindKind176ClassKindFromLiteralKind(SemaObjC::ObjCLiteralKind LiteralKind) {177switch (LiteralKind) {178case SemaObjC::LK_Array:179return NSAPI::ClassId_NSArray;180case SemaObjC::LK_Dictionary:181return NSAPI::ClassId_NSDictionary;182case SemaObjC::LK_Numeric:183return NSAPI::ClassId_NSNumber;184case SemaObjC::LK_String:185return NSAPI::ClassId_NSString;186case SemaObjC::LK_Boxed:187return NSAPI::ClassId_NSValue;188189// there is no corresponding matching190// between LK_None/LK_Block and NSClassIdKindKind191case SemaObjC::LK_Block:192case SemaObjC::LK_None:193break;194}195llvm_unreachable("LiteralKind can't be converted into a ClassKind");196}197198/// Validates ObjCInterfaceDecl availability.199/// ObjCInterfaceDecl, used to create ObjC literals, should be defined200/// if clang not in a debugger mode.201static bool202ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,203SourceLocation Loc,204SemaObjC::ObjCLiteralKind LiteralKind) {205if (!Decl) {206NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind);207IdentifierInfo *II = S.ObjC().NSAPIObj->getNSClassId(Kind);208S.Diag(Loc, diag::err_undeclared_objc_literal_class)209<< II->getName() << LiteralKind;210return false;211} else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) {212S.Diag(Loc, diag::err_undeclared_objc_literal_class)213<< Decl->getName() << LiteralKind;214S.Diag(Decl->getLocation(), diag::note_forward_class);215return false;216}217218return true;219}220221/// Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.222/// Used to create ObjC literals, such as NSDictionary (@{}),223/// NSArray (@[]) and Boxed Expressions (@())224static ObjCInterfaceDecl *225LookupObjCInterfaceDeclForLiteral(Sema &S, SourceLocation Loc,226SemaObjC::ObjCLiteralKind LiteralKind) {227NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind);228IdentifierInfo *II = S.ObjC().NSAPIObj->getNSClassId(ClassKind);229NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc,230Sema::LookupOrdinaryName);231ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF);232if (!ID && S.getLangOpts().DebuggerObjCLiteral) {233ASTContext &Context = S.Context;234TranslationUnitDecl *TU = Context.getTranslationUnitDecl();235ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II,236nullptr, nullptr, SourceLocation());237}238239if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) {240ID = nullptr;241}242243return ID;244}245246/// Retrieve the NSNumber factory method that should be used to create247/// an Objective-C literal for the given type.248static ObjCMethodDecl *getNSNumberFactoryMethod(SemaObjC &S, SourceLocation Loc,249QualType NumberType,250bool isLiteral = false,251SourceRange R = SourceRange()) {252std::optional<NSAPI::NSNumberLiteralMethodKind> Kind =253S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType);254255if (!Kind) {256if (isLiteral) {257S.Diag(Loc, diag::err_invalid_nsnumber_type)258<< NumberType << R;259}260return nullptr;261}262263// If we already looked up this method, we're done.264if (S.NSNumberLiteralMethods[*Kind])265return S.NSNumberLiteralMethods[*Kind];266267Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind,268/*Instance=*/false);269270ASTContext &CX = S.SemaRef.Context;271272// Look up the NSNumber class, if we haven't done so already. It's cached273// in the Sema instance.274if (!S.NSNumberDecl) {275S.NSNumberDecl =276LookupObjCInterfaceDeclForLiteral(S.SemaRef, Loc, SemaObjC::LK_Numeric);277if (!S.NSNumberDecl) {278return nullptr;279}280}281282if (S.NSNumberPointer.isNull()) {283// generate the pointer to NSNumber type.284QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl);285S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject);286}287288// Look for the appropriate method within NSNumber.289ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);290if (!Method && S.getLangOpts().DebuggerObjCLiteral) {291// create a stub definition this NSNumber factory method.292TypeSourceInfo *ReturnTInfo = nullptr;293Method = ObjCMethodDecl::Create(294CX, SourceLocation(), SourceLocation(), Sel, S.NSNumberPointer,295ReturnTInfo, S.NSNumberDecl,296/*isInstance=*/false, /*isVariadic=*/false,297/*isPropertyAccessor=*/false,298/*isSynthesizedAccessorStub=*/false,299/*isImplicitlyDeclared=*/true,300/*isDefined=*/false, ObjCImplementationControl::Required,301/*HasRelatedResultType=*/false);302ParmVarDecl *value =303ParmVarDecl::Create(S.SemaRef.Context, Method, SourceLocation(),304SourceLocation(), &CX.Idents.get("value"),305NumberType, /*TInfo=*/nullptr, SC_None, nullptr);306Method->setMethodParams(S.SemaRef.Context, value, std::nullopt);307}308309if (!validateBoxingMethod(S.SemaRef, Loc, S.NSNumberDecl, Sel, Method))310return nullptr;311312// Note: if the parameter type is out-of-line, we'll catch it later in the313// implicit conversion.314315S.NSNumberLiteralMethods[*Kind] = Method;316return Method;317}318319/// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the320/// numeric literal expression. Type of the expression will be "NSNumber *".321ExprResult SemaObjC::BuildObjCNumericLiteral(SourceLocation AtLoc,322Expr *Number) {323ASTContext &Context = getASTContext();324// Determine the type of the literal.325QualType NumberType = Number->getType();326if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) {327// In C, character literals have type 'int'. That's not the type we want328// to use to determine the Objective-c literal kind.329switch (Char->getKind()) {330case CharacterLiteralKind::Ascii:331case CharacterLiteralKind::UTF8:332NumberType = Context.CharTy;333break;334335case CharacterLiteralKind::Wide:336NumberType = Context.getWideCharType();337break;338339case CharacterLiteralKind::UTF16:340NumberType = Context.Char16Ty;341break;342343case CharacterLiteralKind::UTF32:344NumberType = Context.Char32Ty;345break;346}347}348349// Look for the appropriate method within NSNumber.350// Construct the literal.351SourceRange NR(Number->getSourceRange());352ObjCMethodDecl *Method = getNSNumberFactoryMethod(*this, AtLoc, NumberType,353true, NR);354if (!Method)355return ExprError();356357// Convert the number to the type that the parameter expects.358ParmVarDecl *ParamDecl = Method->parameters()[0];359InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,360ParamDecl);361ExprResult ConvertedNumber =362SemaRef.PerformCopyInitialization(Entity, SourceLocation(), Number);363if (ConvertedNumber.isInvalid())364return ExprError();365Number = ConvertedNumber.get();366367// Use the effective source range of the literal, including the leading '@'.368return SemaRef.MaybeBindToTemporary(new (Context) ObjCBoxedExpr(369Number, NSNumberPointer, Method, SourceRange(AtLoc, NR.getEnd())));370}371372ExprResult SemaObjC::ActOnObjCBoolLiteral(SourceLocation AtLoc,373SourceLocation ValueLoc, bool Value) {374ASTContext &Context = getASTContext();375ExprResult Inner;376if (getLangOpts().CPlusPlus) {377Inner = SemaRef.ActOnCXXBoolLiteral(ValueLoc,378Value ? tok::kw_true : tok::kw_false);379} else {380// C doesn't actually have a way to represent literal values of type381// _Bool. So, we'll use 0/1 and implicit cast to _Bool.382Inner = SemaRef.ActOnIntegerConstant(ValueLoc, Value ? 1 : 0);383Inner = SemaRef.ImpCastExprToType(Inner.get(), Context.BoolTy,384CK_IntegralToBoolean);385}386387return BuildObjCNumericLiteral(AtLoc, Inner.get());388}389390/// Check that the given expression is a valid element of an Objective-C391/// collection literal.392static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,393QualType T,394bool ArrayLiteral = false) {395// If the expression is type-dependent, there's nothing for us to do.396if (Element->isTypeDependent())397return Element;398399ExprResult Result = S.CheckPlaceholderExpr(Element);400if (Result.isInvalid())401return ExprError();402Element = Result.get();403404// In C++, check for an implicit conversion to an Objective-C object pointer405// type.406if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) {407InitializedEntity Entity408= InitializedEntity::InitializeParameter(S.Context, T,409/*Consumed=*/false);410InitializationKind Kind = InitializationKind::CreateCopy(411Element->getBeginLoc(), SourceLocation());412InitializationSequence Seq(S, Entity, Kind, Element);413if (!Seq.Failed())414return Seq.Perform(S, Entity, Kind, Element);415}416417Expr *OrigElement = Element;418419// Perform lvalue-to-rvalue conversion.420Result = S.DefaultLvalueConversion(Element);421if (Result.isInvalid())422return ExprError();423Element = Result.get();424425// Make sure that we have an Objective-C pointer type or block.426if (!Element->getType()->isObjCObjectPointerType() &&427!Element->getType()->isBlockPointerType()) {428bool Recovered = false;429430// If this is potentially an Objective-C numeric literal, add the '@'.431if (isa<IntegerLiteral>(OrigElement) ||432isa<CharacterLiteral>(OrigElement) ||433isa<FloatingLiteral>(OrigElement) ||434isa<ObjCBoolLiteralExpr>(OrigElement) ||435isa<CXXBoolLiteralExpr>(OrigElement)) {436if (S.ObjC().NSAPIObj->getNSNumberFactoryMethodKind(437OrigElement->getType())) {438int Which = isa<CharacterLiteral>(OrigElement) ? 1439: (isa<CXXBoolLiteralExpr>(OrigElement) ||440isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2441: 3;442443S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection)444<< Which << OrigElement->getSourceRange()445<< FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@");446447Result = S.ObjC().BuildObjCNumericLiteral(OrigElement->getBeginLoc(),448OrigElement);449if (Result.isInvalid())450return ExprError();451452Element = Result.get();453Recovered = true;454}455}456// If this is potentially an Objective-C string literal, add the '@'.457else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) {458if (String->isOrdinary()) {459S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection)460<< 0 << OrigElement->getSourceRange()461<< FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@");462463Result =464S.ObjC().BuildObjCStringLiteral(OrigElement->getBeginLoc(), String);465if (Result.isInvalid())466return ExprError();467468Element = Result.get();469Recovered = true;470}471}472473if (!Recovered) {474S.Diag(Element->getBeginLoc(), diag::err_invalid_collection_element)475<< Element->getType();476return ExprError();477}478}479if (ArrayLiteral)480if (ObjCStringLiteral *getString =481dyn_cast<ObjCStringLiteral>(OrigElement)) {482if (StringLiteral *SL = getString->getString()) {483unsigned numConcat = SL->getNumConcatenated();484if (numConcat > 1) {485// Only warn if the concatenated string doesn't come from a macro.486bool hasMacro = false;487for (unsigned i = 0; i < numConcat ; ++i)488if (SL->getStrTokenLoc(i).isMacroID()) {489hasMacro = true;490break;491}492if (!hasMacro)493S.Diag(Element->getBeginLoc(),494diag::warn_concatenated_nsarray_literal)495<< Element->getType();496}497}498}499500// Make sure that the element has the type that the container factory501// function expects.502return S.PerformCopyInitialization(503InitializedEntity::InitializeParameter(S.Context, T,504/*Consumed=*/false),505Element->getBeginLoc(), Element);506}507508ExprResult SemaObjC::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {509ASTContext &Context = getASTContext();510if (ValueExpr->isTypeDependent()) {511ObjCBoxedExpr *BoxedExpr =512new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR);513return BoxedExpr;514}515ObjCMethodDecl *BoxingMethod = nullptr;516QualType BoxedType;517// Convert the expression to an RValue, so we can check for pointer types...518ExprResult RValue = SemaRef.DefaultFunctionArrayLvalueConversion(ValueExpr);519if (RValue.isInvalid()) {520return ExprError();521}522SourceLocation Loc = SR.getBegin();523ValueExpr = RValue.get();524QualType ValueType(ValueExpr->getType());525if (const PointerType *PT = ValueType->getAs<PointerType>()) {526QualType PointeeType = PT->getPointeeType();527if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {528529if (!NSStringDecl) {530NSStringDecl =531LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, LK_String);532if (!NSStringDecl) {533return ExprError();534}535QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl);536NSStringPointer = Context.getObjCObjectPointerType(NSStringObject);537}538539// The boxed expression can be emitted as a compile time constant if it is540// a string literal whose character encoding is compatible with UTF-8.541if (auto *CE = dyn_cast<ImplicitCastExpr>(ValueExpr))542if (CE->getCastKind() == CK_ArrayToPointerDecay)543if (auto *SL =544dyn_cast<StringLiteral>(CE->getSubExpr()->IgnoreParens())) {545assert((SL->isOrdinary() || SL->isUTF8()) &&546"unexpected character encoding");547StringRef Str = SL->getString();548const llvm::UTF8 *StrBegin = Str.bytes_begin();549const llvm::UTF8 *StrEnd = Str.bytes_end();550// Check that this is a valid UTF-8 string.551if (llvm::isLegalUTF8String(&StrBegin, StrEnd)) {552BoxedType = Context.getAttributedType(553AttributedType::getNullabilityAttrKind(554NullabilityKind::NonNull),555NSStringPointer, NSStringPointer);556return new (Context) ObjCBoxedExpr(CE, BoxedType, nullptr, SR);557}558559Diag(SL->getBeginLoc(), diag::warn_objc_boxing_invalid_utf8_string)560<< NSStringPointer << SL->getSourceRange();561}562563if (!StringWithUTF8StringMethod) {564IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String");565Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II);566567// Look for the appropriate method within NSString.568BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);569if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {570// Debugger needs to work even if NSString hasn't been defined.571TypeSourceInfo *ReturnTInfo = nullptr;572ObjCMethodDecl *M = ObjCMethodDecl::Create(573Context, SourceLocation(), SourceLocation(), stringWithUTF8String,574NSStringPointer, ReturnTInfo, NSStringDecl,575/*isInstance=*/false, /*isVariadic=*/false,576/*isPropertyAccessor=*/false,577/*isSynthesizedAccessorStub=*/false,578/*isImplicitlyDeclared=*/true,579/*isDefined=*/false, ObjCImplementationControl::Required,580/*HasRelatedResultType=*/false);581QualType ConstCharType = Context.CharTy.withConst();582ParmVarDecl *value =583ParmVarDecl::Create(Context, M,584SourceLocation(), SourceLocation(),585&Context.Idents.get("value"),586Context.getPointerType(ConstCharType),587/*TInfo=*/nullptr,588SC_None, nullptr);589M->setMethodParams(Context, value, std::nullopt);590BoxingMethod = M;591}592593if (!validateBoxingMethod(SemaRef, Loc, NSStringDecl,594stringWithUTF8String, BoxingMethod))595return ExprError();596597StringWithUTF8StringMethod = BoxingMethod;598}599600BoxingMethod = StringWithUTF8StringMethod;601BoxedType = NSStringPointer;602// Transfer the nullability from method's return type.603std::optional<NullabilityKind> Nullability =604BoxingMethod->getReturnType()->getNullability();605if (Nullability)606BoxedType = Context.getAttributedType(607AttributedType::getNullabilityAttrKind(*Nullability), BoxedType,608BoxedType);609}610} else if (ValueType->isBuiltinType()) {611// The other types we support are numeric, char and BOOL/bool. We could also612// provide limited support for structure types, such as NSRange, NSRect, and613// NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h>614// for more details.615616// Check for a top-level character literal.617if (const CharacterLiteral *Char =618dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) {619// In C, character literals have type 'int'. That's not the type we want620// to use to determine the Objective-c literal kind.621switch (Char->getKind()) {622case CharacterLiteralKind::Ascii:623case CharacterLiteralKind::UTF8:624ValueType = Context.CharTy;625break;626627case CharacterLiteralKind::Wide:628ValueType = Context.getWideCharType();629break;630631case CharacterLiteralKind::UTF16:632ValueType = Context.Char16Ty;633break;634635case CharacterLiteralKind::UTF32:636ValueType = Context.Char32Ty;637break;638}639}640// FIXME: Do I need to do anything special with BoolTy expressions?641642// Look for the appropriate method within NSNumber.643BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType);644BoxedType = NSNumberPointer;645} else if (const EnumType *ET = ValueType->getAs<EnumType>()) {646if (!ET->getDecl()->isComplete()) {647Diag(Loc, diag::err_objc_incomplete_boxed_expression_type)648<< ValueType << ValueExpr->getSourceRange();649return ExprError();650}651652BoxingMethod = getNSNumberFactoryMethod(*this, Loc,653ET->getDecl()->getIntegerType());654BoxedType = NSNumberPointer;655} else if (ValueType->isObjCBoxableRecordType()) {656// Support for structure types, that marked as objc_boxable657// struct __attribute__((objc_boxable)) s { ... };658659// Look up the NSValue class, if we haven't done so already. It's cached660// in the Sema instance.661if (!NSValueDecl) {662NSValueDecl = LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, LK_Boxed);663if (!NSValueDecl) {664return ExprError();665}666667// generate the pointer to NSValue type.668QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);669NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);670}671672if (!ValueWithBytesObjCTypeMethod) {673const IdentifierInfo *II[] = {&Context.Idents.get("valueWithBytes"),674&Context.Idents.get("objCType")};675Selector ValueWithBytesObjCType = Context.Selectors.getSelector(2, II);676677// Look for the appropriate method within NSValue.678BoxingMethod = NSValueDecl->lookupClassMethod(ValueWithBytesObjCType);679if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {680// Debugger needs to work even if NSValue hasn't been defined.681TypeSourceInfo *ReturnTInfo = nullptr;682ObjCMethodDecl *M = ObjCMethodDecl::Create(683Context, SourceLocation(), SourceLocation(), ValueWithBytesObjCType,684NSValuePointer, ReturnTInfo, NSValueDecl,685/*isInstance=*/false,686/*isVariadic=*/false,687/*isPropertyAccessor=*/false,688/*isSynthesizedAccessorStub=*/false,689/*isImplicitlyDeclared=*/true,690/*isDefined=*/false, ObjCImplementationControl::Required,691/*HasRelatedResultType=*/false);692693SmallVector<ParmVarDecl *, 2> Params;694695ParmVarDecl *bytes =696ParmVarDecl::Create(Context, M,697SourceLocation(), SourceLocation(),698&Context.Idents.get("bytes"),699Context.VoidPtrTy.withConst(),700/*TInfo=*/nullptr,701SC_None, nullptr);702Params.push_back(bytes);703704QualType ConstCharType = Context.CharTy.withConst();705ParmVarDecl *type =706ParmVarDecl::Create(Context, M,707SourceLocation(), SourceLocation(),708&Context.Idents.get("type"),709Context.getPointerType(ConstCharType),710/*TInfo=*/nullptr,711SC_None, nullptr);712Params.push_back(type);713714M->setMethodParams(Context, Params, std::nullopt);715BoxingMethod = M;716}717718if (!validateBoxingMethod(SemaRef, Loc, NSValueDecl,719ValueWithBytesObjCType, BoxingMethod))720return ExprError();721722ValueWithBytesObjCTypeMethod = BoxingMethod;723}724725if (!ValueType.isTriviallyCopyableType(Context)) {726Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type)727<< ValueType << ValueExpr->getSourceRange();728return ExprError();729}730731BoxingMethod = ValueWithBytesObjCTypeMethod;732BoxedType = NSValuePointer;733}734735if (!BoxingMethod) {736Diag(Loc, diag::err_objc_illegal_boxed_expression_type)737<< ValueType << ValueExpr->getSourceRange();738return ExprError();739}740741SemaRef.DiagnoseUseOfDecl(BoxingMethod, Loc);742743ExprResult ConvertedValueExpr;744if (ValueType->isObjCBoxableRecordType()) {745InitializedEntity IE = InitializedEntity::InitializeTemporary(ValueType);746ConvertedValueExpr = SemaRef.PerformCopyInitialization(747IE, ValueExpr->getExprLoc(), ValueExpr);748} else {749// Convert the expression to the type that the parameter requires.750ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];751InitializedEntity IE = InitializedEntity::InitializeParameter(Context,752ParamDecl);753ConvertedValueExpr =754SemaRef.PerformCopyInitialization(IE, SourceLocation(), ValueExpr);755}756757if (ConvertedValueExpr.isInvalid())758return ExprError();759ValueExpr = ConvertedValueExpr.get();760761ObjCBoxedExpr *BoxedExpr =762new (Context) ObjCBoxedExpr(ValueExpr, BoxedType,763BoxingMethod, SR);764return SemaRef.MaybeBindToTemporary(BoxedExpr);765}766767/// Build an ObjC subscript pseudo-object expression, given that768/// that's supported by the runtime.769ExprResult SemaObjC::BuildObjCSubscriptExpression(770SourceLocation RB, Expr *BaseExpr, Expr *IndexExpr,771ObjCMethodDecl *getterMethod, ObjCMethodDecl *setterMethod) {772assert(!getLangOpts().isSubscriptPointerArithmetic());773ASTContext &Context = getASTContext();774775// We can't get dependent types here; our callers should have776// filtered them out.777assert((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) &&778"base or index cannot have dependent type here");779780// Filter out placeholders in the index. In theory, overloads could781// be preserved here, although that might not actually work correctly.782ExprResult Result = SemaRef.CheckPlaceholderExpr(IndexExpr);783if (Result.isInvalid())784return ExprError();785IndexExpr = Result.get();786787// Perform lvalue-to-rvalue conversion on the base.788Result = SemaRef.DefaultLvalueConversion(BaseExpr);789if (Result.isInvalid())790return ExprError();791BaseExpr = Result.get();792793// Build the pseudo-object expression.794return new (Context) ObjCSubscriptRefExpr(795BaseExpr, IndexExpr, Context.PseudoObjectTy, VK_LValue, OK_ObjCSubscript,796getterMethod, setterMethod, RB);797}798799ExprResult SemaObjC::BuildObjCArrayLiteral(SourceRange SR,800MultiExprArg Elements) {801ASTContext &Context = getASTContext();802SourceLocation Loc = SR.getBegin();803804if (!NSArrayDecl) {805NSArrayDecl =806LookupObjCInterfaceDeclForLiteral(SemaRef, Loc, SemaObjC::LK_Array);807if (!NSArrayDecl) {808return ExprError();809}810}811812// Find the arrayWithObjects:count: method, if we haven't done so already.813QualType IdT = Context.getObjCIdType();814if (!ArrayWithObjectsMethod) {815Selector816Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);817ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);818if (!Method && getLangOpts().DebuggerObjCLiteral) {819TypeSourceInfo *ReturnTInfo = nullptr;820Method = ObjCMethodDecl::Create(821Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,822Context.getTranslationUnitDecl(), false /*Instance*/,823false /*isVariadic*/,824/*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,825/*isImplicitlyDeclared=*/true, /*isDefined=*/false,826ObjCImplementationControl::Required, false);827SmallVector<ParmVarDecl *, 2> Params;828ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,829SourceLocation(),830SourceLocation(),831&Context.Idents.get("objects"),832Context.getPointerType(IdT),833/*TInfo=*/nullptr,834SC_None, nullptr);835Params.push_back(objects);836ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,837SourceLocation(),838SourceLocation(),839&Context.Idents.get("cnt"),840Context.UnsignedLongTy,841/*TInfo=*/nullptr, SC_None,842nullptr);843Params.push_back(cnt);844Method->setMethodParams(Context, Params, std::nullopt);845}846847if (!validateBoxingMethod(SemaRef, Loc, NSArrayDecl, Sel, Method))848return ExprError();849850// Dig out the type that all elements should be converted to.851QualType T = Method->parameters()[0]->getType();852const PointerType *PtrT = T->getAs<PointerType>();853if (!PtrT ||854!Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {855Diag(SR.getBegin(), diag::err_objc_literal_method_sig)856<< Sel;857Diag(Method->parameters()[0]->getLocation(),858diag::note_objc_literal_method_param)859<< 0 << T860<< Context.getPointerType(IdT.withConst());861return ExprError();862}863864// Check that the 'count' parameter is integral.865if (!Method->parameters()[1]->getType()->isIntegerType()) {866Diag(SR.getBegin(), diag::err_objc_literal_method_sig)867<< Sel;868Diag(Method->parameters()[1]->getLocation(),869diag::note_objc_literal_method_param)870<< 1871<< Method->parameters()[1]->getType()872<< "integral";873return ExprError();874}875876// We've found a good +arrayWithObjects:count: method. Save it!877ArrayWithObjectsMethod = Method;878}879880QualType ObjectsType = ArrayWithObjectsMethod->parameters()[0]->getType();881QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType();882883// Check that each of the elements provided is valid in a collection literal,884// performing conversions as necessary.885Expr **ElementsBuffer = Elements.data();886for (unsigned I = 0, N = Elements.size(); I != N; ++I) {887ExprResult Converted = CheckObjCCollectionLiteralElement(888SemaRef, ElementsBuffer[I], RequiredType, true);889if (Converted.isInvalid())890return ExprError();891892ElementsBuffer[I] = Converted.get();893}894895QualType Ty896= Context.getObjCObjectPointerType(897Context.getObjCInterfaceType(NSArrayDecl));898899return SemaRef.MaybeBindToTemporary(ObjCArrayLiteral::Create(900Context, Elements, Ty, ArrayWithObjectsMethod, SR));901}902903/// Check for duplicate keys in an ObjC dictionary literal. For instance:904/// NSDictionary *nd = @{ @"foo" : @"bar", @"foo" : @"baz" };905static void906CheckObjCDictionaryLiteralDuplicateKeys(Sema &S,907ObjCDictionaryLiteral *Literal) {908if (Literal->isValueDependent() || Literal->isTypeDependent())909return;910911// NSNumber has quite relaxed equality semantics (for instance, @YES is912// considered equal to @1.0). For now, ignore floating points and just do a913// bit-width and sign agnostic integer compare.914struct APSIntCompare {915bool operator()(const llvm::APSInt &LHS, const llvm::APSInt &RHS) const {916return llvm::APSInt::compareValues(LHS, RHS) < 0;917}918};919920llvm::DenseMap<StringRef, SourceLocation> StringKeys;921std::map<llvm::APSInt, SourceLocation, APSIntCompare> IntegralKeys;922923auto checkOneKey = [&](auto &Map, const auto &Key, SourceLocation Loc) {924auto Pair = Map.insert({Key, Loc});925if (!Pair.second) {926S.Diag(Loc, diag::warn_nsdictionary_duplicate_key);927S.Diag(Pair.first->second, diag::note_nsdictionary_duplicate_key_here);928}929};930931for (unsigned Idx = 0, End = Literal->getNumElements(); Idx != End; ++Idx) {932Expr *Key = Literal->getKeyValueElement(Idx).Key->IgnoreParenImpCasts();933934if (auto *StrLit = dyn_cast<ObjCStringLiteral>(Key)) {935StringRef Bytes = StrLit->getString()->getBytes();936SourceLocation Loc = StrLit->getExprLoc();937checkOneKey(StringKeys, Bytes, Loc);938}939940if (auto *BE = dyn_cast<ObjCBoxedExpr>(Key)) {941Expr *Boxed = BE->getSubExpr();942SourceLocation Loc = BE->getExprLoc();943944// Check for @("foo").945if (auto *Str = dyn_cast<StringLiteral>(Boxed->IgnoreParenImpCasts())) {946checkOneKey(StringKeys, Str->getBytes(), Loc);947continue;948}949950Expr::EvalResult Result;951if (Boxed->EvaluateAsInt(Result, S.getASTContext(),952Expr::SE_AllowSideEffects)) {953checkOneKey(IntegralKeys, Result.Val.getInt(), Loc);954}955}956}957}958959ExprResult SemaObjC::BuildObjCDictionaryLiteral(960SourceRange SR, MutableArrayRef<ObjCDictionaryElement> Elements) {961ASTContext &Context = getASTContext();962SourceLocation Loc = SR.getBegin();963964if (!NSDictionaryDecl) {965NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(966SemaRef, Loc, SemaObjC::LK_Dictionary);967if (!NSDictionaryDecl) {968return ExprError();969}970}971972// Find the dictionaryWithObjects:forKeys:count: method, if we haven't done973// so already.974QualType IdT = Context.getObjCIdType();975if (!DictionaryWithObjectsMethod) {976Selector Sel = NSAPIObj->getNSDictionarySelector(977NSAPI::NSDict_dictionaryWithObjectsForKeysCount);978ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);979if (!Method && getLangOpts().DebuggerObjCLiteral) {980Method = ObjCMethodDecl::Create(981Context, SourceLocation(), SourceLocation(), Sel, IdT,982nullptr /*TypeSourceInfo */, Context.getTranslationUnitDecl(),983false /*Instance*/, false /*isVariadic*/,984/*isPropertyAccessor=*/false,985/*isSynthesizedAccessorStub=*/false,986/*isImplicitlyDeclared=*/true, /*isDefined=*/false,987ObjCImplementationControl::Required, false);988SmallVector<ParmVarDecl *, 3> Params;989ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,990SourceLocation(),991SourceLocation(),992&Context.Idents.get("objects"),993Context.getPointerType(IdT),994/*TInfo=*/nullptr, SC_None,995nullptr);996Params.push_back(objects);997ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,998SourceLocation(),999SourceLocation(),1000&Context.Idents.get("keys"),1001Context.getPointerType(IdT),1002/*TInfo=*/nullptr, SC_None,1003nullptr);1004Params.push_back(keys);1005ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,1006SourceLocation(),1007SourceLocation(),1008&Context.Idents.get("cnt"),1009Context.UnsignedLongTy,1010/*TInfo=*/nullptr, SC_None,1011nullptr);1012Params.push_back(cnt);1013Method->setMethodParams(Context, Params, std::nullopt);1014}10151016if (!validateBoxingMethod(SemaRef, SR.getBegin(), NSDictionaryDecl, Sel,1017Method))1018return ExprError();10191020// Dig out the type that all values should be converted to.1021QualType ValueT = Method->parameters()[0]->getType();1022const PointerType *PtrValue = ValueT->getAs<PointerType>();1023if (!PtrValue ||1024!Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {1025Diag(SR.getBegin(), diag::err_objc_literal_method_sig)1026<< Sel;1027Diag(Method->parameters()[0]->getLocation(),1028diag::note_objc_literal_method_param)1029<< 0 << ValueT1030<< Context.getPointerType(IdT.withConst());1031return ExprError();1032}10331034// Dig out the type that all keys should be converted to.1035QualType KeyT = Method->parameters()[1]->getType();1036const PointerType *PtrKey = KeyT->getAs<PointerType>();1037if (!PtrKey ||1038!Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),1039IdT)) {1040bool err = true;1041if (PtrKey) {1042if (QIDNSCopying.isNull()) {1043// key argument of selector is id<NSCopying>?1044if (ObjCProtocolDecl *NSCopyingPDecl =1045LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {1046ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};1047QIDNSCopying = Context.getObjCObjectType(1048Context.ObjCBuiltinIdTy, {},1049llvm::ArrayRef((ObjCProtocolDecl **)PQ, 1), false);1050QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);1051}1052}1053if (!QIDNSCopying.isNull())1054err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),1055QIDNSCopying);1056}10571058if (err) {1059Diag(SR.getBegin(), diag::err_objc_literal_method_sig)1060<< Sel;1061Diag(Method->parameters()[1]->getLocation(),1062diag::note_objc_literal_method_param)1063<< 1 << KeyT1064<< Context.getPointerType(IdT.withConst());1065return ExprError();1066}1067}10681069// Check that the 'count' parameter is integral.1070QualType CountType = Method->parameters()[2]->getType();1071if (!CountType->isIntegerType()) {1072Diag(SR.getBegin(), diag::err_objc_literal_method_sig)1073<< Sel;1074Diag(Method->parameters()[2]->getLocation(),1075diag::note_objc_literal_method_param)1076<< 2 << CountType1077<< "integral";1078return ExprError();1079}10801081// We've found a good +dictionaryWithObjects:keys:count: method; save it!1082DictionaryWithObjectsMethod = Method;1083}10841085QualType ValuesT = DictionaryWithObjectsMethod->parameters()[0]->getType();1086QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType();1087QualType KeysT = DictionaryWithObjectsMethod->parameters()[1]->getType();1088QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType();10891090// Check that each of the keys and values provided is valid in a collection1091// literal, performing conversions as necessary.1092bool HasPackExpansions = false;1093for (ObjCDictionaryElement &Element : Elements) {1094// Check the key.1095ExprResult Key =1096CheckObjCCollectionLiteralElement(SemaRef, Element.Key, KeyT);1097if (Key.isInvalid())1098return ExprError();10991100// Check the value.1101ExprResult Value =1102CheckObjCCollectionLiteralElement(SemaRef, Element.Value, ValueT);1103if (Value.isInvalid())1104return ExprError();11051106Element.Key = Key.get();1107Element.Value = Value.get();11081109if (Element.EllipsisLoc.isInvalid())1110continue;11111112if (!Element.Key->containsUnexpandedParameterPack() &&1113!Element.Value->containsUnexpandedParameterPack()) {1114Diag(Element.EllipsisLoc,1115diag::err_pack_expansion_without_parameter_packs)1116<< SourceRange(Element.Key->getBeginLoc(),1117Element.Value->getEndLoc());1118return ExprError();1119}11201121HasPackExpansions = true;1122}11231124QualType Ty = Context.getObjCObjectPointerType(1125Context.getObjCInterfaceType(NSDictionaryDecl));11261127auto *Literal =1128ObjCDictionaryLiteral::Create(Context, Elements, HasPackExpansions, Ty,1129DictionaryWithObjectsMethod, SR);1130CheckObjCDictionaryLiteralDuplicateKeys(SemaRef, Literal);1131return SemaRef.MaybeBindToTemporary(Literal);1132}11331134ExprResult SemaObjC::BuildObjCEncodeExpression(SourceLocation AtLoc,1135TypeSourceInfo *EncodedTypeInfo,1136SourceLocation RParenLoc) {1137ASTContext &Context = getASTContext();1138QualType EncodedType = EncodedTypeInfo->getType();1139QualType StrTy;1140if (EncodedType->isDependentType())1141StrTy = Context.DependentTy;1142else {1143if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled.1144!EncodedType->isVoidType()) // void is handled too.1145if (SemaRef.RequireCompleteType(AtLoc, EncodedType,1146diag::err_incomplete_type_objc_at_encode,1147EncodedTypeInfo->getTypeLoc()))1148return ExprError();11491150std::string Str;1151QualType NotEncodedT;1152Context.getObjCEncodingForType(EncodedType, Str, nullptr, &NotEncodedT);1153if (!NotEncodedT.isNull())1154Diag(AtLoc, diag::warn_incomplete_encoded_type)1155<< EncodedType << NotEncodedT;11561157// The type of @encode is the same as the type of the corresponding string,1158// which is an array type.1159StrTy = Context.getStringLiteralArrayType(Context.CharTy, Str.size());1160}11611162return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);1163}11641165ExprResult SemaObjC::ParseObjCEncodeExpression(SourceLocation AtLoc,1166SourceLocation EncodeLoc,1167SourceLocation LParenLoc,1168ParsedType ty,1169SourceLocation RParenLoc) {1170ASTContext &Context = getASTContext();1171// FIXME: Preserve type source info ?1172TypeSourceInfo *TInfo;1173QualType EncodedType = SemaRef.GetTypeFromParser(ty, &TInfo);1174if (!TInfo)1175TInfo = Context.getTrivialTypeSourceInfo(1176EncodedType, SemaRef.getLocForEndOfToken(LParenLoc));11771178return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);1179}11801181static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,1182SourceLocation AtLoc,1183SourceLocation LParenLoc,1184SourceLocation RParenLoc,1185ObjCMethodDecl *Method,1186ObjCMethodList &MethList) {1187ObjCMethodList *M = &MethList;1188bool Warned = false;1189for (M = M->getNext(); M; M=M->getNext()) {1190ObjCMethodDecl *MatchingMethodDecl = M->getMethod();1191if (MatchingMethodDecl == Method ||1192isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) ||1193MatchingMethodDecl->getSelector() != Method->getSelector())1194continue;1195if (!S.ObjC().MatchTwoMethodDeclarations(Method, MatchingMethodDecl,1196SemaObjC::MMS_loose)) {1197if (!Warned) {1198Warned = true;1199S.Diag(AtLoc, diag::warn_multiple_selectors)1200<< Method->getSelector() << FixItHint::CreateInsertion(LParenLoc, "(")1201<< FixItHint::CreateInsertion(RParenLoc, ")");1202S.Diag(Method->getLocation(), diag::note_method_declared_at)1203<< Method->getDeclName();1204}1205S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at)1206<< MatchingMethodDecl->getDeclName();1207}1208}1209return Warned;1210}12111212static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,1213ObjCMethodDecl *Method,1214SourceLocation LParenLoc,1215SourceLocation RParenLoc,1216bool WarnMultipleSelectors) {1217if (!WarnMultipleSelectors ||1218S.Diags.isIgnored(diag::warn_multiple_selectors, SourceLocation()))1219return;1220bool Warned = false;1221for (SemaObjC::GlobalMethodPool::iterator b = S.ObjC().MethodPool.begin(),1222e = S.ObjC().MethodPool.end();1223b != e; b++) {1224// first, instance methods1225ObjCMethodList &InstMethList = b->second.first;1226if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,1227Method, InstMethList))1228Warned = true;12291230// second, class methods1231ObjCMethodList &ClsMethList = b->second.second;1232if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,1233Method, ClsMethList) || Warned)1234return;1235}1236}12371238static ObjCMethodDecl *LookupDirectMethodInMethodList(Sema &S, Selector Sel,1239ObjCMethodList &MethList,1240bool &onlyDirect,1241bool &anyDirect) {1242(void)Sel;1243ObjCMethodList *M = &MethList;1244ObjCMethodDecl *DirectMethod = nullptr;1245for (; M; M = M->getNext()) {1246ObjCMethodDecl *Method = M->getMethod();1247if (!Method)1248continue;1249assert(Method->getSelector() == Sel && "Method with wrong selector in method list");1250if (Method->isDirectMethod()) {1251anyDirect = true;1252DirectMethod = Method;1253} else1254onlyDirect = false;1255}12561257return DirectMethod;1258}12591260// Search the global pool for (potentially) direct methods matching the given1261// selector. If a non-direct method is found, set \param onlyDirect to false. If1262// a direct method is found, set \param anyDirect to true. Returns a direct1263// method, if any.1264static ObjCMethodDecl *LookupDirectMethodInGlobalPool(Sema &S, Selector Sel,1265bool &onlyDirect,1266bool &anyDirect) {1267auto Iter = S.ObjC().MethodPool.find(Sel);1268if (Iter == S.ObjC().MethodPool.end())1269return nullptr;12701271ObjCMethodDecl *DirectInstance = LookupDirectMethodInMethodList(1272S, Sel, Iter->second.first, onlyDirect, anyDirect);1273ObjCMethodDecl *DirectClass = LookupDirectMethodInMethodList(1274S, Sel, Iter->second.second, onlyDirect, anyDirect);12751276return DirectInstance ? DirectInstance : DirectClass;1277}12781279static ObjCMethodDecl *findMethodInCurrentClass(Sema &S, Selector Sel) {1280auto *CurMD = S.getCurMethodDecl();1281if (!CurMD)1282return nullptr;1283ObjCInterfaceDecl *IFace = CurMD->getClassInterface();12841285// The language enforce that only one direct method is present in a given1286// class, so we just need to find one method in the current class to know1287// whether Sel is potentially direct in this context.1288if (ObjCMethodDecl *MD = IFace->lookupMethod(Sel, /*isInstance=*/true))1289return MD;1290if (ObjCMethodDecl *MD = IFace->lookupPrivateMethod(Sel, /*Instance=*/true))1291return MD;1292if (ObjCMethodDecl *MD = IFace->lookupMethod(Sel, /*isInstance=*/false))1293return MD;1294if (ObjCMethodDecl *MD = IFace->lookupPrivateMethod(Sel, /*Instance=*/false))1295return MD;12961297return nullptr;1298}12991300ExprResult SemaObjC::ParseObjCSelectorExpression(Selector Sel,1301SourceLocation AtLoc,1302SourceLocation SelLoc,1303SourceLocation LParenLoc,1304SourceLocation RParenLoc,1305bool WarnMultipleSelectors) {1306ASTContext &Context = getASTContext();1307ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,1308SourceRange(LParenLoc, RParenLoc));1309if (!Method)1310Method = LookupFactoryMethodInGlobalPool(Sel,1311SourceRange(LParenLoc, RParenLoc));1312if (!Method) {1313if (const ObjCMethodDecl *OM = SelectorsForTypoCorrection(Sel)) {1314Selector MatchedSel = OM->getSelector();1315SourceRange SelectorRange(LParenLoc.getLocWithOffset(1),1316RParenLoc.getLocWithOffset(-1));1317Diag(SelLoc, diag::warn_undeclared_selector_with_typo)1318<< Sel << MatchedSel1319<< FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());13201321} else1322Diag(SelLoc, diag::warn_undeclared_selector) << Sel;1323} else {1324DiagnoseMismatchedSelectors(SemaRef, AtLoc, Method, LParenLoc, RParenLoc,1325WarnMultipleSelectors);13261327bool onlyDirect = true;1328bool anyDirect = false;1329ObjCMethodDecl *GlobalDirectMethod =1330LookupDirectMethodInGlobalPool(SemaRef, Sel, onlyDirect, anyDirect);13311332if (onlyDirect) {1333Diag(AtLoc, diag::err_direct_selector_expression)1334<< Method->getSelector();1335Diag(Method->getLocation(), diag::note_direct_method_declared_at)1336<< Method->getDeclName();1337} else if (anyDirect) {1338// If we saw any direct methods, see if we see a direct member of the1339// current class. If so, the @selector will likely be used to refer to1340// this direct method.1341ObjCMethodDecl *LikelyTargetMethod =1342findMethodInCurrentClass(SemaRef, Sel);1343if (LikelyTargetMethod && LikelyTargetMethod->isDirectMethod()) {1344Diag(AtLoc, diag::warn_potentially_direct_selector_expression) << Sel;1345Diag(LikelyTargetMethod->getLocation(),1346diag::note_direct_method_declared_at)1347<< LikelyTargetMethod->getDeclName();1348} else if (!LikelyTargetMethod) {1349// Otherwise, emit the "strict" variant of this diagnostic, unless1350// LikelyTargetMethod is non-direct.1351Diag(AtLoc, diag::warn_strict_potentially_direct_selector_expression)1352<< Sel;1353Diag(GlobalDirectMethod->getLocation(),1354diag::note_direct_method_declared_at)1355<< GlobalDirectMethod->getDeclName();1356}1357}1358}13591360if (Method &&1361Method->getImplementationControl() !=1362ObjCImplementationControl::Optional &&1363!SemaRef.getSourceManager().isInSystemHeader(Method->getLocation()))1364ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));13651366// In ARC, forbid the user from using @selector for1367// retain/release/autorelease/dealloc/retainCount.1368if (getLangOpts().ObjCAutoRefCount) {1369switch (Sel.getMethodFamily()) {1370case OMF_retain:1371case OMF_release:1372case OMF_autorelease:1373case OMF_retainCount:1374case OMF_dealloc:1375Diag(AtLoc, diag::err_arc_illegal_selector) <<1376Sel << SourceRange(LParenLoc, RParenLoc);1377break;13781379case OMF_None:1380case OMF_alloc:1381case OMF_copy:1382case OMF_finalize:1383case OMF_init:1384case OMF_mutableCopy:1385case OMF_new:1386case OMF_self:1387case OMF_initialize:1388case OMF_performSelector:1389break;1390}1391}1392QualType Ty = Context.getObjCSelType();1393return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);1394}13951396ExprResult SemaObjC::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,1397SourceLocation AtLoc,1398SourceLocation ProtoLoc,1399SourceLocation LParenLoc,1400SourceLocation ProtoIdLoc,1401SourceLocation RParenLoc) {1402ASTContext &Context = getASTContext();1403ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoIdLoc);1404if (!PDecl) {1405Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;1406return true;1407}1408if (PDecl->isNonRuntimeProtocol())1409Diag(ProtoLoc, diag::err_objc_non_runtime_protocol_in_protocol_expr)1410<< PDecl;1411if (!PDecl->hasDefinition()) {1412Diag(ProtoLoc, diag::err_atprotocol_protocol) << PDecl;1413Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;1414} else {1415PDecl = PDecl->getDefinition();1416}14171418QualType Ty = Context.getObjCProtoType();1419if (Ty.isNull())1420return true;1421Ty = Context.getObjCObjectPointerType(Ty);1422return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, ProtoIdLoc, RParenLoc);1423}14241425/// Try to capture an implicit reference to 'self'.1426ObjCMethodDecl *SemaObjC::tryCaptureObjCSelf(SourceLocation Loc) {1427DeclContext *DC = SemaRef.getFunctionLevelDeclContext();14281429// If we're not in an ObjC method, error out. Note that, unlike the1430// C++ case, we don't require an instance method --- class methods1431// still have a 'self', and we really do still need to capture it!1432ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC);1433if (!method)1434return nullptr;14351436SemaRef.tryCaptureVariable(method->getSelfDecl(), Loc);14371438return method;1439}14401441static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {1442QualType origType = T;1443if (auto nullability = AttributedType::stripOuterNullability(T)) {1444if (T == Context.getObjCInstanceType()) {1445return Context.getAttributedType(1446AttributedType::getNullabilityAttrKind(*nullability),1447Context.getObjCIdType(),1448Context.getObjCIdType());1449}14501451return origType;1452}14531454if (T == Context.getObjCInstanceType())1455return Context.getObjCIdType();14561457return origType;1458}14591460/// Determine the result type of a message send based on the receiver type,1461/// method, and the kind of message send.1462///1463/// This is the "base" result type, which will still need to be adjusted1464/// to account for nullability.1465static QualType getBaseMessageSendResultType(Sema &S,1466QualType ReceiverType,1467ObjCMethodDecl *Method,1468bool isClassMessage,1469bool isSuperMessage) {1470assert(Method && "Must have a method");1471if (!Method->hasRelatedResultType())1472return Method->getSendResultType(ReceiverType);14731474ASTContext &Context = S.Context;14751476// Local function that transfers the nullability of the method's1477// result type to the returned result.1478auto transferNullability = [&](QualType type) -> QualType {1479// If the method's result type has nullability, extract it.1480if (auto nullability =1481Method->getSendResultType(ReceiverType)->getNullability()) {1482// Strip off any outer nullability sugar from the provided type.1483(void)AttributedType::stripOuterNullability(type);14841485// Form a new attributed type using the method result type's nullability.1486return Context.getAttributedType(1487AttributedType::getNullabilityAttrKind(*nullability),1488type,1489type);1490}14911492return type;1493};14941495// If a method has a related return type:1496// - if the method found is an instance method, but the message send1497// was a class message send, T is the declared return type of the method1498// found1499if (Method->isInstanceMethod() && isClassMessage)1500return stripObjCInstanceType(Context,1501Method->getSendResultType(ReceiverType));15021503// - if the receiver is super, T is a pointer to the class of the1504// enclosing method definition1505if (isSuperMessage) {1506if (ObjCMethodDecl *CurMethod = S.getCurMethodDecl())1507if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) {1508return transferNullability(1509Context.getObjCObjectPointerType(1510Context.getObjCInterfaceType(Class)));1511}1512}15131514// - if the receiver is the name of a class U, T is a pointer to U1515if (ReceiverType->getAsObjCInterfaceType())1516return transferNullability(Context.getObjCObjectPointerType(ReceiverType));1517// - if the receiver is of type Class or qualified Class type,1518// T is the declared return type of the method.1519if (ReceiverType->isObjCClassType() ||1520ReceiverType->isObjCQualifiedClassType())1521return stripObjCInstanceType(Context,1522Method->getSendResultType(ReceiverType));15231524// - if the receiver is id, qualified id, Class, or qualified Class, T1525// is the receiver type, otherwise1526// - T is the type of the receiver expression.1527return transferNullability(ReceiverType);1528}15291530QualType SemaObjC::getMessageSendResultType(const Expr *Receiver,1531QualType ReceiverType,1532ObjCMethodDecl *Method,1533bool isClassMessage,1534bool isSuperMessage) {1535ASTContext &Context = getASTContext();1536// Produce the result type.1537QualType resultType = getBaseMessageSendResultType(1538SemaRef, ReceiverType, Method, isClassMessage, isSuperMessage);15391540// If this is a class message, ignore the nullability of the receiver.1541if (isClassMessage) {1542// In a class method, class messages to 'self' that return instancetype can1543// be typed as the current class. We can safely do this in ARC because self1544// can't be reassigned, and we do it unsafely outside of ARC because in1545// practice people never reassign self in class methods and there's some1546// virtue in not being aggressively pedantic.1547if (Receiver && Receiver->isObjCSelfExpr()) {1548assert(ReceiverType->isObjCClassType() && "expected a Class self");1549QualType T = Method->getSendResultType(ReceiverType);1550AttributedType::stripOuterNullability(T);1551if (T == Context.getObjCInstanceType()) {1552const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(1553cast<ImplicitParamDecl>(1554cast<DeclRefExpr>(Receiver->IgnoreParenImpCasts())->getDecl())1555->getDeclContext());1556assert(MD->isClassMethod() && "expected a class method");1557QualType NewResultType = Context.getObjCObjectPointerType(1558Context.getObjCInterfaceType(MD->getClassInterface()));1559if (auto Nullability = resultType->getNullability())1560NewResultType = Context.getAttributedType(1561AttributedType::getNullabilityAttrKind(*Nullability),1562NewResultType, NewResultType);1563return NewResultType;1564}1565}1566return resultType;1567}15681569// There is nothing left to do if the result type cannot have a nullability1570// specifier.1571if (!resultType->canHaveNullability())1572return resultType;15731574// Map the nullability of the result into a table index.1575unsigned receiverNullabilityIdx = 0;1576if (std::optional<NullabilityKind> nullability =1577ReceiverType->getNullability()) {1578if (*nullability == NullabilityKind::NullableResult)1579nullability = NullabilityKind::Nullable;1580receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);1581}15821583unsigned resultNullabilityIdx = 0;1584if (std::optional<NullabilityKind> nullability =1585resultType->getNullability()) {1586if (*nullability == NullabilityKind::NullableResult)1587nullability = NullabilityKind::Nullable;1588resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability);1589}15901591// The table of nullability mappings, indexed by the receiver's nullability1592// and then the result type's nullability.1593static const uint8_t None = 0;1594static const uint8_t NonNull = 1;1595static const uint8_t Nullable = 2;1596static const uint8_t Unspecified = 3;1597static const uint8_t nullabilityMap[4][4] = {1598// None NonNull Nullable Unspecified1599/* None */ { None, None, Nullable, None },1600/* NonNull */ { None, NonNull, Nullable, Unspecified },1601/* Nullable */ { Nullable, Nullable, Nullable, Nullable },1602/* Unspecified */ { None, Unspecified, Nullable, Unspecified }1603};16041605unsigned newResultNullabilityIdx1606= nullabilityMap[receiverNullabilityIdx][resultNullabilityIdx];1607if (newResultNullabilityIdx == resultNullabilityIdx)1608return resultType;16091610// Strip off the existing nullability. This removes as little type sugar as1611// possible.1612do {1613if (auto attributed = dyn_cast<AttributedType>(resultType.getTypePtr())) {1614resultType = attributed->getModifiedType();1615} else {1616resultType = resultType.getDesugaredType(Context);1617}1618} while (resultType->getNullability());16191620// Add nullability back if needed.1621if (newResultNullabilityIdx > 0) {1622auto newNullability1623= static_cast<NullabilityKind>(newResultNullabilityIdx-1);1624return Context.getAttributedType(1625AttributedType::getNullabilityAttrKind(newNullability),1626resultType, resultType);1627}16281629return resultType;1630}16311632/// Look for an ObjC method whose result type exactly matches the given type.1633static const ObjCMethodDecl *1634findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,1635QualType instancetype) {1636if (MD->getReturnType() == instancetype)1637return MD;16381639// For these purposes, a method in an @implementation overrides a1640// declaration in the @interface.1641if (const ObjCImplDecl *impl =1642dyn_cast<ObjCImplDecl>(MD->getDeclContext())) {1643const ObjCContainerDecl *iface;1644if (const ObjCCategoryImplDecl *catImpl =1645dyn_cast<ObjCCategoryImplDecl>(impl)) {1646iface = catImpl->getCategoryDecl();1647} else {1648iface = impl->getClassInterface();1649}16501651const ObjCMethodDecl *ifaceMD =1652iface->getMethod(MD->getSelector(), MD->isInstanceMethod());1653if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype);1654}16551656SmallVector<const ObjCMethodDecl *, 4> overrides;1657MD->getOverriddenMethods(overrides);1658for (unsigned i = 0, e = overrides.size(); i != e; ++i) {1659if (const ObjCMethodDecl *result =1660findExplicitInstancetypeDeclarer(overrides[i], instancetype))1661return result;1662}16631664return nullptr;1665}16661667void SemaObjC::EmitRelatedResultTypeNoteForReturn(QualType destType) {1668ASTContext &Context = getASTContext();1669// Only complain if we're in an ObjC method and the required return1670// type doesn't match the method's declared return type.1671ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext);1672if (!MD || !MD->hasRelatedResultType() ||1673Context.hasSameUnqualifiedType(destType, MD->getReturnType()))1674return;16751676// Look for a method overridden by this method which explicitly uses1677// 'instancetype'.1678if (const ObjCMethodDecl *overridden =1679findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {1680SourceRange range = overridden->getReturnTypeSourceRange();1681SourceLocation loc = range.getBegin();1682if (loc.isInvalid())1683loc = overridden->getLocation();1684Diag(loc, diag::note_related_result_type_explicit)1685<< /*current method*/ 1 << range;1686return;1687}16881689// Otherwise, if we have an interesting method family, note that.1690// This should always trigger if the above didn't.1691if (ObjCMethodFamily family = MD->getMethodFamily())1692Diag(MD->getLocation(), diag::note_related_result_type_family)1693<< /*current method*/ 11694<< family;1695}16961697void SemaObjC::EmitRelatedResultTypeNote(const Expr *E) {1698ASTContext &Context = getASTContext();1699E = E->IgnoreParenImpCasts();1700const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);1701if (!MsgSend)1702return;17031704const ObjCMethodDecl *Method = MsgSend->getMethodDecl();1705if (!Method)1706return;17071708if (!Method->hasRelatedResultType())1709return;17101711if (Context.hasSameUnqualifiedType(1712Method->getReturnType().getNonReferenceType(), MsgSend->getType()))1713return;17141715if (!Context.hasSameUnqualifiedType(Method->getReturnType(),1716Context.getObjCInstanceType()))1717return;17181719Diag(Method->getLocation(), diag::note_related_result_type_inferred)1720<< Method->isInstanceMethod() << Method->getSelector()1721<< MsgSend->getType();1722}17231724bool SemaObjC::CheckMessageArgumentTypes(1725const Expr *Receiver, QualType ReceiverType, MultiExprArg Args,1726Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method,1727bool isClassMessage, bool isSuperMessage, SourceLocation lbrac,1728SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType,1729ExprValueKind &VK) {1730ASTContext &Context = getASTContext();1731SourceLocation SelLoc;1732if (!SelectorLocs.empty() && SelectorLocs.front().isValid())1733SelLoc = SelectorLocs.front();1734else1735SelLoc = lbrac;17361737if (!Method) {1738// Apply default argument promotion as for (C99 6.5.2.2p6).1739for (unsigned i = 0, e = Args.size(); i != e; i++) {1740if (Args[i]->isTypeDependent())1741continue;17421743ExprResult result;1744if (getLangOpts().DebuggerSupport) {1745QualType paramTy; // ignored1746result = SemaRef.checkUnknownAnyArg(SelLoc, Args[i], paramTy);1747} else {1748result = SemaRef.DefaultArgumentPromotion(Args[i]);1749}1750if (result.isInvalid())1751return true;1752Args[i] = result.get();1753}17541755unsigned DiagID;1756if (getLangOpts().ObjCAutoRefCount)1757DiagID = diag::err_arc_method_not_found;1758else1759DiagID = isClassMessage ? diag::warn_class_method_not_found1760: diag::warn_inst_method_not_found;1761if (!getLangOpts().DebuggerSupport) {1762const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType);1763if (OMD && !OMD->isInvalidDecl()) {1764if (getLangOpts().ObjCAutoRefCount)1765DiagID = diag::err_method_not_found_with_typo;1766else1767DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo1768: diag::warn_instance_method_not_found_with_typo;1769Selector MatchedSel = OMD->getSelector();1770SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back());1771if (MatchedSel.isUnarySelector())1772Diag(SelLoc, DiagID)1773<< Sel<< isClassMessage << MatchedSel1774<< FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());1775else1776Diag(SelLoc, DiagID) << Sel<< isClassMessage << MatchedSel;1777}1778else1779Diag(SelLoc, DiagID)1780<< Sel << isClassMessage << SourceRange(SelectorLocs.front(),1781SelectorLocs.back());1782// Find the class to which we are sending this message.1783if (auto *ObjPT = ReceiverType->getAs<ObjCObjectPointerType>()) {1784if (ObjCInterfaceDecl *ThisClass = ObjPT->getInterfaceDecl()) {1785Diag(ThisClass->getLocation(), diag::note_receiver_class_declared);1786if (!RecRange.isInvalid())1787if (ThisClass->lookupClassMethod(Sel))1788Diag(RecRange.getBegin(), diag::note_receiver_expr_here)1789<< FixItHint::CreateReplacement(RecRange,1790ThisClass->getNameAsString());1791}1792}1793}17941795// In debuggers, we want to use __unknown_anytype for these1796// results so that clients can cast them.1797if (getLangOpts().DebuggerSupport) {1798ReturnType = Context.UnknownAnyTy;1799} else {1800ReturnType = Context.getObjCIdType();1801}1802VK = VK_PRValue;1803return false;1804}18051806ReturnType = getMessageSendResultType(Receiver, ReceiverType, Method,1807isClassMessage, isSuperMessage);1808VK = Expr::getValueKindForType(Method->getReturnType());18091810unsigned NumNamedArgs = Sel.getNumArgs();1811// Method might have more arguments than selector indicates. This is due1812// to addition of c-style arguments in method.1813if (Method->param_size() > Sel.getNumArgs())1814NumNamedArgs = Method->param_size();1815// FIXME. This need be cleaned up.1816if (Args.size() < NumNamedArgs) {1817Diag(SelLoc, diag::err_typecheck_call_too_few_args)1818<< 2 << NumNamedArgs << static_cast<unsigned>(Args.size())1819<< /*is non object*/ 0;1820return false;1821}18221823// Compute the set of type arguments to be substituted into each parameter1824// type.1825std::optional<ArrayRef<QualType>> typeArgs =1826ReceiverType->getObjCSubstitutions(Method->getDeclContext());1827bool IsError = false;1828for (unsigned i = 0; i < NumNamedArgs; i++) {1829// We can't do any type-checking on a type-dependent argument.1830if (Args[i]->isTypeDependent())1831continue;18321833Expr *argExpr = Args[i];18341835ParmVarDecl *param = Method->parameters()[i];1836assert(argExpr && "CheckMessageArgumentTypes(): missing expression");18371838if (param->hasAttr<NoEscapeAttr>() &&1839param->getType()->isBlockPointerType())1840if (auto *BE = dyn_cast<BlockExpr>(1841argExpr->IgnoreParenNoopCasts(Context)))1842BE->getBlockDecl()->setDoesNotEscape();18431844// Strip the unbridged-cast placeholder expression off unless it's1845// a consumed argument.1846if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&1847!param->hasAttr<CFConsumedAttr>())1848argExpr = stripARCUnbridgedCast(argExpr);18491850// If the parameter is __unknown_anytype, infer its type1851// from the argument.1852if (param->getType() == Context.UnknownAnyTy) {1853QualType paramType;1854ExprResult argE = SemaRef.checkUnknownAnyArg(SelLoc, argExpr, paramType);1855if (argE.isInvalid()) {1856IsError = true;1857} else {1858Args[i] = argE.get();18591860// Update the parameter type in-place.1861param->setType(paramType);1862}1863continue;1864}18651866QualType origParamType = param->getType();1867QualType paramType = param->getType();1868if (typeArgs)1869paramType = paramType.substObjCTypeArgs(1870Context,1871*typeArgs,1872ObjCSubstitutionContext::Parameter);18731874if (SemaRef.RequireCompleteType(1875argExpr->getSourceRange().getBegin(), paramType,1876diag::err_call_incomplete_argument, argExpr))1877return true;18781879InitializedEntity Entity1880= InitializedEntity::InitializeParameter(Context, param, paramType);1881ExprResult ArgE =1882SemaRef.PerformCopyInitialization(Entity, SourceLocation(), argExpr);1883if (ArgE.isInvalid())1884IsError = true;1885else {1886Args[i] = ArgE.getAs<Expr>();18871888// If we are type-erasing a block to a block-compatible1889// Objective-C pointer type, we may need to extend the lifetime1890// of the block object.1891if (typeArgs && Args[i]->isPRValue() && paramType->isBlockPointerType() &&1892Args[i]->getType()->isBlockPointerType() &&1893origParamType->isObjCObjectPointerType()) {1894ExprResult arg = Args[i];1895SemaRef.maybeExtendBlockObject(arg);1896Args[i] = arg.get();1897}1898}1899}19001901// Promote additional arguments to variadic methods.1902if (Method->isVariadic()) {1903for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {1904if (Args[i]->isTypeDependent())1905continue;19061907ExprResult Arg = SemaRef.DefaultVariadicArgumentPromotion(1908Args[i], Sema::VariadicMethod, nullptr);1909IsError |= Arg.isInvalid();1910Args[i] = Arg.get();1911}1912} else {1913// Check for extra arguments to non-variadic methods.1914if (Args.size() != NumNamedArgs) {1915Diag(Args[NumNamedArgs]->getBeginLoc(),1916diag::err_typecheck_call_too_many_args)1917<< 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size())1918<< Method->getSourceRange() << /*is non object*/ 01919<< SourceRange(Args[NumNamedArgs]->getBeginLoc(),1920Args.back()->getEndLoc());1921}1922}19231924SemaRef.DiagnoseSentinelCalls(Method, SelLoc, Args);19251926// Do additional checkings on method.1927IsError |=1928CheckObjCMethodCall(Method, SelLoc, ArrayRef(Args.data(), Args.size()));19291930return IsError;1931}19321933bool SemaObjC::isSelfExpr(Expr *RExpr) {1934// 'self' is objc 'self' in an objc method only.1935ObjCMethodDecl *Method = dyn_cast_or_null<ObjCMethodDecl>(1936SemaRef.CurContext->getNonClosureAncestor());1937return isSelfExpr(RExpr, Method);1938}19391940bool SemaObjC::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) {1941if (!method) return false;19421943receiver = receiver->IgnoreParenLValueCasts();1944if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver))1945if (DRE->getDecl() == method->getSelfDecl())1946return true;1947return false;1948}19491950/// LookupMethodInType - Look up a method in an ObjCObjectType.1951ObjCMethodDecl *SemaObjC::LookupMethodInObjectType(Selector sel, QualType type,1952bool isInstance) {1953const ObjCObjectType *objType = type->castAs<ObjCObjectType>();1954if (ObjCInterfaceDecl *iface = objType->getInterface()) {1955// Look it up in the main interface (and categories, etc.)1956if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance))1957return method;19581959// Okay, look for "private" methods declared in any1960// @implementations we've seen.1961if (ObjCMethodDecl *method = iface->lookupPrivateMethod(sel, isInstance))1962return method;1963}19641965// Check qualifiers.1966for (const auto *I : objType->quals())1967if (ObjCMethodDecl *method = I->lookupMethod(sel, isInstance))1968return method;19691970return nullptr;1971}19721973/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier1974/// list of a qualified objective pointer type.1975ObjCMethodDecl *SemaObjC::LookupMethodInQualifiedType(1976Selector Sel, const ObjCObjectPointerType *OPT, bool Instance) {1977ObjCMethodDecl *MD = nullptr;1978for (const auto *PROTO : OPT->quals()) {1979if ((MD = PROTO->lookupMethod(Sel, Instance))) {1980return MD;1981}1982}1983return nullptr;1984}19851986/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an1987/// objective C interface. This is a property reference expression.1988ExprResult SemaObjC::HandleExprPropertyRefExpr(1989const ObjCObjectPointerType *OPT, Expr *BaseExpr, SourceLocation OpLoc,1990DeclarationName MemberName, SourceLocation MemberLoc,1991SourceLocation SuperLoc, QualType SuperType, bool Super) {1992ASTContext &Context = getASTContext();1993const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();1994ObjCInterfaceDecl *IFace = IFaceT->getDecl();19951996if (!MemberName.isIdentifier()) {1997Diag(MemberLoc, diag::err_invalid_property_name)1998<< MemberName << QualType(OPT, 0);1999return ExprError();2000}20012002IdentifierInfo *Member = MemberName.getAsIdentifierInfo();20032004SourceRange BaseRange = Super? SourceRange(SuperLoc)2005: BaseExpr->getSourceRange();2006if (SemaRef.RequireCompleteType(MemberLoc, OPT->getPointeeType(),2007diag::err_property_not_found_forward_class,2008MemberName, BaseRange))2009return ExprError();20102011if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(2012Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {2013// Check whether we can reference this property.2014if (SemaRef.DiagnoseUseOfDecl(PD, MemberLoc))2015return ExprError();2016if (Super)2017return new (Context)2018ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,2019OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);2020else2021return new (Context)2022ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,2023OK_ObjCProperty, MemberLoc, BaseExpr);2024}2025// Check protocols on qualified interfaces.2026for (const auto *I : OPT->quals())2027if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(2028Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {2029// Check whether we can reference this property.2030if (SemaRef.DiagnoseUseOfDecl(PD, MemberLoc))2031return ExprError();20322033if (Super)2034return new (Context) ObjCPropertyRefExpr(2035PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc,2036SuperLoc, SuperType);2037else2038return new (Context)2039ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,2040OK_ObjCProperty, MemberLoc, BaseExpr);2041}2042// If that failed, look for an "implicit" property by seeing if the nullary2043// selector is implemented.20442045// FIXME: The logic for looking up nullary and unary selectors should be2046// shared with the code in ActOnInstanceMessage.20472048Selector Sel = SemaRef.PP.getSelectorTable().getNullarySelector(Member);2049ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);20502051// May be found in property's qualified list.2052if (!Getter)2053Getter = LookupMethodInQualifiedType(Sel, OPT, true);20542055// If this reference is in an @implementation, check for 'private' methods.2056if (!Getter)2057Getter = IFace->lookupPrivateMethod(Sel);20582059if (Getter) {2060// Check if we can reference this property.2061if (SemaRef.DiagnoseUseOfDecl(Getter, MemberLoc))2062return ExprError();2063}2064// If we found a getter then this may be a valid dot-reference, we2065// will look for the matching setter, in case it is needed.2066Selector SetterSel = SelectorTable::constructSetterSelector(2067SemaRef.PP.getIdentifierTable(), SemaRef.PP.getSelectorTable(), Member);2068ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);20692070// May be found in property's qualified list.2071if (!Setter)2072Setter = LookupMethodInQualifiedType(SetterSel, OPT, true);20732074if (!Setter) {2075// If this reference is in an @implementation, also check for 'private'2076// methods.2077Setter = IFace->lookupPrivateMethod(SetterSel);2078}20792080if (Setter && SemaRef.DiagnoseUseOfDecl(Setter, MemberLoc))2081return ExprError();20822083// Special warning if member name used in a property-dot for a setter accessor2084// does not use a property with same name; e.g. obj.X = ... for a property with2085// name 'x'.2086if (Setter && Setter->isImplicit() && Setter->isPropertyAccessor() &&2087!IFace->FindPropertyDeclaration(2088Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {2089if (const ObjCPropertyDecl *PDecl = Setter->findPropertyDecl()) {2090// Do not warn if user is using property-dot syntax to make call to2091// user named setter.2092if (!(PDecl->getPropertyAttributes() &2093ObjCPropertyAttribute::kind_setter))2094Diag(MemberLoc,2095diag::warn_property_access_suggest)2096<< MemberName << QualType(OPT, 0) << PDecl->getName()2097<< FixItHint::CreateReplacement(MemberLoc, PDecl->getName());2098}2099}21002101if (Getter || Setter) {2102if (Super)2103return new (Context)2104ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,2105OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);2106else2107return new (Context)2108ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,2109OK_ObjCProperty, MemberLoc, BaseExpr);21102111}21122113// Attempt to correct for typos in property names.2114DeclFilterCCC<ObjCPropertyDecl> CCC{};2115if (TypoCorrection Corrected = SemaRef.CorrectTypo(2116DeclarationNameInfo(MemberName, MemberLoc), Sema::LookupOrdinaryName,2117nullptr, nullptr, CCC, Sema::CTK_ErrorRecovery, IFace, false, OPT)) {2118DeclarationName TypoResult = Corrected.getCorrection();2119if (TypoResult.isIdentifier() &&2120TypoResult.getAsIdentifierInfo() == Member) {2121// There is no need to try the correction if it is the same.2122NamedDecl *ChosenDecl =2123Corrected.isKeyword() ? nullptr : Corrected.getFoundDecl();2124if (ChosenDecl && isa<ObjCPropertyDecl>(ChosenDecl))2125if (cast<ObjCPropertyDecl>(ChosenDecl)->isClassProperty()) {2126// This is a class property, we should not use the instance to2127// access it.2128Diag(MemberLoc, diag::err_class_property_found) << MemberName2129<< OPT->getInterfaceDecl()->getName()2130<< FixItHint::CreateReplacement(BaseExpr->getSourceRange(),2131OPT->getInterfaceDecl()->getName());2132return ExprError();2133}2134} else {2135SemaRef.diagnoseTypo(Corrected,2136PDiag(diag::err_property_not_found_suggest)2137<< MemberName << QualType(OPT, 0));2138return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,2139TypoResult, MemberLoc,2140SuperLoc, SuperType, Super);2141}2142}2143ObjCInterfaceDecl *ClassDeclared;2144if (ObjCIvarDecl *Ivar =2145IFace->lookupInstanceVariable(Member, ClassDeclared)) {2146QualType T = Ivar->getType();2147if (const ObjCObjectPointerType * OBJPT =2148T->getAsObjCInterfacePointerType()) {2149if (SemaRef.RequireCompleteType(MemberLoc, OBJPT->getPointeeType(),2150diag::err_property_not_as_forward_class,2151MemberName, BaseExpr))2152return ExprError();2153}2154Diag(MemberLoc,2155diag::err_ivar_access_using_property_syntax_suggest)2156<< MemberName << QualType(OPT, 0) << Ivar->getDeclName()2157<< FixItHint::CreateReplacement(OpLoc, "->");2158return ExprError();2159}21602161Diag(MemberLoc, diag::err_property_not_found)2162<< MemberName << QualType(OPT, 0);2163if (Setter)2164Diag(Setter->getLocation(), diag::note_getter_unavailable)2165<< MemberName << BaseExpr->getSourceRange();2166return ExprError();2167}21682169ExprResult SemaObjC::ActOnClassPropertyRefExpr(2170const IdentifierInfo &receiverName, const IdentifierInfo &propertyName,2171SourceLocation receiverNameLoc, SourceLocation propertyNameLoc) {2172ASTContext &Context = getASTContext();2173const IdentifierInfo *receiverNamePtr = &receiverName;2174ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,2175receiverNameLoc);21762177QualType SuperType;2178if (!IFace) {2179// If the "receiver" is 'super' in a method, handle it as an expression-like2180// property reference.2181if (receiverNamePtr->isStr("super")) {2182if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) {2183if (auto classDecl = CurMethod->getClassInterface()) {2184SuperType = QualType(classDecl->getSuperClassType(), 0);2185if (CurMethod->isInstanceMethod()) {2186if (SuperType.isNull()) {2187// The current class does not have a superclass.2188Diag(receiverNameLoc, diag::err_root_class_cannot_use_super)2189<< CurMethod->getClassInterface()->getIdentifier();2190return ExprError();2191}2192QualType T = Context.getObjCObjectPointerType(SuperType);21932194return HandleExprPropertyRefExpr(T->castAs<ObjCObjectPointerType>(),2195/*BaseExpr*/nullptr,2196SourceLocation()/*OpLoc*/,2197&propertyName,2198propertyNameLoc,2199receiverNameLoc, T, true);2200}22012202// Otherwise, if this is a class method, try dispatching to our2203// superclass.2204IFace = CurMethod->getClassInterface()->getSuperClass();2205}2206}2207}22082209if (!IFace) {2210Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier2211<< tok::l_paren;2212return ExprError();2213}2214}22152216Selector GetterSel;2217Selector SetterSel;2218if (auto PD = IFace->FindPropertyDeclaration(2219&propertyName, ObjCPropertyQueryKind::OBJC_PR_query_class)) {2220GetterSel = PD->getGetterName();2221SetterSel = PD->getSetterName();2222} else {2223GetterSel = SemaRef.PP.getSelectorTable().getNullarySelector(&propertyName);2224SetterSel = SelectorTable::constructSetterSelector(2225SemaRef.PP.getIdentifierTable(), SemaRef.PP.getSelectorTable(),2226&propertyName);2227}22282229// Search for a declared property first.2230ObjCMethodDecl *Getter = IFace->lookupClassMethod(GetterSel);22312232// If this reference is in an @implementation, check for 'private' methods.2233if (!Getter)2234Getter = IFace->lookupPrivateClassMethod(GetterSel);22352236if (Getter) {2237// FIXME: refactor/share with ActOnMemberReference().2238// Check if we can reference this property.2239if (SemaRef.DiagnoseUseOfDecl(Getter, propertyNameLoc))2240return ExprError();2241}22422243// Look for the matching setter, in case it is needed.2244ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);2245if (!Setter) {2246// If this reference is in an @implementation, also check for 'private'2247// methods.2248Setter = IFace->lookupPrivateClassMethod(SetterSel);2249}2250// Look through local category implementations associated with the class.2251if (!Setter)2252Setter = IFace->getCategoryClassMethod(SetterSel);22532254if (Setter && SemaRef.DiagnoseUseOfDecl(Setter, propertyNameLoc))2255return ExprError();22562257if (Getter || Setter) {2258if (!SuperType.isNull())2259return new (Context)2260ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,2261OK_ObjCProperty, propertyNameLoc, receiverNameLoc,2262SuperType);22632264return new (Context) ObjCPropertyRefExpr(2265Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty,2266propertyNameLoc, receiverNameLoc, IFace);2267}2268return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)2269<< &propertyName << Context.getObjCInterfaceType(IFace));2270}22712272namespace {22732274class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback {2275public:2276ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {2277// Determine whether "super" is acceptable in the current context.2278if (Method && Method->getClassInterface())2279WantObjCSuper = Method->getClassInterface()->getSuperClass();2280}22812282bool ValidateCandidate(const TypoCorrection &candidate) override {2283return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||2284candidate.isKeyword("super");2285}22862287std::unique_ptr<CorrectionCandidateCallback> clone() override {2288return std::make_unique<ObjCInterfaceOrSuperCCC>(*this);2289}2290};22912292} // end anonymous namespace22932294SemaObjC::ObjCMessageKind2295SemaObjC::getObjCMessageKind(Scope *S, IdentifierInfo *Name,2296SourceLocation NameLoc, bool IsSuper,2297bool HasTrailingDot, ParsedType &ReceiverType) {2298ASTContext &Context = getASTContext();2299ReceiverType = nullptr;23002301// If the identifier is "super" and there is no trailing dot, we're2302// messaging super. If the identifier is "super" and there is a2303// trailing dot, it's an instance message.2304if (IsSuper && S->isInObjcMethodScope())2305return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage;23062307LookupResult Result(SemaRef, Name, NameLoc, Sema::LookupOrdinaryName);2308SemaRef.LookupName(Result, S);23092310switch (Result.getResultKind()) {2311case LookupResult::NotFound:2312// Normal name lookup didn't find anything. If we're in an2313// Objective-C method, look for ivars. If we find one, we're done!2314// FIXME: This is a hack. Ivar lookup should be part of normal2315// lookup.2316if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {2317if (!Method->getClassInterface()) {2318// Fall back: let the parser try to parse it as an instance message.2319return ObjCInstanceMessage;2320}23212322ObjCInterfaceDecl *ClassDeclared;2323if (Method->getClassInterface()->lookupInstanceVariable(Name,2324ClassDeclared))2325return ObjCInstanceMessage;2326}23272328// Break out; we'll perform typo correction below.2329break;23302331case LookupResult::NotFoundInCurrentInstantiation:2332case LookupResult::FoundOverloaded:2333case LookupResult::FoundUnresolvedValue:2334case LookupResult::Ambiguous:2335Result.suppressDiagnostics();2336return ObjCInstanceMessage;23372338case LookupResult::Found: {2339// If the identifier is a class or not, and there is a trailing dot,2340// it's an instance message.2341if (HasTrailingDot)2342return ObjCInstanceMessage;2343// We found something. If it's a type, then we have a class2344// message. Otherwise, it's an instance message.2345NamedDecl *ND = Result.getFoundDecl();2346QualType T;2347if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))2348T = Context.getObjCInterfaceType(Class);2349else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) {2350T = Context.getTypeDeclType(Type);2351SemaRef.DiagnoseUseOfDecl(Type, NameLoc);2352}2353else2354return ObjCInstanceMessage;23552356// We have a class message, and T is the type we're2357// messaging. Build source-location information for it.2358TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);2359ReceiverType = SemaRef.CreateParsedType(T, TSInfo);2360return ObjCClassMessage;2361}2362}23632364ObjCInterfaceOrSuperCCC CCC(SemaRef.getCurMethodDecl());2365if (TypoCorrection Corrected = SemaRef.CorrectTypo(2366Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, CCC,2367Sema::CTK_ErrorRecovery, nullptr, false, nullptr, false)) {2368if (Corrected.isKeyword()) {2369// If we've found the keyword "super" (the only keyword that would be2370// returned by CorrectTypo), this is a send to super.2371SemaRef.diagnoseTypo(Corrected, PDiag(diag::err_unknown_receiver_suggest)2372<< Name);2373return ObjCSuperMessage;2374} else if (ObjCInterfaceDecl *Class =2375Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {2376// If we found a declaration, correct when it refers to an Objective-C2377// class.2378SemaRef.diagnoseTypo(Corrected, PDiag(diag::err_unknown_receiver_suggest)2379<< Name);2380QualType T = Context.getObjCInterfaceType(Class);2381TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);2382ReceiverType = SemaRef.CreateParsedType(T, TSInfo);2383return ObjCClassMessage;2384}2385}23862387// Fall back: let the parser try to parse it as an instance message.2388return ObjCInstanceMessage;2389}23902391ExprResult SemaObjC::ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,2392Selector Sel, SourceLocation LBracLoc,2393ArrayRef<SourceLocation> SelectorLocs,2394SourceLocation RBracLoc,2395MultiExprArg Args) {2396ASTContext &Context = getASTContext();2397// Determine whether we are inside a method or not.2398ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc);2399if (!Method) {2400Diag(SuperLoc, diag::err_invalid_receiver_to_message_super);2401return ExprError();2402}24032404ObjCInterfaceDecl *Class = Method->getClassInterface();2405if (!Class) {2406Diag(SuperLoc, diag::err_no_super_class_message)2407<< Method->getDeclName();2408return ExprError();2409}24102411QualType SuperTy(Class->getSuperClassType(), 0);2412if (SuperTy.isNull()) {2413// The current class does not have a superclass.2414Diag(SuperLoc, diag::err_root_class_cannot_use_super)2415<< Class->getIdentifier();2416return ExprError();2417}24182419// We are in a method whose class has a superclass, so 'super'2420// is acting as a keyword.2421if (Method->getSelector() == Sel)2422SemaRef.getCurFunction()->ObjCShouldCallSuper = false;24232424if (Method->isInstanceMethod()) {2425// Since we are in an instance method, this is an instance2426// message to the superclass instance.2427SuperTy = Context.getObjCObjectPointerType(SuperTy);2428return BuildInstanceMessage(nullptr, SuperTy, SuperLoc,2429Sel, /*Method=*/nullptr,2430LBracLoc, SelectorLocs, RBracLoc, Args);2431}24322433// Since we are in a class method, this is a class message to2434// the superclass.2435return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,2436SuperTy,2437SuperLoc, Sel, /*Method=*/nullptr,2438LBracLoc, SelectorLocs, RBracLoc, Args);2439}24402441ExprResult SemaObjC::BuildClassMessageImplicit(QualType ReceiverType,2442bool isSuperReceiver,2443SourceLocation Loc, Selector Sel,2444ObjCMethodDecl *Method,2445MultiExprArg Args) {2446ASTContext &Context = getASTContext();2447TypeSourceInfo *receiverTypeInfo = nullptr;2448if (!ReceiverType.isNull())2449receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType);24502451assert(((isSuperReceiver && Loc.isValid()) || receiverTypeInfo) &&2452"Either the super receiver location needs to be valid or the receiver "2453"needs valid type source information");2454return BuildClassMessage(receiverTypeInfo, ReceiverType,2455/*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(),2456Sel, Method, Loc, Loc, Loc, Args,2457/*isImplicit=*/true);2458}24592460static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,2461unsigned DiagID,2462bool (*refactor)(const ObjCMessageExpr *,2463const NSAPI &, edit::Commit &)) {2464SourceLocation MsgLoc = Msg->getExprLoc();2465if (S.Diags.isIgnored(DiagID, MsgLoc))2466return;24672468SourceManager &SM = S.SourceMgr;2469edit::Commit ECommit(SM, S.LangOpts);2470if (refactor(Msg, *S.ObjC().NSAPIObj, ECommit)) {2471auto Builder = S.Diag(MsgLoc, DiagID)2472<< Msg->getSelector() << Msg->getSourceRange();2473// FIXME: Don't emit diagnostic at all if fixits are non-commitable.2474if (!ECommit.isCommitable())2475return;2476for (edit::Commit::edit_iterator2477I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) {2478const edit::Commit::Edit &Edit = *I;2479switch (Edit.Kind) {2480case edit::Commit::Act_Insert:2481Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc,2482Edit.Text,2483Edit.BeforePrev));2484break;2485case edit::Commit::Act_InsertFromRange:2486Builder.AddFixItHint(2487FixItHint::CreateInsertionFromRange(Edit.OrigLoc,2488Edit.getInsertFromRange(SM),2489Edit.BeforePrev));2490break;2491case edit::Commit::Act_Remove:2492Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM)));2493break;2494}2495}2496}2497}24982499static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) {2500applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use,2501edit::rewriteObjCRedundantCallWithLiteral);2502}25032504static void checkFoundationAPI(Sema &S, SourceLocation Loc,2505const ObjCMethodDecl *Method,2506ArrayRef<Expr *> Args, QualType ReceiverType,2507bool IsClassObjectCall) {2508// Check if this is a performSelector method that uses a selector that returns2509// a record or a vector type.2510if (Method->getSelector().getMethodFamily() != OMF_performSelector ||2511Args.empty())2512return;2513const auto *SE = dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens());2514if (!SE)2515return;2516ObjCMethodDecl *ImpliedMethod;2517if (!IsClassObjectCall) {2518const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>();2519if (!OPT || !OPT->getInterfaceDecl())2520return;2521ImpliedMethod =2522OPT->getInterfaceDecl()->lookupInstanceMethod(SE->getSelector());2523if (!ImpliedMethod)2524ImpliedMethod =2525OPT->getInterfaceDecl()->lookupPrivateMethod(SE->getSelector());2526} else {2527const auto *IT = ReceiverType->getAs<ObjCInterfaceType>();2528if (!IT)2529return;2530ImpliedMethod = IT->getDecl()->lookupClassMethod(SE->getSelector());2531if (!ImpliedMethod)2532ImpliedMethod =2533IT->getDecl()->lookupPrivateClassMethod(SE->getSelector());2534}2535if (!ImpliedMethod)2536return;2537QualType Ret = ImpliedMethod->getReturnType();2538if (Ret->isRecordType() || Ret->isVectorType() || Ret->isExtVectorType()) {2539S.Diag(Loc, diag::warn_objc_unsafe_perform_selector)2540<< Method->getSelector()2541<< (!Ret->isRecordType()2542? /*Vector*/ 22543: Ret->isUnionType() ? /*Union*/ 1 : /*Struct*/ 0);2544S.Diag(ImpliedMethod->getBeginLoc(),2545diag::note_objc_unsafe_perform_selector_method_declared_here)2546<< ImpliedMethod->getSelector() << Ret;2547}2548}25492550/// Diagnose use of %s directive in an NSString which is being passed2551/// as formatting string to formatting method.2552static void2553DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,2554ObjCMethodDecl *Method,2555Selector Sel,2556Expr **Args, unsigned NumArgs) {2557unsigned Idx = 0;2558bool Format = false;2559ObjCStringFormatFamily SFFamily = Sel.getStringFormatFamily();2560if (SFFamily == ObjCStringFormatFamily::SFF_NSString) {2561Idx = 0;2562Format = true;2563}2564else if (Method) {2565for (const auto *I : Method->specific_attrs<FormatAttr>()) {2566if (S.ObjC().GetFormatNSStringIdx(I, Idx)) {2567Format = true;2568break;2569}2570}2571}2572if (!Format || NumArgs <= Idx)2573return;25742575Expr *FormatExpr = Args[Idx];2576if (ObjCStringLiteral *OSL =2577dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts())) {2578StringLiteral *FormatString = OSL->getString();2579if (S.FormatStringHasSArg(FormatString)) {2580S.Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string)2581<< "%s" << 0 << 0;2582if (Method)2583S.Diag(Method->getLocation(), diag::note_method_declared_at)2584<< Method->getDeclName();2585}2586}2587}25882589/// Build an Objective-C class message expression.2590///2591/// This routine takes care of both normal class messages and2592/// class messages to the superclass.2593///2594/// \param ReceiverTypeInfo Type source information that describes the2595/// receiver of this message. This may be NULL, in which case we are2596/// sending to the superclass and \p SuperLoc must be a valid source2597/// location.25982599/// \param ReceiverType The type of the object receiving the2600/// message. When \p ReceiverTypeInfo is non-NULL, this is the same2601/// type as that refers to. For a superclass send, this is the type of2602/// the superclass.2603///2604/// \param SuperLoc The location of the "super" keyword in a2605/// superclass message.2606///2607/// \param Sel The selector to which the message is being sent.2608///2609/// \param Method The method that this class message is invoking, if2610/// already known.2611///2612/// \param LBracLoc The location of the opening square bracket ']'.2613///2614/// \param RBracLoc The location of the closing square bracket ']'.2615///2616/// \param ArgsIn The message arguments.2617ExprResult SemaObjC::BuildClassMessage(2618TypeSourceInfo *ReceiverTypeInfo, QualType ReceiverType,2619SourceLocation SuperLoc, Selector Sel, ObjCMethodDecl *Method,2620SourceLocation LBracLoc, ArrayRef<SourceLocation> SelectorLocs,2621SourceLocation RBracLoc, MultiExprArg ArgsIn, bool isImplicit) {2622ASTContext &Context = getASTContext();2623SourceLocation Loc = SuperLoc.isValid()? SuperLoc2624: ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();2625if (LBracLoc.isInvalid()) {2626Diag(Loc, diag::err_missing_open_square_message_send)2627<< FixItHint::CreateInsertion(Loc, "[");2628LBracLoc = Loc;2629}2630ArrayRef<SourceLocation> SelectorSlotLocs;2631if (!SelectorLocs.empty() && SelectorLocs.front().isValid())2632SelectorSlotLocs = SelectorLocs;2633else2634SelectorSlotLocs = Loc;2635SourceLocation SelLoc = SelectorSlotLocs.front();26362637if (ReceiverType->isDependentType()) {2638// If the receiver type is dependent, we can't type-check anything2639// at this point. Build a dependent expression.2640unsigned NumArgs = ArgsIn.size();2641Expr **Args = ArgsIn.data();2642assert(SuperLoc.isInvalid() && "Message to super with dependent type");2643return ObjCMessageExpr::Create(Context, ReceiverType, VK_PRValue, LBracLoc,2644ReceiverTypeInfo, Sel, SelectorLocs,2645/*Method=*/nullptr, ArrayRef(Args, NumArgs),2646RBracLoc, isImplicit);2647}26482649// Find the class to which we are sending this message.2650ObjCInterfaceDecl *Class = nullptr;2651const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();2652if (!ClassType || !(Class = ClassType->getInterface())) {2653Diag(Loc, diag::err_invalid_receiver_class_message)2654<< ReceiverType;2655return ExprError();2656}2657assert(Class && "We don't know which class we're messaging?");2658// objc++ diagnoses during typename annotation.2659if (!getLangOpts().CPlusPlus)2660(void)SemaRef.DiagnoseUseOfDecl(Class, SelectorSlotLocs);2661// Find the method we are messaging.2662if (!Method) {2663SourceRange TypeRange2664= SuperLoc.isValid()? SourceRange(SuperLoc)2665: ReceiverTypeInfo->getTypeLoc().getSourceRange();2666if (SemaRef.RequireCompleteType(Loc, Context.getObjCInterfaceType(Class),2667(getLangOpts().ObjCAutoRefCount2668? diag::err_arc_receiver_forward_class2669: diag::warn_receiver_forward_class),2670TypeRange)) {2671// A forward class used in messaging is treated as a 'Class'2672Method = LookupFactoryMethodInGlobalPool(Sel,2673SourceRange(LBracLoc, RBracLoc));2674if (Method && !getLangOpts().ObjCAutoRefCount)2675Diag(Method->getLocation(), diag::note_method_sent_forward_class)2676<< Method->getDeclName();2677}2678if (!Method)2679Method = Class->lookupClassMethod(Sel);26802681// If we have an implementation in scope, check "private" methods.2682if (!Method)2683Method = Class->lookupPrivateClassMethod(Sel);26842685if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs, nullptr,2686false, false, Class))2687return ExprError();2688}26892690// Check the argument types and determine the result type.2691QualType ReturnType;2692ExprValueKind VK = VK_PRValue;26932694unsigned NumArgs = ArgsIn.size();2695Expr **Args = ArgsIn.data();2696if (CheckMessageArgumentTypes(/*Receiver=*/nullptr, ReceiverType,2697MultiExprArg(Args, NumArgs), Sel, SelectorLocs,2698Method, true, SuperLoc.isValid(), LBracLoc,2699RBracLoc, SourceRange(), ReturnType, VK))2700return ExprError();27012702if (Method && !Method->getReturnType()->isVoidType() &&2703SemaRef.RequireCompleteType(2704LBracLoc, Method->getReturnType(),2705diag::err_illegal_message_expr_incomplete_type))2706return ExprError();27072708if (Method && Method->isDirectMethod() && SuperLoc.isValid()) {2709Diag(SuperLoc, diag::err_messaging_super_with_direct_method)2710<< FixItHint::CreateReplacement(2711SuperLoc, getLangOpts().ObjCAutoRefCount2712? "self"2713: Method->getClassInterface()->getName());2714Diag(Method->getLocation(), diag::note_direct_method_declared_at)2715<< Method->getDeclName();2716}27172718// Warn about explicit call of +initialize on its own class. But not on 'super'.2719if (Method && Method->getMethodFamily() == OMF_initialize) {2720if (!SuperLoc.isValid()) {2721const ObjCInterfaceDecl *ID =2722dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext());2723if (ID == Class) {2724Diag(Loc, diag::warn_direct_initialize_call);2725Diag(Method->getLocation(), diag::note_method_declared_at)2726<< Method->getDeclName();2727}2728} else if (ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl()) {2729// [super initialize] is allowed only within an +initialize implementation2730if (CurMeth->getMethodFamily() != OMF_initialize) {2731Diag(Loc, diag::warn_direct_super_initialize_call);2732Diag(Method->getLocation(), diag::note_method_declared_at)2733<< Method->getDeclName();2734Diag(CurMeth->getLocation(), diag::note_method_declared_at)2735<< CurMeth->getDeclName();2736}2737}2738}27392740DiagnoseCStringFormatDirectiveInObjCAPI(SemaRef, Method, Sel, Args, NumArgs);27412742// Construct the appropriate ObjCMessageExpr.2743ObjCMessageExpr *Result;2744if (SuperLoc.isValid())2745Result = ObjCMessageExpr::Create(2746Context, ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/false,2747ReceiverType, Sel, SelectorLocs, Method, ArrayRef(Args, NumArgs),2748RBracLoc, isImplicit);2749else {2750Result = ObjCMessageExpr::Create(2751Context, ReturnType, VK, LBracLoc, ReceiverTypeInfo, Sel, SelectorLocs,2752Method, ArrayRef(Args, NumArgs), RBracLoc, isImplicit);2753if (!isImplicit)2754checkCocoaAPI(SemaRef, Result);2755}2756if (Method)2757checkFoundationAPI(SemaRef, SelLoc, Method, ArrayRef(Args, NumArgs),2758ReceiverType, /*IsClassObjectCall=*/true);2759return SemaRef.MaybeBindToTemporary(Result);2760}27612762// ActOnClassMessage - used for both unary and keyword messages.2763// ArgExprs is optional - if it is present, the number of expressions2764// is obtained from Sel.getNumArgs().2765ExprResult SemaObjC::ActOnClassMessage(Scope *S, ParsedType Receiver,2766Selector Sel, SourceLocation LBracLoc,2767ArrayRef<SourceLocation> SelectorLocs,2768SourceLocation RBracLoc,2769MultiExprArg Args) {2770ASTContext &Context = getASTContext();2771TypeSourceInfo *ReceiverTypeInfo;2772QualType ReceiverType =2773SemaRef.GetTypeFromParser(Receiver, &ReceiverTypeInfo);2774if (ReceiverType.isNull())2775return ExprError();27762777if (!ReceiverTypeInfo)2778ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);27792780return BuildClassMessage(ReceiverTypeInfo, ReceiverType,2781/*SuperLoc=*/SourceLocation(), Sel,2782/*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc,2783Args);2784}27852786ExprResult SemaObjC::BuildInstanceMessageImplicit(2787Expr *Receiver, QualType ReceiverType, SourceLocation Loc, Selector Sel,2788ObjCMethodDecl *Method, MultiExprArg Args) {2789return BuildInstanceMessage(Receiver, ReceiverType,2790/*SuperLoc=*/!Receiver ? Loc : SourceLocation(),2791Sel, Method, Loc, Loc, Loc, Args,2792/*isImplicit=*/true);2793}27942795static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) {2796if (!S.ObjC().NSAPIObj)2797return false;2798const auto *Protocol = dyn_cast<ObjCProtocolDecl>(M->getDeclContext());2799if (!Protocol)2800return false;2801const IdentifierInfo *II =2802S.ObjC().NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);2803if (const auto *RootClass = dyn_cast_or_null<ObjCInterfaceDecl>(2804S.LookupSingleName(S.TUScope, II, Protocol->getBeginLoc(),2805Sema::LookupOrdinaryName))) {2806for (const ObjCProtocolDecl *P : RootClass->all_referenced_protocols()) {2807if (P->getCanonicalDecl() == Protocol->getCanonicalDecl())2808return true;2809}2810}2811return false;2812}28132814/// Build an Objective-C instance message expression.2815///2816/// This routine takes care of both normal instance messages and2817/// instance messages to the superclass instance.2818///2819/// \param Receiver The expression that computes the object that will2820/// receive this message. This may be empty, in which case we are2821/// sending to the superclass instance and \p SuperLoc must be a valid2822/// source location.2823///2824/// \param ReceiverType The (static) type of the object receiving the2825/// message. When a \p Receiver expression is provided, this is the2826/// same type as that expression. For a superclass instance send, this2827/// is a pointer to the type of the superclass.2828///2829/// \param SuperLoc The location of the "super" keyword in a2830/// superclass instance message.2831///2832/// \param Sel The selector to which the message is being sent.2833///2834/// \param Method The method that this instance message is invoking, if2835/// already known.2836///2837/// \param LBracLoc The location of the opening square bracket ']'.2838///2839/// \param RBracLoc The location of the closing square bracket ']'.2840///2841/// \param ArgsIn The message arguments.2842ExprResult SemaObjC::BuildInstanceMessage(2843Expr *Receiver, QualType ReceiverType, SourceLocation SuperLoc,2844Selector Sel, ObjCMethodDecl *Method, SourceLocation LBracLoc,2845ArrayRef<SourceLocation> SelectorLocs, SourceLocation RBracLoc,2846MultiExprArg ArgsIn, bool isImplicit) {2847assert((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the "2848"SuperLoc must be valid so we can "2849"use it instead.");2850ASTContext &Context = getASTContext();28512852// The location of the receiver.2853SourceLocation Loc = SuperLoc.isValid() ? SuperLoc : Receiver->getBeginLoc();2854SourceRange RecRange =2855SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();2856ArrayRef<SourceLocation> SelectorSlotLocs;2857if (!SelectorLocs.empty() && SelectorLocs.front().isValid())2858SelectorSlotLocs = SelectorLocs;2859else2860SelectorSlotLocs = Loc;2861SourceLocation SelLoc = SelectorSlotLocs.front();28622863if (LBracLoc.isInvalid()) {2864Diag(Loc, diag::err_missing_open_square_message_send)2865<< FixItHint::CreateInsertion(Loc, "[");2866LBracLoc = Loc;2867}28682869// If we have a receiver expression, perform appropriate promotions2870// and determine receiver type.2871if (Receiver) {2872if (Receiver->hasPlaceholderType()) {2873ExprResult Result;2874if (Receiver->getType() == Context.UnknownAnyTy)2875Result =2876SemaRef.forceUnknownAnyToType(Receiver, Context.getObjCIdType());2877else2878Result = SemaRef.CheckPlaceholderExpr(Receiver);2879if (Result.isInvalid()) return ExprError();2880Receiver = Result.get();2881}28822883if (Receiver->isTypeDependent()) {2884// If the receiver is type-dependent, we can't type-check anything2885// at this point. Build a dependent expression.2886unsigned NumArgs = ArgsIn.size();2887Expr **Args = ArgsIn.data();2888assert(SuperLoc.isInvalid() && "Message to super with dependent type");2889return ObjCMessageExpr::Create(2890Context, Context.DependentTy, VK_PRValue, LBracLoc, Receiver, Sel,2891SelectorLocs, /*Method=*/nullptr, ArrayRef(Args, NumArgs), RBracLoc,2892isImplicit);2893}28942895// If necessary, apply function/array conversion to the receiver.2896// C99 6.7.5.3p[7,8].2897ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Receiver);2898if (Result.isInvalid())2899return ExprError();2900Receiver = Result.get();2901ReceiverType = Receiver->getType();29022903// If the receiver is an ObjC pointer, a block pointer, or an2904// __attribute__((NSObject)) pointer, we don't need to do any2905// special conversion in order to look up a receiver.2906if (ReceiverType->isObjCRetainableType()) {2907// do nothing2908} else if (!getLangOpts().ObjCAutoRefCount &&2909!Context.getObjCIdType().isNull() &&2910(ReceiverType->isPointerType() ||2911ReceiverType->isIntegerType())) {2912// Implicitly convert integers and pointers to 'id' but emit a warning.2913// But not in ARC.2914Diag(Loc, diag::warn_bad_receiver_type) << ReceiverType << RecRange;2915if (ReceiverType->isPointerType()) {2916Receiver = SemaRef2917.ImpCastExprToType(Receiver, Context.getObjCIdType(),2918CK_CPointerToObjCPointerCast)2919.get();2920} else {2921// TODO: specialized warning on null receivers?2922bool IsNull = Receiver->isNullPointerConstant(Context,2923Expr::NPC_ValueDependentIsNull);2924CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;2925Receiver =2926SemaRef.ImpCastExprToType(Receiver, Context.getObjCIdType(), Kind)2927.get();2928}2929ReceiverType = Receiver->getType();2930} else if (getLangOpts().CPlusPlus) {2931// The receiver must be a complete type.2932if (SemaRef.RequireCompleteType(Loc, Receiver->getType(),2933diag::err_incomplete_receiver_type))2934return ExprError();29352936ExprResult result =2937SemaRef.PerformContextuallyConvertToObjCPointer(Receiver);2938if (result.isUsable()) {2939Receiver = result.get();2940ReceiverType = Receiver->getType();2941}2942}2943}29442945// There's a somewhat weird interaction here where we assume that we2946// won't actually have a method unless we also don't need to do some2947// of the more detailed type-checking on the receiver.29482949if (!Method) {2950// Handle messages to id and __kindof types (where we use the2951// global method pool).2952const ObjCObjectType *typeBound = nullptr;2953bool receiverIsIdLike = ReceiverType->isObjCIdOrObjectKindOfType(Context,2954typeBound);2955if (receiverIsIdLike || ReceiverType->isBlockPointerType() ||2956(Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {2957SmallVector<ObjCMethodDecl*, 4> Methods;2958// If we have a type bound, further filter the methods.2959CollectMultipleMethodsInGlobalPool(Sel, Methods, true/*InstanceFirst*/,2960true/*CheckTheOther*/, typeBound);2961if (!Methods.empty()) {2962// We choose the first method as the initial candidate, then try to2963// select a better one.2964Method = Methods[0];29652966if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(2967Sel, ArgsIn, Method->isInstanceMethod(), Methods))2968Method = BestMethod;29692970if (!AreMultipleMethodsInGlobalPool(Sel, Method,2971SourceRange(LBracLoc, RBracLoc),2972receiverIsIdLike, Methods))2973SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs);2974}2975} else if (ReceiverType->isObjCClassOrClassKindOfType() ||2976ReceiverType->isObjCQualifiedClassType()) {2977// Handle messages to Class.2978// We allow sending a message to a qualified Class ("Class<foo>"), which2979// is ok as long as one of the protocols implements the selector (if not,2980// warn).2981if (!ReceiverType->isObjCClassOrClassKindOfType()) {2982const ObjCObjectPointerType *QClassTy2983= ReceiverType->getAsObjCQualifiedClassType();2984// Search protocols for class methods.2985Method = LookupMethodInQualifiedType(Sel, QClassTy, false);2986if (!Method) {2987Method = LookupMethodInQualifiedType(Sel, QClassTy, true);2988// warn if instance method found for a Class message.2989if (Method && !isMethodDeclaredInRootProtocol(SemaRef, Method)) {2990Diag(SelLoc, diag::warn_instance_method_on_class_found)2991<< Method->getSelector() << Sel;2992Diag(Method->getLocation(), diag::note_method_declared_at)2993<< Method->getDeclName();2994}2995}2996} else {2997if (ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl()) {2998if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {2999// As a guess, try looking for the method in the current interface.3000// This very well may not produce the "right" method.30013002// First check the public methods in the class interface.3003Method = ClassDecl->lookupClassMethod(Sel);30043005if (!Method)3006Method = ClassDecl->lookupPrivateClassMethod(Sel);30073008if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs))3009return ExprError();3010}3011}3012if (!Method) {3013// If not messaging 'self', look for any factory method named 'Sel'.3014if (!Receiver || !isSelfExpr(Receiver)) {3015// If no class (factory) method was found, check if an _instance_3016// method of the same name exists in the root class only.3017SmallVector<ObjCMethodDecl*, 4> Methods;3018CollectMultipleMethodsInGlobalPool(Sel, Methods,3019false/*InstanceFirst*/,3020true/*CheckTheOther*/);3021if (!Methods.empty()) {3022// We choose the first method as the initial candidate, then try3023// to select a better one.3024Method = Methods[0];30253026// If we find an instance method, emit warning.3027if (Method->isInstanceMethod()) {3028if (const ObjCInterfaceDecl *ID =3029dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {3030if (ID->getSuperClass())3031Diag(SelLoc, diag::warn_root_inst_method_not_found)3032<< Sel << SourceRange(LBracLoc, RBracLoc);3033}3034}30353036if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(3037Sel, ArgsIn, Method->isInstanceMethod(), Methods))3038Method = BestMethod;3039}3040}3041}3042}3043} else {3044ObjCInterfaceDecl *ClassDecl = nullptr;30453046// We allow sending a message to a qualified ID ("id<foo>"), which is ok as3047// long as one of the protocols implements the selector (if not, warn).3048// And as long as message is not deprecated/unavailable (warn if it is).3049if (const ObjCObjectPointerType *QIdTy3050= ReceiverType->getAsObjCQualifiedIdType()) {3051// Search protocols for instance methods.3052Method = LookupMethodInQualifiedType(Sel, QIdTy, true);3053if (!Method)3054Method = LookupMethodInQualifiedType(Sel, QIdTy, false);3055if (Method && SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs))3056return ExprError();3057} else if (const ObjCObjectPointerType *OCIType3058= ReceiverType->getAsObjCInterfacePointerType()) {3059// We allow sending a message to a pointer to an interface (an object).3060ClassDecl = OCIType->getInterfaceDecl();30613062// Try to complete the type. Under ARC, this is a hard error from which3063// we don't try to recover.3064// FIXME: In the non-ARC case, this will still be a hard error if the3065// definition is found in a module that's not visible.3066const ObjCInterfaceDecl *forwardClass = nullptr;3067if (SemaRef.RequireCompleteType(3068Loc, OCIType->getPointeeType(),3069getLangOpts().ObjCAutoRefCount3070? diag::err_arc_receiver_forward_instance3071: diag::warn_receiver_forward_instance,3072RecRange)) {3073if (getLangOpts().ObjCAutoRefCount)3074return ExprError();30753076forwardClass = OCIType->getInterfaceDecl();3077Diag(Receiver ? Receiver->getBeginLoc() : SuperLoc,3078diag::note_receiver_is_id);3079Method = nullptr;3080} else {3081Method = ClassDecl->lookupInstanceMethod(Sel);3082}30833084if (!Method)3085// Search protocol qualifiers.3086Method = LookupMethodInQualifiedType(Sel, OCIType, true);30873088if (!Method) {3089// If we have implementations in scope, check "private" methods.3090Method = ClassDecl->lookupPrivateMethod(Sel);30913092if (!Method && getLangOpts().ObjCAutoRefCount) {3093Diag(SelLoc, diag::err_arc_may_not_respond)3094<< OCIType->getPointeeType() << Sel << RecRange3095<< SourceRange(SelectorLocs.front(), SelectorLocs.back());3096return ExprError();3097}30983099if (!Method && (!Receiver || !isSelfExpr(Receiver))) {3100// If we still haven't found a method, look in the global pool. This3101// behavior isn't very desirable, however we need it for GCC3102// compatibility. FIXME: should we deviate??3103if (OCIType->qual_empty()) {3104SmallVector<ObjCMethodDecl*, 4> Methods;3105CollectMultipleMethodsInGlobalPool(Sel, Methods,3106true/*InstanceFirst*/,3107false/*CheckTheOther*/);3108if (!Methods.empty()) {3109// We choose the first method as the initial candidate, then try3110// to select a better one.3111Method = Methods[0];31123113if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(3114Sel, ArgsIn, Method->isInstanceMethod(), Methods))3115Method = BestMethod;31163117AreMultipleMethodsInGlobalPool(Sel, Method,3118SourceRange(LBracLoc, RBracLoc),3119true/*receiverIdOrClass*/,3120Methods);3121}3122if (Method && !forwardClass)3123Diag(SelLoc, diag::warn_maynot_respond)3124<< OCIType->getInterfaceDecl()->getIdentifier()3125<< Sel << RecRange;3126}3127}3128}3129if (Method &&3130SemaRef.DiagnoseUseOfDecl(Method, SelectorSlotLocs, forwardClass))3131return ExprError();3132} else {3133// Reject other random receiver types (e.g. structs).3134Diag(Loc, diag::err_bad_receiver_type) << ReceiverType << RecRange;3135return ExprError();3136}3137}3138}31393140FunctionScopeInfo *DIFunctionScopeInfo =3141(Method && Method->getMethodFamily() == OMF_init)3142? SemaRef.getEnclosingFunction()3143: nullptr;31443145if (Method && Method->isDirectMethod()) {3146if (ReceiverType->isObjCIdType() && !isImplicit) {3147Diag(Receiver->getExprLoc(),3148diag::err_messaging_unqualified_id_with_direct_method);3149Diag(Method->getLocation(), diag::note_direct_method_declared_at)3150<< Method->getDeclName();3151}31523153// Under ARC, self can't be assigned, and doing a direct call to `self`3154// when it's a Class is hence safe. For other cases, we can't trust `self`3155// is what we think it is, so we reject it.3156if (ReceiverType->isObjCClassType() && !isImplicit &&3157!(Receiver->isObjCSelfExpr() && getLangOpts().ObjCAutoRefCount)) {3158{3159auto Builder = Diag(Receiver->getExprLoc(),3160diag::err_messaging_class_with_direct_method);3161if (Receiver->isObjCSelfExpr()) {3162Builder.AddFixItHint(FixItHint::CreateReplacement(3163RecRange, Method->getClassInterface()->getName()));3164}3165}3166Diag(Method->getLocation(), diag::note_direct_method_declared_at)3167<< Method->getDeclName();3168}31693170if (SuperLoc.isValid()) {3171{3172auto Builder =3173Diag(SuperLoc, diag::err_messaging_super_with_direct_method);3174if (ReceiverType->isObjCClassType()) {3175Builder.AddFixItHint(FixItHint::CreateReplacement(3176SuperLoc, Method->getClassInterface()->getName()));3177} else {3178Builder.AddFixItHint(FixItHint::CreateReplacement(SuperLoc, "self"));3179}3180}3181Diag(Method->getLocation(), diag::note_direct_method_declared_at)3182<< Method->getDeclName();3183}3184} else if (ReceiverType->isObjCIdType() && !isImplicit) {3185Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id);3186}31873188if (DIFunctionScopeInfo &&3189DIFunctionScopeInfo->ObjCIsDesignatedInit &&3190(SuperLoc.isValid() || isSelfExpr(Receiver))) {3191bool isDesignatedInitChain = false;3192if (SuperLoc.isValid()) {3193if (const ObjCObjectPointerType *3194OCIType = ReceiverType->getAsObjCInterfacePointerType()) {3195if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {3196// Either we know this is a designated initializer or we3197// conservatively assume it because we don't know for sure.3198if (!ID->declaresOrInheritsDesignatedInitializers() ||3199ID->isDesignatedInitializer(Sel)) {3200isDesignatedInitChain = true;3201DIFunctionScopeInfo->ObjCWarnForNoDesignatedInitChain = false;3202}3203}3204}3205}3206if (!isDesignatedInitChain) {3207const ObjCMethodDecl *InitMethod = nullptr;3208bool isDesignated =3209SemaRef.getCurMethodDecl()->isDesignatedInitializerForTheInterface(3210&InitMethod);3211assert(isDesignated && InitMethod);3212(void)isDesignated;3213Diag(SelLoc, SuperLoc.isValid() ?3214diag::warn_objc_designated_init_non_designated_init_call :3215diag::warn_objc_designated_init_non_super_designated_init_call);3216Diag(InitMethod->getLocation(),3217diag::note_objc_designated_init_marked_here);3218}3219}32203221if (DIFunctionScopeInfo &&3222DIFunctionScopeInfo->ObjCIsSecondaryInit &&3223(SuperLoc.isValid() || isSelfExpr(Receiver))) {3224if (SuperLoc.isValid()) {3225Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call);3226} else {3227DIFunctionScopeInfo->ObjCWarnForNoInitDelegation = false;3228}3229}32303231// Check the message arguments.3232unsigned NumArgs = ArgsIn.size();3233Expr **Args = ArgsIn.data();3234QualType ReturnType;3235ExprValueKind VK = VK_PRValue;3236bool ClassMessage = (ReceiverType->isObjCClassType() ||3237ReceiverType->isObjCQualifiedClassType());3238if (CheckMessageArgumentTypes(Receiver, ReceiverType,3239MultiExprArg(Args, NumArgs), Sel, SelectorLocs,3240Method, ClassMessage, SuperLoc.isValid(),3241LBracLoc, RBracLoc, RecRange, ReturnType, VK))3242return ExprError();32433244if (Method && !Method->getReturnType()->isVoidType() &&3245SemaRef.RequireCompleteType(3246LBracLoc, Method->getReturnType(),3247diag::err_illegal_message_expr_incomplete_type))3248return ExprError();32493250// In ARC, forbid the user from sending messages to3251// retain/release/autorelease/dealloc/retainCount explicitly.3252if (getLangOpts().ObjCAutoRefCount) {3253ObjCMethodFamily family =3254(Method ? Method->getMethodFamily() : Sel.getMethodFamily());3255switch (family) {3256case OMF_init:3257if (Method)3258checkInitMethod(Method, ReceiverType);3259break;32603261case OMF_None:3262case OMF_alloc:3263case OMF_copy:3264case OMF_finalize:3265case OMF_mutableCopy:3266case OMF_new:3267case OMF_self:3268case OMF_initialize:3269break;32703271case OMF_dealloc:3272case OMF_retain:3273case OMF_release:3274case OMF_autorelease:3275case OMF_retainCount:3276Diag(SelLoc, diag::err_arc_illegal_explicit_message)3277<< Sel << RecRange;3278break;32793280case OMF_performSelector:3281if (Method && NumArgs >= 1) {3282if (const auto *SelExp =3283dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens())) {3284Selector ArgSel = SelExp->getSelector();3285ObjCMethodDecl *SelMethod =3286LookupInstanceMethodInGlobalPool(ArgSel,3287SelExp->getSourceRange());3288if (!SelMethod)3289SelMethod =3290LookupFactoryMethodInGlobalPool(ArgSel,3291SelExp->getSourceRange());3292if (SelMethod) {3293ObjCMethodFamily SelFamily = SelMethod->getMethodFamily();3294switch (SelFamily) {3295case OMF_alloc:3296case OMF_copy:3297case OMF_mutableCopy:3298case OMF_new:3299case OMF_init:3300// Issue error, unless ns_returns_not_retained.3301if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) {3302// selector names a +1 method3303Diag(SelLoc,3304diag::err_arc_perform_selector_retains);3305Diag(SelMethod->getLocation(), diag::note_method_declared_at)3306<< SelMethod->getDeclName();3307}3308break;3309default:3310// +0 call. OK. unless ns_returns_retained.3311if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) {3312// selector names a +1 method3313Diag(SelLoc,3314diag::err_arc_perform_selector_retains);3315Diag(SelMethod->getLocation(), diag::note_method_declared_at)3316<< SelMethod->getDeclName();3317}3318break;3319}3320}3321} else {3322// error (may leak).3323Diag(SelLoc, diag::warn_arc_perform_selector_leaks);3324Diag(Args[0]->getExprLoc(), diag::note_used_here);3325}3326}3327break;3328}3329}33303331DiagnoseCStringFormatDirectiveInObjCAPI(SemaRef, Method, Sel, Args, NumArgs);33323333// Construct the appropriate ObjCMessageExpr instance.3334ObjCMessageExpr *Result;3335if (SuperLoc.isValid())3336Result = ObjCMessageExpr::Create(3337Context, ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/true,3338ReceiverType, Sel, SelectorLocs, Method, ArrayRef(Args, NumArgs),3339RBracLoc, isImplicit);3340else {3341Result = ObjCMessageExpr::Create(3342Context, ReturnType, VK, LBracLoc, Receiver, Sel, SelectorLocs, Method,3343ArrayRef(Args, NumArgs), RBracLoc, isImplicit);3344if (!isImplicit)3345checkCocoaAPI(SemaRef, Result);3346}3347if (Method) {3348bool IsClassObjectCall = ClassMessage;3349// 'self' message receivers in class methods should be treated as message3350// sends to the class object in order for the semantic checks to be3351// performed correctly. Messages to 'super' already count as class messages,3352// so they don't need to be handled here.3353if (Receiver && isSelfExpr(Receiver)) {3354if (const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>()) {3355if (OPT->getObjectType()->isObjCClass()) {3356if (const auto *CurMeth = SemaRef.getCurMethodDecl()) {3357IsClassObjectCall = true;3358ReceiverType =3359Context.getObjCInterfaceType(CurMeth->getClassInterface());3360}3361}3362}3363}3364checkFoundationAPI(SemaRef, SelLoc, Method, ArrayRef(Args, NumArgs),3365ReceiverType, IsClassObjectCall);3366}33673368if (getLangOpts().ObjCAutoRefCount) {3369// In ARC, annotate delegate init calls.3370if (Result->getMethodFamily() == OMF_init &&3371(SuperLoc.isValid() || isSelfExpr(Receiver))) {3372// Only consider init calls *directly* in init implementations,3373// not within blocks.3374ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext);3375if (method && method->getMethodFamily() == OMF_init) {3376// The implicit assignment to self means we also don't want to3377// consume the result.3378Result->setDelegateInitCall(true);3379return Result;3380}3381}33823383// In ARC, check for message sends which are likely to introduce3384// retain cycles.3385checkRetainCycles(Result);3386}33873388if (getLangOpts().ObjCWeak) {3389if (!isImplicit && Method) {3390if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) {3391bool IsWeak =3392Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak;3393if (!IsWeak && Sel.isUnarySelector())3394IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;3395if (IsWeak && !SemaRef.isUnevaluatedContext() &&3396!getDiagnostics().isIgnored(diag::warn_arc_repeated_use_of_weak,3397LBracLoc))3398SemaRef.getCurFunction()->recordUseOfWeak(Result, Prop);3399}3400}3401}34023403CheckObjCCircularContainer(Result);34043405return SemaRef.MaybeBindToTemporary(Result);3406}34073408static void RemoveSelectorFromWarningCache(SemaObjC &S, Expr *Arg) {3409if (ObjCSelectorExpr *OSE =3410dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) {3411Selector Sel = OSE->getSelector();3412SourceLocation Loc = OSE->getAtLoc();3413auto Pos = S.ReferencedSelectors.find(Sel);3414if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)3415S.ReferencedSelectors.erase(Pos);3416}3417}34183419// ActOnInstanceMessage - used for both unary and keyword messages.3420// ArgExprs is optional - if it is present, the number of expressions3421// is obtained from Sel.getNumArgs().3422ExprResult SemaObjC::ActOnInstanceMessage(Scope *S, Expr *Receiver,3423Selector Sel, SourceLocation LBracLoc,3424ArrayRef<SourceLocation> SelectorLocs,3425SourceLocation RBracLoc,3426MultiExprArg Args) {3427ASTContext &Context = getASTContext();3428if (!Receiver)3429return ExprError();34303431// A ParenListExpr can show up while doing error recovery with invalid code.3432if (isa<ParenListExpr>(Receiver)) {3433ExprResult Result =3434SemaRef.MaybeConvertParenListExprToParenExpr(S, Receiver);3435if (Result.isInvalid()) return ExprError();3436Receiver = Result.get();3437}34383439if (RespondsToSelectorSel.isNull()) {3440IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector");3441RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId);3442}3443if (Sel == RespondsToSelectorSel)3444RemoveSelectorFromWarningCache(*this, Args[0]);34453446return BuildInstanceMessage(Receiver, Receiver->getType(),3447/*SuperLoc=*/SourceLocation(), Sel,3448/*Method=*/nullptr, LBracLoc, SelectorLocs,3449RBracLoc, Args);3450}34513452enum ARCConversionTypeClass {3453/// int, void, struct A3454ACTC_none,34553456/// id, void (^)()3457ACTC_retainable,34583459/// id*, id***, void (^*)(),3460ACTC_indirectRetainable,34613462/// void* might be a normal C type, or it might a CF type.3463ACTC_voidPtr,34643465/// struct A*3466ACTC_coreFoundation3467};34683469static bool isAnyRetainable(ARCConversionTypeClass ACTC) {3470return (ACTC == ACTC_retainable ||3471ACTC == ACTC_coreFoundation ||3472ACTC == ACTC_voidPtr);3473}34743475static bool isAnyCLike(ARCConversionTypeClass ACTC) {3476return ACTC == ACTC_none ||3477ACTC == ACTC_voidPtr ||3478ACTC == ACTC_coreFoundation;3479}34803481static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) {3482bool isIndirect = false;34833484// Ignore an outermost reference type.3485if (const ReferenceType *ref = type->getAs<ReferenceType>()) {3486type = ref->getPointeeType();3487isIndirect = true;3488}34893490// Drill through pointers and arrays recursively.3491while (true) {3492if (const PointerType *ptr = type->getAs<PointerType>()) {3493type = ptr->getPointeeType();34943495// The first level of pointer may be the innermost pointer on a CF type.3496if (!isIndirect) {3497if (type->isVoidType()) return ACTC_voidPtr;3498if (type->isRecordType()) return ACTC_coreFoundation;3499}3500} else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) {3501type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0);3502} else {3503break;3504}3505isIndirect = true;3506}35073508if (isIndirect) {3509if (type->isObjCARCBridgableType())3510return ACTC_indirectRetainable;3511return ACTC_none;3512}35133514if (type->isObjCARCBridgableType())3515return ACTC_retainable;35163517return ACTC_none;3518}35193520namespace {3521/// A result from the cast checker.3522enum ACCResult {3523/// Cannot be casted.3524ACC_invalid,35253526/// Can be safely retained or not retained.3527ACC_bottom,35283529/// Can be casted at +0.3530ACC_plusZero,35313532/// Can be casted at +1.3533ACC_plusOne3534};3535ACCResult merge(ACCResult left, ACCResult right) {3536if (left == right) return left;3537if (left == ACC_bottom) return right;3538if (right == ACC_bottom) return left;3539return ACC_invalid;3540}35413542/// A checker which white-lists certain expressions whose conversion3543/// to or from retainable type would otherwise be forbidden in ARC.3544class ARCCastChecker : public StmtVisitor<ARCCastChecker, ACCResult> {3545typedef StmtVisitor<ARCCastChecker, ACCResult> super;35463547ASTContext &Context;3548ARCConversionTypeClass SourceClass;3549ARCConversionTypeClass TargetClass;3550bool Diagnose;35513552static bool isCFType(QualType type) {3553// Someday this can use ns_bridged. For now, it has to do this.3554return type->isCARCBridgableType();3555}35563557public:3558ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source,3559ARCConversionTypeClass target, bool diagnose)3560: Context(Context), SourceClass(source), TargetClass(target),3561Diagnose(diagnose) {}35623563using super::Visit;3564ACCResult Visit(Expr *e) {3565return super::Visit(e->IgnoreParens());3566}35673568ACCResult VisitStmt(Stmt *s) {3569return ACC_invalid;3570}35713572/// Null pointer constants can be casted however you please.3573ACCResult VisitExpr(Expr *e) {3574if (e->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))3575return ACC_bottom;3576return ACC_invalid;3577}35783579/// Objective-C string literals can be safely casted.3580ACCResult VisitObjCStringLiteral(ObjCStringLiteral *e) {3581// If we're casting to any retainable type, go ahead. Global3582// strings are immune to retains, so this is bottom.3583if (isAnyRetainable(TargetClass)) return ACC_bottom;35843585return ACC_invalid;3586}35873588/// Look through certain implicit and explicit casts.3589ACCResult VisitCastExpr(CastExpr *e) {3590switch (e->getCastKind()) {3591case CK_NullToPointer:3592return ACC_bottom;35933594case CK_NoOp:3595case CK_LValueToRValue:3596case CK_BitCast:3597case CK_CPointerToObjCPointerCast:3598case CK_BlockPointerToObjCPointerCast:3599case CK_AnyPointerToBlockPointerCast:3600return Visit(e->getSubExpr());36013602default:3603return ACC_invalid;3604}3605}36063607/// Look through unary extension.3608ACCResult VisitUnaryExtension(UnaryOperator *e) {3609return Visit(e->getSubExpr());3610}36113612/// Ignore the LHS of a comma operator.3613ACCResult VisitBinComma(BinaryOperator *e) {3614return Visit(e->getRHS());3615}36163617/// Conditional operators are okay if both sides are okay.3618ACCResult VisitConditionalOperator(ConditionalOperator *e) {3619ACCResult left = Visit(e->getTrueExpr());3620if (left == ACC_invalid) return ACC_invalid;3621return merge(left, Visit(e->getFalseExpr()));3622}36233624/// Look through pseudo-objects.3625ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) {3626// If we're getting here, we should always have a result.3627return Visit(e->getResultExpr());3628}36293630/// Statement expressions are okay if their result expression is okay.3631ACCResult VisitStmtExpr(StmtExpr *e) {3632return Visit(e->getSubStmt()->body_back());3633}36343635/// Some declaration references are okay.3636ACCResult VisitDeclRefExpr(DeclRefExpr *e) {3637VarDecl *var = dyn_cast<VarDecl>(e->getDecl());3638// References to global constants are okay.3639if (isAnyRetainable(TargetClass) &&3640isAnyRetainable(SourceClass) &&3641var &&3642!var->hasDefinition(Context) &&3643var->getType().isConstQualified()) {36443645// In system headers, they can also be assumed to be immune to retains.3646// These are things like 'kCFStringTransformToLatin'.3647if (Context.getSourceManager().isInSystemHeader(var->getLocation()))3648return ACC_bottom;36493650return ACC_plusZero;3651}36523653// Nothing else.3654return ACC_invalid;3655}36563657/// Some calls are okay.3658ACCResult VisitCallExpr(CallExpr *e) {3659if (FunctionDecl *fn = e->getDirectCallee())3660if (ACCResult result = checkCallToFunction(fn))3661return result;36623663return super::VisitCallExpr(e);3664}36653666ACCResult checkCallToFunction(FunctionDecl *fn) {3667// Require a CF*Ref return type.3668if (!isCFType(fn->getReturnType()))3669return ACC_invalid;36703671if (!isAnyRetainable(TargetClass))3672return ACC_invalid;36733674// Honor an explicit 'not retained' attribute.3675if (fn->hasAttr<CFReturnsNotRetainedAttr>())3676return ACC_plusZero;36773678// Honor an explicit 'retained' attribute, except that for3679// now we're not going to permit implicit handling of +1 results,3680// because it's a bit frightening.3681if (fn->hasAttr<CFReturnsRetainedAttr>())3682return Diagnose ? ACC_plusOne3683: ACC_invalid; // ACC_plusOne if we start accepting this36843685// Recognize this specific builtin function, which is used by CFSTR.3686unsigned builtinID = fn->getBuiltinID();3687if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString)3688return ACC_bottom;36893690// Otherwise, don't do anything implicit with an unaudited function.3691if (!fn->hasAttr<CFAuditedTransferAttr>())3692return ACC_invalid;36933694// Otherwise, it's +0 unless it follows the create convention.3695if (ento::coreFoundation::followsCreateRule(fn))3696return Diagnose ? ACC_plusOne3697: ACC_invalid; // ACC_plusOne if we start accepting this36983699return ACC_plusZero;3700}37013702ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) {3703return checkCallToMethod(e->getMethodDecl());3704}37053706ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) {3707ObjCMethodDecl *method;3708if (e->isExplicitProperty())3709method = e->getExplicitProperty()->getGetterMethodDecl();3710else3711method = e->getImplicitPropertyGetter();3712return checkCallToMethod(method);3713}37143715ACCResult checkCallToMethod(ObjCMethodDecl *method) {3716if (!method) return ACC_invalid;37173718// Check for message sends to functions returning CF types. We3719// just obey the Cocoa conventions with these, even though the3720// return type is CF.3721if (!isAnyRetainable(TargetClass) || !isCFType(method->getReturnType()))3722return ACC_invalid;37233724// If the method is explicitly marked not-retained, it's +0.3725if (method->hasAttr<CFReturnsNotRetainedAttr>())3726return ACC_plusZero;37273728// If the method is explicitly marked as returning retained, or its3729// selector follows a +1 Cocoa convention, treat it as +1.3730if (method->hasAttr<CFReturnsRetainedAttr>())3731return ACC_plusOne;37323733switch (method->getSelector().getMethodFamily()) {3734case OMF_alloc:3735case OMF_copy:3736case OMF_mutableCopy:3737case OMF_new:3738return ACC_plusOne;37393740default:3741// Otherwise, treat it as +0.3742return ACC_plusZero;3743}3744}3745};3746} // end anonymous namespace37473748bool SemaObjC::isKnownName(StringRef name) {3749ASTContext &Context = getASTContext();3750if (name.empty())3751return false;3752LookupResult R(SemaRef, &Context.Idents.get(name), SourceLocation(),3753Sema::LookupOrdinaryName);3754return SemaRef.LookupName(R, SemaRef.TUScope, false);3755}37563757template <typename DiagBuilderT>3758static void addFixitForObjCARCConversion(3759Sema &S, DiagBuilderT &DiagB, CheckedConversionKind CCK,3760SourceLocation afterLParen, QualType castType, Expr *castExpr,3761Expr *realCast, const char *bridgeKeyword, const char *CFBridgeName) {3762// We handle C-style and implicit casts here.3763switch (CCK) {3764case CheckedConversionKind::Implicit:3765case CheckedConversionKind::ForBuiltinOverloadedOp:3766case CheckedConversionKind::CStyleCast:3767case CheckedConversionKind::OtherCast:3768break;3769case CheckedConversionKind::FunctionalCast:3770return;3771}37723773if (CFBridgeName) {3774if (CCK == CheckedConversionKind::OtherCast) {3775if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {3776SourceRange range(NCE->getOperatorLoc(),3777NCE->getAngleBrackets().getEnd());3778SmallString<32> BridgeCall;37793780SourceManager &SM = S.getSourceManager();3781char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));3782if (Lexer::isAsciiIdentifierContinueChar(PrevChar, S.getLangOpts()))3783BridgeCall += ' ';37843785BridgeCall += CFBridgeName;3786DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall));3787}3788return;3789}3790Expr *castedE = castExpr;3791if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE))3792castedE = CCE->getSubExpr();3793castedE = castedE->IgnoreImpCasts();3794SourceRange range = castedE->getSourceRange();37953796SmallString<32> BridgeCall;37973798SourceManager &SM = S.getSourceManager();3799char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));3800if (Lexer::isAsciiIdentifierContinueChar(PrevChar, S.getLangOpts()))3801BridgeCall += ' ';38023803BridgeCall += CFBridgeName;38043805if (isa<ParenExpr>(castedE)) {3806DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),3807BridgeCall));3808} else {3809BridgeCall += '(';3810DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),3811BridgeCall));3812DiagB.AddFixItHint(FixItHint::CreateInsertion(3813S.getLocForEndOfToken(range.getEnd()),3814")"));3815}3816return;3817}38183819if (CCK == CheckedConversionKind::CStyleCast) {3820DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword));3821} else if (CCK == CheckedConversionKind::OtherCast) {3822if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {3823std::string castCode = "(";3824castCode += bridgeKeyword;3825castCode += castType.getAsString();3826castCode += ")";3827SourceRange Range(NCE->getOperatorLoc(),3828NCE->getAngleBrackets().getEnd());3829DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode));3830}3831} else {3832std::string castCode = "(";3833castCode += bridgeKeyword;3834castCode += castType.getAsString();3835castCode += ")";3836Expr *castedE = castExpr->IgnoreImpCasts();3837SourceRange range = castedE->getSourceRange();3838if (isa<ParenExpr>(castedE)) {3839DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),3840castCode));3841} else {3842castCode += "(";3843DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),3844castCode));3845DiagB.AddFixItHint(FixItHint::CreateInsertion(3846S.getLocForEndOfToken(range.getEnd()),3847")"));3848}3849}3850}38513852template <typename T>3853static inline T *getObjCBridgeAttr(const TypedefType *TD) {3854TypedefNameDecl *TDNDecl = TD->getDecl();3855QualType QT = TDNDecl->getUnderlyingType();3856if (QT->isPointerType()) {3857QT = QT->getPointeeType();3858if (const RecordType *RT = QT->getAs<RecordType>()) {3859for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {3860if (auto *attr = Redecl->getAttr<T>())3861return attr;3862}3863}3864}3865return nullptr;3866}38673868static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T,3869TypedefNameDecl *&TDNDecl) {3870while (const auto *TD = T->getAs<TypedefType>()) {3871TDNDecl = TD->getDecl();3872if (ObjCBridgeRelatedAttr *ObjCBAttr =3873getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD))3874return ObjCBAttr;3875T = TDNDecl->getUnderlyingType();3876}3877return nullptr;3878}38793880static void diagnoseObjCARCConversion(Sema &S, SourceRange castRange,3881QualType castType,3882ARCConversionTypeClass castACTC,3883Expr *castExpr, Expr *realCast,3884ARCConversionTypeClass exprACTC,3885CheckedConversionKind CCK) {3886SourceLocation loc =3887(castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());38883889if (S.makeUnavailableInSystemHeader(loc,3890UnavailableAttr::IR_ARCForbiddenConversion))3891return;38923893QualType castExprType = castExpr->getType();3894// Defer emitting a diagnostic for bridge-related casts; that will be3895// handled by CheckObjCBridgeRelatedConversions.3896TypedefNameDecl *TDNDecl = nullptr;3897if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&3898ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) ||3899(exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&3900ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl)))3901return;39023903unsigned srcKind = 0;3904switch (exprACTC) {3905case ACTC_none:3906case ACTC_coreFoundation:3907case ACTC_voidPtr:3908srcKind = (castExprType->isPointerType() ? 1 : 0);3909break;3910case ACTC_retainable:3911srcKind = (castExprType->isBlockPointerType() ? 2 : 3);3912break;3913case ACTC_indirectRetainable:3914srcKind = 4;3915break;3916}39173918// Check whether this could be fixed with a bridge cast.3919SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin());3920SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;39213922unsigned convKindForDiag = Sema::isCast(CCK) ? 0 : 1;39233924// Bridge from an ARC type to a CF type.3925if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {39263927S.Diag(loc, diag::err_arc_cast_requires_bridge)3928<< convKindForDiag3929<< 2 // of C pointer type3930<< castExprType3931<< unsigned(castType->isBlockPointerType()) // to ObjC|block type3932<< castType3933<< castRange3934<< castExpr->getSourceRange();3935bool br = S.ObjC().isKnownName("CFBridgingRelease");3936ACCResult CreateRule =3937ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);3938assert(CreateRule != ACC_bottom && "This cast should already be accepted.");3939if (CreateRule != ACC_plusOne)3940{3941auto DiagB = (CCK != CheckedConversionKind::OtherCast)3942? S.Diag(noteLoc, diag::note_arc_bridge)3943: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);39443945addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,3946castType, castExpr, realCast, "__bridge ",3947nullptr);3948}3949if (CreateRule != ACC_plusZero)3950{3951auto DiagB = (CCK == CheckedConversionKind::OtherCast && !br)3952? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer)3953<< castExprType3954: S.Diag(br ? castExpr->getExprLoc() : noteLoc,3955diag::note_arc_bridge_transfer)3956<< castExprType << br;39573958addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,3959castType, castExpr, realCast, "__bridge_transfer ",3960br ? "CFBridgingRelease" : nullptr);3961}39623963return;3964}39653966// Bridge from a CF type to an ARC type.3967if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {3968bool br = S.ObjC().isKnownName("CFBridgingRetain");3969S.Diag(loc, diag::err_arc_cast_requires_bridge)3970<< convKindForDiag3971<< unsigned(castExprType->isBlockPointerType()) // of ObjC|block type3972<< castExprType3973<< 2 // to C pointer type3974<< castType3975<< castRange3976<< castExpr->getSourceRange();3977ACCResult CreateRule =3978ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);3979assert(CreateRule != ACC_bottom && "This cast should already be accepted.");3980if (CreateRule != ACC_plusOne)3981{3982auto DiagB = (CCK != CheckedConversionKind::OtherCast)3983? S.Diag(noteLoc, diag::note_arc_bridge)3984: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);3985addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,3986castType, castExpr, realCast, "__bridge ",3987nullptr);3988}3989if (CreateRule != ACC_plusZero)3990{3991auto DiagB = (CCK == CheckedConversionKind::OtherCast && !br)3992? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained)3993<< castType3994: S.Diag(br ? castExpr->getExprLoc() : noteLoc,3995diag::note_arc_bridge_retained)3996<< castType << br;39973998addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,3999castType, castExpr, realCast, "__bridge_retained ",4000br ? "CFBridgingRetain" : nullptr);4001}40024003return;4004}40054006S.Diag(loc, diag::err_arc_mismatched_cast)4007<< !convKindForDiag4008<< srcKind << castExprType << castType4009<< castRange << castExpr->getSourceRange();4010}40114012template <typename TB>4013static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,4014bool &HadTheAttribute, bool warn) {4015QualType T = castExpr->getType();4016HadTheAttribute = false;4017while (const auto *TD = T->getAs<TypedefType>()) {4018TypedefNameDecl *TDNDecl = TD->getDecl();4019if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {4020if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {4021HadTheAttribute = true;4022if (Parm->isStr("id"))4023return true;40244025// Check for an existing type with this name.4026LookupResult R(S, DeclarationName(Parm), SourceLocation(),4027Sema::LookupOrdinaryName);4028if (S.LookupName(R, S.TUScope)) {4029NamedDecl *Target = R.getFoundDecl();4030if (Target && isa<ObjCInterfaceDecl>(Target)) {4031ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Target);4032if (const ObjCObjectPointerType *InterfacePointerType =4033castType->getAsObjCInterfacePointerType()) {4034ObjCInterfaceDecl *CastClass4035= InterfacePointerType->getObjectType()->getInterface();4036if ((CastClass == ExprClass) ||4037(CastClass && CastClass->isSuperClassOf(ExprClass)))4038return true;4039if (warn)4040S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge)4041<< T << Target->getName() << castType->getPointeeType();4042return false;4043} else if (castType->isObjCIdType() ||4044(S.Context.ObjCObjectAdoptsQTypeProtocols(4045castType, ExprClass)))4046// ok to cast to 'id'.4047// casting to id<p-list> is ok if bridge type adopts all of4048// p-list protocols.4049return true;4050else {4051if (warn) {4052S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge)4053<< T << Target->getName() << castType;4054S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4055S.Diag(Target->getBeginLoc(), diag::note_declared_at);4056}4057return false;4058}4059}4060} else if (!castType->isObjCIdType()) {4061S.Diag(castExpr->getBeginLoc(),4062diag::err_objc_cf_bridged_not_interface)4063<< castExpr->getType() << Parm;4064S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4065}4066return true;4067}4068return false;4069}4070T = TDNDecl->getUnderlyingType();4071}4072return true;4073}40744075template <typename TB>4076static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,4077bool &HadTheAttribute, bool warn) {4078QualType T = castType;4079HadTheAttribute = false;4080while (const auto *TD = T->getAs<TypedefType>()) {4081TypedefNameDecl *TDNDecl = TD->getDecl();4082if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {4083if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {4084HadTheAttribute = true;4085if (Parm->isStr("id"))4086return true;40874088NamedDecl *Target = nullptr;4089// Check for an existing type with this name.4090LookupResult R(S, DeclarationName(Parm), SourceLocation(),4091Sema::LookupOrdinaryName);4092if (S.LookupName(R, S.TUScope)) {4093Target = R.getFoundDecl();4094if (Target && isa<ObjCInterfaceDecl>(Target)) {4095ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target);4096if (const ObjCObjectPointerType *InterfacePointerType =4097castExpr->getType()->getAsObjCInterfacePointerType()) {4098ObjCInterfaceDecl *ExprClass4099= InterfacePointerType->getObjectType()->getInterface();4100if ((CastClass == ExprClass) ||4101(ExprClass && CastClass->isSuperClassOf(ExprClass)))4102return true;4103if (warn) {4104S.Diag(castExpr->getBeginLoc(),4105diag::warn_objc_invalid_bridge_to_cf)4106<< castExpr->getType()->getPointeeType() << T;4107S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4108}4109return false;4110} else if (castExpr->getType()->isObjCIdType() ||4111(S.Context.QIdProtocolsAdoptObjCObjectProtocols(4112castExpr->getType(), CastClass)))4113// ok to cast an 'id' expression to a CFtype.4114// ok to cast an 'id<plist>' expression to CFtype provided plist4115// adopts all of CFtype's ObjetiveC's class plist.4116return true;4117else {4118if (warn) {4119S.Diag(castExpr->getBeginLoc(),4120diag::warn_objc_invalid_bridge_to_cf)4121<< castExpr->getType() << castType;4122S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4123S.Diag(Target->getBeginLoc(), diag::note_declared_at);4124}4125return false;4126}4127}4128}4129S.Diag(castExpr->getBeginLoc(),4130diag::err_objc_ns_bridged_invalid_cfobject)4131<< castExpr->getType() << castType;4132S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4133if (Target)4134S.Diag(Target->getBeginLoc(), diag::note_declared_at);4135return true;4136}4137return false;4138}4139T = TDNDecl->getUnderlyingType();4140}4141return true;4142}41434144void SemaObjC::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {4145if (!getLangOpts().ObjC)4146return;4147// warn in presence of __bridge casting to or from a toll free bridge cast.4148ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType());4149ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);4150if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) {4151bool HasObjCBridgeAttr;4152bool ObjCBridgeAttrWillNotWarn = CheckObjCBridgeNSCast<ObjCBridgeAttr>(4153SemaRef, castType, castExpr, HasObjCBridgeAttr, false);4154if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)4155return;4156bool HasObjCBridgeMutableAttr;4157bool ObjCBridgeMutableAttrWillNotWarn =4158CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(4159SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, false);4160if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)4161return;41624163if (HasObjCBridgeAttr)4164CheckObjCBridgeNSCast<ObjCBridgeAttr>(SemaRef, castType, castExpr,4165HasObjCBridgeAttr, true);4166else if (HasObjCBridgeMutableAttr)4167CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(4168SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, true);4169}4170else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) {4171bool HasObjCBridgeAttr;4172bool ObjCBridgeAttrWillNotWarn = CheckObjCBridgeCFCast<ObjCBridgeAttr>(4173SemaRef, castType, castExpr, HasObjCBridgeAttr, false);4174if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)4175return;4176bool HasObjCBridgeMutableAttr;4177bool ObjCBridgeMutableAttrWillNotWarn =4178CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(4179SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, false);4180if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)4181return;41824183if (HasObjCBridgeAttr)4184CheckObjCBridgeCFCast<ObjCBridgeAttr>(SemaRef, castType, castExpr,4185HasObjCBridgeAttr, true);4186else if (HasObjCBridgeMutableAttr)4187CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(4188SemaRef, castType, castExpr, HasObjCBridgeMutableAttr, true);4189}4190}41914192void SemaObjC::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) {4193QualType SrcType = castExpr->getType();4194if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(castExpr)) {4195if (PRE->isExplicitProperty()) {4196if (ObjCPropertyDecl *PDecl = PRE->getExplicitProperty())4197SrcType = PDecl->getType();4198}4199else if (PRE->isImplicitProperty()) {4200if (ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter())4201SrcType = Getter->getReturnType();4202}4203}42044205ARCConversionTypeClass srcExprACTC = classifyTypeForARCConversion(SrcType);4206ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType);4207if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation)4208return;4209CheckObjCBridgeRelatedConversions(castExpr->getBeginLoc(), castType, SrcType,4210castExpr);4211}42124213bool SemaObjC::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,4214CastKind &Kind) {4215if (!getLangOpts().ObjC)4216return false;4217ARCConversionTypeClass exprACTC =4218classifyTypeForARCConversion(castExpr->getType());4219ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);4220if ((castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) ||4221(castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable)) {4222CheckTollFreeBridgeCast(castType, castExpr);4223Kind = (castACTC == ACTC_coreFoundation) ? CK_BitCast4224: CK_CPointerToObjCPointerCast;4225return true;4226}4227return false;4228}42294230bool SemaObjC::checkObjCBridgeRelatedComponents(4231SourceLocation Loc, QualType DestType, QualType SrcType,4232ObjCInterfaceDecl *&RelatedClass, ObjCMethodDecl *&ClassMethod,4233ObjCMethodDecl *&InstanceMethod, TypedefNameDecl *&TDNDecl, bool CfToNs,4234bool Diagnose) {4235ASTContext &Context = getASTContext();4236QualType T = CfToNs ? SrcType : DestType;4237ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl);4238if (!ObjCBAttr)4239return false;42404241IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();4242IdentifierInfo *CMId = ObjCBAttr->getClassMethod();4243IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();4244if (!RCId)4245return false;4246NamedDecl *Target = nullptr;4247// Check for an existing type with this name.4248LookupResult R(SemaRef, DeclarationName(RCId), SourceLocation(),4249Sema::LookupOrdinaryName);4250if (!SemaRef.LookupName(R, SemaRef.TUScope)) {4251if (Diagnose) {4252Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId4253<< SrcType << DestType;4254Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4255}4256return false;4257}4258Target = R.getFoundDecl();4259if (Target && isa<ObjCInterfaceDecl>(Target))4260RelatedClass = cast<ObjCInterfaceDecl>(Target);4261else {4262if (Diagnose) {4263Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId4264<< SrcType << DestType;4265Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4266if (Target)4267Diag(Target->getBeginLoc(), diag::note_declared_at);4268}4269return false;4270}42714272// Check for an existing class method with the given selector name.4273if (CfToNs && CMId) {4274Selector Sel = Context.Selectors.getUnarySelector(CMId);4275ClassMethod = RelatedClass->lookupMethod(Sel, false);4276if (!ClassMethod) {4277if (Diagnose) {4278Diag(Loc, diag::err_objc_bridged_related_known_method)4279<< SrcType << DestType << Sel << false;4280Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4281}4282return false;4283}4284}42854286// Check for an existing instance method with the given selector name.4287if (!CfToNs && IMId) {4288Selector Sel = Context.Selectors.getNullarySelector(IMId);4289InstanceMethod = RelatedClass->lookupMethod(Sel, true);4290if (!InstanceMethod) {4291if (Diagnose) {4292Diag(Loc, diag::err_objc_bridged_related_known_method)4293<< SrcType << DestType << Sel << true;4294Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);4295}4296return false;4297}4298}4299return true;4300}43014302bool SemaObjC::CheckObjCBridgeRelatedConversions(SourceLocation Loc,4303QualType DestType,4304QualType SrcType,4305Expr *&SrcExpr,4306bool Diagnose) {4307ASTContext &Context = getASTContext();4308ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType);4309ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType);4310bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);4311bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);4312if (!CfToNs && !NsToCf)4313return false;43144315ObjCInterfaceDecl *RelatedClass;4316ObjCMethodDecl *ClassMethod = nullptr;4317ObjCMethodDecl *InstanceMethod = nullptr;4318TypedefNameDecl *TDNDecl = nullptr;4319if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,4320ClassMethod, InstanceMethod, TDNDecl,4321CfToNs, Diagnose))4322return false;43234324if (CfToNs) {4325// Implicit conversion from CF to ObjC object is needed.4326if (ClassMethod) {4327if (Diagnose) {4328std::string ExpressionString = "[";4329ExpressionString += RelatedClass->getNameAsString();4330ExpressionString += " ";4331ExpressionString += ClassMethod->getSelector().getAsString();4332SourceLocation SrcExprEndLoc =4333SemaRef.getLocForEndOfToken(SrcExpr->getEndLoc());4334// Provide a fixit: [RelatedClass ClassMethod SrcExpr]4335Diag(Loc, diag::err_objc_bridged_related_known_method)4336<< SrcType << DestType << ClassMethod->getSelector() << false4337<< FixItHint::CreateInsertion(SrcExpr->getBeginLoc(),4338ExpressionString)4339<< FixItHint::CreateInsertion(SrcExprEndLoc, "]");4340Diag(RelatedClass->getBeginLoc(), diag::note_declared_at);4341Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);43424343QualType receiverType = Context.getObjCInterfaceType(RelatedClass);4344// Argument.4345Expr *args[] = { SrcExpr };4346ExprResult msg = BuildClassMessageImplicit(receiverType, false,4347ClassMethod->getLocation(),4348ClassMethod->getSelector(), ClassMethod,4349MultiExprArg(args, 1));4350SrcExpr = msg.get();4351}4352return true;4353}4354}4355else {4356// Implicit conversion from ObjC type to CF object is needed.4357if (InstanceMethod) {4358if (Diagnose) {4359std::string ExpressionString;4360SourceLocation SrcExprEndLoc =4361SemaRef.getLocForEndOfToken(SrcExpr->getEndLoc());4362if (InstanceMethod->isPropertyAccessor())4363if (const ObjCPropertyDecl *PDecl =4364InstanceMethod->findPropertyDecl()) {4365// fixit: ObjectExpr.propertyname when it is aproperty accessor.4366ExpressionString = ".";4367ExpressionString += PDecl->getNameAsString();4368Diag(Loc, diag::err_objc_bridged_related_known_method)4369<< SrcType << DestType << InstanceMethod->getSelector() << true4370<< FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);4371}4372if (ExpressionString.empty()) {4373// Provide a fixit: [ObjectExpr InstanceMethod]4374ExpressionString = " ";4375ExpressionString += InstanceMethod->getSelector().getAsString();4376ExpressionString += "]";43774378Diag(Loc, diag::err_objc_bridged_related_known_method)4379<< SrcType << DestType << InstanceMethod->getSelector() << true4380<< FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "[")4381<< FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);4382}4383Diag(RelatedClass->getBeginLoc(), diag::note_declared_at);4384Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);43854386ExprResult msg = BuildInstanceMessageImplicit(4387SrcExpr, SrcType, InstanceMethod->getLocation(),4388InstanceMethod->getSelector(), InstanceMethod, std::nullopt);4389SrcExpr = msg.get();4390}4391return true;4392}4393}4394return false;4395}43964397SemaObjC::ARCConversionResult4398SemaObjC::CheckObjCConversion(SourceRange castRange, QualType castType,4399Expr *&castExpr, CheckedConversionKind CCK,4400bool Diagnose, bool DiagnoseCFAudited,4401BinaryOperatorKind Opc) {4402ASTContext &Context = getASTContext();4403QualType castExprType = castExpr->getType();44044405// For the purposes of the classification, we assume reference types4406// will bind to temporaries.4407QualType effCastType = castType;4408if (const ReferenceType *ref = castType->getAs<ReferenceType>())4409effCastType = ref->getPointeeType();44104411ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType);4412ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType);4413if (exprACTC == castACTC) {4414// Check for viability and report error if casting an rvalue to a4415// life-time qualifier.4416if (castACTC == ACTC_retainable &&4417(CCK == CheckedConversionKind::CStyleCast ||4418CCK == CheckedConversionKind::OtherCast) &&4419castType != castExprType) {4420const Type *DT = castType.getTypePtr();4421QualType QDT = castType;4422// We desugar some types but not others. We ignore those4423// that cannot happen in a cast; i.e. auto, and those which4424// should not be de-sugared; i.e typedef.4425if (const ParenType *PT = dyn_cast<ParenType>(DT))4426QDT = PT->desugar();4427else if (const TypeOfType *TP = dyn_cast<TypeOfType>(DT))4428QDT = TP->desugar();4429else if (const AttributedType *AT = dyn_cast<AttributedType>(DT))4430QDT = AT->desugar();4431if (QDT != castType &&4432QDT.getObjCLifetime() != Qualifiers::OCL_None) {4433if (Diagnose) {4434SourceLocation loc = (castRange.isValid() ? castRange.getBegin()4435: castExpr->getExprLoc());4436Diag(loc, diag::err_arc_nolifetime_behavior);4437}4438return ACR_error;4439}4440}4441return ACR_okay;4442}44434444// The life-time qualifier cast check above is all we need for ObjCWeak.4445// ObjCAutoRefCount has more restrictions on what is legal.4446if (!getLangOpts().ObjCAutoRefCount)4447return ACR_okay;44484449if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay;44504451// Allow all of these types to be cast to integer types (but not4452// vice-versa).4453if (castACTC == ACTC_none && castType->isIntegralType(Context))4454return ACR_okay;44554456// Allow casts between pointers to lifetime types (e.g., __strong id*)4457// and pointers to void (e.g., cv void *). Casting from void* to lifetime*4458// must be explicit.4459// Allow conversions between pointers to lifetime types and coreFoundation4460// pointers too, but only when the conversions are explicit.4461if (exprACTC == ACTC_indirectRetainable &&4462(castACTC == ACTC_voidPtr ||4463(castACTC == ACTC_coreFoundation && SemaRef.isCast(CCK))))4464return ACR_okay;4465if (castACTC == ACTC_indirectRetainable &&4466(exprACTC == ACTC_voidPtr || exprACTC == ACTC_coreFoundation) &&4467SemaRef.isCast(CCK))4468return ACR_okay;44694470switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {4471// For invalid casts, fall through.4472case ACC_invalid:4473break;44744475// Do nothing for both bottom and +0.4476case ACC_bottom:4477case ACC_plusZero:4478return ACR_okay;44794480// If the result is +1, consume it here.4481case ACC_plusOne:4482castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),4483CK_ARCConsumeObject, castExpr, nullptr,4484VK_PRValue, FPOptionsOverride());4485SemaRef.Cleanup.setExprNeedsCleanups(true);4486return ACR_okay;4487}44884489// If this is a non-implicit cast from id or block type to a4490// CoreFoundation type, delay complaining in case the cast is used4491// in an acceptable context.4492if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) &&4493SemaRef.isCast(CCK))4494return ACR_unbridged;44954496// Issue a diagnostic about a missing @-sign when implicit casting a cstring4497// to 'NSString *', instead of falling through to report a "bridge cast"4498// diagnostic.4499if (castACTC == ACTC_retainable && exprACTC == ACTC_none &&4500CheckConversionToObjCLiteral(castType, castExpr, Diagnose))4501return ACR_error;45024503// Do not issue "bridge cast" diagnostic when implicit casting4504// a retainable object to a CF type parameter belonging to an audited4505// CF API function. Let caller issue a normal type mismatched diagnostic4506// instead.4507if ((!DiagnoseCFAudited || exprACTC != ACTC_retainable ||4508castACTC != ACTC_coreFoundation) &&4509!(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable &&4510(Opc == BO_NE || Opc == BO_EQ))) {4511if (Diagnose)4512diagnoseObjCARCConversion(SemaRef, castRange, castType, castACTC,4513castExpr, castExpr, exprACTC, CCK);4514return ACR_error;4515}4516return ACR_okay;4517}45184519/// Given that we saw an expression with the ARCUnbridgedCastTy4520/// placeholder type, complain bitterly.4521void SemaObjC::diagnoseARCUnbridgedCast(Expr *e) {4522// We expect the spurious ImplicitCastExpr to already have been stripped.4523assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));4524CastExpr *realCast = cast<CastExpr>(e->IgnoreParens());45254526SourceRange castRange;4527QualType castType;4528CheckedConversionKind CCK;45294530if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) {4531castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc());4532castType = cast->getTypeAsWritten();4533CCK = CheckedConversionKind::CStyleCast;4534} else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) {4535castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange();4536castType = cast->getTypeAsWritten();4537CCK = CheckedConversionKind::OtherCast;4538} else {4539llvm_unreachable("Unexpected ImplicitCastExpr");4540}45414542ARCConversionTypeClass castACTC =4543classifyTypeForARCConversion(castType.getNonReferenceType());45444545Expr *castExpr = realCast->getSubExpr();4546assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);45474548diagnoseObjCARCConversion(SemaRef, castRange, castType, castACTC, castExpr,4549realCast, ACTC_retainable, CCK);4550}45514552/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast4553/// type, remove the placeholder cast.4554Expr *SemaObjC::stripARCUnbridgedCast(Expr *e) {4555assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));4556ASTContext &Context = getASTContext();45574558if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) {4559Expr *sub = stripARCUnbridgedCast(pe->getSubExpr());4560return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub);4561} else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {4562assert(uo->getOpcode() == UO_Extension);4563Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());4564return UnaryOperator::Create(Context, sub, UO_Extension, sub->getType(),4565sub->getValueKind(), sub->getObjectKind(),4566uo->getOperatorLoc(), false,4567SemaRef.CurFPFeatureOverrides());4568} else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {4569assert(!gse->isResultDependent());4570assert(!gse->isTypePredicate());45714572unsigned n = gse->getNumAssocs();4573SmallVector<Expr *, 4> subExprs;4574SmallVector<TypeSourceInfo *, 4> subTypes;4575subExprs.reserve(n);4576subTypes.reserve(n);4577for (const GenericSelectionExpr::Association assoc : gse->associations()) {4578subTypes.push_back(assoc.getTypeSourceInfo());4579Expr *sub = assoc.getAssociationExpr();4580if (assoc.isSelected())4581sub = stripARCUnbridgedCast(sub);4582subExprs.push_back(sub);4583}45844585return GenericSelectionExpr::Create(4586Context, gse->getGenericLoc(), gse->getControllingExpr(), subTypes,4587subExprs, gse->getDefaultLoc(), gse->getRParenLoc(),4588gse->containsUnexpandedParameterPack(), gse->getResultIndex());4589} else {4590assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!");4591return cast<ImplicitCastExpr>(e)->getSubExpr();4592}4593}45944595bool SemaObjC::CheckObjCARCUnavailableWeakConversion(QualType castType,4596QualType exprType) {4597ASTContext &Context = getASTContext();4598QualType canCastType =4599Context.getCanonicalType(castType).getUnqualifiedType();4600QualType canExprType =4601Context.getCanonicalType(exprType).getUnqualifiedType();4602if (isa<ObjCObjectPointerType>(canCastType) &&4603castType.getObjCLifetime() == Qualifiers::OCL_Weak &&4604canExprType->isObjCObjectPointerType()) {4605if (const ObjCObjectPointerType *ObjT =4606canExprType->getAs<ObjCObjectPointerType>())4607if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl())4608return !ObjI->isArcWeakrefUnavailable();4609}4610return true;4611}46124613/// Look for an ObjCReclaimReturnedObject cast and destroy it.4614static Expr *maybeUndoReclaimObject(Expr *e) {4615Expr *curExpr = e, *prevExpr = nullptr;46164617// Walk down the expression until we hit an implicit cast of kind4618// ARCReclaimReturnedObject or an Expr that is neither a Paren nor a Cast.4619while (true) {4620if (auto *pe = dyn_cast<ParenExpr>(curExpr)) {4621prevExpr = curExpr;4622curExpr = pe->getSubExpr();4623continue;4624}46254626if (auto *ce = dyn_cast<CastExpr>(curExpr)) {4627if (auto *ice = dyn_cast<ImplicitCastExpr>(ce))4628if (ice->getCastKind() == CK_ARCReclaimReturnedObject) {4629if (!prevExpr)4630return ice->getSubExpr();4631if (auto *pe = dyn_cast<ParenExpr>(prevExpr))4632pe->setSubExpr(ice->getSubExpr());4633else4634cast<CastExpr>(prevExpr)->setSubExpr(ice->getSubExpr());4635return e;4636}46374638prevExpr = curExpr;4639curExpr = ce->getSubExpr();4640continue;4641}46424643// Break out of the loop if curExpr is neither a Paren nor a Cast.4644break;4645}46464647return e;4648}46494650ExprResult SemaObjC::BuildObjCBridgedCast(SourceLocation LParenLoc,4651ObjCBridgeCastKind Kind,4652SourceLocation BridgeKeywordLoc,4653TypeSourceInfo *TSInfo,4654Expr *SubExpr) {4655ASTContext &Context = getASTContext();4656ExprResult SubResult = SemaRef.UsualUnaryConversions(SubExpr);4657if (SubResult.isInvalid()) return ExprError();4658SubExpr = SubResult.get();46594660QualType T = TSInfo->getType();4661QualType FromType = SubExpr->getType();46624663CastKind CK;46644665bool MustConsume = false;4666if (T->isDependentType() || SubExpr->isTypeDependent()) {4667// Okay: we'll build a dependent expression type.4668CK = CK_Dependent;4669} else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) {4670// Casting CF -> id4671CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast4672: CK_CPointerToObjCPointerCast);4673switch (Kind) {4674case OBC_Bridge:4675break;46764677case OBC_BridgeRetained: {4678bool br = isKnownName("CFBridgingRelease");4679Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)4680<< 24681<< FromType4682<< (T->isBlockPointerType()? 1 : 0)4683<< T4684<< SubExpr->getSourceRange()4685<< Kind;4686Diag(BridgeKeywordLoc, diag::note_arc_bridge)4687<< FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge");4688Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer)4689<< FromType << br4690<< FixItHint::CreateReplacement(BridgeKeywordLoc,4691br ? "CFBridgingRelease "4692: "__bridge_transfer ");46934694Kind = OBC_Bridge;4695break;4696}46974698case OBC_BridgeTransfer:4699// We must consume the Objective-C object produced by the cast.4700MustConsume = true;4701break;4702}4703} else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) {4704// Okay: id -> CF4705CK = CK_BitCast;4706switch (Kind) {4707case OBC_Bridge:4708// Reclaiming a value that's going to be __bridge-casted to CF4709// is very dangerous, so we don't do it.4710SubExpr = maybeUndoReclaimObject(SubExpr);4711break;47124713case OBC_BridgeRetained:4714// Produce the object before casting it.4715SubExpr = ImplicitCastExpr::Create(Context, FromType, CK_ARCProduceObject,4716SubExpr, nullptr, VK_PRValue,4717FPOptionsOverride());4718break;47194720case OBC_BridgeTransfer: {4721bool br = isKnownName("CFBridgingRetain");4722Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)4723<< (FromType->isBlockPointerType()? 1 : 0)4724<< FromType4725<< 24726<< T4727<< SubExpr->getSourceRange()4728<< Kind;47294730Diag(BridgeKeywordLoc, diag::note_arc_bridge)4731<< FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge ");4732Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained)4733<< T << br4734<< FixItHint::CreateReplacement(BridgeKeywordLoc,4735br ? "CFBridgingRetain " : "__bridge_retained");47364737Kind = OBC_Bridge;4738break;4739}4740}4741} else {4742Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible)4743<< FromType << T << Kind4744<< SubExpr->getSourceRange()4745<< TSInfo->getTypeLoc().getSourceRange();4746return ExprError();4747}47484749Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK,4750BridgeKeywordLoc,4751TSInfo, SubExpr);47524753if (MustConsume) {4754SemaRef.Cleanup.setExprNeedsCleanups(true);4755Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,4756nullptr, VK_PRValue, FPOptionsOverride());4757}47584759return Result;4760}47614762ExprResult SemaObjC::ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc,4763ObjCBridgeCastKind Kind,4764SourceLocation BridgeKeywordLoc,4765ParsedType Type,4766SourceLocation RParenLoc,4767Expr *SubExpr) {4768ASTContext &Context = getASTContext();4769TypeSourceInfo *TSInfo = nullptr;4770QualType T = SemaRef.GetTypeFromParser(Type, &TSInfo);4771if (Kind == OBC_Bridge)4772CheckTollFreeBridgeCast(T, SubExpr);4773if (!TSInfo)4774TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc);4775return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,4776SubExpr);4777}47784779DeclResult SemaObjC::LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,4780IdentifierInfo *II) {4781SourceLocation Loc = Lookup.getNameLoc();4782ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl();47834784// Check for error condition which is already reported.4785if (!CurMethod)4786return DeclResult(true);47874788// There are two cases to handle here. 1) scoped lookup could have failed,4789// in which case we should look for an ivar. 2) scoped lookup could have4790// found a decl, but that decl is outside the current instance method (i.e.4791// a global variable). In these two cases, we do a lookup for an ivar with4792// this name, if the lookup sucedes, we replace it our current decl.47934794// If we're in a class method, we don't normally want to look for4795// ivars. But if we don't find anything else, and there's an4796// ivar, that's an error.4797bool IsClassMethod = CurMethod->isClassMethod();47984799bool LookForIvars;4800if (Lookup.empty())4801LookForIvars = true;4802else if (IsClassMethod)4803LookForIvars = false;4804else4805LookForIvars = (Lookup.isSingleResult() &&4806Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());4807ObjCInterfaceDecl *IFace = nullptr;4808if (LookForIvars) {4809IFace = CurMethod->getClassInterface();4810ObjCInterfaceDecl *ClassDeclared;4811ObjCIvarDecl *IV = nullptr;4812if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {4813// Diagnose using an ivar in a class method.4814if (IsClassMethod) {4815Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName();4816return DeclResult(true);4817}48184819// Diagnose the use of an ivar outside of the declaring class.4820if (IV->getAccessControl() == ObjCIvarDecl::Private &&4821!declaresSameEntity(ClassDeclared, IFace) &&4822!getLangOpts().DebuggerSupport)4823Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName();48244825// Success.4826return IV;4827}4828} else if (CurMethod->isInstanceMethod()) {4829// We should warn if a local variable hides an ivar.4830if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) {4831ObjCInterfaceDecl *ClassDeclared;4832if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {4833if (IV->getAccessControl() != ObjCIvarDecl::Private ||4834declaresSameEntity(IFace, ClassDeclared))4835Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();4836}4837}4838} else if (Lookup.isSingleResult() &&4839Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {4840// If accessing a stand-alone ivar in a class method, this is an error.4841if (const ObjCIvarDecl *IV =4842dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl())) {4843Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName();4844return DeclResult(true);4845}4846}48474848// Didn't encounter an error, didn't find an ivar.4849return DeclResult(false);4850}48514852ExprResult SemaObjC::LookupInObjCMethod(LookupResult &Lookup, Scope *S,4853IdentifierInfo *II,4854bool AllowBuiltinCreation) {4855// FIXME: Integrate this lookup step into LookupParsedName.4856DeclResult Ivar = LookupIvarInObjCMethod(Lookup, S, II);4857if (Ivar.isInvalid())4858return ExprError();4859if (Ivar.isUsable())4860return BuildIvarRefExpr(S, Lookup.getNameLoc(),4861cast<ObjCIvarDecl>(Ivar.get()));48624863if (Lookup.empty() && II && AllowBuiltinCreation)4864SemaRef.LookupBuiltin(Lookup);48654866// Sentinel value saying that we didn't do anything special.4867return ExprResult(false);4868}48694870ExprResult SemaObjC::BuildIvarRefExpr(Scope *S, SourceLocation Loc,4871ObjCIvarDecl *IV) {4872ASTContext &Context = getASTContext();4873ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl();4874assert(CurMethod && CurMethod->isInstanceMethod() &&4875"should not reference ivar from this context");48764877ObjCInterfaceDecl *IFace = CurMethod->getClassInterface();4878assert(IFace && "should not reference ivar from this context");48794880// If we're referencing an invalid decl, just return this as a silent4881// error node. The error diagnostic was already emitted on the decl.4882if (IV->isInvalidDecl())4883return ExprError();48844885// Check if referencing a field with __attribute__((deprecated)).4886if (SemaRef.DiagnoseUseOfDecl(IV, Loc))4887return ExprError();48884889// FIXME: This should use a new expr for a direct reference, don't4890// turn this into Self->ivar, just return a BareIVarExpr or something.4891IdentifierInfo &II = Context.Idents.get("self");4892UnqualifiedId SelfName;4893SelfName.setImplicitSelfParam(&II);4894CXXScopeSpec SelfScopeSpec;4895SourceLocation TemplateKWLoc;4896ExprResult SelfExpr =4897SemaRef.ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName,4898/*HasTrailingLParen=*/false,4899/*IsAddressOfOperand=*/false);4900if (SelfExpr.isInvalid())4901return ExprError();49024903SelfExpr = SemaRef.DefaultLvalueConversion(SelfExpr.get());4904if (SelfExpr.isInvalid())4905return ExprError();49064907SemaRef.MarkAnyDeclReferenced(Loc, IV, true);49084909ObjCMethodFamily MF = CurMethod->getMethodFamily();4910if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&4911!IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))4912Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();49134914ObjCIvarRefExpr *Result = new (Context)4915ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc,4916IV->getLocation(), SelfExpr.get(), true, true);49174918if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {4919if (!SemaRef.isUnevaluatedContext() &&4920!getDiagnostics().isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))4921SemaRef.getCurFunction()->recordUseOfWeak(Result);4922}4923if (getLangOpts().ObjCAutoRefCount && !SemaRef.isUnevaluatedContext())4924if (const BlockDecl *BD = SemaRef.CurContext->getInnermostBlockDecl())4925SemaRef.ImplicitlyRetainedSelfLocs.push_back({Loc, BD});49264927return Result;4928}49294930QualType SemaObjC::FindCompositeObjCPointerType(ExprResult &LHS,4931ExprResult &RHS,4932SourceLocation QuestionLoc) {4933ASTContext &Context = getASTContext();4934QualType LHSTy = LHS.get()->getType();4935QualType RHSTy = RHS.get()->getType();49364937// Handle things like Class and struct objc_class*. Here we case the result4938// to the pseudo-builtin, because that will be implicitly cast back to the4939// redefinition type if an attempt is made to access its fields.4940if (LHSTy->isObjCClassType() &&4941(Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) {4942RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy,4943CK_CPointerToObjCPointerCast);4944return LHSTy;4945}4946if (RHSTy->isObjCClassType() &&4947(Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) {4948LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy,4949CK_CPointerToObjCPointerCast);4950return RHSTy;4951}4952// And the same for struct objc_object* / id4953if (LHSTy->isObjCIdType() &&4954(Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) {4955RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy,4956CK_CPointerToObjCPointerCast);4957return LHSTy;4958}4959if (RHSTy->isObjCIdType() &&4960(Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) {4961LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy,4962CK_CPointerToObjCPointerCast);4963return RHSTy;4964}4965// And the same for struct objc_selector* / SEL4966if (Context.isObjCSelType(LHSTy) &&4967(Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) {4968RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSTy, CK_BitCast);4969return LHSTy;4970}4971if (Context.isObjCSelType(RHSTy) &&4972(Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) {4973LHS = SemaRef.ImpCastExprToType(LHS.get(), RHSTy, CK_BitCast);4974return RHSTy;4975}4976// Check constraints for Objective-C object pointers types.4977if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {49784979if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {4980// Two identical object pointer types are always compatible.4981return LHSTy;4982}4983const ObjCObjectPointerType *LHSOPT =4984LHSTy->castAs<ObjCObjectPointerType>();4985const ObjCObjectPointerType *RHSOPT =4986RHSTy->castAs<ObjCObjectPointerType>();4987QualType compositeType = LHSTy;49884989// If both operands are interfaces and either operand can be4990// assigned to the other, use that type as the composite4991// type. This allows4992// xxx ? (A*) a : (B*) b4993// where B is a subclass of A.4994//4995// Additionally, as for assignment, if either type is 'id'4996// allow silent coercion. Finally, if the types are4997// incompatible then make sure to use 'id' as the composite4998// type so the result is acceptable for sending messages to.49995000// FIXME: Consider unifying with 'areComparableObjCPointerTypes'.5001// It could return the composite type.5002if (!(compositeType = Context.areCommonBaseCompatible(LHSOPT, RHSOPT))5003.isNull()) {5004// Nothing more to do.5005} else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {5006compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;5007} else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {5008compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;5009} else if ((LHSOPT->isObjCQualifiedIdType() ||5010RHSOPT->isObjCQualifiedIdType()) &&5011Context.ObjCQualifiedIdTypesAreCompatible(LHSOPT, RHSOPT,5012true)) {5013// Need to handle "id<xx>" explicitly.5014// GCC allows qualified id and any Objective-C type to devolve to5015// id. Currently localizing to here until clear this should be5016// part of ObjCQualifiedIdTypesAreCompatible.5017compositeType = Context.getObjCIdType();5018} else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {5019compositeType = Context.getObjCIdType();5020} else {5021Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)5022<< LHSTy << RHSTy << LHS.get()->getSourceRange()5023<< RHS.get()->getSourceRange();5024QualType incompatTy = Context.getObjCIdType();5025LHS = SemaRef.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast);5026RHS = SemaRef.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast);5027return incompatTy;5028}5029// The object pointer types are compatible.5030LHS = SemaRef.ImpCastExprToType(LHS.get(), compositeType, CK_BitCast);5031RHS = SemaRef.ImpCastExprToType(RHS.get(), compositeType, CK_BitCast);5032return compositeType;5033}5034// Check Objective-C object pointer types and 'void *'5035if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {5036if (getLangOpts().ObjCAutoRefCount) {5037// ARC forbids the implicit conversion of object pointers to 'void *',5038// so these types are not compatible.5039Diag(QuestionLoc, diag::err_cond_voidptr_arc)5040<< LHSTy << RHSTy << LHS.get()->getSourceRange()5041<< RHS.get()->getSourceRange();5042LHS = RHS = true;5043return QualType();5044}5045QualType lhptee = LHSTy->castAs<PointerType>()->getPointeeType();5046QualType rhptee = RHSTy->castAs<ObjCObjectPointerType>()->getPointeeType();5047QualType destPointee =5048Context.getQualifiedType(lhptee, rhptee.getQualifiers());5049QualType destType = Context.getPointerType(destPointee);5050// Add qualifiers if necessary.5051LHS = SemaRef.ImpCastExprToType(LHS.get(), destType, CK_NoOp);5052// Promote to void*.5053RHS = SemaRef.ImpCastExprToType(RHS.get(), destType, CK_BitCast);5054return destType;5055}5056if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {5057if (getLangOpts().ObjCAutoRefCount) {5058// ARC forbids the implicit conversion of object pointers to 'void *',5059// so these types are not compatible.5060Diag(QuestionLoc, diag::err_cond_voidptr_arc)5061<< LHSTy << RHSTy << LHS.get()->getSourceRange()5062<< RHS.get()->getSourceRange();5063LHS = RHS = true;5064return QualType();5065}5066QualType lhptee = LHSTy->castAs<ObjCObjectPointerType>()->getPointeeType();5067QualType rhptee = RHSTy->castAs<PointerType>()->getPointeeType();5068QualType destPointee =5069Context.getQualifiedType(rhptee, lhptee.getQualifiers());5070QualType destType = Context.getPointerType(destPointee);5071// Add qualifiers if necessary.5072RHS = SemaRef.ImpCastExprToType(RHS.get(), destType, CK_NoOp);5073// Promote to void*.5074LHS = SemaRef.ImpCastExprToType(LHS.get(), destType, CK_BitCast);5075return destType;5076}5077return QualType();5078}50795080bool SemaObjC::CheckConversionToObjCLiteral(QualType DstType, Expr *&Exp,5081bool Diagnose) {5082if (!getLangOpts().ObjC)5083return false;50845085const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();5086if (!PT)5087return false;5088const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();50895090// Ignore any parens, implicit casts (should only be5091// array-to-pointer decays), and not-so-opaque values. The last is5092// important for making this trigger for property assignments.5093Expr *SrcExpr = Exp->IgnoreParenImpCasts();5094if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr))5095if (OV->getSourceExpr())5096SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();50975098if (auto *SL = dyn_cast<StringLiteral>(SrcExpr)) {5099if (!PT->isObjCIdType() && !(ID && ID->getIdentifier()->isStr("NSString")))5100return false;5101if (!SL->isOrdinary())5102return false;51035104if (Diagnose) {5105Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix)5106<< /*string*/ 0 << FixItHint::CreateInsertion(SL->getBeginLoc(), "@");5107Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get();5108}5109return true;5110}51115112if ((isa<IntegerLiteral>(SrcExpr) || isa<CharacterLiteral>(SrcExpr) ||5113isa<FloatingLiteral>(SrcExpr) || isa<ObjCBoolLiteralExpr>(SrcExpr) ||5114isa<CXXBoolLiteralExpr>(SrcExpr)) &&5115!SrcExpr->isNullPointerConstant(getASTContext(),5116Expr::NPC_NeverValueDependent)) {5117if (!ID || !ID->getIdentifier()->isStr("NSNumber"))5118return false;5119if (Diagnose) {5120Diag(SrcExpr->getBeginLoc(), diag::err_missing_atsign_prefix)5121<< /*number*/ 15122<< FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "@");5123Expr *NumLit =5124BuildObjCNumericLiteral(SrcExpr->getBeginLoc(), SrcExpr).get();5125if (NumLit)5126Exp = NumLit;5127}5128return true;5129}51305131return false;5132}51335134/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.5135ExprResult SemaObjC::ActOnObjCBoolLiteral(SourceLocation OpLoc,5136tok::TokenKind Kind) {5137assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) &&5138"Unknown Objective-C Boolean value!");5139ASTContext &Context = getASTContext();5140QualType BoolT = Context.ObjCBuiltinBoolTy;5141if (!Context.getBOOLDecl()) {5142LookupResult Result(SemaRef, &Context.Idents.get("BOOL"), OpLoc,5143Sema::LookupOrdinaryName);5144if (SemaRef.LookupName(Result, SemaRef.getCurScope()) &&5145Result.isSingleResult()) {5146NamedDecl *ND = Result.getFoundDecl();5147if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND))5148Context.setBOOLDecl(TD);5149}5150}5151if (Context.getBOOLDecl())5152BoolT = Context.getBOOLType();5153return new (Context)5154ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, BoolT, OpLoc);5155}51565157ExprResult SemaObjC::ActOnObjCAvailabilityCheckExpr(5158llvm::ArrayRef<AvailabilitySpec> AvailSpecs, SourceLocation AtLoc,5159SourceLocation RParen) {5160ASTContext &Context = getASTContext();5161auto FindSpecVersion =5162[&](StringRef Platform) -> std::optional<VersionTuple> {5163auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) {5164return Spec.getPlatform() == Platform;5165});5166// Transcribe the "ios" availability check to "maccatalyst" when compiling5167// for "maccatalyst" if "maccatalyst" is not specified.5168if (Spec == AvailSpecs.end() && Platform == "maccatalyst") {5169Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) {5170return Spec.getPlatform() == "ios";5171});5172}5173if (Spec == AvailSpecs.end())5174return std::nullopt;5175return Spec->getVersion();5176};51775178VersionTuple Version;5179if (auto MaybeVersion =5180FindSpecVersion(Context.getTargetInfo().getPlatformName()))5181Version = *MaybeVersion;51825183// The use of `@available` in the enclosing context should be analyzed to5184// warn when it's used inappropriately (i.e. not if(@available)).5185if (FunctionScopeInfo *Context = SemaRef.getCurFunctionAvailabilityContext())5186Context->HasPotentialAvailabilityViolations = true;51875188return new (Context)5189ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);5190}51915192/// Prepare a conversion of the given expression to an ObjC object5193/// pointer type.5194CastKind SemaObjC::PrepareCastToObjCObjectPointer(ExprResult &E) {5195QualType type = E.get()->getType();5196if (type->isObjCObjectPointerType()) {5197return CK_BitCast;5198} else if (type->isBlockPointerType()) {5199SemaRef.maybeExtendBlockObject(E);5200return CK_BlockPointerToObjCPointerCast;5201} else {5202assert(type->isPointerType());5203return CK_CPointerToObjCPointerCast;5204}5205}52065207SemaObjC::ObjCLiteralKind SemaObjC::CheckLiteralKind(Expr *FromE) {5208FromE = FromE->IgnoreParenImpCasts();5209switch (FromE->getStmtClass()) {5210default:5211break;5212case Stmt::ObjCStringLiteralClass:5213// "string literal"5214return LK_String;5215case Stmt::ObjCArrayLiteralClass:5216// "array literal"5217return LK_Array;5218case Stmt::ObjCDictionaryLiteralClass:5219// "dictionary literal"5220return LK_Dictionary;5221case Stmt::BlockExprClass:5222return LK_Block;5223case Stmt::ObjCBoxedExprClass: {5224Expr *Inner = cast<ObjCBoxedExpr>(FromE)->getSubExpr()->IgnoreParens();5225switch (Inner->getStmtClass()) {5226case Stmt::IntegerLiteralClass:5227case Stmt::FloatingLiteralClass:5228case Stmt::CharacterLiteralClass:5229case Stmt::ObjCBoolLiteralExprClass:5230case Stmt::CXXBoolLiteralExprClass:5231// "numeric literal"5232return LK_Numeric;5233case Stmt::ImplicitCastExprClass: {5234CastKind CK = cast<CastExpr>(Inner)->getCastKind();5235// Boolean literals can be represented by implicit casts.5236if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast)5237return LK_Numeric;5238break;5239}5240default:5241break;5242}5243return LK_Boxed;5244}5245}5246return LK_None;5247}524852495250