//===----- SemaObjC.cpp ---- Semantic Analysis for Objective-C ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements semantic analysis for Objective-C.
///
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaObjC.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Attr.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/Support/ConvertUTF.h"

namespace clang {

SemaObjC::SemaObjC(Sema &S)
    : SemaBase(S), NSNumberDecl(nullptr), NSValueDecl(nullptr),
      NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
      ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
      ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
      DictionaryWithObjectsMethod(nullptr) {}

StmtResult SemaObjC::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
                                                Stmt *First, Expr *collection,
                                                SourceLocation RParenLoc) {
  ASTContext &Context = getASTContext();
  SemaRef.setFunctionHasBranchProtectedScope();

  ExprResult CollectionExprResult =
      CheckObjCForCollectionOperand(ForLoc, collection);

  if (First) {
    QualType FirstType;
    if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) {
      if (!DS->isSingleDecl())
        return StmtError(Diag((*DS->decl_begin())->getLocation(),
                              diag::err_toomany_element_decls));

      VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl());
      if (!D || D->isInvalidDecl())
        return StmtError();

      FirstType = D->getType();
      // C99 6.8.5p3: The declaration part of a 'for' statement shall only
      // declare identifiers for objects having storage class 'auto' or
      // 'register'.
      if (!D->hasLocalStorage())
        return StmtError(
            Diag(D->getLocation(), diag::err_non_local_variable_decl_in_for));

      // If the type contained 'auto', deduce the 'auto' to 'id'.
      if (FirstType->getContainedAutoType()) {
        SourceLocation Loc = D->getLocation();
        OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue);
        Expr *DeducedInit = &OpaqueId;
        sema::TemplateDeductionInfo Info(Loc);
        FirstType = QualType();
        TemplateDeductionResult Result = SemaRef.DeduceAutoType(
            D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info);
        if (Result != TemplateDeductionResult::Success &&
            Result != TemplateDeductionResult::AlreadyDiagnosed)
          SemaRef.DiagnoseAutoDeductionFailure(D, DeducedInit);
        if (FirstType.isNull()) {
          D->setInvalidDecl();
          return StmtError();
        }

        D->setType(FirstType);

        if (!SemaRef.inTemplateInstantiation()) {
          SourceLocation Loc =
              D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
          Diag(Loc, diag::warn_auto_var_is_id) << D->getDeclName();
        }
      }

    } else {
      Expr *FirstE = cast<Expr>(First);
      if (!FirstE->isTypeDependent() && !FirstE->isLValue())
        return StmtError(
            Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue)
            << First->getSourceRange());

      FirstType = static_cast<Expr *>(First)->getType();
      if (FirstType.isConstQualified())
        Diag(ForLoc, diag::err_selector_element_const_type)
            << FirstType << First->getSourceRange();
    }
    if (!FirstType->isDependentType() &&
        !FirstType->isObjCObjectPointerType() &&
        !FirstType->isBlockPointerType())
      return StmtError(Diag(ForLoc, diag::err_selector_element_type)
                       << FirstType << First->getSourceRange());
  }

  if (CollectionExprResult.isInvalid())
    return StmtError();

  CollectionExprResult = SemaRef.ActOnFinishFullExpr(CollectionExprResult.get(),
                                                     /*DiscardedValue*/ false);
  if (CollectionExprResult.isInvalid())
    return StmtError();

  return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(),
                                             nullptr, ForLoc, RParenLoc);
}

ExprResult SemaObjC::CheckObjCForCollectionOperand(SourceLocation forLoc,
                                                   Expr *collection) {
  ASTContext &Context = getASTContext();
  if (!collection)
    return ExprError();

  ExprResult result = SemaRef.CorrectDelayedTyposInExpr(collection);
  if (!result.isUsable())
    return ExprError();
  collection = result.get();

  // Bail out early if we've got a type-dependent expression.
  if (collection->isTypeDependent())
    return collection;

  // Perform normal l-value conversion.
  result = SemaRef.DefaultFunctionArrayLvalueConversion(collection);
  if (result.isInvalid())
    return ExprError();
  collection = result.get();

  // The operand needs to have object-pointer type.
  // TODO: should we do a contextual conversion?
  const ObjCObjectPointerType *pointerType =
      collection->getType()->getAs<ObjCObjectPointerType>();
  if (!pointerType)
    return Diag(forLoc, diag::err_collection_expr_type)
           << collection->getType() << collection->getSourceRange();

  // Check that the operand provides
  //   - countByEnumeratingWithState:objects:count:
  const ObjCObjectType *objectType = pointerType->getObjectType();
  ObjCInterfaceDecl *iface = objectType->getInterface();

  // If we have a forward-declared type, we can't do this check.
  // Under ARC, it is an error not to have a forward-declared class.
  if (iface &&
      (getLangOpts().ObjCAutoRefCount
           ? SemaRef.RequireCompleteType(forLoc, QualType(objectType, 0),
                                         diag::err_arc_collection_forward,
                                         collection)
           : !SemaRef.isCompleteType(forLoc, QualType(objectType, 0)))) {
    // Otherwise, if we have any useful type information, check that
    // the type declares the appropriate method.
  } else if (iface || !objectType->qual_empty()) {
    const IdentifierInfo *selectorIdents[] = {
        &Context.Idents.get("countByEnumeratingWithState"),
        &Context.Idents.get("objects"), &Context.Idents.get("count")};
    Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);

    ObjCMethodDecl *method = nullptr;

    // If there's an interface, look in both the public and private APIs.
    if (iface) {
      method = iface->lookupInstanceMethod(selector);
      if (!method)
        method = iface->lookupPrivateMethod(selector);
    }

    // Also check protocol qualifiers.
    if (!method)
      method = LookupMethodInQualifiedType(selector, pointerType,
                                           /*instance*/ true);

    // If we didn't find it anywhere, give up.
    if (!method) {
      Diag(forLoc, diag::warn_collection_expr_type)
          << collection->getType() << selector << collection->getSourceRange();
    }

    // TODO: check for an incompatible signature?
  }

  // Wrap up any cleanups in the expression.
  return collection;
}

StmtResult SemaObjC::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) {
  if (!S || !B)
    return StmtError();
  ObjCForCollectionStmt *ForStmt = cast<ObjCForCollectionStmt>(S);

  ForStmt->setBody(B);
  return S;
}

StmtResult SemaObjC::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
                                          SourceLocation RParen, Decl *Parm,
                                          Stmt *Body) {
  ASTContext &Context = getASTContext();
  VarDecl *Var = cast_or_null<VarDecl>(Parm);
  if (Var && Var->isInvalidDecl())
    return StmtError();

  return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body);
}

StmtResult SemaObjC::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {
  ASTContext &Context = getASTContext();
  return new (Context) ObjCAtFinallyStmt(AtLoc, Body);
}

StmtResult SemaObjC::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
                                        MultiStmtArg CatchStmts,
                                        Stmt *Finally) {
  ASTContext &Context = getASTContext();
  if (!getLangOpts().ObjCExceptions)
    Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";

  // Objective-C try is incompatible with SEH __try.
  sema::FunctionScopeInfo *FSI = SemaRef.getCurFunction();
  if (FSI->FirstSEHTryLoc.isValid()) {
    Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1;
    Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";
  }

  FSI->setHasObjCTry(AtLoc);
  unsigned NumCatchStmts = CatchStmts.size();
  return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
                               NumCatchStmts, Finally);
}

StmtResult SemaObjC::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
  ASTContext &Context = getASTContext();
  if (Throw) {
    ExprResult Result = SemaRef.DefaultLvalueConversion(Throw);
    if (Result.isInvalid())
      return StmtError();

    Result =
        SemaRef.ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false);
    if (Result.isInvalid())
      return StmtError();
    Throw = Result.get();

    QualType ThrowType = Throw->getType();
    // Make sure the expression type is an ObjC pointer or "void *".
    if (!ThrowType->isDependentType() &&
        !ThrowType->isObjCObjectPointerType()) {
      const PointerType *PT = ThrowType->getAs<PointerType>();
      if (!PT || !PT->getPointeeType()->isVoidType())
        return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object)
                         << Throw->getType() << Throw->getSourceRange());
    }
  }

  return new (Context) ObjCAtThrowStmt(AtLoc, Throw);
}

StmtResult SemaObjC::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
                                          Scope *CurScope) {
  if (!getLangOpts().ObjCExceptions)
    Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw";

  if (!Throw) {
    // @throw without an expression designates a rethrow (which must occur
    // in the context of an @catch clause).
    Scope *AtCatchParent = CurScope;
    while (AtCatchParent && !AtCatchParent->isAtCatchScope())
      AtCatchParent = AtCatchParent->getParent();
    if (!AtCatchParent)
      return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch));
  }
  return BuildObjCAtThrowStmt(AtLoc, Throw);
}

ExprResult SemaObjC::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc,
                                                    Expr *operand) {
  ExprResult result = SemaRef.DefaultLvalueConversion(operand);
  if (result.isInvalid())
    return ExprError();
  operand = result.get();

  // Make sure the expression type is an ObjC pointer or "void *".
  QualType type = operand->getType();
  if (!type->isDependentType() && !type->isObjCObjectPointerType()) {
    const PointerType *pointerType = type->getAs<PointerType>();
    if (!pointerType || !pointerType->getPointeeType()->isVoidType()) {
      if (getLangOpts().CPlusPlus) {
        if (SemaRef.RequireCompleteType(atLoc, type,
                                        diag::err_incomplete_receiver_type))
          return Diag(atLoc, diag::err_objc_synchronized_expects_object)
                 << type << operand->getSourceRange();

        ExprResult result =
            SemaRef.PerformContextuallyConvertToObjCPointer(operand);
        if (result.isInvalid())
          return ExprError();
        if (!result.isUsable())
          return Diag(atLoc, diag::err_objc_synchronized_expects_object)
                 << type << operand->getSourceRange();

        operand = result.get();
      } else {
        return Diag(atLoc, diag::err_objc_synchronized_expects_object)
               << type << operand->getSourceRange();
      }
    }
  }

  // The operand to @synchronized is a full-expression.
  return SemaRef.ActOnFinishFullExpr(operand, /*DiscardedValue*/ false);
}

