brintos

brintos / llvm-project-archived public Read only

0
0
Text · 82.9 KiB · 7aaa56e Raw
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