2409 lines · cpp
1//===----- SemaObjC.cpp ---- Semantic Analysis for Objective-C ------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file implements semantic analysis for Objective-C.10///11//===----------------------------------------------------------------------===//12 13#include "clang/Sema/SemaObjC.h"14#include "clang/AST/ASTMutationListener.h"15#include "clang/AST/EvaluatedExprVisitor.h"16#include "clang/AST/StmtObjC.h"17#include "clang/Basic/DiagnosticSema.h"18#include "clang/Lex/Preprocessor.h"19#include "clang/Sema/Attr.h"20#include "clang/Sema/Lookup.h"21#include "clang/Sema/ParsedAttr.h"22#include "clang/Sema/ScopeInfo.h"23#include "clang/Sema/Sema.h"24#include "clang/Sema/TemplateDeduction.h"25#include "llvm/Support/ConvertUTF.h"26 27namespace clang {28 29SemaObjC::SemaObjC(Sema &S)30 : SemaBase(S), NSNumberDecl(nullptr), NSValueDecl(nullptr),31 NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),32 ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),33 ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),34 DictionaryWithObjectsMethod(nullptr) {}35 36StmtResult SemaObjC::ActOnObjCForCollectionStmt(SourceLocation ForLoc,37 Stmt *First, Expr *collection,38 SourceLocation RParenLoc) {39 ASTContext &Context = getASTContext();40 SemaRef.setFunctionHasBranchProtectedScope();41 42 ExprResult CollectionExprResult =43 CheckObjCForCollectionOperand(ForLoc, collection);44 45 if (First) {46 QualType FirstType;47 if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) {48 if (!DS->isSingleDecl())49 return StmtError(Diag((*DS->decl_begin())->getLocation(),50 diag::err_toomany_element_decls));51 52 VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl());53 if (!D || D->isInvalidDecl())54 return StmtError();55 56 FirstType = D->getType();57 // C99 6.8.5p3: The declaration part of a 'for' statement shall only58 // declare identifiers for objects having storage class 'auto' or59 // 'register'.60 if (!D->hasLocalStorage())61 return StmtError(62 Diag(D->getLocation(), diag::err_non_local_variable_decl_in_for));63 64 // If the type contained 'auto', deduce the 'auto' to 'id'.65 if (FirstType->getContainedAutoType()) {66 SourceLocation Loc = D->getLocation();67 OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue);68 Expr *DeducedInit = &OpaqueId;69 sema::TemplateDeductionInfo Info(Loc);70 FirstType = QualType();71 TemplateDeductionResult Result = SemaRef.DeduceAutoType(72 D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info);73 if (Result != TemplateDeductionResult::Success &&74 Result != TemplateDeductionResult::AlreadyDiagnosed)75 SemaRef.DiagnoseAutoDeductionFailure(D, DeducedInit);76 if (FirstType.isNull()) {77 D->setInvalidDecl();78 return StmtError();79 }80 81 D->setType(FirstType);82 83 if (!SemaRef.inTemplateInstantiation()) {84 SourceLocation Loc =85 D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();86 Diag(Loc, diag::warn_auto_var_is_id) << D->getDeclName();87 }88 }89 90 } else {91 Expr *FirstE = cast<Expr>(First);92 if (!FirstE->isTypeDependent() && !FirstE->isLValue())93 return StmtError(94 Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue)95 << First->getSourceRange());96 97 FirstType = static_cast<Expr *>(First)->getType();98 if (FirstType.isConstQualified())99 Diag(ForLoc, diag::err_selector_element_const_type)100 << FirstType << First->getSourceRange();101 }102 if (!FirstType->isDependentType() &&103 !FirstType->isObjCObjectPointerType() &&104 !FirstType->isBlockPointerType())105 return StmtError(Diag(ForLoc, diag::err_selector_element_type)106 << FirstType << First->getSourceRange());107 }108 109 if (CollectionExprResult.isInvalid())110 return StmtError();111 112 CollectionExprResult = SemaRef.ActOnFinishFullExpr(CollectionExprResult.get(),113 /*DiscardedValue*/ false);114 if (CollectionExprResult.isInvalid())115 return StmtError();116 117 return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(),118 nullptr, ForLoc, RParenLoc);119}120 121ExprResult SemaObjC::CheckObjCForCollectionOperand(SourceLocation forLoc,122 Expr *collection) {123 ASTContext &Context = getASTContext();124 if (!collection)125 return ExprError();126 127 // Bail out early if we've got a type-dependent expression.128 if (collection->isTypeDependent())129 return collection;130 131 // Perform normal l-value conversion.132 ExprResult result = SemaRef.DefaultFunctionArrayLvalueConversion(collection);133 if (result.isInvalid())134 return ExprError();135 collection = result.get();136 137 // The operand needs to have object-pointer type.138 // TODO: should we do a contextual conversion?139 const ObjCObjectPointerType *pointerType =140 collection->getType()->getAs<ObjCObjectPointerType>();141 if (!pointerType)142 return Diag(forLoc, diag::err_collection_expr_type)143 << collection->getType() << collection->getSourceRange();144 145 // Check that the operand provides146 // - countByEnumeratingWithState:objects:count:147 const ObjCObjectType *objectType = pointerType->getObjectType();148 ObjCInterfaceDecl *iface = objectType->getInterface();149 150 // If we have a forward-declared type, we can't do this check.151 // Under ARC, it is an error not to have a forward-declared class.152 if (iface &&153 (getLangOpts().ObjCAutoRefCount154 ? SemaRef.RequireCompleteType(forLoc, QualType(objectType, 0),155 diag::err_arc_collection_forward,156 collection)157 : !SemaRef.isCompleteType(forLoc, QualType(objectType, 0)))) {158 // Otherwise, if we have any useful type information, check that159 // the type declares the appropriate method.160 } else if (iface || !objectType->qual_empty()) {161 const IdentifierInfo *selectorIdents[] = {162 &Context.Idents.get("countByEnumeratingWithState"),163 &Context.Idents.get("objects"), &Context.Idents.get("count")};164 Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);165 166 ObjCMethodDecl *method = nullptr;167 168 // If there's an interface, look in both the public and private APIs.169 if (iface) {170 method = iface->lookupInstanceMethod(selector);171 if (!method)172 method = iface->lookupPrivateMethod(selector);173 }174 175 // Also check protocol qualifiers.176 if (!method)177 method = LookupMethodInQualifiedType(selector, pointerType,178 /*instance*/ true);179 180 // If we didn't find it anywhere, give up.181 if (!method) {182 Diag(forLoc, diag::warn_collection_expr_type)183 << collection->getType() << selector << collection->getSourceRange();184 }185 186 // TODO: check for an incompatible signature?187 }188 189 // Wrap up any cleanups in the expression.190 return collection;191}192 193StmtResult SemaObjC::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) {194 if (!S || !B)195 return StmtError();196 ObjCForCollectionStmt *ForStmt = cast<ObjCForCollectionStmt>(S);197 198 ForStmt->setBody(B);199 return S;200}201 202StmtResult SemaObjC::ActOnObjCAtCatchStmt(SourceLocation AtLoc,203 SourceLocation RParen, Decl *Parm,204 Stmt *Body) {205 ASTContext &Context = getASTContext();206 VarDecl *Var = cast_or_null<VarDecl>(Parm);207 if (Var && Var->isInvalidDecl())208 return StmtError();209 210 return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body);211}212 213StmtResult SemaObjC::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {214 ASTContext &Context = getASTContext();215 return new (Context) ObjCAtFinallyStmt(AtLoc, Body);216}217 218StmtResult SemaObjC::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,219 MultiStmtArg CatchStmts,220 Stmt *Finally) {221 ASTContext &Context = getASTContext();222 if (!getLangOpts().ObjCExceptions)223 Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";224 225 // Objective-C try is incompatible with SEH __try.226 sema::FunctionScopeInfo *FSI = SemaRef.getCurFunction();227 if (FSI->FirstSEHTryLoc.isValid()) {228 Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1;229 Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";230 }231 232 FSI->setHasObjCTry(AtLoc);233 unsigned NumCatchStmts = CatchStmts.size();234 return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),235 NumCatchStmts, Finally);236}237 238StmtResult SemaObjC::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {239 ASTContext &Context = getASTContext();240 if (Throw) {241 ExprResult Result = SemaRef.DefaultLvalueConversion(Throw);242 if (Result.isInvalid())243 return StmtError();244 245 Result =246 SemaRef.ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false);247 if (Result.isInvalid())248 return StmtError();249 Throw = Result.get();250 251 QualType ThrowType = Throw->getType();252 // Make sure the expression type is an ObjC pointer or "void *".253 if (!ThrowType->isDependentType() &&254 !ThrowType->isObjCObjectPointerType()) {255 const PointerType *PT = ThrowType->getAs<PointerType>();256 if (!PT || !PT->getPointeeType()->isVoidType())257 return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object)258 << Throw->getType() << Throw->getSourceRange());259 }260 }261 262 return new (Context) ObjCAtThrowStmt(AtLoc, Throw);263}264 265StmtResult SemaObjC::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,266 Scope *CurScope) {267 if (!getLangOpts().ObjCExceptions)268 Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw";269 270 if (!Throw) {271 // @throw without an expression designates a rethrow (which must occur272 // in the context of an @catch clause).273 Scope *AtCatchParent = CurScope;274 while (AtCatchParent && !AtCatchParent->isAtCatchScope())275 AtCatchParent = AtCatchParent->getParent();276 if (!AtCatchParent)277 return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch));278 }279 return BuildObjCAtThrowStmt(AtLoc, Throw);280}281 282ExprResult SemaObjC::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc,283 Expr *operand) {284 ExprResult result = SemaRef.DefaultLvalueConversion(operand);285 if (result.isInvalid())286 return ExprError();287 operand = result.get();288 289 // Make sure the expression type is an ObjC pointer or "void *".290 QualType type = operand->getType();291 if (!type->isDependentType() && !type->isObjCObjectPointerType()) {292 const PointerType *pointerType = type->getAs<PointerType>();293 if (!pointerType || !pointerType->getPointeeType()->isVoidType()) {294 if (getLangOpts().CPlusPlus) {295 if (SemaRef.RequireCompleteType(atLoc, type,296 diag::err_incomplete_receiver_type))297 return Diag(atLoc, diag::err_objc_synchronized_expects_object)298 << type << operand->getSourceRange();299 300 ExprResult result =301 SemaRef.PerformContextuallyConvertToObjCPointer(operand);302 if (result.isInvalid())303 return ExprError();304 if (!result.isUsable())305 return Diag(atLoc, diag::err_objc_synchronized_expects_object)306 << type << operand->getSourceRange();307 308 operand = result.get();309 } else {310 return Diag(atLoc, diag::err_objc_synchronized_expects_object)311 << type << operand->getSourceRange();312 }313 }314 }315 316 // The operand to @synchronized is a full-expression.317 return SemaRef.ActOnFinishFullExpr(operand, /*DiscardedValue*/ false);318}319 320StmtResult SemaObjC::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,321 Expr *SyncExpr,322 Stmt *SyncBody) {323 ASTContext &Context = getASTContext();324 // We can't jump into or indirect-jump out of a @synchronized block.325 SemaRef.setFunctionHasBranchProtectedScope();326 return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);327}328 329StmtResult SemaObjC::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc,330 Stmt *Body) {331 ASTContext &Context = getASTContext();332 SemaRef.setFunctionHasBranchProtectedScope();333 return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);334}335 336TypeResult SemaObjC::actOnObjCProtocolQualifierType(337 SourceLocation lAngleLoc, ArrayRef<Decl *> protocols,338 ArrayRef<SourceLocation> protocolLocs, SourceLocation rAngleLoc) {339 ASTContext &Context = getASTContext();340 // Form id<protocol-list>.341 QualType Result = Context.getObjCObjectType(342 Context.ObjCBuiltinIdTy, {},343 llvm::ArrayRef((ObjCProtocolDecl *const *)protocols.data(),344 protocols.size()),345 false);346 Result = Context.getObjCObjectPointerType(Result);347 348 TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);349 TypeLoc ResultTL = ResultTInfo->getTypeLoc();350 351 auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>();352 ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit353 354 auto ObjCObjectTL =355 ObjCObjectPointerTL.getPointeeLoc().castAs<ObjCObjectTypeLoc>();356 ObjCObjectTL.setHasBaseTypeAsWritten(false);357 ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation());358 359 // No type arguments.360 ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());361 ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());362 363 // Fill in protocol qualifiers.364 ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc);365 ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc);366 for (unsigned i = 0, n = protocols.size(); i != n; ++i)367 ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]);368 369 // We're done. Return the completed type to the parser.370 return SemaRef.CreateParsedType(Result, ResultTInfo);371}372 373TypeResult SemaObjC::actOnObjCTypeArgsAndProtocolQualifiers(374 Scope *S, SourceLocation Loc, ParsedType BaseType,375 SourceLocation TypeArgsLAngleLoc, ArrayRef<ParsedType> TypeArgs,376 SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc,377 ArrayRef<Decl *> Protocols, ArrayRef<SourceLocation> ProtocolLocs,378 SourceLocation ProtocolRAngleLoc) {379 ASTContext &Context = getASTContext();380 TypeSourceInfo *BaseTypeInfo = nullptr;381 QualType T = SemaRef.GetTypeFromParser(BaseType, &BaseTypeInfo);382 if (T.isNull())383 return true;384 385 // Handle missing type-source info.386 if (!BaseTypeInfo)387 BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc);388 389 // Extract type arguments.390 SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos;391 for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) {392 TypeSourceInfo *TypeArgInfo = nullptr;393 QualType TypeArg = SemaRef.GetTypeFromParser(TypeArgs[i], &TypeArgInfo);394 if (TypeArg.isNull()) {395 ActualTypeArgInfos.clear();396 break;397 }398 399 assert(TypeArgInfo && "No type source info?");400 ActualTypeArgInfos.push_back(TypeArgInfo);401 }402 403 // Build the object type.404 QualType Result = BuildObjCObjectType(405 T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(),406 TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc,407 ProtocolLAngleLoc,408 llvm::ArrayRef((ObjCProtocolDecl *const *)Protocols.data(),409 Protocols.size()),410 ProtocolLocs, ProtocolRAngleLoc,411 /*FailOnError=*/false,412 /*Rebuilding=*/false);413 414 if (Result == T)415 return BaseType;416 417 // Create source information for this type.418 TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);419 TypeLoc ResultTL = ResultTInfo->getTypeLoc();420 421 // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an422 // object pointer type. Fill in source information for it.423 if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) {424 // The '*' is implicit.425 ObjCObjectPointerTL.setStarLoc(SourceLocation());426 ResultTL = ObjCObjectPointerTL.getPointeeLoc();427 }428 429 if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) {430 // Protocol qualifier information.431 if (OTPTL.getNumProtocols() > 0) {432 assert(OTPTL.getNumProtocols() == Protocols.size());433 OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc);434 OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc);435 for (unsigned i = 0, n = Protocols.size(); i != n; ++i)436 OTPTL.setProtocolLoc(i, ProtocolLocs[i]);437 }438 439 // We're done. Return the completed type to the parser.440 return SemaRef.CreateParsedType(Result, ResultTInfo);441 }442 443 auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>();444 445 // Type argument information.446 if (ObjCObjectTL.getNumTypeArgs() > 0) {447 assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size());448 ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc);449 ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc);450 for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i)451 ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]);452 } else {453 ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());454 ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());455 }456 457 // Protocol qualifier information.458 if (ObjCObjectTL.getNumProtocols() > 0) {459 assert(ObjCObjectTL.getNumProtocols() == Protocols.size());460 ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc);461 ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc);462 for (unsigned i = 0, n = Protocols.size(); i != n; ++i)463 ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]);464 } else {465 ObjCObjectTL.setProtocolLAngleLoc(SourceLocation());466 ObjCObjectTL.setProtocolRAngleLoc(SourceLocation());467 }468 469 // Base type.470 ObjCObjectTL.setHasBaseTypeAsWritten(true);471 if (ObjCObjectTL.getType() == T)472 ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc());473 else474 ObjCObjectTL.getBaseLoc().initialize(Context, Loc);475 476 // We're done. Return the completed type to the parser.477 return SemaRef.CreateParsedType(Result, ResultTInfo);478}479 480QualType SemaObjC::BuildObjCTypeParamType(481 const ObjCTypeParamDecl *Decl, SourceLocation ProtocolLAngleLoc,482 ArrayRef<ObjCProtocolDecl *> Protocols,483 ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,484 bool FailOnError) {485 ASTContext &Context = getASTContext();486 QualType Result = QualType(Decl->getTypeForDecl(), 0);487 if (!Protocols.empty()) {488 bool HasError;489 Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError);490 if (HasError) {491 Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers)492 << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);493 if (FailOnError)494 Result = QualType();495 }496 if (FailOnError && Result.isNull())497 return QualType();498 }499 500 return Result;501}502 503/// Apply Objective-C type arguments to the given type.504static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,505 ArrayRef<TypeSourceInfo *> typeArgs,506 SourceRange typeArgsRange, bool failOnError,507 bool rebuilding) {508 // We can only apply type arguments to an Objective-C class type.509 const auto *objcObjectType = type->getAs<ObjCObjectType>();510 if (!objcObjectType || !objcObjectType->getInterface()) {511 S.Diag(loc, diag::err_objc_type_args_non_class) << type << typeArgsRange;512 513 if (failOnError)514 return QualType();515 return type;516 }517 518 // The class type must be parameterized.519 ObjCInterfaceDecl *objcClass = objcObjectType->getInterface();520 ObjCTypeParamList *typeParams = objcClass->getTypeParamList();521 if (!typeParams) {522 S.Diag(loc, diag::err_objc_type_args_non_parameterized_class)523 << objcClass->getDeclName() << FixItHint::CreateRemoval(typeArgsRange);524 525 if (failOnError)526 return QualType();527 528 return type;529 }530 531 // The type must not already be specialized.532 if (objcObjectType->isSpecialized()) {533 S.Diag(loc, diag::err_objc_type_args_specialized_class)534 << type << FixItHint::CreateRemoval(typeArgsRange);535 536 if (failOnError)537 return QualType();538 539 return type;540 }541 542 // Check the type arguments.543 SmallVector<QualType, 4> finalTypeArgs;544 unsigned numTypeParams = typeParams->size();545 bool anyPackExpansions = false;546 for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) {547 TypeSourceInfo *typeArgInfo = typeArgs[i];548 QualType typeArg = typeArgInfo->getType();549 550 // Type arguments cannot have explicit qualifiers or nullability.551 // We ignore indirect sources of these, e.g. behind typedefs or552 // template arguments.553 if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) {554 bool diagnosed = false;555 SourceRange rangeToRemove;556 if (auto attr = qual.getAs<AttributedTypeLoc>()) {557 rangeToRemove = attr.getLocalSourceRange();558 if (attr.getTypePtr()->getImmediateNullability()) {559 typeArg = attr.getTypePtr()->getModifiedType();560 S.Diag(attr.getBeginLoc(),561 diag::err_objc_type_arg_explicit_nullability)562 << typeArg << FixItHint::CreateRemoval(rangeToRemove);563 diagnosed = true;564 }565 }566 567 // When rebuilding, qualifiers might have gotten here through a568 // final substitution.569 if (!rebuilding && !diagnosed) {570 S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified)571 << typeArg << typeArg.getQualifiers().getAsString()572 << FixItHint::CreateRemoval(rangeToRemove);573 }574 }575 576 // Remove qualifiers even if they're non-local.577 typeArg = typeArg.getUnqualifiedType();578 579 finalTypeArgs.push_back(typeArg);580 581 if (typeArg->getAs<PackExpansionType>())582 anyPackExpansions = true;583 584 // Find the corresponding type parameter, if there is one.585 ObjCTypeParamDecl *typeParam = nullptr;586 if (!anyPackExpansions) {587 if (i < numTypeParams) {588 typeParam = typeParams->begin()[i];589 } else {590 // Too many arguments.591 S.Diag(loc, diag::err_objc_type_args_wrong_arity)592 << false << objcClass->getDeclName() << (unsigned)typeArgs.size()593 << numTypeParams;594 S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass;595 596 if (failOnError)597 return QualType();598 599 return type;600 }601 }602 603 // Objective-C object pointer types must be substitutable for the bounds.604 if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) {605 // If we don't have a type parameter to match against, assume606 // everything is fine. There was a prior pack expansion that607 // means we won't be able to match anything.608 if (!typeParam) {609 assert(anyPackExpansions && "Too many arguments?");610 continue;611 }612 613 // Retrieve the bound.614 QualType bound = typeParam->getUnderlyingType();615 const auto *boundObjC = bound->castAs<ObjCObjectPointerType>();616 617 // Determine whether the type argument is substitutable for the bound.618 if (typeArgObjC->isObjCIdType()) {619 // When the type argument is 'id', the only acceptable type620 // parameter bound is 'id'.621 if (boundObjC->isObjCIdType())622 continue;623 } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) {624 // Otherwise, we follow the assignability rules.625 continue;626 }627 628 // Diagnose the mismatch.629 S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),630 diag::err_objc_type_arg_does_not_match_bound)631 << typeArg << bound << typeParam->getDeclName();632 S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)633 << typeParam->getDeclName();634 635 if (failOnError)636 return QualType();637 638 return type;639 }640 641 // Block pointer types are permitted for unqualified 'id' bounds.642 if (typeArg->isBlockPointerType()) {643 // If we don't have a type parameter to match against, assume644 // everything is fine. There was a prior pack expansion that645 // means we won't be able to match anything.646 if (!typeParam) {647 assert(anyPackExpansions && "Too many arguments?");648 continue;649 }650 651 // Retrieve the bound.652 QualType bound = typeParam->getUnderlyingType();653 if (bound->isBlockCompatibleObjCPointerType(S.Context))654 continue;655 656 // Diagnose the mismatch.657 S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),658 diag::err_objc_type_arg_does_not_match_bound)659 << typeArg << bound << typeParam->getDeclName();660 S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)661 << typeParam->getDeclName();662 663 if (failOnError)664 return QualType();665 666 return type;667 }668 669 // Types that have __attribute__((NSObject)) are permitted.670 if (typeArg->isObjCNSObjectType()) {671 continue;672 }673 674 // Dependent types will be checked at instantiation time.675 if (typeArg->isDependentType()) {676 continue;677 }678 679 // Diagnose non-id-compatible type arguments.680 S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),681 diag::err_objc_type_arg_not_id_compatible)682 << typeArg << typeArgInfo->getTypeLoc().getSourceRange();683 684 if (failOnError)685 return QualType();686 687 return type;688 }689 690 // Make sure we didn't have the wrong number of arguments.691 if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) {692 S.Diag(loc, diag::err_objc_type_args_wrong_arity)693 << (typeArgs.size() < typeParams->size()) << objcClass->getDeclName()694 << (unsigned)finalTypeArgs.size() << numTypeParams;695 S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass;696 697 if (failOnError)698 return QualType();699 700 return type;701 }702 703 // Success. Form the specialized type.704 return S.Context.getObjCObjectType(type, finalTypeArgs, {}, false);705}706 707QualType SemaObjC::BuildObjCObjectType(708 QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,709 ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc,710 SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols,711 ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,712 bool FailOnError, bool Rebuilding) {713 ASTContext &Context = getASTContext();714 QualType Result = BaseType;715 if (!TypeArgs.empty()) {716 Result =717 applyObjCTypeArgs(SemaRef, Loc, Result, TypeArgs,718 SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc),719 FailOnError, Rebuilding);720 if (FailOnError && Result.isNull())721 return QualType();722 }723 724 if (!Protocols.empty()) {725 bool HasError;726 Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError);727 if (HasError) {728 Diag(Loc, diag::err_invalid_protocol_qualifiers)729 << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);730 if (FailOnError)731 Result = QualType();732 }733 if (FailOnError && Result.isNull())734 return QualType();735 }736 737 return Result;738}739 740ParsedType SemaObjC::ActOnObjCInstanceType(SourceLocation Loc) {741 ASTContext &Context = getASTContext();742 QualType T = Context.getObjCInstanceType();743 TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);744 return SemaRef.CreateParsedType(T, TInfo);745}746 747//===--- CHECK: Objective-C retain cycles ----------------------------------//748 749namespace {750 751struct RetainCycleOwner {752 VarDecl *Variable = nullptr;753 SourceRange Range;754 SourceLocation Loc;755 bool Indirect = false;756 757 RetainCycleOwner() = default;758 759 void setLocsFrom(Expr *e) {760 Loc = e->getExprLoc();761 Range = e->getSourceRange();762 }763};764 765} // namespace766 767/// Consider whether capturing the given variable can possibly lead to768/// a retain cycle.769static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) {770 // In ARC, it's captured strongly iff the variable has __strong771 // lifetime. In MRR, it's captured strongly if the variable is772 // __block and has an appropriate type.773 if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong)774 return false;775 776 owner.Variable = var;777 if (ref)778 owner.setLocsFrom(ref);779 return true;780}781 782static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) {783 while (true) {784 e = e->IgnoreParens();785 if (CastExpr *cast = dyn_cast<CastExpr>(e)) {786 switch (cast->getCastKind()) {787 case CK_BitCast:788 case CK_LValueBitCast:789 case CK_LValueToRValue:790 case CK_ARCReclaimReturnedObject:791 e = cast->getSubExpr();792 continue;793 794 default:795 return false;796 }797 }798 799 if (ObjCIvarRefExpr *ref = dyn_cast<ObjCIvarRefExpr>(e)) {800 ObjCIvarDecl *ivar = ref->getDecl();801 if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong)802 return false;803 804 // Try to find a retain cycle in the base.805 if (!findRetainCycleOwner(S, ref->getBase(), owner))806 return false;807 808 if (ref->isFreeIvar())809 owner.setLocsFrom(ref);810 owner.Indirect = true;811 return true;812 }813 814 if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {815 VarDecl *var = dyn_cast<VarDecl>(ref->getDecl());816 if (!var)817 return false;818 return considerVariable(var, ref, owner);819 }820 821 if (MemberExpr *member = dyn_cast<MemberExpr>(e)) {822 if (member->isArrow())823 return false;824 825 // Don't count this as an indirect ownership.826 e = member->getBase();827 continue;828 }829 830 if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) {831 // Only pay attention to pseudo-objects on property references.832 ObjCPropertyRefExpr *pre = dyn_cast<ObjCPropertyRefExpr>(833 pseudo->getSyntacticForm()->IgnoreParens());834 if (!pre)835 return false;836 if (pre->isImplicitProperty())837 return false;838 ObjCPropertyDecl *property = pre->getExplicitProperty();839 if (!property->isRetaining() &&840 !(property->getPropertyIvarDecl() &&841 property->getPropertyIvarDecl()->getType().getObjCLifetime() ==842 Qualifiers::OCL_Strong))843 return false;844 845 owner.Indirect = true;846 if (pre->isSuperReceiver()) {847 owner.Variable = S.getCurMethodDecl()->getSelfDecl();848 if (!owner.Variable)849 return false;850 owner.Loc = pre->getLocation();851 owner.Range = pre->getSourceRange();852 return true;853 }854 e = const_cast<Expr *>(855 cast<OpaqueValueExpr>(pre->getBase())->getSourceExpr());856 continue;857 }858 859 // Array ivars?860 861 return false;862 }863}864 865namespace {866 867struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {868 VarDecl *Variable;869 Expr *Capturer = nullptr;870 bool VarWillBeReased = false;871 872 FindCaptureVisitor(ASTContext &Context, VarDecl *variable)873 : EvaluatedExprVisitor<FindCaptureVisitor>(Context), Variable(variable) {}874 875 void VisitDeclRefExpr(DeclRefExpr *ref) {876 if (ref->getDecl() == Variable && !Capturer)877 Capturer = ref;878 }879 880 void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) {881 if (Capturer)882 return;883 Visit(ref->getBase());884 if (Capturer && ref->isFreeIvar())885 Capturer = ref;886 }887 888 void VisitBlockExpr(BlockExpr *block) {889 // Look inside nested blocks890 if (block->getBlockDecl()->capturesVariable(Variable))891 Visit(block->getBlockDecl()->getBody());892 }893 894 void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) {895 if (Capturer)896 return;897 if (OVE->getSourceExpr())898 Visit(OVE->getSourceExpr());899 }900 901 void VisitBinaryOperator(BinaryOperator *BinOp) {902 if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign)903 return;904 Expr *LHS = BinOp->getLHS();905 if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(LHS)) {906 if (DRE->getDecl() != Variable)907 return;908 if (Expr *RHS = BinOp->getRHS()) {909 RHS = RHS->IgnoreParenCasts();910 std::optional<llvm::APSInt> Value;911 VarWillBeReased =912 (RHS && (Value = RHS->getIntegerConstantExpr(Context)) &&913 *Value == 0);914 }915 }916 }917};918 919} // namespace920 921/// Check whether the given argument is a block which captures a922/// variable.923static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {924 assert(owner.Variable && owner.Loc.isValid());925 926 e = e->IgnoreParenCasts();927 928 // Look through [^{...} copy] and Block_copy(^{...}).929 if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(e)) {930 Selector Cmd = ME->getSelector();931 if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") {932 e = ME->getInstanceReceiver();933 if (!e)934 return nullptr;935 e = e->IgnoreParenCasts();936 }937 } else if (CallExpr *CE = dyn_cast<CallExpr>(e)) {938 if (CE->getNumArgs() == 1) {939 FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl());940 if (Fn) {941 const IdentifierInfo *FnI = Fn->getIdentifier();942 if (FnI && FnI->isStr("_Block_copy")) {943 e = CE->getArg(0)->IgnoreParenCasts();944 }945 }946 }947 }948 949 BlockExpr *block = dyn_cast<BlockExpr>(e);950 if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable))951 return nullptr;952 953 FindCaptureVisitor visitor(S.Context, owner.Variable);954 visitor.Visit(block->getBlockDecl()->getBody());955 return visitor.VarWillBeReased ? nullptr : visitor.Capturer;956}957 958static void diagnoseRetainCycle(Sema &S, Expr *capturer,959 RetainCycleOwner &owner) {960 assert(capturer);961 assert(owner.Variable && owner.Loc.isValid());962 963 S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle)964 << owner.Variable << capturer->getSourceRange();965 S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner)966 << owner.Indirect << owner.Range;967}968 969/// Check for a keyword selector that starts with the word 'add' or970/// 'set'.971static bool isSetterLikeSelector(Selector sel) {972 if (sel.isUnarySelector())973 return false;974 975 StringRef str = sel.getNameForSlot(0);976 str = str.ltrim('_');977 if (str.starts_with("set"))978 str = str.substr(3);979 else if (str.starts_with("add")) {980 // Specially allow 'addOperationWithBlock:'.981 if (sel.getNumArgs() == 1 && str.starts_with("addOperationWithBlock"))982 return false;983 str = str.substr(3);984 } else985 return false;986 987 if (str.empty())988 return true;989 return !isLowercase(str.front());990}991 992static std::optional<int>993GetNSMutableArrayArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) {994 bool IsMutableArray = S.NSAPIObj->isSubclassOfNSClass(995 Message->getReceiverInterface(), NSAPI::ClassId_NSMutableArray);996 if (!IsMutableArray) {997 return std::nullopt;998 }999 1000 Selector Sel = Message->getSelector();1001 1002 std::optional<NSAPI::NSArrayMethodKind> MKOpt =1003 S.NSAPIObj->getNSArrayMethodKind(Sel);1004 if (!MKOpt) {1005 return std::nullopt;1006 }1007 1008 NSAPI::NSArrayMethodKind MK = *MKOpt;1009 1010 switch (MK) {1011 case NSAPI::NSMutableArr_addObject:1012 case NSAPI::NSMutableArr_insertObjectAtIndex:1013 case NSAPI::NSMutableArr_setObjectAtIndexedSubscript:1014 return 0;1015 case NSAPI::NSMutableArr_replaceObjectAtIndex:1016 return 1;1017 1018 default:1019 return std::nullopt;1020 }1021 1022 return std::nullopt;1023}1024 1025static std::optional<int>1026GetNSMutableDictionaryArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) {1027 bool IsMutableDictionary = S.NSAPIObj->isSubclassOfNSClass(1028 Message->getReceiverInterface(), NSAPI::ClassId_NSMutableDictionary);1029 if (!IsMutableDictionary) {1030 return std::nullopt;1031 }1032 1033 Selector Sel = Message->getSelector();1034 1035 std::optional<NSAPI::NSDictionaryMethodKind> MKOpt =1036 S.NSAPIObj->getNSDictionaryMethodKind(Sel);1037 if (!MKOpt) {1038 return std::nullopt;1039 }1040 1041 NSAPI::NSDictionaryMethodKind MK = *MKOpt;1042 1043 switch (MK) {1044 case NSAPI::NSMutableDict_setObjectForKey:1045 case NSAPI::NSMutableDict_setValueForKey:1046 case NSAPI::NSMutableDict_setObjectForKeyedSubscript:1047 return 0;1048 1049 default:1050 return std::nullopt;1051 }1052 1053 return std::nullopt;1054}1055 1056static std::optional<int> GetNSSetArgumentIndex(SemaObjC &S,1057 ObjCMessageExpr *Message) {1058 bool IsMutableSet = S.NSAPIObj->isSubclassOfNSClass(1059 Message->getReceiverInterface(), NSAPI::ClassId_NSMutableSet);1060 1061 bool IsMutableOrderedSet = S.NSAPIObj->isSubclassOfNSClass(1062 Message->getReceiverInterface(), NSAPI::ClassId_NSMutableOrderedSet);1063 if (!IsMutableSet && !IsMutableOrderedSet) {1064 return std::nullopt;1065 }1066 1067 Selector Sel = Message->getSelector();1068 1069 std::optional<NSAPI::NSSetMethodKind> MKOpt =1070 S.NSAPIObj->getNSSetMethodKind(Sel);1071 if (!MKOpt) {1072 return std::nullopt;1073 }1074 1075 NSAPI::NSSetMethodKind MK = *MKOpt;1076 1077 switch (MK) {1078 case NSAPI::NSMutableSet_addObject:1079 case NSAPI::NSOrderedSet_setObjectAtIndex:1080 case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript:1081 case NSAPI::NSOrderedSet_insertObjectAtIndex:1082 return 0;1083 case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject:1084 return 1;1085 }1086 1087 return std::nullopt;1088}1089 1090void SemaObjC::CheckObjCCircularContainer(ObjCMessageExpr *Message) {1091 if (!Message->isInstanceMessage()) {1092 return;1093 }1094 1095 std::optional<int> ArgOpt;1096 1097 if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) &&1098 !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) &&1099 !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) {1100 return;1101 }1102 1103 int ArgIndex = *ArgOpt;1104 1105 Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts();1106 if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) {1107 Arg = OE->getSourceExpr()->IgnoreImpCasts();1108 }1109 1110 if (Message->getReceiverKind() == ObjCMessageExpr::SuperInstance) {1111 if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {1112 if (ArgRE->isObjCSelfExpr()) {1113 Diag(Message->getSourceRange().getBegin(),1114 diag::warn_objc_circular_container)1115 << ArgRE->getDecl() << StringRef("'super'");1116 }1117 }1118 } else {1119 Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts();1120 1121 if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) {1122 Receiver = OE->getSourceExpr()->IgnoreImpCasts();1123 }1124 1125 if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) {1126 if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {1127 if (ReceiverRE->getDecl() == ArgRE->getDecl()) {1128 ValueDecl *Decl = ReceiverRE->getDecl();1129 Diag(Message->getSourceRange().getBegin(),1130 diag::warn_objc_circular_container)1131 << Decl << Decl;1132 if (!ArgRE->isObjCSelfExpr()) {1133 Diag(Decl->getLocation(),1134 diag::note_objc_circular_container_declared_here)1135 << Decl;1136 }1137 }1138 }1139 } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) {1140 if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) {1141 if (IvarRE->getDecl() == IvarArgRE->getDecl()) {1142 ObjCIvarDecl *Decl = IvarRE->getDecl();1143 Diag(Message->getSourceRange().getBegin(),1144 diag::warn_objc_circular_container)1145 << Decl << Decl;1146 Diag(Decl->getLocation(),1147 diag::note_objc_circular_container_declared_here)1148 << Decl;1149 }1150 }1151 }1152 }1153}1154 1155/// Check a message send to see if it's likely to cause a retain cycle.1156void SemaObjC::checkRetainCycles(ObjCMessageExpr *msg) {1157 // Only check instance methods whose selector looks like a setter.1158 if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector()))1159 return;1160 1161 // Try to find a variable that the receiver is strongly owned by.1162 RetainCycleOwner owner;1163 if (msg->getReceiverKind() == ObjCMessageExpr::Instance) {1164 if (!findRetainCycleOwner(SemaRef, msg->getInstanceReceiver(), owner))1165 return;1166 } else {1167 assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);1168 owner.Variable = SemaRef.getCurMethodDecl()->getSelfDecl();1169 owner.Loc = msg->getSuperLoc();1170 owner.Range = msg->getSuperLoc();1171 }1172 1173 // Check whether the receiver is captured by any of the arguments.1174 const ObjCMethodDecl *MD = msg->getMethodDecl();1175 for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) {1176 if (Expr *capturer = findCapturingExpr(SemaRef, msg->getArg(i), owner)) {1177 // noescape blocks should not be retained by the method.1178 if (MD && MD->parameters()[i]->hasAttr<NoEscapeAttr>())1179 continue;1180 return diagnoseRetainCycle(SemaRef, capturer, owner);1181 }1182 }1183}1184 1185/// Check a property assign to see if it's likely to cause a retain cycle.1186void SemaObjC::checkRetainCycles(Expr *receiver, Expr *argument) {1187 RetainCycleOwner owner;1188 if (!findRetainCycleOwner(SemaRef, receiver, owner))1189 return;1190 1191 if (Expr *capturer = findCapturingExpr(SemaRef, argument, owner))1192 diagnoseRetainCycle(SemaRef, capturer, owner);1193}1194 1195void SemaObjC::checkRetainCycles(VarDecl *Var, Expr *Init) {1196 RetainCycleOwner Owner;1197 if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner))1198 return;1199 1200 // Because we don't have an expression for the variable, we have to set the1201 // location explicitly here.1202 Owner.Loc = Var->getLocation();1203 Owner.Range = Var->getSourceRange();1204 1205 if (Expr *Capturer = findCapturingExpr(SemaRef, Init, Owner))1206 diagnoseRetainCycle(SemaRef, Capturer, Owner);1207}1208 1209/// CheckObjCString - Checks that the argument to the builtin1210/// CFString constructor is correct1211/// Note: It might also make sense to do the UTF-16 conversion here (would1212/// simplify the backend).1213bool SemaObjC::CheckObjCString(Expr *Arg) {1214 Arg = Arg->IgnoreParenCasts();1215 StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);1216 1217 if (!Literal || !Literal->isOrdinary()) {1218 Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant)1219 << Arg->getSourceRange();1220 return true;1221 }1222 1223 if (Literal->containsNonAsciiOrNull()) {1224 StringRef String = Literal->getString();1225 unsigned NumBytes = String.size();1226 SmallVector<llvm::UTF16, 128> ToBuf(NumBytes);1227 const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data();1228 llvm::UTF16 *ToPtr = &ToBuf[0];1229 1230 llvm::ConversionResult Result =1231 llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr,1232 ToPtr + NumBytes, llvm::strictConversion);1233 // Check for conversion failure.1234 if (Result != llvm::conversionOK)1235 Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated)1236 << Arg->getSourceRange();1237 }1238 return false;1239}1240 1241bool SemaObjC::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,1242 ArrayRef<const Expr *> Args) {1243 VariadicCallType CallType = Method->isVariadic()1244 ? VariadicCallType::Method1245 : VariadicCallType::DoesNotApply;1246 1247 SemaRef.checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args,1248 /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),1249 CallType);1250 1251 SemaRef.CheckTCBEnforcement(lbrac, Method);1252 1253 return false;1254}1255 1256const DeclContext *SemaObjC::getCurObjCLexicalContext() const {1257 const DeclContext *DC = SemaRef.getCurLexicalContext();1258 // A category implicitly has the attribute of the interface.1259 if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC))1260 DC = CatD->getClassInterface();1261 return DC;1262}1263 1264/// Retrieve the identifier "NSError".1265IdentifierInfo *SemaObjC::getNSErrorIdent() {1266 if (!Ident_NSError)1267 Ident_NSError = SemaRef.PP.getIdentifierInfo("NSError");1268 1269 return Ident_NSError;1270}1271 1272void SemaObjC::ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl) {1273 assert(1274 IDecl->getLexicalParent() == SemaRef.CurContext &&1275 "The next DeclContext should be lexically contained in the current one.");1276 SemaRef.CurContext = IDecl;1277}1278 1279void SemaObjC::ActOnObjCContainerFinishDefinition() {1280 // Exit this scope of this interface definition.1281 SemaRef.PopDeclContext();1282}1283 1284void SemaObjC::ActOnObjCTemporaryExitContainerContext(1285 ObjCContainerDecl *ObjCCtx) {1286 assert(ObjCCtx == SemaRef.CurContext && "Mismatch of container contexts");1287 SemaRef.OriginalLexicalContext = ObjCCtx;1288 ActOnObjCContainerFinishDefinition();1289}1290 1291void SemaObjC::ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx) {1292 ActOnObjCContainerStartDefinition(ObjCCtx);1293 SemaRef.OriginalLexicalContext = nullptr;1294}1295 1296/// Find the protocol with the given name, if any.1297ObjCProtocolDecl *SemaObjC::LookupProtocol(IdentifierInfo *II,1298 SourceLocation IdLoc,1299 RedeclarationKind Redecl) {1300 Decl *D = SemaRef.LookupSingleName(SemaRef.TUScope, II, IdLoc,1301 Sema::LookupObjCProtocolName, Redecl);1302 return cast_or_null<ObjCProtocolDecl>(D);1303}1304 1305/// Determine whether this is an Objective-C writeback conversion,1306/// used for parameter passing when performing automatic reference counting.1307///1308/// \param FromType The type we're converting form.1309///1310/// \param ToType The type we're converting to.1311///1312/// \param ConvertedType The type that will be produced after applying1313/// this conversion.1314bool SemaObjC::isObjCWritebackConversion(QualType FromType, QualType ToType,1315 QualType &ConvertedType) {1316 ASTContext &Context = getASTContext();1317 if (!getLangOpts().ObjCAutoRefCount ||1318 Context.hasSameUnqualifiedType(FromType, ToType))1319 return false;1320 1321 // Parameter must be a pointer to __autoreleasing (with no other qualifiers).1322 QualType ToPointee;1323 if (const PointerType *ToPointer = ToType->getAs<PointerType>())1324 ToPointee = ToPointer->getPointeeType();1325 else1326 return false;1327 1328 Qualifiers ToQuals = ToPointee.getQualifiers();1329 if (!ToPointee->isObjCLifetimeType() ||1330 ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing ||1331 !ToQuals.withoutObjCLifetime().empty())1332 return false;1333 1334 // Argument must be a pointer to __strong to __weak.1335 QualType FromPointee;1336 if (const PointerType *FromPointer = FromType->getAs<PointerType>())1337 FromPointee = FromPointer->getPointeeType();1338 else1339 return false;1340 1341 Qualifiers FromQuals = FromPointee.getQualifiers();1342 if (!FromPointee->isObjCLifetimeType() ||1343 (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong &&1344 FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak))1345 return false;1346 1347 // Make sure that we have compatible qualifiers.1348 FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing);1349 if (!ToQuals.compatiblyIncludes(FromQuals, getASTContext()))1350 return false;1351 1352 // Remove qualifiers from the pointee type we're converting from; they1353 // aren't used in the compatibility check belong, and we'll be adding back1354 // qualifiers (with __autoreleasing) if the compatibility check succeeds.1355 FromPointee = FromPointee.getUnqualifiedType();1356 1357 // The unqualified form of the pointee types must be compatible.1358 ToPointee = ToPointee.getUnqualifiedType();1359 bool IncompatibleObjC;1360 if (Context.typesAreCompatible(FromPointee, ToPointee))1361 FromPointee = ToPointee;1362 else if (!SemaRef.isObjCPointerConversion(FromPointee, ToPointee, FromPointee,1363 IncompatibleObjC))1364 return false;1365 1366 /// Construct the type we're converting to, which is a pointer to1367 /// __autoreleasing pointee.1368 FromPointee = Context.getQualifiedType(FromPointee, FromQuals);1369 ConvertedType = Context.getPointerType(FromPointee);1370 return true;1371}1372 1373/// CheckSubscriptingKind - This routine decide what type1374/// of indexing represented by "FromE" is being done.1375SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) {1376 // If the expression already has integral or enumeration type, we're golden.1377 QualType T = FromE->getType();1378 if (T->isIntegralOrEnumerationType())1379 return SemaObjC::OS_Array;1380 1381 // If we don't have a class type in C++, there's no way we can get an1382 // expression of integral or enumeration type.1383 const RecordType *RecordTy = T->getAsCanonical<RecordType>();1384 if (!RecordTy && (T->isObjCObjectPointerType() || T->isVoidPointerType()))1385 // All other scalar cases are assumed to be dictionary indexing which1386 // caller handles, with diagnostics if needed.1387 return SemaObjC::OS_Dictionary;1388 if (!getLangOpts().CPlusPlus || !RecordTy || RecordTy->isIncompleteType()) {1389 // No indexing can be done. Issue diagnostics and quit.1390 const Expr *IndexExpr = FromE->IgnoreParenImpCasts();1391 if (isa<StringLiteral>(IndexExpr))1392 Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)1393 << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");1394 else1395 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) << T;1396 return SemaObjC::OS_Error;1397 }1398 1399 // We must have a complete class type.1400 if (SemaRef.RequireCompleteType(FromE->getExprLoc(), T,1401 diag::err_objc_index_incomplete_class_type,1402 FromE))1403 return SemaObjC::OS_Error;1404 1405 // Look for a conversion to an integral, enumeration type, or1406 // objective-C pointer type.1407 int NoIntegrals = 0, NoObjCIdPointers = 0;1408 SmallVector<CXXConversionDecl *, 4> ConversionDecls;1409 1410 for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())1411 ->getDefinitionOrSelf()1412 ->getVisibleConversionFunctions()) {1413 if (CXXConversionDecl *Conversion =1414 dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {1415 QualType CT = Conversion->getConversionType().getNonReferenceType();1416 if (CT->isIntegralOrEnumerationType()) {1417 ++NoIntegrals;1418 ConversionDecls.push_back(Conversion);1419 } else if (CT->isObjCIdType() || CT->isBlockPointerType()) {1420 ++NoObjCIdPointers;1421 ConversionDecls.push_back(Conversion);1422 }1423 }1424 }1425 if (NoIntegrals == 1 && NoObjCIdPointers == 0)1426 return SemaObjC::OS_Array;1427 if (NoIntegrals == 0 && NoObjCIdPointers == 1)1428 return SemaObjC::OS_Dictionary;1429 if (NoIntegrals == 0 && NoObjCIdPointers == 0) {1430 // No conversion function was found. Issue diagnostic and return.1431 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)1432 << FromE->getType();1433 return SemaObjC::OS_Error;1434 }1435 Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)1436 << FromE->getType();1437 for (unsigned int i = 0; i < ConversionDecls.size(); i++)1438 Diag(ConversionDecls[i]->getLocation(),1439 diag::note_conv_function_declared_at);1440 1441 return SemaObjC::OS_Error;1442}1443 1444void SemaObjC::AddCFAuditedAttribute(Decl *D) {1445 ASTContext &Context = getASTContext();1446 auto IdLoc = SemaRef.PP.getPragmaARCCFCodeAuditedInfo();1447 if (!IdLoc.getLoc().isValid())1448 return;1449 1450 // Don't add a redundant or conflicting attribute.1451 if (D->hasAttr<CFAuditedTransferAttr>() ||1452 D->hasAttr<CFUnknownTransferAttr>())1453 return;1454 1455 AttributeCommonInfo Info(IdLoc.getIdentifierInfo(),1456 SourceRange(IdLoc.getLoc()),1457 AttributeCommonInfo::Form::Pragma());1458 D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info));1459}1460 1461bool SemaObjC::isCFError(RecordDecl *RD) {1462 // If we already know about CFError, test it directly.1463 if (CFError)1464 return CFError == RD;1465 1466 // Check whether this is CFError, which we identify based on its bridge to1467 // NSError. CFErrorRef used to be declared with "objc_bridge" but is now1468 // declared with "objc_bridge_mutable", so look for either one of the two1469 // attributes.1470 if (RD->getTagKind() == TagTypeKind::Struct) {1471 IdentifierInfo *bridgedType = nullptr;1472 if (auto bridgeAttr = RD->getAttr<ObjCBridgeAttr>())1473 bridgedType = bridgeAttr->getBridgedType();1474 else if (auto bridgeAttr = RD->getAttr<ObjCBridgeMutableAttr>())1475 bridgedType = bridgeAttr->getBridgedType();1476 1477 if (bridgedType == getNSErrorIdent()) {1478 CFError = RD;1479 return true;1480 }1481 }1482 1483 return false;1484}1485 1486bool SemaObjC::isNSStringType(QualType T, bool AllowNSAttributedString) {1487 const auto *PT = T->getAs<ObjCObjectPointerType>();1488 if (!PT)1489 return false;1490 1491 ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();1492 if (!Cls)1493 return false;1494 1495 IdentifierInfo *ClsName = Cls->getIdentifier();1496 1497 if (AllowNSAttributedString &&1498 ClsName == &getASTContext().Idents.get("NSAttributedString"))1499 return true;1500 // FIXME: Should we walk the chain of classes?1501 return ClsName == &getASTContext().Idents.get("NSString") ||1502 ClsName == &getASTContext().Idents.get("NSMutableString");1503}1504 1505bool SemaObjC::isCFStringType(QualType T) {1506 const auto *PT = T->getAs<PointerType>();1507 if (!PT)1508 return false;1509 1510 const auto *RT = PT->getPointeeType()->getAsCanonical<RecordType>();1511 if (!RT)1512 return false;1513 1514 const RecordDecl *RD = RT->getDecl();1515 if (RD->getTagKind() != TagTypeKind::Struct)1516 return false;1517 1518 return RD->getIdentifier() == &getASTContext().Idents.get("__CFString");1519}1520 1521static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {1522 // The IBOutlet/IBOutletCollection attributes only apply to instance1523 // variables or properties of Objective-C classes. The outlet must also1524 // have an object reference type.1525 if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {1526 if (!VD->getType()->getAs<ObjCObjectPointerType>()) {1527 S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)1528 << AL << VD->getType() << 0;1529 return false;1530 }1531 } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {1532 if (!PD->getType()->getAs<ObjCObjectPointerType>()) {1533 S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)1534 << AL << PD->getType() << 1;1535 return false;1536 }1537 } else {1538 S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL;1539 return false;1540 }1541 1542 return true;1543}1544 1545void SemaObjC::handleIBOutlet(Decl *D, const ParsedAttr &AL) {1546 if (!checkIBOutletCommon(SemaRef, D, AL))1547 return;1548 1549 D->addAttr(::new (getASTContext()) IBOutletAttr(getASTContext(), AL));1550}1551 1552void SemaObjC::handleIBOutletCollection(Decl *D, const ParsedAttr &AL) {1553 1554 ASTContext &Context = getASTContext();1555 // The iboutletcollection attribute can have zero or one arguments.1556 if (AL.getNumArgs() > 1) {1557 Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;1558 return;1559 }1560 1561 if (!checkIBOutletCommon(SemaRef, D, AL))1562 return;1563 1564 ParsedType PT;1565 1566 if (AL.hasParsedType())1567 PT = AL.getTypeArg();1568 else {1569 PT = SemaRef.getTypeName(1570 Context.Idents.get("NSObject"), AL.getLoc(),1571 SemaRef.getScopeForContext(D->getDeclContext()->getParent()));1572 if (!PT) {1573 Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject";1574 return;1575 }1576 }1577 1578 TypeSourceInfo *QTLoc = nullptr;1579 QualType QT = SemaRef.GetTypeFromParser(PT, &QTLoc);1580 if (!QTLoc)1581 QTLoc = Context.getTrivialTypeSourceInfo(QT, AL.getLoc());1582 1583 // Diagnose use of non-object type in iboutletcollection attribute.1584 // FIXME. Gnu attribute extension ignores use of builtin types in1585 // attributes. So, __attribute__((iboutletcollection(char))) will be1586 // treated as __attribute__((iboutletcollection())).1587 if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {1588 Diag(AL.getLoc(), QT->isBuiltinType()1589 ? diag::err_iboutletcollection_builtintype1590 : diag::err_iboutletcollection_type)1591 << QT;1592 return;1593 }1594 1595 D->addAttr(::new (Context) IBOutletCollectionAttr(Context, AL, QTLoc));1596}1597 1598void SemaObjC::handleSuppresProtocolAttr(Decl *D, const ParsedAttr &AL) {1599 if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {1600 Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)1601 << AL << AL.getRange();1602 return;1603 }1604 1605 D->addAttr(::new (getASTContext())1606 ObjCExplicitProtocolImplAttr(getASTContext(), AL));1607}1608 1609void SemaObjC::handleDirectAttr(Decl *D, const ParsedAttr &AL) {1610 // objc_direct cannot be set on methods declared in the context of a protocol1611 if (isa<ObjCProtocolDecl>(D->getDeclContext())) {1612 Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false;1613 return;1614 }1615 1616 if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) {1617 handleSimpleAttribute<ObjCDirectAttr>(*this, D, AL);1618 } else {1619 Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;1620 }1621}1622 1623void SemaObjC::handleDirectMembersAttr(Decl *D, const ParsedAttr &AL) {1624 if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) {1625 handleSimpleAttribute<ObjCDirectMembersAttr>(*this, D, AL);1626 } else {1627 Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;1628 }1629}1630 1631void SemaObjC::handleMethodFamilyAttr(Decl *D, const ParsedAttr &AL) {1632 const auto *M = cast<ObjCMethodDecl>(D);1633 if (!AL.isArgIdent(0)) {1634 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)1635 << AL << 1 << AANT_ArgumentIdentifier;1636 return;1637 }1638 1639 IdentifierLoc *IL = AL.getArgAsIdent(0);1640 ObjCMethodFamilyAttr::FamilyKind F;1641 if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(1642 IL->getIdentifierInfo()->getName(), F)) {1643 Diag(IL->getLoc(), diag::warn_attribute_type_not_supported)1644 << AL << IL->getIdentifierInfo();1645 return;1646 }1647 1648 if (F == ObjCMethodFamilyAttr::OMF_init &&1649 !M->getReturnType()->isObjCObjectPointerType()) {1650 Diag(M->getLocation(), diag::err_init_method_bad_return_type)1651 << M->getReturnType();1652 // Ignore the attribute.1653 return;1654 }1655 1656 D->addAttr(new (getASTContext())1657 ObjCMethodFamilyAttr(getASTContext(), AL, F));1658}1659 1660void SemaObjC::handleNSObject(Decl *D, const ParsedAttr &AL) {1661 if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {1662 QualType T = TD->getUnderlyingType();1663 if (!T->isCARCBridgableType()) {1664 Diag(TD->getLocation(), diag::err_nsobject_attribute);1665 return;1666 }1667 } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {1668 QualType T = PD->getType();1669 if (!T->isCARCBridgableType()) {1670 Diag(PD->getLocation(), diag::err_nsobject_attribute);1671 return;1672 }1673 } else {1674 // It is okay to include this attribute on properties, e.g.:1675 //1676 // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));1677 //1678 // In this case it follows tradition and suppresses an error in the above1679 // case.1680 Diag(D->getLocation(), diag::warn_nsobject_attribute);1681 }1682 D->addAttr(::new (getASTContext()) ObjCNSObjectAttr(getASTContext(), AL));1683}1684 1685void SemaObjC::handleIndependentClass(Decl *D, const ParsedAttr &AL) {1686 if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {1687 QualType T = TD->getUnderlyingType();1688 if (!T->isObjCObjectPointerType()) {1689 Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);1690 return;1691 }1692 } else {1693 Diag(D->getLocation(), diag::warn_independentclass_attribute);1694 return;1695 }1696 D->addAttr(::new (getASTContext())1697 ObjCIndependentClassAttr(getASTContext(), AL));1698}1699 1700void SemaObjC::handleBlocksAttr(Decl *D, const ParsedAttr &AL) {1701 if (!AL.isArgIdent(0)) {1702 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)1703 << AL << 1 << AANT_ArgumentIdentifier;1704 return;1705 }1706 1707 IdentifierInfo *II = AL.getArgAsIdent(0)->getIdentifierInfo();1708 BlocksAttr::BlockType type;1709 if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {1710 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;1711 return;1712 }1713 1714 D->addAttr(::new (getASTContext()) BlocksAttr(getASTContext(), AL, type));1715}1716 1717static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {1718 return QT->isDependentType() || QT->isObjCRetainableType();1719}1720 1721static bool isValidSubjectOfNSAttribute(QualType QT) {1722 return QT->isDependentType() || QT->isObjCObjectPointerType() ||1723 QT->isObjCNSObjectType();1724}1725 1726static bool isValidSubjectOfCFAttribute(QualType QT) {1727 return QT->isDependentType() || QT->isPointerType() ||1728 isValidSubjectOfNSAttribute(QT);1729}1730 1731static bool isValidSubjectOfOSAttribute(QualType QT) {1732 if (QT->isDependentType())1733 return true;1734 QualType PT = QT->getPointeeType();1735 return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr;1736}1737 1738void SemaObjC::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,1739 Sema::RetainOwnershipKind K,1740 bool IsTemplateInstantiation) {1741 ValueDecl *VD = cast<ValueDecl>(D);1742 switch (K) {1743 case Sema::RetainOwnershipKind::OS:1744 handleSimpleAttributeOrDiagnose<OSConsumedAttr>(1745 *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()),1746 diag::warn_ns_attribute_wrong_parameter_type,1747 /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1);1748 return;1749 case Sema::RetainOwnershipKind::NS:1750 handleSimpleAttributeOrDiagnose<NSConsumedAttr>(1751 *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()),1752 1753 // These attributes are normally just advisory, but in ARC, ns_consumed1754 // is significant. Allow non-dependent code to contain inappropriate1755 // attributes even in ARC, but require template instantiations to be1756 // set up correctly.1757 ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount)1758 ? diag::err_ns_attribute_wrong_parameter_type1759 : diag::warn_ns_attribute_wrong_parameter_type),1760 /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0);1761 return;1762 case Sema::RetainOwnershipKind::CF:1763 handleSimpleAttributeOrDiagnose<CFConsumedAttr>(1764 *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()),1765 diag::warn_ns_attribute_wrong_parameter_type,1766 /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1);1767 return;1768 }1769}1770 1771Sema::RetainOwnershipKind1772SemaObjC::parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) {1773 switch (AL.getKind()) {1774 case ParsedAttr::AT_CFConsumed:1775 case ParsedAttr::AT_CFReturnsRetained:1776 case ParsedAttr::AT_CFReturnsNotRetained:1777 return Sema::RetainOwnershipKind::CF;1778 case ParsedAttr::AT_OSConsumesThis:1779 case ParsedAttr::AT_OSConsumed:1780 case ParsedAttr::AT_OSReturnsRetained:1781 case ParsedAttr::AT_OSReturnsNotRetained:1782 case ParsedAttr::AT_OSReturnsRetainedOnZero:1783 case ParsedAttr::AT_OSReturnsRetainedOnNonZero:1784 return Sema::RetainOwnershipKind::OS;1785 case ParsedAttr::AT_NSConsumesSelf:1786 case ParsedAttr::AT_NSConsumed:1787 case ParsedAttr::AT_NSReturnsRetained:1788 case ParsedAttr::AT_NSReturnsNotRetained:1789 case ParsedAttr::AT_NSReturnsAutoreleased:1790 return Sema::RetainOwnershipKind::NS;1791 default:1792 llvm_unreachable("Wrong argument supplied");1793 }1794}1795 1796bool SemaObjC::checkNSReturnsRetainedReturnType(SourceLocation Loc,1797 QualType QT) {1798 if (isValidSubjectOfNSReturnsRetainedAttribute(QT))1799 return false;1800 1801 Diag(Loc, diag::warn_ns_attribute_wrong_return_type)1802 << "'ns_returns_retained'" << 0 << 0;1803 return true;1804}1805 1806/// \return whether the parameter is a pointer to OSObject pointer.1807bool SemaObjC::isValidOSObjectOutParameter(const Decl *D) {1808 const auto *PVD = dyn_cast<ParmVarDecl>(D);1809 if (!PVD)1810 return false;1811 QualType QT = PVD->getType();1812 QualType PT = QT->getPointeeType();1813 return !PT.isNull() && isValidSubjectOfOSAttribute(PT);1814}1815 1816void SemaObjC::handleXReturnsXRetainedAttr(Decl *D, const ParsedAttr &AL) {1817 QualType ReturnType;1818 Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);1819 1820 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {1821 ReturnType = MD->getReturnType();1822 } else if (getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&1823 (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) {1824 return; // ignore: was handled as a type attribute1825 } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {1826 ReturnType = PD->getType();1827 } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {1828 ReturnType = FD->getReturnType();1829 } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {1830 // Attributes on parameters are used for out-parameters,1831 // passed as pointers-to-pointers.1832 unsigned DiagID = K == Sema::RetainOwnershipKind::CF1833 ? /*pointer-to-CF-pointer*/ 21834 : /*pointer-to-OSObject-pointer*/ 3;1835 ReturnType = Param->getType()->getPointeeType();1836 if (ReturnType.isNull()) {1837 Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)1838 << AL << DiagID << AL.getRange();1839 return;1840 }1841 } else if (AL.isUsedAsTypeAttr()) {1842 return;1843 } else {1844 AttributeDeclKind ExpectedDeclKind;1845 switch (AL.getKind()) {1846 default:1847 llvm_unreachable("invalid ownership attribute");1848 case ParsedAttr::AT_NSReturnsRetained:1849 case ParsedAttr::AT_NSReturnsAutoreleased:1850 case ParsedAttr::AT_NSReturnsNotRetained:1851 ExpectedDeclKind = ExpectedFunctionOrMethod;1852 break;1853 1854 case ParsedAttr::AT_OSReturnsRetained:1855 case ParsedAttr::AT_OSReturnsNotRetained:1856 case ParsedAttr::AT_CFReturnsRetained:1857 case ParsedAttr::AT_CFReturnsNotRetained:1858 ExpectedDeclKind = ExpectedFunctionMethodOrParameter;1859 break;1860 }1861 Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type)1862 << AL.getRange() << AL << AL.isRegularKeywordAttribute()1863 << ExpectedDeclKind;1864 return;1865 }1866 1867 bool TypeOK;1868 bool Cf;1869 unsigned ParmDiagID = 2; // Pointer-to-CF-pointer1870 switch (AL.getKind()) {1871 default:1872 llvm_unreachable("invalid ownership attribute");1873 case ParsedAttr::AT_NSReturnsRetained:1874 TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);1875 Cf = false;1876 break;1877 1878 case ParsedAttr::AT_NSReturnsAutoreleased:1879 case ParsedAttr::AT_NSReturnsNotRetained:1880 TypeOK = isValidSubjectOfNSAttribute(ReturnType);1881 Cf = false;1882 break;1883 1884 case ParsedAttr::AT_CFReturnsRetained:1885 case ParsedAttr::AT_CFReturnsNotRetained:1886 TypeOK = isValidSubjectOfCFAttribute(ReturnType);1887 Cf = true;1888 break;1889 1890 case ParsedAttr::AT_OSReturnsRetained:1891 case ParsedAttr::AT_OSReturnsNotRetained:1892 TypeOK = isValidSubjectOfOSAttribute(ReturnType);1893 Cf = true;1894 ParmDiagID = 3; // Pointer-to-OSObject-pointer1895 break;1896 }1897 1898 if (!TypeOK) {1899 if (AL.isUsedAsTypeAttr())1900 return;1901 1902 if (isa<ParmVarDecl>(D)) {1903 Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)1904 << AL << ParmDiagID << AL.getRange();1905 } else {1906 // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.1907 enum : unsigned { Function, Method, Property } SubjectKind = Function;1908 if (isa<ObjCMethodDecl>(D))1909 SubjectKind = Method;1910 else if (isa<ObjCPropertyDecl>(D))1911 SubjectKind = Property;1912 Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)1913 << AL << SubjectKind << Cf << AL.getRange();1914 }1915 return;1916 }1917 1918 switch (AL.getKind()) {1919 default:1920 llvm_unreachable("invalid ownership attribute");1921 case ParsedAttr::AT_NSReturnsAutoreleased:1922 handleSimpleAttribute<NSReturnsAutoreleasedAttr>(*this, D, AL);1923 return;1924 case ParsedAttr::AT_CFReturnsNotRetained:1925 handleSimpleAttribute<CFReturnsNotRetainedAttr>(*this, D, AL);1926 return;1927 case ParsedAttr::AT_NSReturnsNotRetained:1928 handleSimpleAttribute<NSReturnsNotRetainedAttr>(*this, D, AL);1929 return;1930 case ParsedAttr::AT_CFReturnsRetained:1931 handleSimpleAttribute<CFReturnsRetainedAttr>(*this, D, AL);1932 return;1933 case ParsedAttr::AT_NSReturnsRetained:1934 handleSimpleAttribute<NSReturnsRetainedAttr>(*this, D, AL);1935 return;1936 case ParsedAttr::AT_OSReturnsRetained:1937 handleSimpleAttribute<OSReturnsRetainedAttr>(*this, D, AL);1938 return;1939 case ParsedAttr::AT_OSReturnsNotRetained:1940 handleSimpleAttribute<OSReturnsNotRetainedAttr>(*this, D, AL);1941 return;1942 };1943}1944 1945void SemaObjC::handleReturnsInnerPointerAttr(Decl *D, const ParsedAttr &Attrs) {1946 const int EP_ObjCMethod = 1;1947 const int EP_ObjCProperty = 2;1948 1949 SourceLocation loc = Attrs.getLoc();1950 QualType resultType;1951 if (isa<ObjCMethodDecl>(D))1952 resultType = cast<ObjCMethodDecl>(D)->getReturnType();1953 else1954 resultType = cast<ObjCPropertyDecl>(D)->getType();1955 1956 if (!resultType->isReferenceType() &&1957 (!resultType->isPointerType() || resultType->isObjCRetainableType())) {1958 Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)1959 << SourceRange(loc) << Attrs1960 << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)1961 << /*non-retainable pointer*/ 2;1962 1963 // Drop the attribute.1964 return;1965 }1966 1967 D->addAttr(::new (getASTContext())1968 ObjCReturnsInnerPointerAttr(getASTContext(), Attrs));1969}1970 1971void SemaObjC::handleRequiresSuperAttr(Decl *D, const ParsedAttr &Attrs) {1972 const auto *Method = cast<ObjCMethodDecl>(D);1973 1974 const DeclContext *DC = Method->getDeclContext();1975 if (const auto *PDecl = dyn_cast_if_present<ObjCProtocolDecl>(DC)) {1976 Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol)1977 << Attrs << 0;1978 Diag(PDecl->getLocation(), diag::note_protocol_decl);1979 return;1980 }1981 if (Method->getMethodFamily() == OMF_dealloc) {1982 Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol)1983 << Attrs << 1;1984 return;1985 }1986 1987 D->addAttr(::new (getASTContext())1988 ObjCRequiresSuperAttr(getASTContext(), Attrs));1989}1990 1991void SemaObjC::handleNSErrorDomain(Decl *D, const ParsedAttr &Attr) {1992 if (!isa<TagDecl>(D)) {1993 Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;1994 return;1995 }1996 1997 IdentifierLoc *IdentLoc =1998 Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;1999 if (!IdentLoc || !IdentLoc->getIdentifierInfo()) {2000 // Try to locate the argument directly.2001 SourceLocation Loc = Attr.getLoc();2002 if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))2003 Loc = Attr.getArgAsExpr(0)->getBeginLoc();2004 2005 Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;2006 return;2007 }2008 2009 // Verify that the identifier is a valid decl in the C decl namespace.2010 LookupResult Result(SemaRef, DeclarationName(IdentLoc->getIdentifierInfo()),2011 SourceLocation(),2012 Sema::LookupNameKind::LookupOrdinaryName);2013 if (!SemaRef.LookupName(Result, SemaRef.TUScope) ||2014 !Result.getAsSingle<VarDecl>()) {2015 Diag(IdentLoc->getLoc(), diag::err_nserrordomain_invalid_decl)2016 << 1 << IdentLoc->getIdentifierInfo();2017 return;2018 }2019 2020 D->addAttr(::new (getASTContext()) NSErrorDomainAttr(2021 getASTContext(), Attr, IdentLoc->getIdentifierInfo()));2022}2023 2024void SemaObjC::handleBridgeAttr(Decl *D, const ParsedAttr &AL) {2025 IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;2026 2027 if (!Parm) {2028 Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;2029 return;2030 }2031 2032 // Typedefs only allow objc_bridge(id) and have some additional checking.2033 if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {2034 if (!Parm->getIdentifierInfo()->isStr("id")) {2035 Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL;2036 return;2037 }2038 2039 // Only allow 'cv void *'.2040 QualType T = TD->getUnderlyingType();2041 if (!T->isVoidPointerType()) {2042 Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);2043 return;2044 }2045 }2046 2047 D->addAttr(::new (getASTContext()) ObjCBridgeAttr(getASTContext(), AL,2048 Parm->getIdentifierInfo()));2049}2050 2051void SemaObjC::handleBridgeMutableAttr(Decl *D, const ParsedAttr &AL) {2052 IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;2053 2054 if (!Parm) {2055 Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;2056 return;2057 }2058 2059 D->addAttr(::new (getASTContext()) ObjCBridgeMutableAttr(2060 getASTContext(), AL, Parm->getIdentifierInfo()));2061}2062 2063void SemaObjC::handleBridgeRelatedAttr(Decl *D, const ParsedAttr &AL) {2064 IdentifierInfo *RelatedClass =2065 AL.isArgIdent(0) ? AL.getArgAsIdent(0)->getIdentifierInfo() : nullptr;2066 if (!RelatedClass) {2067 Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;2068 return;2069 }2070 IdentifierInfo *ClassMethod =2071 AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->getIdentifierInfo() : nullptr;2072 IdentifierInfo *InstanceMethod =2073 AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->getIdentifierInfo() : nullptr;2074 D->addAttr(::new (getASTContext()) ObjCBridgeRelatedAttr(2075 getASTContext(), AL, RelatedClass, ClassMethod, InstanceMethod));2076}2077 2078void SemaObjC::handleDesignatedInitializer(Decl *D, const ParsedAttr &AL) {2079 DeclContext *Ctx = D->getDeclContext();2080 2081 // This attribute can only be applied to methods in interfaces or class2082 // extensions.2083 if (!isa<ObjCInterfaceDecl>(Ctx) &&2084 !(isa<ObjCCategoryDecl>(Ctx) &&2085 cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) {2086 Diag(D->getLocation(), diag::err_designated_init_attr_non_init);2087 return;2088 }2089 2090 ObjCInterfaceDecl *IFace;2091 if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx))2092 IFace = CatDecl->getClassInterface();2093 else2094 IFace = cast<ObjCInterfaceDecl>(Ctx);2095 2096 if (!IFace)2097 return;2098 2099 IFace->setHasDesignatedInitializers();2100 D->addAttr(::new (getASTContext())2101 ObjCDesignatedInitializerAttr(getASTContext(), AL));2102}2103 2104void SemaObjC::handleRuntimeName(Decl *D, const ParsedAttr &AL) {2105 StringRef MetaDataName;2106 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, MetaDataName))2107 return;2108 D->addAttr(::new (getASTContext())2109 ObjCRuntimeNameAttr(getASTContext(), AL, MetaDataName));2110}2111 2112// When a user wants to use objc_boxable with a union or struct2113// but they don't have access to the declaration (legacy/third-party code)2114// then they can 'enable' this feature with a typedef:2115// typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;2116void SemaObjC::handleBoxable(Decl *D, const ParsedAttr &AL) {2117 bool notify = false;2118 2119 auto *RD = dyn_cast<RecordDecl>(D);2120 if (RD && RD->getDefinition()) {2121 RD = RD->getDefinition();2122 notify = true;2123 }2124 2125 if (RD) {2126 ObjCBoxableAttr *BoxableAttr =2127 ::new (getASTContext()) ObjCBoxableAttr(getASTContext(), AL);2128 RD->addAttr(BoxableAttr);2129 if (notify) {2130 // we need to notify ASTReader/ASTWriter about2131 // modification of existing declaration2132 if (ASTMutationListener *L = SemaRef.getASTMutationListener())2133 L->AddedAttributeToRecord(BoxableAttr, RD);2134 }2135 }2136}2137 2138void SemaObjC::handleOwnershipAttr(Decl *D, const ParsedAttr &AL) {2139 if (hasDeclarator(D))2140 return;2141 2142 Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)2143 << AL.getRange() << AL << AL.isRegularKeywordAttribute()2144 << ExpectedVariable;2145}2146 2147void SemaObjC::handlePreciseLifetimeAttr(Decl *D, const ParsedAttr &AL) {2148 const auto *VD = cast<ValueDecl>(D);2149 QualType QT = VD->getType();2150 2151 if (!QT->isDependentType() && !QT->isObjCLifetimeType()) {2152 Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type) << QT;2153 return;2154 }2155 2156 Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime();2157 2158 // If we have no lifetime yet, check the lifetime we're presumably2159 // going to infer.2160 if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType())2161 Lifetime = QT->getObjCARCImplicitLifetime();2162 2163 switch (Lifetime) {2164 case Qualifiers::OCL_None:2165 assert(QT->isDependentType() &&2166 "didn't infer lifetime for non-dependent type?");2167 break;2168 2169 case Qualifiers::OCL_Weak: // meaningful2170 case Qualifiers::OCL_Strong: // meaningful2171 break;2172 2173 case Qualifiers::OCL_ExplicitNone:2174 case Qualifiers::OCL_Autoreleasing:2175 Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless)2176 << (Lifetime == Qualifiers::OCL_Autoreleasing);2177 break;2178 }2179 2180 D->addAttr(::new (getASTContext())2181 ObjCPreciseLifetimeAttr(getASTContext(), AL));2182}2183 2184static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD,2185 bool DiagnoseFailure) {2186 QualType Ty = VD->getType();2187 if (!Ty->isObjCRetainableType()) {2188 if (DiagnoseFailure) {2189 S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)2190 << 0;2191 }2192 return false;2193 }2194 2195 Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime();2196 2197 // SemaObjC::inferObjCARCLifetime must run after processing decl attributes2198 // (because __block lowers to an attribute), so if the lifetime hasn't been2199 // explicitly specified, infer it locally now.2200 if (LifetimeQual == Qualifiers::OCL_None)2201 LifetimeQual = Ty->getObjCARCImplicitLifetime();2202 2203 // The attributes only really makes sense for __strong variables; ignore any2204 // attempts to annotate a parameter with any other lifetime qualifier.2205 if (LifetimeQual != Qualifiers::OCL_Strong) {2206 if (DiagnoseFailure) {2207 S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)2208 << 1;2209 }2210 return false;2211 }2212 2213 // Tampering with the type of a VarDecl here is a bit of a hack, but we need2214 // to ensure that the variable is 'const' so that we can error on2215 // modification, which can otherwise over-release.2216 VD->setType(Ty.withConst());2217 VD->setARCPseudoStrong(true);2218 return true;2219}2220 2221void SemaObjC::handleExternallyRetainedAttr(Decl *D, const ParsedAttr &AL) {2222 if (auto *VD = dyn_cast<VarDecl>(D)) {2223 assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically");2224 if (!VD->hasLocalStorage()) {2225 Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained) << 0;2226 return;2227 }2228 2229 if (!tryMakeVariablePseudoStrong(SemaRef, VD, /*DiagnoseFailure=*/true))2230 return;2231 2232 handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL);2233 return;2234 }2235 2236 // If D is a function-like declaration (method, block, or function), then we2237 // make every parameter psuedo-strong.2238 unsigned NumParams =2239 hasFunctionProto(D) ? getFunctionOrMethodNumParams(D) : 0;2240 for (unsigned I = 0; I != NumParams; ++I) {2241 auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I));2242 QualType Ty = PVD->getType();2243 2244 // If a user wrote a parameter with __strong explicitly, then assume they2245 // want "real" strong semantics for that parameter. This works because if2246 // the parameter was written with __strong, then the strong qualifier will2247 // be non-local.2248 if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() ==2249 Qualifiers::OCL_Strong)2250 continue;2251 2252 tryMakeVariablePseudoStrong(SemaRef, PVD, /*DiagnoseFailure=*/false);2253 }2254 handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL);2255}2256 2257bool SemaObjC::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {2258 Sema::FormatStringInfo FSI;2259 if ((SemaRef.GetFormatStringType(Format) == FormatStringType::NSString) &&2260 SemaRef.getFormatStringInfo(Format->getFormatIdx(), Format->getFirstArg(),2261 false, true, &FSI)) {2262 Idx = FSI.FormatIdx;2263 return true;2264 }2265 return false;2266}2267 2268/// Diagnose use of %s directive in an NSString which is being passed2269/// as formatting string to formatting method.2270void SemaObjC::DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl *FDecl,2271 Expr **Args,2272 unsigned NumArgs) {2273 unsigned Idx = 0;2274 bool Format = false;2275 ObjCStringFormatFamily SFFamily = FDecl->getObjCFStringFormattingFamily();2276 if (SFFamily == ObjCStringFormatFamily::SFF_CFString) {2277 Idx = 2;2278 Format = true;2279 } else2280 for (const auto *I : FDecl->specific_attrs<FormatAttr>()) {2281 if (GetFormatNSStringIdx(I, Idx)) {2282 Format = true;2283 break;2284 }2285 }2286 if (!Format || NumArgs <= Idx)2287 return;2288 const Expr *FormatExpr = Args[Idx];2289 if (const CStyleCastExpr *CSCE = dyn_cast<CStyleCastExpr>(FormatExpr))2290 FormatExpr = CSCE->getSubExpr();2291 const StringLiteral *FormatString;2292 if (const ObjCStringLiteral *OSL =2293 dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts()))2294 FormatString = OSL->getString();2295 else2296 FormatString = dyn_cast<StringLiteral>(FormatExpr->IgnoreParenImpCasts());2297 if (!FormatString)2298 return;2299 if (SemaRef.FormatStringHasSArg(FormatString)) {2300 Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string)2301 << "%s" << 1 << 1;2302 Diag(FDecl->getLocation(), diag::note_entity_declared_at)2303 << FDecl->getDeclName();2304 }2305}2306 2307bool SemaObjC::isSignedCharBool(QualType Ty) {2308 return Ty->isSpecificBuiltinType(BuiltinType::SChar) && getLangOpts().ObjC &&2309 NSAPIObj->isObjCBOOLType(Ty);2310}2311 2312void SemaObjC::adornBoolConversionDiagWithTernaryFixit(2313 const Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder) {2314 const Expr *Ignored = SourceExpr->IgnoreImplicit();2315 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ignored))2316 Ignored = OVE->getSourceExpr();2317 bool NeedsParens = isa<AbstractConditionalOperator>(Ignored) ||2318 isa<BinaryOperator>(Ignored) ||2319 isa<CXXOperatorCallExpr>(Ignored);2320 SourceLocation EndLoc = SemaRef.getLocForEndOfToken(SourceExpr->getEndLoc());2321 if (NeedsParens)2322 Builder << FixItHint::CreateInsertion(SourceExpr->getBeginLoc(), "(")2323 << FixItHint::CreateInsertion(EndLoc, ")");2324 Builder << FixItHint::CreateInsertion(EndLoc, " ? YES : NO");2325}2326 2327/// Check a single element within a collection literal against the2328/// target element type.2329static void checkCollectionLiteralElement(Sema &S, QualType TargetElementType,2330 Expr *Element, unsigned ElementKind) {2331 // Skip a bitcast to 'id' or qualified 'id'.2332 if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) {2333 if (ICE->getCastKind() == CK_BitCast &&2334 ICE->getSubExpr()->getType()->getAs<ObjCObjectPointerType>())2335 Element = ICE->getSubExpr();2336 }2337 2338 QualType ElementType = Element->getType();2339 ExprResult ElementResult(Element);2340 if (ElementType->getAs<ObjCObjectPointerType>() &&2341 !S.IsAssignConvertCompatible(S.CheckSingleAssignmentConstraints(2342 TargetElementType, ElementResult, false, false))) {2343 S.Diag(Element->getBeginLoc(), diag::warn_objc_collection_literal_element)2344 << ElementType << ElementKind << TargetElementType2345 << Element->getSourceRange();2346 }2347 2348 if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element))2349 S.ObjC().checkArrayLiteral(TargetElementType, ArrayLiteral);2350 else if (auto DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(Element))2351 S.ObjC().checkDictionaryLiteral(TargetElementType, DictionaryLiteral);2352}2353 2354/// Check an Objective-C array literal being converted to the given2355/// target type.2356void SemaObjC::checkArrayLiteral(QualType TargetType,2357 ObjCArrayLiteral *ArrayLiteral) {2358 if (!NSArrayDecl)2359 return;2360 2361 const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();2362 if (!TargetObjCPtr)2363 return;2364 2365 if (TargetObjCPtr->isUnspecialized() ||2366 TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() !=2367 NSArrayDecl->getCanonicalDecl())2368 return;2369 2370 auto TypeArgs = TargetObjCPtr->getTypeArgs();2371 if (TypeArgs.size() != 1)2372 return;2373 2374 QualType TargetElementType = TypeArgs[0];2375 for (unsigned I = 0, N = ArrayLiteral->getNumElements(); I != N; ++I) {2376 checkCollectionLiteralElement(SemaRef, TargetElementType,2377 ArrayLiteral->getElement(I), 0);2378 }2379}2380 2381void SemaObjC::checkDictionaryLiteral(2382 QualType TargetType, ObjCDictionaryLiteral *DictionaryLiteral) {2383 if (!NSDictionaryDecl)2384 return;2385 2386 const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();2387 if (!TargetObjCPtr)2388 return;2389 2390 if (TargetObjCPtr->isUnspecialized() ||2391 TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() !=2392 NSDictionaryDecl->getCanonicalDecl())2393 return;2394 2395 auto TypeArgs = TargetObjCPtr->getTypeArgs();2396 if (TypeArgs.size() != 2)2397 return;2398 2399 QualType TargetKeyType = TypeArgs[0];2400 QualType TargetObjectType = TypeArgs[1];2401 for (unsigned I = 0, N = DictionaryLiteral->getNumElements(); I != N; ++I) {2402 auto Element = DictionaryLiteral->getKeyValueElement(I);2403 checkCollectionLiteralElement(SemaRef, TargetKeyType, Element.Key, 1);2404 checkCollectionLiteralElement(SemaRef, TargetObjectType, Element.Value, 2);2405 }2406}2407 2408} // namespace clang2409