StmtResult SemaObjC::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
                                                 Expr *SyncExpr,
                                                 Stmt *SyncBody) {
  ASTContext &Context = getASTContext();
  // We can't jump into or indirect-jump out of a @synchronized block.
  SemaRef.setFunctionHasBranchProtectedScope();
  return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);
}

StmtResult SemaObjC::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc,
                                                  Stmt *Body) {
  ASTContext &Context = getASTContext();
  SemaRef.setFunctionHasBranchProtectedScope();
  return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
}

TypeResult SemaObjC::actOnObjCProtocolQualifierType(
    SourceLocation lAngleLoc, ArrayRef<Decl *> protocols,
    ArrayRef<SourceLocation> protocolLocs, SourceLocation rAngleLoc) {
  ASTContext &Context = getASTContext();
  // Form id<protocol-list>.
  QualType Result = Context.getObjCObjectType(
      Context.ObjCBuiltinIdTy, {},
      llvm::ArrayRef((ObjCProtocolDecl *const *)protocols.data(),
                     protocols.size()),
      false);
  Result = Context.getObjCObjectPointerType(Result);

  TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
  TypeLoc ResultTL = ResultTInfo->getTypeLoc();

  auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>();
  ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit

  auto ObjCObjectTL =
      ObjCObjectPointerTL.getPointeeLoc().castAs<ObjCObjectTypeLoc>();
  ObjCObjectTL.setHasBaseTypeAsWritten(false);
  ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation());

  // No type arguments.
  ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
  ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());

  // Fill in protocol qualifiers.
  ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc);
  ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc);
  for (unsigned i = 0, n = protocols.size(); i != n; ++i)
    ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]);

  // We're done. Return the completed type to the parser.
  return SemaRef.CreateParsedType(Result, ResultTInfo);
}

TypeResult SemaObjC::actOnObjCTypeArgsAndProtocolQualifiers(
    Scope *S, SourceLocation Loc, ParsedType BaseType,
    SourceLocation TypeArgsLAngleLoc, ArrayRef<ParsedType> TypeArgs,
    SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc,
    ArrayRef<Decl *> Protocols, ArrayRef<SourceLocation> ProtocolLocs,
    SourceLocation ProtocolRAngleLoc) {
  ASTContext &Context = getASTContext();
  TypeSourceInfo *BaseTypeInfo = nullptr;
  QualType T = SemaRef.GetTypeFromParser(BaseType, &BaseTypeInfo);
  if (T.isNull())
    return true;

  // Handle missing type-source info.
  if (!BaseTypeInfo)
    BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc);

  // Extract type arguments.
  SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos;
  for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) {
    TypeSourceInfo *TypeArgInfo = nullptr;
    QualType TypeArg = SemaRef.GetTypeFromParser(TypeArgs[i], &TypeArgInfo);
    if (TypeArg.isNull()) {
      ActualTypeArgInfos.clear();
      break;
    }

    assert(TypeArgInfo && "No type source info?");
    ActualTypeArgInfos.push_back(TypeArgInfo);
  }

  // Build the object type.
  QualType Result = BuildObjCObjectType(
      T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(),
      TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc,
      ProtocolLAngleLoc,
      llvm::ArrayRef((ObjCProtocolDecl *const *)Protocols.data(),
                     Protocols.size()),
      ProtocolLocs, ProtocolRAngleLoc,
      /*FailOnError=*/false,
      /*Rebuilding=*/false);

  if (Result == T)
    return BaseType;

  // Create source information for this type.
  TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
  TypeLoc ResultTL = ResultTInfo->getTypeLoc();

  // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an
  // object pointer type. Fill in source information for it.
  if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) {
    // The '*' is implicit.
    ObjCObjectPointerTL.setStarLoc(SourceLocation());
    ResultTL = ObjCObjectPointerTL.getPointeeLoc();
  }

  if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) {
    // Protocol qualifier information.
    if (OTPTL.getNumProtocols() > 0) {
      assert(OTPTL.getNumProtocols() == Protocols.size());
      OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
      OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
      for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
        OTPTL.setProtocolLoc(i, ProtocolLocs[i]);
    }

    // We're done. Return the completed type to the parser.
    return SemaRef.CreateParsedType(Result, ResultTInfo);
  }

  auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>();

  // Type argument information.
  if (ObjCObjectTL.getNumTypeArgs() > 0) {
    assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size());
    ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc);
    ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc);
    for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i)
      ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]);
  } else {
    ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
    ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
  }

  // Protocol qualifier information.
  if (ObjCObjectTL.getNumProtocols() > 0) {
    assert(ObjCObjectTL.getNumProtocols() == Protocols.size());
    ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
    ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
    for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
      ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]);
  } else {
    ObjCObjectTL.setProtocolLAngleLoc(SourceLocation());
    ObjCObjectTL.setProtocolRAngleLoc(SourceLocation());
  }

  // Base type.
  ObjCObjectTL.setHasBaseTypeAsWritten(true);
  if (ObjCObjectTL.getType() == T)
    ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc());
  else
    ObjCObjectTL.getBaseLoc().initialize(Context, Loc);

  // We're done. Return the completed type to the parser.
  return SemaRef.CreateParsedType(Result, ResultTInfo);
}

QualType SemaObjC::BuildObjCTypeParamType(
    const ObjCTypeParamDecl *Decl, SourceLocation ProtocolLAngleLoc,
    ArrayRef<ObjCProtocolDecl *> Protocols,
    ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
    bool FailOnError) {
  ASTContext &Context = getASTContext();
  QualType Result = QualType(Decl->getTypeForDecl(), 0);
  if (!Protocols.empty()) {
    bool HasError;
    Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError);
    if (HasError) {
      Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers)
          << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
      if (FailOnError)
        Result = QualType();
    }
    if (FailOnError && Result.isNull())
      return QualType();
  }

  return Result;
}

/// Apply Objective-C type arguments to the given type.
static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
                                  ArrayRef<TypeSourceInfo *> typeArgs,
                                  SourceRange typeArgsRange, bool failOnError,
                                  bool rebuilding) {
  // We can only apply type arguments to an Objective-C class type.
  const auto *objcObjectType = type->getAs<ObjCObjectType>();
  if (!objcObjectType || !objcObjectType->getInterface()) {
    S.Diag(loc, diag::err_objc_type_args_non_class) << type << typeArgsRange;

    if (failOnError)
      return QualType();
    return type;
  }

  // The class type must be parameterized.
  ObjCInterfaceDecl *objcClass = objcObjectType->getInterface();
  ObjCTypeParamList *typeParams = objcClass->getTypeParamList();
  if (!typeParams) {
    S.Diag(loc, diag::err_objc_type_args_non_parameterized_class)
        << objcClass->getDeclName() << FixItHint::CreateRemoval(typeArgsRange);

    if (failOnError)
      return QualType();

    return type;
  }

  // The type must not already be specialized.
  if (objcObjectType->isSpecialized()) {
    S.Diag(loc, diag::err_objc_type_args_specialized_class)
        << type << FixItHint::CreateRemoval(typeArgsRange);

    if (failOnError)
      return QualType();

    return type;
  }

  // Check the type arguments.
  SmallVector<QualType, 4> finalTypeArgs;
  unsigned numTypeParams = typeParams->size();
  bool anyPackExpansions = false;
  for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) {
    TypeSourceInfo *typeArgInfo = typeArgs[i];
    QualType typeArg = typeArgInfo->getType();

    // Type arguments cannot have explicit qualifiers or nullability.
    // We ignore indirect sources of these, e.g. behind typedefs or
    // template arguments.
    if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) {
      bool diagnosed = false;
      SourceRange rangeToRemove;
      if (auto attr = qual.getAs<AttributedTypeLoc>()) {
        rangeToRemove = attr.getLocalSourceRange();
        if (attr.getTypePtr()->getImmediateNullability()) {
          typeArg = attr.getTypePtr()->getModifiedType();
          S.Diag(attr.getBeginLoc(),
                 diag::err_objc_type_arg_explicit_nullability)
              << typeArg << FixItHint::CreateRemoval(rangeToRemove);
          diagnosed = true;
        }
      }

      // When rebuilding, qualifiers might have gotten here through a
      // final substitution.
      if (!rebuilding && !diagnosed) {
        S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified)
            << typeArg << typeArg.getQualifiers().getAsString()
            << FixItHint::CreateRemoval(rangeToRemove);
      }
    }

    // Remove qualifiers even if they're non-local.
    typeArg = typeArg.getUnqualifiedType();

    finalTypeArgs.push_back(typeArg);

    if (typeArg->getAs<PackExpansionType>())
      anyPackExpansions = true;

    // Find the corresponding type parameter, if there is one.
    ObjCTypeParamDecl *typeParam = nullptr;
    if (!anyPackExpansions) {
      if (i < numTypeParams) {
        typeParam = typeParams->begin()[i];
      } else {
        // Too many arguments.
        S.Diag(loc, diag::err_objc_type_args_wrong_arity)
            << false << objcClass->getDeclName() << (unsigned)typeArgs.size()
            << numTypeParams;
        S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass;

        if (failOnError)
          return QualType();

        return type;
      }
    }

    // Objective-C object pointer types must be substitutable for the bounds.
    if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) {
      // If we don't have a type parameter to match against, assume
      // everything is fine. There was a prior pack expansion that
      // means we won't be able to match anything.
      if (!typeParam) {
        assert(anyPackExpansions && "Too many arguments?");
        continue;
      }

      // Retrieve the bound.
      QualType bound = typeParam->getUnderlyingType();
      const auto *boundObjC = bound->castAs<ObjCObjectPointerType>();

      // Determine whether the type argument is substitutable for the bound.
      if (typeArgObjC->isObjCIdType()) {
        // When the type argument is 'id', the only acceptable type
        // parameter bound is 'id'.
        if (boundObjC->isObjCIdType())
          continue;
      } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) {
        // Otherwise, we follow the assignability rules.
        continue;
      }

      // Diagnose the mismatch.
      S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
             diag::err_objc_type_arg_does_not_match_bound)
          << typeArg << bound << typeParam->getDeclName();
      S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
          << typeParam->getDeclName();

      if (failOnError)
        return QualType();

      return type;
    }

    // Block pointer types are permitted for unqualified 'id' bounds.
    if (typeArg->isBlockPointerType()) {
      // If we don't have a type parameter to match against, assume
      // everything is fine. There was a prior pack expansion that
      // means we won't be able to match anything.
      if (!typeParam) {
        assert(anyPackExpansions && "Too many arguments?");
        continue;
      }

      // Retrieve the bound.
      QualType bound = typeParam->getUnderlyingType();
      if (bound->isBlockCompatibleObjCPointerType(S.Context))
        continue;

      // Diagnose the mismatch.
      S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
             diag::err_objc_type_arg_does_not_match_bound)
          << typeArg << bound << typeParam->getDeclName();
      S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
          << typeParam->getDeclName();

      if (failOnError)
        return QualType();

      return type;
    }

    // Types that have __attribute__((NSObject)) are permitted.
    if (typeArg->isObjCNSObjectType()) {
      continue;
    }

    // Dependent types will be checked at instantiation time.
    if (typeArg->isDependentType()) {
      continue;
    }

    // Diagnose non-id-compatible type arguments.
    S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
           diag::err_objc_type_arg_not_id_compatible)
        << typeArg << typeArgInfo->getTypeLoc().getSourceRange();

    if (failOnError)
      return QualType();

    return type;
  }

  // Make sure we didn't have the wrong number of arguments.
  if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) {
    S.Diag(loc, diag::err_objc_type_args_wrong_arity)
        << (typeArgs.size() < typeParams->size()) << objcClass->getDeclName()
        << (unsigned)finalTypeArgs.size() << (unsigned)numTypeParams;
    S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass;

    if (failOnError)
      return QualType();

    return type;
  }

  // Success. Form the specialized type.
  return S.Context.getObjCObjectType(type, finalTypeArgs, {}, false);
}

QualType SemaObjC::BuildObjCObjectType(
    QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
    ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc,
    SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols,
    ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
    bool FailOnError, bool Rebuilding) {
  ASTContext &Context = getASTContext();
  QualType Result = BaseType;
  if (!TypeArgs.empty()) {
    Result =
        applyObjCTypeArgs(SemaRef, Loc, Result, TypeArgs,
                          SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc),
                          FailOnError, Rebuilding);
    if (FailOnError && Result.isNull())
      return QualType();
  }

  if (!Protocols.empty()) {
    bool HasError;
    Result = Context.applyObjCProtocolQualifiers(Result, Protocols, HasError);
    if (HasError) {
      Diag(Loc, diag::err_invalid_protocol_qualifiers)
          << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
      if (FailOnError)
        Result = QualType();
    }
    if (FailOnError && Result.isNull())
      return QualType();
  }

  return Result;
}

ParsedType SemaObjC::ActOnObjCInstanceType(SourceLocation Loc) {
  ASTContext &Context = getASTContext();
  QualType T = Context.getObjCInstanceType();
  TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
  return SemaRef.CreateParsedType(T, TInfo);
}

//===--- CHECK: Objective-C retain cycles ----------------------------------//

namespace {

struct RetainCycleOwner {
  VarDecl *Variable = nullptr;
  SourceRange Range;
  SourceLocation Loc;
  bool Indirect = false;

  RetainCycleOwner() = default;

  void setLocsFrom(Expr *e) {
    Loc = e->getExprLoc();
    Range = e->getSourceRange();
  }
};

} // namespace

/// Consider whether capturing the given variable can possibly lead to
/// a retain cycle.
static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) {
  // In ARC, it's captured strongly iff the variable has __strong
  // lifetime.  In MRR, it's captured strongly if the variable is
  // __block and has an appropriate type.
  if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
    return false;

  owner.Variable = var;
  if (ref)
    owner.setLocsFrom(ref);
  return true;
}

static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) {
  while (true) {
    e = e->IgnoreParens();
    if (CastExpr *cast = dyn_cast<CastExpr>(e)) {
      switch (cast->getCastKind()) {
      case CK_BitCast:
      case CK_LValueBitCast:
      case CK_LValueToRValue:
      case CK_ARCReclaimReturnedObject:
        e = cast->getSubExpr();
        continue;

      default:
        return false;
      }
    }

    if (ObjCIvarRefExpr *ref = dyn_cast<ObjCIvarRefExpr>(e)) {
      ObjCIvarDecl *ivar = ref->getDecl();
      if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
        return false;

      // Try to find a retain cycle in the base.
      if (!findRetainCycleOwner(S, ref->getBase(), owner))
        return false;

      if (ref->isFreeIvar())
        owner.setLocsFrom(ref);
      owner.Indirect = true;
      return true;
    }

    if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {
      VarDecl *var = dyn_cast<VarDecl>(ref->getDecl());
      if (!var)
        return false;
      return considerVariable(var, ref, owner);
    }

    if (MemberExpr *member = dyn_cast<MemberExpr>(e)) {
      if (member->isArrow())
        return false;

      // Don't count this as an indirect ownership.
      e = member->getBase();
      continue;
    }

    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) {
      // Only pay attention to pseudo-objects on property references.
      ObjCPropertyRefExpr *pre = dyn_cast<ObjCPropertyRefExpr>(
          pseudo->getSyntacticForm()->IgnoreParens());
      if (!pre)
        return false;
      if (pre->isImplicitProperty())
        return false;
      ObjCPropertyDecl *property = pre->getExplicitProperty();
      if (!property->isRetaining() &&
          !(property->getPropertyIvarDecl() &&
            property->getPropertyIvarDecl()->getType().getObjCLifetime() ==
                Qualifiers::OCL_Strong))
        return false;

      owner.Indirect = true;
      if (pre->isSuperReceiver()) {
        owner.Variable = S.getCurMethodDecl()->getSelfDecl();
        if (!owner.Variable)
          return false;
        owner.Loc = pre->getLocation();
        owner.Range = pre->getSourceRange();
        return true;
      }
      e = const_cast<Expr *>(
          cast<OpaqueValueExpr>(pre->getBase())->getSourceExpr());
      continue;
    }

    // Array ivars?

    return false;
  }
}

namespace {

struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {
  VarDecl *Variable;
  Expr *Capturer = nullptr;
  bool VarWillBeReased = false;

  FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
      : EvaluatedExprVisitor<FindCaptureVisitor>(Context), Variable(variable) {}

  void VisitDeclRefExpr(DeclRefExpr *ref) {
    if (ref->getDecl() == Variable && !Capturer)
      Capturer = ref;
  }

  void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) {
    if (Capturer)
      return;
    Visit(ref->getBase());
    if (Capturer && ref->isFreeIvar())
      Capturer = ref;
  }

  void VisitBlockExpr(BlockExpr *block) {
    // Look inside nested blocks
    if (block->getBlockDecl()->capturesVariable(Variable))
      Visit(block->getBlockDecl()->getBody());
  }

  void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) {
    if (Capturer)
      return;
    if (OVE->getSourceExpr())
      Visit(OVE->getSourceExpr());
  }

  void VisitBinaryOperator(BinaryOperator *BinOp) {
    if (!Variable || VarWillBeReased || BinOp->getOpcode() != BO_Assign)
      return;
    Expr *LHS = BinOp->getLHS();
    if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(LHS)) {
      if (DRE->getDecl() != Variable)
        return;
      if (Expr *RHS = BinOp->getRHS()) {
        RHS = RHS->IgnoreParenCasts();
        std::optional<llvm::APSInt> Value;
        VarWillBeReased =
            (RHS && (Value = RHS->getIntegerConstantExpr(Context)) &&
             *Value == 0);
      }
    }
  }
};

} // namespace

/// Check whether the given argument is a block which captures a
/// variable.
static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {
  assert(owner.Variable && owner.Loc.isValid());

  e = e->IgnoreParenCasts();

  // Look through [^{...} copy] and Block_copy(^{...}).
  if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(e)) {
    Selector Cmd = ME->getSelector();
    if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") {
      e = ME->getInstanceReceiver();
      if (!e)
        return nullptr;
      e = e->IgnoreParenCasts();
    }
  } else if (CallExpr *CE = dyn_cast<CallExpr>(e)) {
    if (CE->getNumArgs() == 1) {
      FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl());
      if (Fn) {
        const IdentifierInfo *FnI = Fn->getIdentifier();
        if (FnI && FnI->isStr("_Block_copy")) {
          e = CE->getArg(0)->IgnoreParenCasts();
        }
      }
    }
  }

  BlockExpr *block = dyn_cast<BlockExpr>(e);
  if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable))
    return nullptr;

  FindCaptureVisitor visitor(S.Context, owner.Variable);
  visitor.Visit(block->getBlockDecl()->getBody());
  return visitor.VarWillBeReased ? nullptr : visitor.Capturer;
}

static void diagnoseRetainCycle(Sema &S, Expr *capturer,
                                RetainCycleOwner &owner) {
  assert(capturer);
  assert(owner.Variable && owner.Loc.isValid());

  S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle)
      << owner.Variable << capturer->getSourceRange();
  S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner)
      << owner.Indirect << owner.Range;
}

/// Check for a keyword selector that starts with the word 'add' or
/// 'set'.
static bool isSetterLikeSelector(Selector sel) {
  if (sel.isUnarySelector())
    return false;

  StringRef str = sel.getNameForSlot(0);
  str = str.ltrim('_');
  if (str.starts_with("set"))
    str = str.substr(3);
  else if (str.starts_with("add")) {
    // Specially allow 'addOperationWithBlock:'.
    if (sel.getNumArgs() == 1 && str.starts_with("addOperationWithBlock"))
      return false;
    str = str.substr(3);
  } else
    return false;

  if (str.empty())
    return true;
  return !isLowercase(str.front());
}

static std::optional<int>
GetNSMutableArrayArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) {
  bool IsMutableArray = S.NSAPIObj->isSubclassOfNSClass(
      Message->getReceiverInterface(), NSAPI::ClassId_NSMutableArray);
  if (!IsMutableArray) {
    return std::nullopt;
  }

  Selector Sel = Message->getSelector();

  std::optional<NSAPI::NSArrayMethodKind> MKOpt =
      S.NSAPIObj->getNSArrayMethodKind(Sel);
  if (!MKOpt) {
    return std::nullopt;
  }

  NSAPI::NSArrayMethodKind MK = *MKOpt;

  switch (MK) {
  case NSAPI::NSMutableArr_addObject:
  case NSAPI::NSMutableArr_insertObjectAtIndex:
  case NSAPI::NSMutableArr_setObjectAtIndexedSubscript:
    return 0;
  case NSAPI::NSMutableArr_replaceObjectAtIndex:
    return 1;

  default:
    return std::nullopt;
  }

  return std::nullopt;
}

static std::optional<int>
GetNSMutableDictionaryArgumentIndex(SemaObjC &S, ObjCMessageExpr *Message) {
  bool IsMutableDictionary = S.NSAPIObj->isSubclassOfNSClass(
      Message->getReceiverInterface(), NSAPI::ClassId_NSMutableDictionary);
  if (!IsMutableDictionary) {
    return std::nullopt;
  }

  Selector Sel = Message->getSelector();

  std::optional<NSAPI::NSDictionaryMethodKind> MKOpt =
      S.NSAPIObj->getNSDictionaryMethodKind(Sel);
  if (!MKOpt) {
    return std::nullopt;
  }

  NSAPI::NSDictionaryMethodKind MK = *MKOpt;

  switch (MK) {
  case NSAPI::NSMutableDict_setObjectForKey:
  case NSAPI::NSMutableDict_setValueForKey:
  case NSAPI::NSMutableDict_setObjectForKeyedSubscript:
    return 0;

  default:
    return std::nullopt;
  }

  return std::nullopt;
}

static std::optional<int> GetNSSetArgumentIndex(SemaObjC &S,
                                                ObjCMessageExpr *Message) {
  bool IsMutableSet = S.NSAPIObj->isSubclassOfNSClass(
      Message->getReceiverInterface(), NSAPI::ClassId_NSMutableSet);

  bool IsMutableOrderedSet = S.NSAPIObj->isSubclassOfNSClass(
      Message->getReceiverInterface(), NSAPI::ClassId_NSMutableOrderedSet);
  if (!IsMutableSet && !IsMutableOrderedSet) {
    return std::nullopt;
  }

  Selector Sel = Message->getSelector();

  std::optional<NSAPI::NSSetMethodKind> MKOpt =
      S.NSAPIObj->getNSSetMethodKind(Sel);
  if (!MKOpt) {
    return std::nullopt;
  }

  NSAPI::NSSetMethodKind MK = *MKOpt;

  switch (MK) {
  case NSAPI::NSMutableSet_addObject:
  case NSAPI::NSOrderedSet_setObjectAtIndex:
  case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript:
  case NSAPI::NSOrderedSet_insertObjectAtIndex:
    return 0;
  case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject:
    return 1;
  }

  return std::nullopt;
}

void SemaObjC::CheckObjCCircularContainer(ObjCMessageExpr *Message) {
  if (!Message->isInstanceMessage()) {
    return;
  }

  std::optional<int> ArgOpt;

  if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) &&
      !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) &&
      !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) {
    return;
  }

  int ArgIndex = *ArgOpt;

  Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts();
  if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) {
    Arg = OE->getSourceExpr()->IgnoreImpCasts();
  }

  if (Message->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
    if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {
      if (ArgRE->isObjCSelfExpr()) {
        Diag(Message->getSourceRange().getBegin(),
             diag::warn_objc_circular_container)
            << ArgRE->getDecl() << StringRef("'super'");
      }
    }
  } else {
    Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts();

    if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) {
      Receiver = OE->getSourceExpr()->IgnoreImpCasts();
    }

    if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) {
      if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {
        if (ReceiverRE->getDecl() == ArgRE->getDecl()) {
          ValueDecl *Decl = ReceiverRE->getDecl();
          Diag(Message->getSourceRange().getBegin(),
               diag::warn_objc_circular_container)
              << Decl << Decl;
          if (!ArgRE->isObjCSelfExpr()) {
            Diag(Decl->getLocation(),
                 diag::note_objc_circular_container_declared_here)
                << Decl;
          }
        }
      }
    } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) {
      if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) {
        if (IvarRE->getDecl() == IvarArgRE->getDecl()) {
          ObjCIvarDecl *Decl = IvarRE->getDecl();
          Diag(Message->getSourceRange().getBegin(),
               diag::warn_objc_circular_container)
              << Decl << Decl;
          Diag(Decl->getLocation(),
               diag::note_objc_circular_container_declared_here)
              << Decl;
        }
      }
    }
  }
}

/// Check a message send to see if it's likely to cause a retain cycle.
void SemaObjC::checkRetainCycles(ObjCMessageExpr *msg) {
  // Only check instance methods whose selector looks like a setter.
  if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector()))
    return;

  // Try to find a variable that the receiver is strongly owned by.
  RetainCycleOwner owner;
  if (msg->getReceiverKind() == ObjCMessageExpr::Instance) {
    if (!findRetainCycleOwner(SemaRef, msg->getInstanceReceiver(), owner))
      return;
  } else {
    assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
    owner.Variable = SemaRef.getCurMethodDecl()->getSelfDecl();
    owner.Loc = msg->getSuperLoc();
    owner.Range = msg->getSuperLoc();
  }

  // Check whether the receiver is captured by any of the arguments.
  const ObjCMethodDecl *MD = msg->getMethodDecl();
  for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) {
    if (Expr *capturer = findCapturingExpr(SemaRef, msg->getArg(i), owner)) {
      // noescape blocks should not be retained by the method.
      if (MD && MD->parameters()[i]->hasAttr<NoEscapeAttr>())
        continue;
      return diagnoseRetainCycle(SemaRef, capturer, owner);
    }
  }
}

/// Check a property assign to see if it's likely to cause a retain cycle.
void SemaObjC::checkRetainCycles(Expr *receiver, Expr *argument) {
  RetainCycleOwner owner;
  if (!findRetainCycleOwner(SemaRef, receiver, owner))
    return;

  if (Expr *capturer = findCapturingExpr(SemaRef, argument, owner))
    diagnoseRetainCycle(SemaRef, capturer, owner);
}

void SemaObjC::checkRetainCycles(VarDecl *Var, Expr *Init) {
  RetainCycleOwner Owner;
  if (!considerVariable(Var, /*DeclRefExpr=*/nullptr, Owner))
    return;

  // Because we don't have an expression for the variable, we have to set the
  // location explicitly here.
  Owner.Loc = Var->getLocation();
  Owner.Range = Var->getSourceRange();

  if (Expr *Capturer = findCapturingExpr(SemaRef, Init, Owner))
    diagnoseRetainCycle(SemaRef, Capturer, Owner);
}

/// CheckObjCString - Checks that the argument to the builtin
/// CFString constructor is correct
/// Note: It might also make sense to do the UTF-16 conversion here (would
/// simplify the backend).
bool SemaObjC::CheckObjCString(Expr *Arg) {
  Arg = Arg->IgnoreParenCasts();
  StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);

  if (!Literal || !Literal->isOrdinary()) {
    Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant)
        << Arg->getSourceRange();
    return true;
  }

  if (Literal->containsNonAsciiOrNull()) {
    StringRef String = Literal->getString();
    unsigned NumBytes = String.size();
    SmallVector<llvm::UTF16, 128> ToBuf(NumBytes);
    const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data();
    llvm::UTF16 *ToPtr = &ToBuf[0];

    llvm::ConversionResult Result =
        llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr,
                                 ToPtr + NumBytes, llvm::strictConversion);
    // Check for conversion failure.
    if (Result != llvm::conversionOK)
      Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated)
          << Arg->getSourceRange();
  }
  return false;
}

bool SemaObjC::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
                                   ArrayRef<const Expr *> Args) {
  Sema::VariadicCallType CallType =
      Method->isVariadic() ? Sema::VariadicMethod : Sema::VariadicDoesNotApply;

  SemaRef.checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args,
                    /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
                    CallType);

  SemaRef.CheckTCBEnforcement(lbrac, Method);

  return false;
}

const DeclContext *SemaObjC::getCurObjCLexicalContext() const {
  const DeclContext *DC = SemaRef.getCurLexicalContext();
  // A category implicitly has the attribute of the interface.
  if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC))
    DC = CatD->getClassInterface();
  return DC;
}

/// Retrieve the identifier "NSError".
IdentifierInfo *SemaObjC::getNSErrorIdent() {
  if (!Ident_NSError)
    Ident_NSError = SemaRef.PP.getIdentifierInfo("NSError");

  return Ident_NSError;
}

void SemaObjC::ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl) {
  assert(
      IDecl->getLexicalParent() == SemaRef.CurContext &&
      "The next DeclContext should be lexically contained in the current one.");
  SemaRef.CurContext = IDecl;
}

void SemaObjC::ActOnObjCContainerFinishDefinition() {
  // Exit this scope of this interface definition.
  SemaRef.PopDeclContext();
}

void SemaObjC::ActOnObjCTemporaryExitContainerContext(
    ObjCContainerDecl *ObjCCtx) {
  assert(ObjCCtx == SemaRef.CurContext && "Mismatch of container contexts");
  SemaRef.OriginalLexicalContext = ObjCCtx;
  ActOnObjCContainerFinishDefinition();
}

void SemaObjC::ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx) {
  ActOnObjCContainerStartDefinition(ObjCCtx);
  SemaRef.OriginalLexicalContext = nullptr;
}

/// Find the protocol with the given name, if any.
ObjCProtocolDecl *SemaObjC::LookupProtocol(IdentifierInfo *II,
                                           SourceLocation IdLoc,
                                           RedeclarationKind Redecl) {
  Decl *D = SemaRef.LookupSingleName(SemaRef.TUScope, II, IdLoc,
                                     Sema::LookupObjCProtocolName, Redecl);
  return cast_or_null<ObjCProtocolDecl>(D);
}

/// Determine whether this is an Objective-C writeback conversion,
/// used for parameter passing when performing automatic reference counting.
///
/// \param FromType The type we're converting form.
///
/// \param ToType The type we're converting to.
///
/// \param ConvertedType The type that will be produced after applying
/// this conversion.
bool SemaObjC::isObjCWritebackConversion(QualType FromType, QualType ToType,
                                         QualType &ConvertedType) {
  ASTContext &Context = getASTContext();
  if (!getLangOpts().ObjCAutoRefCount ||
      Context.hasSameUnqualifiedType(FromType, ToType))
    return false;

  // Parameter must be a pointer to __autoreleasing (with no other qualifiers).
  QualType ToPointee;
  if (const PointerType *ToPointer = ToType->getAs<PointerType>())
    ToPointee = ToPointer->getPointeeType();
  else
    return false;

  Qualifiers ToQuals = ToPointee.getQualifiers();
  if (!ToPointee->isObjCLifetimeType() ||
      ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing ||
      !ToQuals.withoutObjCLifetime().empty())
    return false;

  // Argument must be a pointer to __strong to __weak.
  QualType FromPointee;
  if (const PointerType *FromPointer = FromType->getAs<PointerType>())
    FromPointee = FromPointer->getPointeeType();
  else
    return false;

  Qualifiers FromQuals = FromPointee.getQualifiers();
  if (!FromPointee->isObjCLifetimeType() ||
      (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong &&
       FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak))
    return false;

  // Make sure that we have compatible qualifiers.
  FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing);
  if (!ToQuals.compatiblyIncludes(FromQuals, getASTContext()))
    return false;

  // Remove qualifiers from the pointee type we're converting from; they
  // aren't used in the compatibility check belong, and we'll be adding back
  // qualifiers (with __autoreleasing) if the compatibility check succeeds.
  FromPointee = FromPointee.getUnqualifiedType();

  // The unqualified form of the pointee types must be compatible.
  ToPointee = ToPointee.getUnqualifiedType();
  bool IncompatibleObjC;
  if (Context.typesAreCompatible(FromPointee, ToPointee))
    FromPointee = ToPointee;
  else if (!SemaRef.isObjCPointerConversion(FromPointee, ToPointee, FromPointee,
                                            IncompatibleObjC))
    return false;

  /// Construct the type we're converting to, which is a pointer to
  /// __autoreleasing pointee.
  FromPointee = Context.getQualifiedType(FromPointee, FromQuals);
  ConvertedType = Context.getPointerType(FromPointee);
  return true;
}

/// CheckSubscriptingKind - This routine decide what type
/// of indexing represented by "FromE" is being done.
SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) {
  // If the expression already has integral or enumeration type, we're golden.
  QualType T = FromE->getType();
  if (T->isIntegralOrEnumerationType())
    return SemaObjC::OS_Array;

  // If we don't have a class type in C++, there's no way we can get an
  // expression of integral or enumeration type.
  const RecordType *RecordTy = T->getAs<RecordType>();
  if (!RecordTy && (T->isObjCObjectPointerType() || T->isVoidPointerType()))
    // All other scalar cases are assumed to be dictionary indexing which
    // caller handles, with diagnostics if needed.
    return SemaObjC::OS_Dictionary;
  if (!getLangOpts().CPlusPlus || !RecordTy || RecordTy->isIncompleteType()) {
    // No indexing can be done. Issue diagnostics and quit.
    const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
    if (isa<StringLiteral>(IndexExpr))
      Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
          << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
    else
      Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) << T;
    return SemaObjC::OS_Error;
  }

  // We must have a complete class type.
  if (SemaRef.RequireCompleteType(FromE->getExprLoc(), T,
                                  diag::err_objc_index_incomplete_class_type,
                                  FromE))
    return SemaObjC::OS_Error;

  // Look for a conversion to an integral, enumeration type, or
  // objective-C pointer type.
  int NoIntegrals = 0, NoObjCIdPointers = 0;
  SmallVector<CXXConversionDecl *, 4> ConversionDecls;

  for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())
                          ->getVisibleConversionFunctions()) {
    if (CXXConversionDecl *Conversion =
            dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {
      QualType CT = Conversion->getConversionType().getNonReferenceType();
      if (CT->isIntegralOrEnumerationType()) {
        ++NoIntegrals;
        ConversionDecls.push_back(Conversion);
      } else if (CT->isObjCIdType() || CT->isBlockPointerType()) {
        ++NoObjCIdPointers;
        ConversionDecls.push_back(Conversion);
      }
    }
  }
  if (NoIntegrals == 1 && NoObjCIdPointers == 0)
    return SemaObjC::OS_Array;
  if (NoIntegrals == 0 && NoObjCIdPointers == 1)
    return SemaObjC::OS_Dictionary;
  if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
    // No conversion function was found. Issue diagnostic and return.
    Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
        << FromE->getType();
    return SemaObjC::OS_Error;
  }
  Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
      << FromE->getType();
  for (unsigned int i = 0; i < ConversionDecls.size(); i++)
    Diag(ConversionDecls[i]->getLocation(),
         diag::note_conv_function_declared_at);

  return SemaObjC::OS_Error;
}

void SemaObjC::AddCFAuditedAttribute(Decl *D) {
  ASTContext &Context = getASTContext();
  IdentifierInfo *Ident;
  SourceLocation Loc;
  std::tie(Ident, Loc) = SemaRef.PP.getPragmaARCCFCodeAuditedInfo();
  if (!Loc.isValid())
    return;

  // Don't add a redundant or conflicting attribute.
  if (D->hasAttr<CFAuditedTransferAttr>() ||
      D->hasAttr<CFUnknownTransferAttr>())
    return;

  AttributeCommonInfo Info(Ident, SourceRange(Loc),
                           AttributeCommonInfo::Form::Pragma());
  D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info));
}

bool SemaObjC::isCFError(RecordDecl *RD) {
  // If we already know about CFError, test it directly.
  if (CFError)
    return CFError == RD;

  // Check whether this is CFError, which we identify based on its bridge to
  // NSError. CFErrorRef used to be declared with "objc_bridge" but is now
  // declared with "objc_bridge_mutable", so look for either one of the two
  // attributes.
  if (RD->getTagKind() == TagTypeKind::Struct) {
    IdentifierInfo *bridgedType = nullptr;
    if (auto bridgeAttr = RD->getAttr<ObjCBridgeAttr>())
      bridgedType = bridgeAttr->getBridgedType();
    else if (auto bridgeAttr = RD->getAttr<ObjCBridgeMutableAttr>())
      bridgedType = bridgeAttr->getBridgedType();

    if (bridgedType == getNSErrorIdent()) {
      CFError = RD;
      return true;
    }
  }

  return false;
}

bool SemaObjC::isNSStringType(QualType T, bool AllowNSAttributedString) {
  const auto *PT = T->getAs<ObjCObjectPointerType>();
  if (!PT)
    return false;

  ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
  if (!Cls)
    return false;

  IdentifierInfo *ClsName = Cls->getIdentifier();

  if (AllowNSAttributedString &&
      ClsName == &getASTContext().Idents.get("NSAttributedString"))
    return true;
  // FIXME: Should we walk the chain of classes?
  return ClsName == &getASTContext().Idents.get("NSString") ||
         ClsName == &getASTContext().Idents.get("NSMutableString");
}

bool SemaObjC::isCFStringType(QualType T) {
  const auto *PT = T->getAs<PointerType>();
  if (!PT)
    return false;

  const auto *RT = PT->getPointeeType()->getAs<RecordType>();
  if (!RT)
    return false;

  const RecordDecl *RD = RT->getDecl();
  if (RD->getTagKind() != TagTypeKind::Struct)
    return false;

  return RD->getIdentifier() == &getASTContext().Idents.get("__CFString");
}

static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
  // The IBOutlet/IBOutletCollection attributes only apply to instance
  // variables or properties of Objective-C classes.  The outlet must also
  // have an object reference type.
  if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {
    if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
      S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
          << AL << VD->getType() << 0;
      return false;
    }
  } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
    if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
      S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
          << AL << PD->getType() << 1;
      return false;
    }
  } else {
    S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL;
    return false;
  }

  return true;
}

void SemaObjC::handleIBOutlet(Decl *D, const ParsedAttr &AL) {
  if (!checkIBOutletCommon(SemaRef, D, AL))
    return;

  D->addAttr(::new (getASTContext()) IBOutletAttr(getASTContext(), AL));
}

void SemaObjC::handleIBOutletCollection(Decl *D, const ParsedAttr &AL) {

  ASTContext &Context = getASTContext();
  // The iboutletcollection attribute can have zero or one arguments.
  if (AL.getNumArgs() > 1) {
    Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
    return;
  }

  if (!checkIBOutletCommon(SemaRef, D, AL))
    return;

  ParsedType PT;

  if (AL.hasParsedType())
    PT = AL.getTypeArg();
  else {
    PT = SemaRef.getTypeName(
        Context.Idents.get("NSObject"), AL.getLoc(),
        SemaRef.getScopeForContext(D->getDeclContext()->getParent()));
    if (!PT) {
      Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
      return;
    }
  }

  TypeSourceInfo *QTLoc = nullptr;
  QualType QT = SemaRef.GetTypeFromParser(PT, &QTLoc);
  if (!QTLoc)
    QTLoc = Context.getTrivialTypeSourceInfo(QT, AL.getLoc());

  // Diagnose use of non-object type in iboutletcollection attribute.
  // FIXME. Gnu attribute extension ignores use of builtin types in
  // attributes. So, __attribute__((iboutletcollection(char))) will be
  // treated as __attribute__((iboutletcollection())).
  if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
    Diag(AL.getLoc(), QT->isBuiltinType()
                          ? diag::err_iboutletcollection_builtintype
                          : diag::err_iboutletcollection_type)
        << QT;
    return;
  }

  D->addAttr(::new (Context) IBOutletCollectionAttr(Context, AL, QTLoc));
}

void SemaObjC::handleSuppresProtocolAttr(Decl *D, const ParsedAttr &AL) {
  if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
    Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)
        << AL << AL.getRange();
    return;
  }

  D->addAttr(::new (getASTContext())
                 ObjCExplicitProtocolImplAttr(getASTContext(), AL));
}

void SemaObjC::handleDirectAttr(Decl *D, const ParsedAttr &AL) {
  // objc_direct cannot be set on methods declared in the context of a protocol
  if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
    Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false;
    return;
  }

  if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
    handleSimpleAttribute<ObjCDirectAttr>(*this, D, AL);
  } else {
    Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
  }
}

void SemaObjC::handleDirectMembersAttr(Decl *D, const ParsedAttr &AL) {
  if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
    handleSimpleAttribute<ObjCDirectMembersAttr>(*this, D, AL);
  } else {
    Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
  }
}

void SemaObjC::handleMethodFamilyAttr(Decl *D, const ParsedAttr &AL) {
  const auto *M = cast<ObjCMethodDecl>(D);
  if (!AL.isArgIdent(0)) {
    Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
        << AL << 1 << AANT_ArgumentIdentifier;
    return;
  }

  IdentifierLoc *IL = AL.getArgAsIdent(0);
  ObjCMethodFamilyAttr::FamilyKind F;
  if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
    Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident;
    return;
  }

  if (F == ObjCMethodFamilyAttr::OMF_init &&
      !M->getReturnType()->isObjCObjectPointerType()) {
    Diag(M->getLocation(), diag::err_init_method_bad_return_type)
        << M->getReturnType();
    // Ignore the attribute.
    return;
  }

  D->addAttr(new (getASTContext())
                 ObjCMethodFamilyAttr(getASTContext(), AL, F));
}

void SemaObjC::handleNSObject(Decl *D, const ParsedAttr &AL) {
  if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
    QualType T = TD->getUnderlyingType();
    if (!T->isCARCBridgableType()) {
      Diag(TD->getLocation(), diag::err_nsobject_attribute);
      return;
    }
  } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
    QualType T = PD->getType();
    if (!T->isCARCBridgableType()) {
      Diag(PD->getLocation(), diag::err_nsobject_attribute);
      return;
    }
  } else {
    // It is okay to include this attribute on properties, e.g.:
    //
    //  @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
    //
    // In this case it follows tradition and suppresses an error in the above
    // case.
    Diag(D->getLocation(), diag::warn_nsobject_attribute);
  }
  D->addAttr(::new (getASTContext()) ObjCNSObjectAttr(getASTContext(), AL));
}

void SemaObjC::handleIndependentClass(Decl *D, const ParsedAttr &AL) {
  if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
    QualType T = TD->getUnderlyingType();
    if (!T->isObjCObjectPointerType()) {
      Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
      return;
    }
  } else {
    Diag(D->getLocation(), diag::warn_independentclass_attribute);
    return;
  }
  D->addAttr(::new (getASTContext())
                 ObjCIndependentClassAttr(getASTContext(), AL));
}

void SemaObjC::handleBlocksAttr(Decl *D, const ParsedAttr &AL) {
  if (!AL.isArgIdent(0)) {
    Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
        << AL << 1 << AANT_ArgumentIdentifier;
    return;
  }

  IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
  BlocksAttr::BlockType type;
  if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
    Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
    return;
  }

  D->addAttr(::new (getASTContext()) BlocksAttr(getASTContext(), AL, type));
}

static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {
  return QT->isDependentType() || QT->isObjCRetainableType();
}

static bool isValidSubjectOfNSAttribute(QualType QT) {
  return QT->isDependentType() || QT->isObjCObjectPointerType() ||
         QT->isObjCNSObjectType();
}

static bool isValidSubjectOfCFAttribute(QualType QT) {
  return QT->isDependentType() || QT->isPointerType() ||
         isValidSubjectOfNSAttribute(QT);
}

static bool isValidSubjectOfOSAttribute(QualType QT) {
  if (QT->isDependentType())
    return true;
  QualType PT = QT->getPointeeType();
  return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr;
}

void SemaObjC::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
                                Sema::RetainOwnershipKind K,
                                bool IsTemplateInstantiation) {
  ValueDecl *VD = cast<ValueDecl>(D);
  switch (K) {
  case Sema::RetainOwnershipKind::OS:
    handleSimpleAttributeOrDiagnose<OSConsumedAttr>(
        *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()),
        diag::warn_ns_attribute_wrong_parameter_type,
        /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1);
    return;
  case Sema::RetainOwnershipKind::NS:
    handleSimpleAttributeOrDiagnose<NSConsumedAttr>(
        *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()),

        // These attributes are normally just advisory, but in ARC, ns_consumed
        // is significant.  Allow non-dependent code to contain inappropriate
        // attributes even in ARC, but require template instantiations to be
        // set up correctly.
        ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount)
             ? diag::err_ns_attribute_wrong_parameter_type
             : diag::warn_ns_attribute_wrong_parameter_type),
        /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0);
    return;
  case Sema::RetainOwnershipKind::CF:
    handleSimpleAttributeOrDiagnose<CFConsumedAttr>(
        *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()),
        diag::warn_ns_attribute_wrong_parameter_type,
        /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1);
    return;
  }
}

Sema::RetainOwnershipKind
SemaObjC::parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) {
  switch (AL.getKind()) {
  case ParsedAttr::AT_CFConsumed:
  case ParsedAttr::AT_CFReturnsRetained:
  case ParsedAttr::AT_CFReturnsNotRetained:
    return Sema::RetainOwnershipKind::CF;
  case ParsedAttr::AT_OSConsumesThis:
  case ParsedAttr::AT_OSConsumed:
  case ParsedAttr::AT_OSReturnsRetained:
  case ParsedAttr::AT_OSReturnsNotRetained:
  case ParsedAttr::AT_OSReturnsRetainedOnZero:
  case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
    return Sema::RetainOwnershipKind::OS;
  case ParsedAttr::AT_NSConsumesSelf:
  case ParsedAttr::AT_NSConsumed:
  case ParsedAttr::AT_NSReturnsRetained:
  case ParsedAttr::AT_NSReturnsNotRetained:
  case ParsedAttr::AT_NSReturnsAutoreleased:
    return Sema::RetainOwnershipKind::NS;
  default:
    llvm_unreachable("Wrong argument supplied");
  }
}

bool SemaObjC::checkNSReturnsRetainedReturnType(SourceLocation Loc,
                                                QualType QT) {
  if (isValidSubjectOfNSReturnsRetainedAttribute(QT))
    return false;

  Diag(Loc, diag::warn_ns_attribute_wrong_return_type)
      << "'ns_returns_retained'" << 0 << 0;
  return true;
}

/// \return whether the parameter is a pointer to OSObject pointer.
bool SemaObjC::isValidOSObjectOutParameter(const Decl *D) {
  const auto *PVD = dyn_cast<ParmVarDecl>(D);
  if (!PVD)
    return false;
  QualType QT = PVD->getType();
  QualType PT = QT->getPointeeType();
  return !PT.isNull() && isValidSubjectOfOSAttribute(PT);
}

void SemaObjC::handleXReturnsXRetainedAttr(Decl *D, const ParsedAttr &AL) {
  QualType ReturnType;
  Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);

  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
    ReturnType = MD->getReturnType();
  } else if (getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
             (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) {
    return; // ignore: was handled as a type attribute
  } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
    ReturnType = PD->getType();
  } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
    ReturnType = FD->getReturnType();
  } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
    // Attributes on parameters are used for out-parameters,
    // passed as pointers-to-pointers.
    unsigned DiagID = K == Sema::RetainOwnershipKind::CF
                          ? /*pointer-to-CF-pointer*/ 2
                          : /*pointer-to-OSObject-pointer*/ 3;
    ReturnType = Param->getType()->getPointeeType();
    if (ReturnType.isNull()) {
      Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
          << AL << DiagID << AL.getRange();
      return;
    }
  } else if (AL.isUsedAsTypeAttr()) {
    return;
  } else {
    AttributeDeclKind ExpectedDeclKind;
    switch (AL.getKind()) {
    default:
      llvm_unreachable("invalid ownership attribute");
    case ParsedAttr::AT_NSReturnsRetained:
    case ParsedAttr::AT_NSReturnsAutoreleased:
    case ParsedAttr::AT_NSReturnsNotRetained:
      ExpectedDeclKind = ExpectedFunctionOrMethod;
      break;

    case ParsedAttr::AT_OSReturnsRetained:
    case ParsedAttr::AT_OSReturnsNotRetained:
    case ParsedAttr::AT_CFReturnsRetained:
    case ParsedAttr::AT_CFReturnsNotRetained:
      ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
      break;
    }
    Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type)
        << AL.getRange() << AL << AL.isRegularKeywordAttribute()
        << ExpectedDeclKind;
    return;
  }

  bool TypeOK;
  bool Cf;
  unsigned ParmDiagID = 2; // Pointer-to-CF-pointer
  switch (AL.getKind()) {
  default:
    llvm_unreachable("invalid ownership attribute");
  case ParsedAttr::AT_NSReturnsRetained:
    TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);
    Cf = false;
    break;

  case ParsedAttr::AT_NSReturnsAutoreleased:
  case ParsedAttr::AT_NSReturnsNotRetained:
    TypeOK = isValidSubjectOfNSAttribute(ReturnType);
    Cf = false;
    break;

  case ParsedAttr::AT_CFReturnsRetained:
  case ParsedAttr::AT_CFReturnsNotRetained:
    TypeOK = isValidSubjectOfCFAttribute(ReturnType);
    Cf = true;
    break;

  case ParsedAttr::AT_OSReturnsRetained:
  case ParsedAttr::AT_OSReturnsNotRetained:
    TypeOK = isValidSubjectOfOSAttribute(ReturnType);
    Cf = true;
    ParmDiagID = 3; // Pointer-to-OSObject-pointer
    break;
  }

  if (!TypeOK) {
    if (AL.isUsedAsTypeAttr())
      return;

    if (isa<ParmVarDecl>(D)) {
      Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
          << AL << ParmDiagID << AL.getRange();
    } else {
      // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
      enum : unsigned { Function, Method, Property } SubjectKind = Function;
      if (isa<ObjCMethodDecl>(D))
        SubjectKind = Method;
      else if (isa<ObjCPropertyDecl>(D))
        SubjectKind = Property;
      Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
          << AL << SubjectKind << Cf << AL.getRange();
    }
    return;
  }

  switch (AL.getKind()) {
  default:
    llvm_unreachable("invalid ownership attribute");
  case ParsedAttr::AT_NSReturnsAutoreleased:
    handleSimpleAttribute<NSReturnsAutoreleasedAttr>(*this, D, AL);
    return;
  case ParsedAttr::AT_CFReturnsNotRetained:
    handleSimpleAttribute<CFReturnsNotRetainedAttr>(*this, D, AL);
    return;
  case ParsedAttr::AT_NSReturnsNotRetained:
    handleSimpleAttribute<NSReturnsNotRetainedAttr>(*this, D, AL);
    return;
  case ParsedAttr::AT_CFReturnsRetained:
    handleSimpleAttribute<CFReturnsRetainedAttr>(*this, D, AL);
    return;
  case ParsedAttr::AT_NSReturnsRetained:
    handleSimpleAttribute<NSReturnsRetainedAttr>(*this, D, AL);
    return;
  case ParsedAttr::AT_OSReturnsRetained:
    handleSimpleAttribute<OSReturnsRetainedAttr>(*this, D, AL);
    return;
  case ParsedAttr::AT_OSReturnsNotRetained:
    handleSimpleAttribute<OSReturnsNotRetainedAttr>(*this, D, AL);
    return;
  };
}

void SemaObjC::handleReturnsInnerPointerAttr(Decl *D, const ParsedAttr &Attrs) {
  const int EP_ObjCMethod = 1;
  const int EP_ObjCProperty = 2;

  SourceLocation loc = Attrs.getLoc();
  QualType resultType;
  if (isa<ObjCMethodDecl>(D))
    resultType = cast<ObjCMethodDecl>(D)->getReturnType();
  else
    resultType = cast<ObjCPropertyDecl>(D)->getType();

  if (!resultType->isReferenceType() &&
      (!resultType->isPointerType() || resultType->isObjCRetainableType())) {
    Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
        << SourceRange(loc) << Attrs
        << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
        << /*non-retainable pointer*/ 2;

    // Drop the attribute.
    return;
  }

  D->addAttr(::new (getASTContext())
                 ObjCReturnsInnerPointerAttr(getASTContext(), Attrs));
}

void SemaObjC::handleRequiresSuperAttr(Decl *D, const ParsedAttr &Attrs) {
  const auto *Method = cast<ObjCMethodDecl>(D);

  const DeclContext *DC = Method->getDeclContext();
  if (const auto *PDecl = dyn_cast_if_present<ObjCProtocolDecl>(DC)) {
    Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol)
        << Attrs << 0;
    Diag(PDecl->getLocation(), diag::note_protocol_decl);
    return;
  }
  if (Method->getMethodFamily() == OMF_dealloc) {
    Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol)
        << Attrs << 1;
    return;
  }

  D->addAttr(::new (getASTContext())
                 ObjCRequiresSuperAttr(getASTContext(), Attrs));
}

void SemaObjC::handleNSErrorDomain(Decl *D, const ParsedAttr &Attr) {
  if (!isa<TagDecl>(D)) {
    Diag(D->getBeginLoc(), diag::err_nserrordomain_invalid_decl) << 0;
    return;
  }

  IdentifierLoc *IdentLoc =
      Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
  if (!IdentLoc || !IdentLoc->Ident) {
    // Try to locate the argument directly.
    SourceLocation Loc = Attr.getLoc();
    if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0))
      Loc = Attr.getArgAsExpr(0)->getBeginLoc();

    Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
    return;
  }

  // Verify that the identifier is a valid decl in the C decl namespace.
  LookupResult Result(SemaRef, DeclarationName(IdentLoc->Ident),
                      SourceLocation(),
                      Sema::LookupNameKind::LookupOrdinaryName);
  if (!SemaRef.LookupName(Result, SemaRef.TUScope) ||
      !Result.getAsSingle<VarDecl>()) {
    Diag(IdentLoc->Loc, diag::err_nserrordomain_invalid_decl)
        << 1 << IdentLoc->Ident;
    return;
  }

  D->addAttr(::new (getASTContext())
                 NSErrorDomainAttr(getASTContext(), Attr, IdentLoc->Ident));
}

void SemaObjC::handleBridgeAttr(Decl *D, const ParsedAttr &AL) {
  IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;

  if (!Parm) {
    Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
    return;
  }

  // Typedefs only allow objc_bridge(id) and have some additional checking.
  if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
    if (!Parm->Ident->isStr("id")) {
      Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL;
      return;
    }

    // Only allow 'cv void *'.
    QualType T = TD->getUnderlyingType();
    if (!T->isVoidPointerType()) {
      Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
      return;
    }
  }

  D->addAttr(::new (getASTContext())
                 ObjCBridgeAttr(getASTContext(), AL, Parm->Ident));
}

void SemaObjC::handleBridgeMutableAttr(Decl *D, const ParsedAttr &AL) {
  IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;

  if (!Parm) {
    Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
    return;
  }

  D->addAttr(::new (getASTContext())
                 ObjCBridgeMutableAttr(getASTContext(), AL, Parm->Ident));
}

void SemaObjC::handleBridgeRelatedAttr(Decl *D, const ParsedAttr &AL) {
  IdentifierInfo *RelatedClass =
      AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr;
  if (!RelatedClass) {
    Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
    return;
  }
  IdentifierInfo *ClassMethod =
      AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
  IdentifierInfo *InstanceMethod =
      AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
  D->addAttr(::new (getASTContext()) ObjCBridgeRelatedAttr(
      getASTContext(), AL, RelatedClass, ClassMethod, InstanceMethod));
}

void SemaObjC::handleDesignatedInitializer(Decl *D, const ParsedAttr &AL) {
  DeclContext *Ctx = D->getDeclContext();

  // This attribute can only be applied to methods in interfaces or class
  // extensions.
  if (!isa<ObjCInterfaceDecl>(Ctx) &&
      !(isa<ObjCCategoryDecl>(Ctx) &&
        cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) {
    Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
    return;
  }

  ObjCInterfaceDecl *IFace;
  if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx))
    IFace = CatDecl->getClassInterface();
  else
    IFace = cast<ObjCInterfaceDecl>(Ctx);

  if (!IFace)
    return;

  IFace->setHasDesignatedInitializers();
  D->addAttr(::new (getASTContext())
                 ObjCDesignatedInitializerAttr(getASTContext(), AL));
}

void SemaObjC::handleRuntimeName(Decl *D, const ParsedAttr &AL) {
  StringRef MetaDataName;
  if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, MetaDataName))
    return;
  D->addAttr(::new (getASTContext())
                 ObjCRuntimeNameAttr(getASTContext(), AL, MetaDataName));
}

// When a user wants to use objc_boxable with a union or struct
// but they don't have access to the declaration (legacy/third-party code)
// then they can 'enable' this feature with a typedef:
// typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
void SemaObjC::handleBoxable(Decl *D, const ParsedAttr &AL) {
  bool notify = false;

  auto *RD = dyn_cast<RecordDecl>(D);
  if (RD && RD->getDefinition()) {
    RD = RD->getDefinition();
    notify = true;
  }

  if (RD) {
    ObjCBoxableAttr *BoxableAttr =
        ::new (getASTContext()) ObjCBoxableAttr(getASTContext(), AL);
    RD->addAttr(BoxableAttr);
    if (notify) {
      // we need to notify ASTReader/ASTWriter about
      // modification of existing declaration
      if (ASTMutationListener *L = SemaRef.getASTMutationListener())
        L->AddedAttributeToRecord(BoxableAttr, RD);
    }
  }
}

void SemaObjC::handleOwnershipAttr(Decl *D, const ParsedAttr &AL) {
  if (hasDeclarator(D))
    return;

  Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)
      << AL.getRange() << AL << AL.isRegularKeywordAttribute()
      << ExpectedVariable;
}

void SemaObjC::handlePreciseLifetimeAttr(Decl *D, const ParsedAttr &AL) {
  const auto *VD = cast<ValueDecl>(D);
  QualType QT = VD->getType();

  if (!QT->isDependentType() && !QT->isObjCLifetimeType()) {
    Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type) << QT;
    return;
  }

  Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime();

  // If we have no lifetime yet, check the lifetime we're presumably
  // going to infer.
  if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType())
    Lifetime = QT->getObjCARCImplicitLifetime();

  switch (Lifetime) {
  case Qualifiers::OCL_None:
    assert(QT->isDependentType() &&
           "didn't infer lifetime for non-dependent type?");
    break;

  case Qualifiers::OCL_Weak:   // meaningful
  case Qualifiers::OCL_Strong: // meaningful
    break;

  case Qualifiers::OCL_ExplicitNone:
  case Qualifiers::OCL_Autoreleasing:
    Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
        << (Lifetime == Qualifiers::OCL_Autoreleasing);
    break;
  }

  D->addAttr(::new (getASTContext())
                 ObjCPreciseLifetimeAttr(getASTContext(), AL));
}

static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD,
                                        bool DiagnoseFailure) {
  QualType Ty = VD->getType();
  if (!Ty->isObjCRetainableType()) {
    if (DiagnoseFailure) {
      S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
          << 0;
    }
    return false;
  }

  Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime();

  // SemaObjC::inferObjCARCLifetime must run after processing decl attributes
  // (because __block lowers to an attribute), so if the lifetime hasn't been
  // explicitly specified, infer it locally now.
  if (LifetimeQual == Qualifiers::OCL_None)
    LifetimeQual = Ty->getObjCARCImplicitLifetime();

  // The attributes only really makes sense for __strong variables; ignore any
  // attempts to annotate a parameter with any other lifetime qualifier.
  if (LifetimeQual != Qualifiers::OCL_Strong) {
    if (DiagnoseFailure) {
      S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
          << 1;
    }
    return false;
  }

  // Tampering with the type of a VarDecl here is a bit of a hack, but we need
  // to ensure that the variable is 'const' so that we can error on
  // modification, which can otherwise over-release.
  VD->setType(Ty.withConst());
  VD->setARCPseudoStrong(true);
  return true;
}

void SemaObjC::handleExternallyRetainedAttr(Decl *D, const ParsedAttr &AL) {
  if (auto *VD = dyn_cast<VarDecl>(D)) {
    assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically");
    if (!VD->hasLocalStorage()) {
      Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained) << 0;
      return;
    }

    if (!tryMakeVariablePseudoStrong(SemaRef, VD, /*DiagnoseFailure=*/true))
      return;

    handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL);
    return;
  }

  // If D is a function-like declaration (method, block, or function), then we
  // make every parameter psuedo-strong.
  unsigned NumParams =
      hasFunctionProto(D) ? getFunctionOrMethodNumParams(D) : 0;
  for (unsigned I = 0; I != NumParams; ++I) {
    auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I));
    QualType Ty = PVD->getType();

    // If a user wrote a parameter with __strong explicitly, then assume they
    // want "real" strong semantics for that parameter. This works because if
    // the parameter was written with __strong, then the strong qualifier will
    // be non-local.
    if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() ==
        Qualifiers::OCL_Strong)
      continue;

    tryMakeVariablePseudoStrong(SemaRef, PVD, /*DiagnoseFailure=*/false);
  }
  handleSimpleAttribute<ObjCExternallyRetainedAttr>(*this, D, AL);
}

bool SemaObjC::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {
  Sema::FormatStringInfo FSI;
  if ((SemaRef.GetFormatStringType(Format) == Sema::FST_NSString) &&
      SemaRef.getFormatStringInfo(Format, false, true, &FSI)) {
    Idx = FSI.FormatIdx;
    return true;
  }
  return false;
}

/// Diagnose use of %s directive in an NSString which is being passed
/// as formatting string to formatting method.
void SemaObjC::DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl *FDecl,
                                                     Expr **Args,
                                                     unsigned NumArgs) {
  unsigned Idx = 0;
  bool Format = false;
  ObjCStringFormatFamily SFFamily = FDecl->getObjCFStringFormattingFamily();
  if (SFFamily == ObjCStringFormatFamily::SFF_CFString) {
    Idx = 2;
    Format = true;
  } else
    for (const auto *I : FDecl->specific_attrs<FormatAttr>()) {
      if (GetFormatNSStringIdx(I, Idx)) {
        Format = true;
        break;
      }
    }
  if (!Format || NumArgs <= Idx)
    return;
  const Expr *FormatExpr = Args[Idx];
  if (const CStyleCastExpr *CSCE = dyn_cast<CStyleCastExpr>(FormatExpr))
    FormatExpr = CSCE->getSubExpr();
  const StringLiteral *FormatString;
  if (const ObjCStringLiteral *OSL =
          dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts()))
    FormatString = OSL->getString();
  else
    FormatString = dyn_cast<StringLiteral>(FormatExpr->IgnoreParenImpCasts());
  if (!FormatString)
    return;
  if (SemaRef.FormatStringHasSArg(FormatString)) {
    Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string)
        << "%s" << 1 << 1;
    Diag(FDecl->getLocation(), diag::note_entity_declared_at)
        << FDecl->getDeclName();
  }
}

bool SemaObjC::isSignedCharBool(QualType Ty) {
  return Ty->isSpecificBuiltinType(BuiltinType::SChar) && getLangOpts().ObjC &&
         NSAPIObj->isObjCBOOLType(Ty);
}

void SemaObjC::adornBoolConversionDiagWithTernaryFixit(
    Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder) {
  Expr *Ignored = SourceExpr->IgnoreImplicit();
  if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ignored))
    Ignored = OVE->getSourceExpr();
  bool NeedsParens = isa<AbstractConditionalOperator>(Ignored) ||
                     isa<BinaryOperator>(Ignored) ||
                     isa<CXXOperatorCallExpr>(Ignored);
  SourceLocation EndLoc = SemaRef.getLocForEndOfToken(SourceExpr->getEndLoc());
  if (NeedsParens)
    Builder << FixItHint::CreateInsertion(SourceExpr->getBeginLoc(), "(")
            << FixItHint::CreateInsertion(EndLoc, ")");
  Builder << FixItHint::CreateInsertion(EndLoc, " ? YES : NO");
}

/// Check a single element within a collection literal against the
/// target element type.
static void checkCollectionLiteralElement(Sema &S, QualType TargetElementType,
                                          Expr *Element, unsigned ElementKind) {
  // Skip a bitcast to 'id' or qualified 'id'.
  if (auto ICE = dyn_cast<ImplicitCastExpr>(Element)) {
    if (ICE->getCastKind() == CK_BitCast &&
        ICE->getSubExpr()->getType()->getAs<ObjCObjectPointerType>())
      Element = ICE->getSubExpr();
  }

  QualType ElementType = Element->getType();
  ExprResult ElementResult(Element);
  if (ElementType->getAs<ObjCObjectPointerType>() &&
      S.CheckSingleAssignmentConstraints(TargetElementType, ElementResult,
                                         false, false) != Sema::Compatible) {
    S.Diag(Element->getBeginLoc(), diag::warn_objc_collection_literal_element)
        << ElementType << ElementKind << TargetElementType
        << Element->getSourceRange();
  }

  if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element))
    S.ObjC().checkArrayLiteral(TargetElementType, ArrayLiteral);
  else if (auto DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(Element))
    S.ObjC().checkDictionaryLiteral(TargetElementType, DictionaryLiteral);
}

/// Check an Objective-C array literal being converted to the given
/// target type.
void SemaObjC::checkArrayLiteral(QualType TargetType,
                                 ObjCArrayLiteral *ArrayLiteral) {
  if (!NSArrayDecl)
    return;

  const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();
  if (!TargetObjCPtr)
    return;

  if (TargetObjCPtr->isUnspecialized() ||
      TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() !=
          NSArrayDecl->getCanonicalDecl())
    return;

  auto TypeArgs = TargetObjCPtr->getTypeArgs();
  if (TypeArgs.size() != 1)
    return;

  QualType TargetElementType = TypeArgs[0];
  for (unsigned I = 0, N = ArrayLiteral->getNumElements(); I != N; ++I) {
    checkCollectionLiteralElement(SemaRef, TargetElementType,
                                  ArrayLiteral->getElement(I), 0);
  }
}

void SemaObjC::checkDictionaryLiteral(
    QualType TargetType, ObjCDictionaryLiteral *DictionaryLiteral) {
  if (!NSDictionaryDecl)
    return;

  const auto *TargetObjCPtr = TargetType->getAs<ObjCObjectPointerType>();
  if (!TargetObjCPtr)
    return;

  if (TargetObjCPtr->isUnspecialized() ||
      TargetObjCPtr->getInterfaceDecl()->getCanonicalDecl() !=
          NSDictionaryDecl->getCanonicalDecl())
    return;

  auto TypeArgs = TargetObjCPtr->getTypeArgs();
  if (TypeArgs.size() != 2)
    return;

  QualType TargetKeyType = TypeArgs[0];
  QualType TargetObjectType = TypeArgs[1];
  for (unsigned I = 0, N = DictionaryLiteral->getNumElements(); I != N; ++I) {
    auto Element = DictionaryLiteral->getKeyValueElement(I);
    checkCollectionLiteralElement(SemaRef, TargetKeyType, Element.Key, 1);
    checkCollectionLiteralElement(SemaRef, TargetObjectType, Element.Value, 2);
  }
}

} // namespace clang
