//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for Objective-C expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/Basic/Builtins.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/Rewriters.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ConvertUTF.h"

using namespace clang;
using namespace sema;
using llvm::makeArrayRef;

ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
                                        ArrayRef<Expr *> Strings) {
  // Most ObjC strings are formed out of a single piece.  However, we *can*
  // have strings formed out of multiple @ strings with multiple pptokens in
  // each one, e.g. @"foo" "bar" @"baz" "qux"   which need to be turned into one
  // StringLiteral for ObjCStringLiteral to hold onto.
  StringLiteral *S = cast<StringLiteral>(Strings[0]);

  // If we have a multi-part string, merge it all together.
  if (Strings.size() != 1) {
    // Concatenate objc strings.
    SmallString<128> StrBuf;
    SmallVector<SourceLocation, 8> StrLocs;

    for (Expr *E : Strings) {
      S = cast<StringLiteral>(E);

      // ObjC strings can't be wide or UTF.
      if (!S->isAscii()) {
        Diag(S->getBeginLoc(), diag::err_cfstring_literal_not_string_constant)
            << S->getSourceRange();
        return true;
      }

      // Append the string.
      StrBuf += S->getString();

      // Get the locations of the string tokens.
      StrLocs.append(S->tokloc_begin(), S->tokloc_end());
    }

    // Create the aggregate string with the appropriate content and location
    // information.
    const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType());
    assert(CAT && "String literal not of constant array type!");
    QualType StrTy = Context.getConstantArrayType(
        CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1), nullptr,
        CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());
    S = StringLiteral::Create(Context, StrBuf, StringLiteral::Ascii,
                              /*Pascal=*/false, StrTy, &StrLocs[0],
                              StrLocs.size());
  }

  return BuildObjCStringLiteral(AtLocs[0], S);
}

ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
  // Verify that this composite string is acceptable for ObjC strings.
  if (CheckObjCString(S))
    return true;

  // Initialize the constant string interface lazily. This assumes
  // the NSString interface is seen in this translation unit. Note: We
  // don't use NSConstantString, since the runtime team considers this
  // interface private (even though it appears in the header files).
  QualType Ty = Context.getObjCConstantStringInterface();
  if (!Ty.isNull()) {
    Ty = Context.getObjCObjectPointerType(Ty);
  } else if (getLangOpts().NoConstantCFStrings) {
    IdentifierInfo *NSIdent=nullptr;
    std::string StringClass(getLangOpts().ObjCConstantStringClass);

    if (StringClass.empty())
      NSIdent = &Context.Idents.get("NSConstantString");
    else
      NSIdent = &Context.Idents.get(StringClass);

    NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
                                     LookupOrdinaryName);
    if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
      Context.setObjCConstantStringInterface(StrIF);
      Ty = Context.getObjCConstantStringInterface();
      Ty = Context.getObjCObjectPointerType(Ty);
    } else {
      // If there is no NSConstantString interface defined then treat this
      // as error and recover from it.
      Diag(S->getBeginLoc(), diag::err_no_nsconstant_string_class)
          << NSIdent << S->getSourceRange();
      Ty = Context.getObjCIdType();
    }
  } else {
    IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
    NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
                                     LookupOrdinaryName);
    if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
      Context.setObjCConstantStringInterface(StrIF);
      Ty = Context.getObjCConstantStringInterface();
      Ty = Context.getObjCObjectPointerType(Ty);
    } else {
      // If there is no NSString interface defined, implicitly declare
      // a @class NSString; and use that instead. This is to make sure
      // type of an NSString literal is represented correctly, instead of
      // being an 'id' type.
      Ty = Context.getObjCNSStringType();
      if (Ty.isNull()) {
        ObjCInterfaceDecl *NSStringIDecl =
          ObjCInterfaceDecl::Create (Context,
                                     Context.getTranslationUnitDecl(),
                                     SourceLocation(), NSIdent,
                                     nullptr, nullptr, SourceLocation());
        Ty = Context.getObjCInterfaceType(NSStringIDecl);
        Context.setObjCNSStringType(Ty);
      }
      Ty = Context.getObjCObjectPointerType(Ty);
    }
  }

  return new (Context) ObjCStringLiteral(S, Ty, AtLoc);
}

/// Emits an error if the given method does not exist, or if the return
/// type is not an Objective-C object.
static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
                                 const ObjCInterfaceDecl *Class,
                                 Selector Sel, const ObjCMethodDecl *Method) {
  if (!Method) {
    // FIXME: Is there a better way to avoid quotes than using getName()?
    S.Diag(Loc, diag::err_undeclared_boxing_method) << Sel << Class->getName();
    return false;
  }

  // Make sure the return type is reasonable.
  QualType ReturnType = Method->getReturnType();
  if (!ReturnType->isObjCObjectPointerType()) {
    S.Diag(Loc, diag::err_objc_literal_method_sig)
      << Sel;
    S.Diag(Method->getLocation(), diag::note_objc_literal_method_return)
      << ReturnType;
    return false;
  }

  return true;
}

/// Maps ObjCLiteralKind to NSClassIdKindKind
static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind(
                                            Sema::ObjCLiteralKind LiteralKind) {
  switch (LiteralKind) {
    case Sema::LK_Array:
      return NSAPI::ClassId_NSArray;
    case Sema::LK_Dictionary:
      return NSAPI::ClassId_NSDictionary;
    case Sema::LK_Numeric:
      return NSAPI::ClassId_NSNumber;
    case Sema::LK_String:
      return NSAPI::ClassId_NSString;
    case Sema::LK_Boxed:
      return NSAPI::ClassId_NSValue;

    // there is no corresponding matching
    // between LK_None/LK_Block and NSClassIdKindKind
    case Sema::LK_Block:
    case Sema::LK_None:
      break;
  }
  llvm_unreachable("LiteralKind can't be converted into a ClassKind");
}

/// Validates ObjCInterfaceDecl availability.
/// ObjCInterfaceDecl, used to create ObjC literals, should be defined
/// if clang not in a debugger mode.
static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
                                            SourceLocation Loc,
                                            Sema::ObjCLiteralKind LiteralKind) {
  if (!Decl) {
    NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind);
    IdentifierInfo *II = S.NSAPIObj->getNSClassId(Kind);
    S.Diag(Loc, diag::err_undeclared_objc_literal_class)
      << II->getName() << LiteralKind;
    return false;
  } else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) {
    S.Diag(Loc, diag::err_undeclared_objc_literal_class)
      << Decl->getName() << LiteralKind;
    S.Diag(Decl->getLocation(), diag::note_forward_class);
    return false;
  }

  return true;
}

/// Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
/// Used to create ObjC literals, such as NSDictionary (@{}),
/// NSArray (@[]) and Boxed Expressions (@())
static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S,
                                            SourceLocation Loc,
                                            Sema::ObjCLiteralKind LiteralKind) {
  NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind);
  IdentifierInfo *II = S.NSAPIObj->getNSClassId(ClassKind);
  NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc,
                                     Sema::LookupOrdinaryName);
  ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
  if (!ID && S.getLangOpts().DebuggerObjCLiteral) {
    ASTContext &Context = S.Context;
    TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
    ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II,
                                    nullptr, nullptr, SourceLocation());
  }

  if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) {
    ID = nullptr;
  }

  return ID;
}

/// Retrieve the NSNumber factory method that should be used to create
/// an Objective-C literal for the given type.
static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
                                                QualType NumberType,
                                                bool isLiteral = false,
                                                SourceRange R = SourceRange()) {
  Optional<NSAPI::NSNumberLiteralMethodKind> Kind =
      S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType);

  if (!Kind) {
    if (isLiteral) {
      S.Diag(Loc, diag::err_invalid_nsnumber_type)
        << NumberType << R;
    }
    return nullptr;
  }

  // If we already looked up this method, we're done.
  if (S.NSNumberLiteralMethods[*Kind])
    return S.NSNumberLiteralMethods[*Kind];

  Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind,
                                                        /*Instance=*/false);

  ASTContext &CX = S.Context;

  // Look up the NSNumber class, if we haven't done so already. It's cached
  // in the Sema instance.
  if (!S.NSNumberDecl) {
    S.NSNumberDecl = LookupObjCInterfaceDeclForLiteral(S, Loc,
                                                       Sema::LK_Numeric);
    if (!S.NSNumberDecl) {
      return nullptr;
    }
  }

  if (S.NSNumberPointer.isNull()) {
    // generate the pointer to NSNumber type.
    QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl);
    S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject);
  }

  // Look for the appropriate method within NSNumber.
  ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);
  if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
    // create a stub definition this NSNumber factory method.
    TypeSourceInfo *ReturnTInfo = nullptr;
    Method =
        ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
                               S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl,
                               /*isInstance=*/false, /*isVariadic=*/false,
                               /*isPropertyAccessor=*/false,
                               /*isSynthesizedAccessorStub=*/false,
                               /*isImplicitlyDeclared=*/true,
                               /*isDefined=*/false, ObjCMethodDecl::Required,
                               /*HasRelatedResultType=*/false);
    ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
                                             SourceLocation(), SourceLocation(),
                                             &CX.Idents.get("value"),
                                             NumberType, /*TInfo=*/nullptr,
                                             SC_None, nullptr);
    Method->setMethodParams(S.Context, value, None);
  }

  if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method))
    return nullptr;

  // Note: if the parameter type is out-of-line, we'll catch it later in the
  // implicit conversion.

  S.NSNumberLiteralMethods[*Kind] = Method;
  return Method;
}

/// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
/// numeric literal expression. Type of the expression will be "NSNumber *".
ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
  // Determine the type of the literal.
  QualType NumberType = Number->getType();
  if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) {
    // In C, character literals have type 'int'. That's not the type we want
    // to use to determine the Objective-c literal kind.
    switch (Char->getKind()) {
    case CharacterLiteral::Ascii:
    case CharacterLiteral::UTF8:
      NumberType = Context.CharTy;
      break;

    case CharacterLiteral::Wide:
      NumberType = Context.getWideCharType();
      break;

    case CharacterLiteral::UTF16:
      NumberType = Context.Char16Ty;
      break;

    case CharacterLiteral::UTF32:
      NumberType = Context.Char32Ty;
      break;
    }
  }

  // Look for the appropriate method within NSNumber.
  // Construct the literal.
  SourceRange NR(Number->getSourceRange());
  ObjCMethodDecl *Method = getNSNumberFactoryMethod(*this, AtLoc, NumberType,
                                                    true, NR);
  if (!Method)
    return ExprError();

  // Convert the number to the type that the parameter expects.
  ParmVarDecl *ParamDecl = Method->parameters()[0];
  InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
                                                                    ParamDecl);
  ExprResult ConvertedNumber = PerformCopyInitialization(Entity,
                                                         SourceLocation(),
                                                         Number);
  if (ConvertedNumber.isInvalid())
    return ExprError();
  Number = ConvertedNumber.get();

  // Use the effective source range of the literal, including the leading '@'.
  return MaybeBindToTemporary(
           new (Context) ObjCBoxedExpr(Number, NSNumberPointer, Method,
                                       SourceRange(AtLoc, NR.getEnd())));
}

ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc,
                                      SourceLocation ValueLoc,
                                      bool Value) {
  ExprResult Inner;
  if (getLangOpts().CPlusPlus) {
    Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false);
  } else {
    // C doesn't actually have a way to represent literal values of type
    // _Bool. So, we'll use 0/1 and implicit cast to _Bool.
    Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0);
    Inner = ImpCastExprToType(Inner.get(), Context.BoolTy,
                              CK_IntegralToBoolean);
  }

  return BuildObjCNumericLiteral(AtLoc, Inner.get());
}

/// Check that the given expression is a valid element of an Objective-C
/// collection literal.
static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
                                                    QualType T,
                                                    bool ArrayLiteral = false) {
  // If the expression is type-dependent, there's nothing for us to do.
  if (Element->isTypeDependent())
    return Element;

  ExprResult Result = S.CheckPlaceholderExpr(Element);
  if (Result.isInvalid())
    return ExprError();
  Element = Result.get();

  // In C++, check for an implicit conversion to an Objective-C object pointer
  // type.
  if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) {
    InitializedEntity Entity
      = InitializedEntity::InitializeParameter(S.Context, T,
                                               /*Consumed=*/false);
    InitializationKind Kind = InitializationKind::CreateCopy(
        Element->getBeginLoc(), SourceLocation());
    InitializationSequence Seq(S, Entity, Kind, Element);
    if (!Seq.Failed())
      return Seq.Perform(S, Entity, Kind, Element);
  }

  Expr *OrigElement = Element;

  // Perform lvalue-to-rvalue conversion.
  Result = S.DefaultLvalueConversion(Element);
  if (Result.isInvalid())
    return ExprError();
  Element = Result.get();

  // Make sure that we have an Objective-C pointer type or block.
  if (!Element->getType()->isObjCObjectPointerType() &&
      !Element->getType()->isBlockPointerType()) {
    bool Recovered = false;

    // If this is potentially an Objective-C numeric literal, add the '@'.
    if (isa<IntegerLiteral>(OrigElement) ||
        isa<CharacterLiteral>(OrigElement) ||
        isa<FloatingLiteral>(OrigElement) ||
        isa<ObjCBoolLiteralExpr>(OrigElement) ||
        isa<CXXBoolLiteralExpr>(OrigElement)) {
      if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) {
        int Which = isa<CharacterLiteral>(OrigElement) ? 1
                  : (isa<CXXBoolLiteralExpr>(OrigElement) ||
                     isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2
                  : 3;

        S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection)
            << Which << OrigElement->getSourceRange()
            << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@");

        Result =
            S.BuildObjCNumericLiteral(OrigElement->getBeginLoc(), OrigElement);
        if (Result.isInvalid())
          return ExprError();

        Element = Result.get();
        Recovered = true;
      }
    }
    // If this is potentially an Objective-C string literal, add the '@'.
    else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) {
      if (String->isAscii()) {
        S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection)
            << 0 << OrigElement->getSourceRange()
            << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@");

        Result = S.BuildObjCStringLiteral(OrigElement->getBeginLoc(), String);
        if (Result.isInvalid())
          return ExprError();

        Element = Result.get();
        Recovered = true;
      }
    }

    if (!Recovered) {
      S.Diag(Element->getBeginLoc(), diag::err_invalid_collection_element)
          << Element->getType();
      return ExprError();
    }
  }
  if (ArrayLiteral)
    if (ObjCStringLiteral *getString =
          dyn_cast<ObjCStringLiteral>(OrigElement)) {
      if (StringLiteral *SL = getString->getString()) {
        unsigned numConcat = SL->getNumConcatenated();
        if (numConcat > 1) {
          // Only warn if the concatenated string doesn't come from a macro.
          bool hasMacro = false;
          for (unsigned i = 0; i < numConcat ; ++i)
            if (SL->getStrTokenLoc(i).isMacroID()) {
              hasMacro = true;
              break;
            }
          if (!hasMacro)
            S.Diag(Element->getBeginLoc(),
                   diag::warn_concatenated_nsarray_literal)
                << Element->getType();
        }
      }
    }

  // Make sure that the element has the type that the container factory
  // function expects.
  return S.PerformCopyInitialization(
      InitializedEntity::InitializeParameter(S.Context, T,
                                             /*Consumed=*/false),
      Element->getBeginLoc(), Element);
}

ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
  if (ValueExpr->isTypeDependent()) {
    ObjCBoxedExpr *BoxedExpr =
      new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR);
    return BoxedExpr;
  }
  ObjCMethodDecl *BoxingMethod = nullptr;
  QualType BoxedType;
  // Convert the expression to an RValue, so we can check for pointer types...
  ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr);
  if (RValue.isInvalid()) {
    return ExprError();
  }
  SourceLocation Loc = SR.getBegin();
  ValueExpr = RValue.get();
  QualType ValueType(ValueExpr->getType());
  if (const PointerType *PT = ValueType->getAs<PointerType>()) {
    QualType PointeeType = PT->getPointeeType();
    if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {

      if (!NSStringDecl) {
        NSStringDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
                                                         Sema::LK_String);
        if (!NSStringDecl) {
          return ExprError();
        }
        QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl);
        NSStringPointer = Context.getObjCObjectPointerType(NSStringObject);
      }

      // The boxed expression can be emitted as a compile time constant if it is
      // a string literal whose character encoding is compatible with UTF-8.
      if (auto *CE = dyn_cast<ImplicitCastExpr>(ValueExpr))
        if (CE->getCastKind() == CK_ArrayToPointerDecay)
          if (auto *SL =
                  dyn_cast<StringLiteral>(CE->getSubExpr()->IgnoreParens())) {
            assert((SL->isAscii() || SL->isUTF8()) &&
                   "unexpected character encoding");
            StringRef Str = SL->getString();
            const llvm::UTF8 *StrBegin = Str.bytes_begin();
            const llvm::UTF8 *StrEnd = Str.bytes_end();
            // Check that this is a valid UTF-8 string.
            if (llvm::isLegalUTF8String(&StrBegin, StrEnd)) {
              BoxedType = Context.getAttributedType(
                  AttributedType::getNullabilityAttrKind(
                      NullabilityKind::NonNull),
                  NSStringPointer, NSStringPointer);
              return new (Context) ObjCBoxedExpr(CE, BoxedType, nullptr, SR);
            }

            Diag(SL->getBeginLoc(), diag::warn_objc_boxing_invalid_utf8_string)
                << NSStringPointer << SL->getSourceRange();
          }

      if (!StringWithUTF8StringMethod) {
        IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String");
        Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II);

        // Look for the appropriate method within NSString.
        BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);
        if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
          // Debugger needs to work even if NSString hasn't been defined.
          TypeSourceInfo *ReturnTInfo = nullptr;
          ObjCMethodDecl *M = ObjCMethodDecl::Create(
              Context, SourceLocation(), SourceLocation(), stringWithUTF8String,
              NSStringPointer, ReturnTInfo, NSStringDecl,
              /*isInstance=*/false, /*isVariadic=*/false,
              /*isPropertyAccessor=*/false,
              /*isSynthesizedAccessorStub=*/false,
              /*isImplicitlyDeclared=*/true,
              /*isDefined=*/false, ObjCMethodDecl::Required,
              /*HasRelatedResultType=*/false);
          QualType ConstCharType = Context.CharTy.withConst();
          ParmVarDecl *value =
            ParmVarDecl::Create(Context, M,
                                SourceLocation(), SourceLocation(),
                                &Context.Idents.get("value"),
                                Context.getPointerType(ConstCharType),
                                /*TInfo=*/nullptr,
                                SC_None, nullptr);
          M->setMethodParams(Context, value, None);
          BoxingMethod = M;
        }

        if (!validateBoxingMethod(*this, Loc, NSStringDecl,
                                  stringWithUTF8String, BoxingMethod))
           return ExprError();

        StringWithUTF8StringMethod = BoxingMethod;
      }

      BoxingMethod = StringWithUTF8StringMethod;
      BoxedType = NSStringPointer;
      // Transfer the nullability from method's return type.
      Optional<NullabilityKind> Nullability =
          BoxingMethod->getReturnType()->getNullability(Context);
      if (Nullability)
        BoxedType = Context.getAttributedType(
            AttributedType::getNullabilityAttrKind(*Nullability), BoxedType,
            BoxedType);
    }
  } else if (ValueType->isBuiltinType()) {
    // The other types we support are numeric, char and BOOL/bool. We could also
    // provide limited support for structure types, such as NSRange, NSRect, and
    // NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h>
    // for more details.

    // Check for a top-level character literal.
    if (const CharacterLiteral *Char =
        dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) {
      // In C, character literals have type 'int'. That's not the type we want
      // to use to determine the Objective-c literal kind.
      switch (Char->getKind()) {
      case CharacterLiteral::Ascii:
      case CharacterLiteral::UTF8:
        ValueType = Context.CharTy;
        break;

      case CharacterLiteral::Wide:
        ValueType = Context.getWideCharType();
        break;

      case CharacterLiteral::UTF16:
        ValueType = Context.Char16Ty;
        break;

      case CharacterLiteral::UTF32:
        ValueType = Context.Char32Ty;
        break;
      }
    }
    // FIXME:  Do I need to do anything special with BoolTy expressions?

    // Look for the appropriate method within NSNumber.
    BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType);
    BoxedType = NSNumberPointer;
  } else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
    if (!ET->getDecl()->isComplete()) {
      Diag(Loc, diag::err_objc_incomplete_boxed_expression_type)
        << ValueType << ValueExpr->getSourceRange();
      return ExprError();
    }

    BoxingMethod = getNSNumberFactoryMethod(*this, Loc,
                                            ET->getDecl()->getIntegerType());
    BoxedType = NSNumberPointer;
  } else if (ValueType->isObjCBoxableRecordType()) {
    // Support for structure types, that marked as objc_boxable
    // struct __attribute__((objc_boxable)) s { ... };

    // Look up the NSValue class, if we haven't done so already. It's cached
    // in the Sema instance.
    if (!NSValueDecl) {
      NSValueDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
                                                      Sema::LK_Boxed);
      if (!NSValueDecl) {
        return ExprError();
      }

      // generate the pointer to NSValue type.
      QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);
      NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);
    }

    if (!ValueWithBytesObjCTypeMethod) {
      IdentifierInfo *II[] = {
        &Context.Idents.get("valueWithBytes"),
        &Context.Idents.get("objCType")
      };
      Selector ValueWithBytesObjCType = Context.Selectors.getSelector(2, II);

      // Look for the appropriate method within NSValue.
      BoxingMethod = NSValueDecl->lookupClassMethod(ValueWithBytesObjCType);
      if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
        // Debugger needs to work even if NSValue hasn't been defined.
        TypeSourceInfo *ReturnTInfo = nullptr;
        ObjCMethodDecl *M = ObjCMethodDecl::Create(
            Context, SourceLocation(), SourceLocation(), ValueWithBytesObjCType,
            NSValuePointer, ReturnTInfo, NSValueDecl,
            /*isInstance=*/false,
            /*isVariadic=*/false,
            /*isPropertyAccessor=*/false,
            /*isSynthesizedAccessorStub=*/false,
            /*isImplicitlyDeclared=*/true,
            /*isDefined=*/false, ObjCMethodDecl::Required,
            /*HasRelatedResultType=*/false);

        SmallVector<ParmVarDecl *, 2> Params;

        ParmVarDecl *bytes =
        ParmVarDecl::Create(Context, M,
                            SourceLocation(), SourceLocation(),
                            &Context.Idents.get("bytes"),
                            Context.VoidPtrTy.withConst(),
                            /*TInfo=*/nullptr,
                            SC_None, nullptr);
        Params.push_back(bytes);

        QualType ConstCharType = Context.CharTy.withConst();
        ParmVarDecl *type =
        ParmVarDecl::Create(Context, M,
                            SourceLocation(), SourceLocation(),
                            &Context.Idents.get("type"),
                            Context.getPointerType(ConstCharType),
                            /*TInfo=*/nullptr,
                            SC_None, nullptr);
        Params.push_back(type);

        M->setMethodParams(Context, Params, None);
        BoxingMethod = M;
      }

      if (!validateBoxingMethod(*this, Loc, NSValueDecl,
                                ValueWithBytesObjCType, BoxingMethod))
        return ExprError();

      ValueWithBytesObjCTypeMethod = BoxingMethod;
    }

    if (!ValueType.isTriviallyCopyableType(Context)) {
      Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type)
        << ValueType << ValueExpr->getSourceRange();
      return ExprError();
    }

    BoxingMethod = ValueWithBytesObjCTypeMethod;
    BoxedType = NSValuePointer;
  }

  if (!BoxingMethod) {
    Diag(Loc, diag::err_objc_illegal_boxed_expression_type)
      << ValueType << ValueExpr->getSourceRange();
    return ExprError();
  }

  DiagnoseUseOfDecl(BoxingMethod, Loc);

  ExprResult ConvertedValueExpr;
  if (ValueType->isObjCBoxableRecordType()) {
    InitializedEntity IE = InitializedEntity::InitializeTemporary(ValueType);
    ConvertedValueExpr = PerformCopyInitialization(IE, ValueExpr->getExprLoc(),
                                                   ValueExpr);
  } else {
    // Convert the expression to the type that the parameter requires.
    ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];
    InitializedEntity IE = InitializedEntity::InitializeParameter(Context,
                                                                  ParamDecl);
    ConvertedValueExpr = PerformCopyInitialization(IE, SourceLocation(),
                                                   ValueExpr);
  }

  if (ConvertedValueExpr.isInvalid())
    return ExprError();
  ValueExpr = ConvertedValueExpr.get();

  ObjCBoxedExpr *BoxedExpr =
    new (Context) ObjCBoxedExpr(ValueExpr, BoxedType,
                                      BoxingMethod, SR);
  return MaybeBindToTemporary(BoxedExpr);
}

/// Build an ObjC subscript pseudo-object expression, given that
/// that's supported by the runtime.
ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
                                        Expr *IndexExpr,
                                        ObjCMethodDecl *getterMethod,
                                        ObjCMethodDecl *setterMethod) {
  assert(!LangOpts.isSubscriptPointerArithmetic());

  // We can't get dependent types here; our callers should have
  // filtered them out.
  assert((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) &&
         "base or index cannot have dependent type here");

  // Filter out placeholders in the index.  In theory, overloads could
  // be preserved here, although that might not actually work correctly.
  ExprResult Result = CheckPlaceholderExpr(IndexExpr);
  if (Result.isInvalid())
    return ExprError();
  IndexExpr = Result.get();

  // Perform lvalue-to-rvalue conversion on the base.
  Result = DefaultLvalueConversion(BaseExpr);
  if (Result.isInvalid())
    return ExprError();
  BaseExpr = Result.get();

  // Build the pseudo-object expression.
  return new (Context) ObjCSubscriptRefExpr(
      BaseExpr, IndexExpr, Context.PseudoObjectTy, VK_LValue, OK_ObjCSubscript,
      getterMethod, setterMethod, RB);
}

ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
  SourceLocation Loc = SR.getBegin();

  if (!NSArrayDecl) {
    NSArrayDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
                                                    Sema::LK_Array);
    if (!NSArrayDecl) {
      return ExprError();
    }
  }

  // Find the arrayWithObjects:count: method, if we haven't done so already.
  QualType IdT = Context.getObjCIdType();
  if (!ArrayWithObjectsMethod) {
    Selector
      Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);
    ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);
    if (!Method && getLangOpts().DebuggerObjCLiteral) {
      TypeSourceInfo *ReturnTInfo = nullptr;
      Method = ObjCMethodDecl::Create(
          Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,
          Context.getTranslationUnitDecl(), false /*Instance*/,
          false /*isVariadic*/,
          /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,
          /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
          ObjCMethodDecl::Required, false);
      SmallVector<ParmVarDecl *, 2> Params;
      ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
                                                 SourceLocation(),
                                                 SourceLocation(),
                                                 &Context.Idents.get("objects"),
                                                 Context.getPointerType(IdT),
                                                 /*TInfo=*/nullptr,
                                                 SC_None, nullptr);
      Params.push_back(objects);
      ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
                                             SourceLocation(),
                                             SourceLocation(),
                                             &Context.Idents.get("cnt"),
                                             Context.UnsignedLongTy,
                                             /*TInfo=*/nullptr, SC_None,
                                             nullptr);
      Params.push_back(cnt);
      Method->setMethodParams(Context, Params, None);
    }

    if (!validateBoxingMethod(*this, Loc, NSArrayDecl, Sel, Method))
      return ExprError();

    // Dig out the type that all elements should be converted to.
    QualType T = Method->parameters()[0]->getType();
    const PointerType *PtrT = T->getAs<PointerType>();
    if (!PtrT ||
        !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {
      Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
        << Sel;
      Diag(Method->parameters()[0]->getLocation(),
           diag::note_objc_literal_method_param)
        << 0 << T
        << Context.getPointerType(IdT.withConst());
      return ExprError();
    }

    // Check that the 'count' parameter is integral.
    if (!Method->parameters()[1]->getType()->isIntegerType()) {
      Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
        << Sel;
      Diag(Method->parameters()[1]->getLocation(),
           diag::note_objc_literal_method_param)
        << 1
        << Method->parameters()[1]->getType()
        << "integral";
      return ExprError();
    }

    // We've found a good +arrayWithObjects:count: method. Save it!
    ArrayWithObjectsMethod = Method;
  }

  QualType ObjectsType = ArrayWithObjectsMethod->parameters()[0]->getType();
  QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType();

  // Check that each of the elements provided is valid in a collection literal,
  // performing conversions as necessary.
  Expr **ElementsBuffer = Elements.data();
  for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
    ExprResult Converted = CheckObjCCollectionLiteralElement(*this,
                                                             ElementsBuffer[I],
                                                             RequiredType, true);
    if (Converted.isInvalid())
      return ExprError();

    ElementsBuffer[I] = Converted.get();
  }

  QualType Ty
    = Context.getObjCObjectPointerType(
                                    Context.getObjCInterfaceType(NSArrayDecl));

  return MaybeBindToTemporary(
           ObjCArrayLiteral::Create(Context, Elements, Ty,
                                    ArrayWithObjectsMethod, SR));
}

/// Check for duplicate keys in an ObjC dictionary literal. For instance:
///   NSDictionary *nd = @{ @"foo" : @"bar", @"foo" : @"baz" };
static void
CheckObjCDictionaryLiteralDuplicateKeys(Sema &S,
                                        ObjCDictionaryLiteral *Literal) {
  if (Literal->isValueDependent() || Literal->isTypeDependent())
    return;

  // NSNumber has quite relaxed equality semantics (for instance, @YES is
  // considered equal to @1.0). For now, ignore floating points and just do a
  // bit-width and sign agnostic integer compare.
  struct APSIntCompare {
    bool operator()(const llvm::APSInt &LHS, const llvm::APSInt &RHS) const {
      return llvm::APSInt::compareValues(LHS, RHS) < 0;
    }
  };

  llvm::DenseMap<StringRef, SourceLocation> StringKeys;
  std::map<llvm::APSInt, SourceLocation, APSIntCompare> IntegralKeys;

  auto checkOneKey = [&](auto &Map, const auto &Key, SourceLocation Loc) {
    auto Pair = Map.insert({Key, Loc});
    if (!Pair.second) {
      S.Diag(Loc, diag::warn_nsdictionary_duplicate_key);
      S.Diag(Pair.first->second, diag::note_nsdictionary_duplicate_key_here);
    }
  };

  for (unsigned Idx = 0, End = Literal->getNumElements(); Idx != End; ++Idx) {
    Expr *Key = Literal->getKeyValueElement(Idx).Key->IgnoreParenImpCasts();

    if (auto *StrLit = dyn_cast<ObjCStringLiteral>(Key)) {
      StringRef Bytes = StrLit->getString()->getBytes();
      SourceLocation Loc = StrLit->getExprLoc();
      checkOneKey(StringKeys, Bytes, Loc);
    }

    if (auto *BE = dyn_cast<ObjCBoxedExpr>(Key)) {
      Expr *Boxed = BE->getSubExpr();
      SourceLocation Loc = BE->getExprLoc();

      // Check for @("foo").
      if (auto *Str = dyn_cast<StringLiteral>(Boxed->IgnoreParenImpCasts())) {
        checkOneKey(StringKeys, Str->getBytes(), Loc);
        continue;
      }

      Expr::EvalResult Result;
      if (Boxed->EvaluateAsInt(Result, S.getASTContext(),
                               Expr::SE_AllowSideEffects)) {
        checkOneKey(IntegralKeys, Result.Val.getInt(), Loc);
      }
    }
  }
}

ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
                              MutableArrayRef<ObjCDictionaryElement> Elements) {
  SourceLocation Loc = SR.getBegin();

  if (!NSDictionaryDecl) {
    NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
                                                         Sema::LK_Dictionary);
    if (!NSDictionaryDecl) {
      return ExprError();
    }
  }

  // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done
  // so already.
  QualType IdT = Context.getObjCIdType();
  if (!DictionaryWithObjectsMethod) {
    Selector Sel = NSAPIObj->getNSDictionarySelector(
                               NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
    ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);
    if (!Method && getLangOpts().DebuggerObjCLiteral) {
      Method = ObjCMethodDecl::Create(
          Context, SourceLocation(), SourceLocation(), Sel, IdT,
          nullptr /*TypeSourceInfo */, Context.getTranslationUnitDecl(),
          false /*Instance*/, false /*isVariadic*/,
          /*isPropertyAccessor=*/false,
          /*isSynthesizedAccessorStub=*/false,
          /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
          ObjCMethodDecl::Required, false);
      SmallVector<ParmVarDecl *, 3> Params;
      ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
                                                 SourceLocation(),
                                                 SourceLocation(),
                                                 &Context.Idents.get("objects"),
                                                 Context.getPointerType(IdT),
                                                 /*TInfo=*/nullptr, SC_None,
                                                 nullptr);
      Params.push_back(objects);
      ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,
                                              SourceLocation(),
                                              SourceLocation(),
                                              &Context.Idents.get("keys"),
                                              Context.getPointerType(IdT),
                                              /*TInfo=*/nullptr, SC_None,
                                              nullptr);
      Params.push_back(keys);
      ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
                                             SourceLocation(),
                                             SourceLocation(),
                                             &Context.Idents.get("cnt"),
                                             Context.UnsignedLongTy,
                                             /*TInfo=*/nullptr, SC_None,
                                             nullptr);
      Params.push_back(cnt);
      Method->setMethodParams(Context, Params, None);
    }

    if (!validateBoxingMethod(*this, SR.getBegin(), NSDictionaryDecl, Sel,
                              Method))
       return ExprError();

    // Dig out the type that all values should be converted to.
    QualType ValueT = Method->parameters()[0]->getType();
    const PointerType *PtrValue = ValueT->getAs<PointerType>();
    if (!PtrValue ||
        !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {
      Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
        << Sel;
      Diag(Method->parameters()[0]->getLocation(),
           diag::note_objc_literal_method_param)
        << 0 << ValueT
        << Context.getPointerType(IdT.withConst());
      return ExprError();
    }

    // Dig out the type that all keys should be converted to.
    QualType KeyT = Method->parameters()[1]->getType();
    const PointerType *PtrKey = KeyT->getAs<PointerType>();
    if (!PtrKey ||
        !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
                                        IdT)) {
      bool err = true;
      if (PtrKey) {
        if (QIDNSCopying.isNull()) {
          // key argument of selector is id<NSCopying>?
          if (ObjCProtocolDecl *NSCopyingPDecl =
              LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
            ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
            QIDNSCopying =
              Context.getObjCObjectType(Context.ObjCBuiltinIdTy, { },
                                        llvm::makeArrayRef(
                                          (ObjCProtocolDecl**) PQ,
                                          1),
                                        false);
            QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
          }
        }
        if (!QIDNSCopying.isNull())
          err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
                                                QIDNSCopying);
      }

      if (err) {
        Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
          << Sel;
        Diag(Method->parameters()[1]->getLocation(),
             diag::note_objc_literal_method_param)
          << 1 << KeyT
          << Context.getPointerType(IdT.withConst());
        return ExprError();
      }
    }

    // Check that the 'count' parameter is integral.
    QualType CountType = Method->parameters()[2]->getType();
    if (!CountType->isIntegerType()) {
      Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
        << Sel;
      Diag(Method->parameters()[2]->getLocation(),
           diag::note_objc_literal_method_param)
        << 2 << CountType
        << "integral";
      return ExprError();
    }

    // We've found a good +dictionaryWithObjects:keys:count: method; save it!
    DictionaryWithObjectsMethod = Method;
  }

  QualType ValuesT = DictionaryWithObjectsMethod->parameters()[0]->getType();
  QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType();
  QualType KeysT = DictionaryWithObjectsMethod->parameters()[1]->getType();
  QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType();

  // Check that each of the keys and values provided is valid in a collection
  // literal, performing conversions as necessary.
  bool HasPackExpansions = false;
  for (ObjCDictionaryElement &Element : Elements) {
    // Check the key.
    ExprResult Key = CheckObjCCollectionLiteralElement(*this, Element.Key,
                                                       KeyT);
    if (Key.isInvalid())
      return ExprError();

    // Check the value.
    ExprResult Value
      = CheckObjCCollectionLiteralElement(*this, Element.Value, ValueT);
    if (Value.isInvalid())
      return ExprError();

    Element.Key = Key.get();
    Element.Value = Value.get();

    if (Element.EllipsisLoc.isInvalid())
      continue;

    if (!Element.Key->containsUnexpandedParameterPack() &&
        !Element.Value->containsUnexpandedParameterPack()) {
      Diag(Element.EllipsisLoc,
           diag::err_pack_expansion_without_parameter_packs)
          << SourceRange(Element.Key->getBeginLoc(),
                         Element.Value->getEndLoc());
      return ExprError();
    }

    HasPackExpansions = true;
  }

  QualType Ty = Context.getObjCObjectPointerType(
      Context.getObjCInterfaceType(NSDictionaryDecl));

  auto *Literal =
      ObjCDictionaryLiteral::Create(Context, Elements, HasPackExpansions, Ty,
                                    DictionaryWithObjectsMethod, SR);
  CheckObjCDictionaryLiteralDuplicateKeys(*this, Literal);
  return MaybeBindToTemporary(Literal);
}

ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
                                      TypeSourceInfo *EncodedTypeInfo,
                                      SourceLocation RParenLoc) {
  QualType EncodedType = EncodedTypeInfo->getType();
  QualType StrTy;
  if (EncodedType->isDependentType())
    StrTy = Context.DependentTy;
  else {
    if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled.
        !EncodedType->isVoidType()) // void is handled too.
      if (RequireCompleteType(AtLoc, EncodedType,
                              diag::err_incomplete_type_objc_at_encode,
                              EncodedTypeInfo->getTypeLoc()))
        return ExprError();

    std::string Str;
    QualType NotEncodedT;
    Context.getObjCEncodingForType(EncodedType, Str, nullptr, &NotEncodedT);
    if (!NotEncodedT.isNull())
      Diag(AtLoc, diag::warn_incomplete_encoded_type)
        << EncodedType << NotEncodedT;

    // The type of @encode is the same as the type of the corresponding string,
    // which is an array type.
    StrTy = Context.getStringLiteralArrayType(Context.CharTy, Str.size());
  }

  return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);
}

ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
                                           SourceLocation EncodeLoc,
                                           SourceLocation LParenLoc,
                                           ParsedType ty,
                                           SourceLocation RParenLoc) {
  // FIXME: Preserve type source info ?
  TypeSourceInfo *TInfo;
  QualType EncodedType = GetTypeFromParser(ty, &TInfo);
  if (!TInfo)
    TInfo = Context.getTrivialTypeSourceInfo(EncodedType,
                                             getLocForEndOfToken(LParenLoc));

  return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
}

static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
                                               SourceLocation AtLoc,
                                               SourceLocation LParenLoc,
                                               SourceLocation RParenLoc,
                                               ObjCMethodDecl *Method,
                                               ObjCMethodList &MethList) {
  ObjCMethodList *M = &MethList;
  bool Warned = false;
  for (M = M->getNext(); M; M=M->getNext()) {
    ObjCMethodDecl *MatchingMethodDecl = M->getMethod();
    if (MatchingMethodDecl == Method ||
        isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) ||
        MatchingMethodDecl->getSelector() != Method->getSelector())
      continue;
    if (!S.MatchTwoMethodDeclarations(Method,
                                      MatchingMethodDecl, Sema::MMS_loose)) {
      if (!Warned) {
        Warned = true;
        S.Diag(AtLoc, diag::warn_multiple_selectors)
          << Method->getSelector() << FixItHint::CreateInsertion(LParenLoc, "(")
          << FixItHint::CreateInsertion(RParenLoc, ")");
        S.Diag(Method->getLocation(), diag::note_method_declared_at)
          << Method->getDeclName();
      }
      S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at)
        << MatchingMethodDecl->getDeclName();
    }
  }
  return Warned;
}

static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
                                        ObjCMethodDecl *Method,
                                        SourceLocation LParenLoc,
                                        SourceLocation RParenLoc,
                                        bool WarnMultipleSelectors) {
  if (!WarnMultipleSelectors ||
      S.Diags.isIgnored(diag::warn_multiple_selectors, SourceLocation()))
    return;
  bool Warned = false;
  for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(),
       e = S.MethodPool.end(); b != e; b++) {
    // first, instance methods
    ObjCMethodList &InstMethList = b->second.first;
    if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
                                                      Method, InstMethList))
      Warned = true;

    // second, class methods
    ObjCMethodList &ClsMethList = b->second.second;
    if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
                                                      Method, ClsMethList) || Warned)
      return;
  }
}

static ObjCMethodDecl *LookupDirectMethodInMethodList(Sema &S, Selector Sel,
                                                      ObjCMethodList &MethList,
                                                      bool &onlyDirect,
                                                      bool &anyDirect) {
  (void)Sel;
  ObjCMethodList *M = &MethList;
  ObjCMethodDecl *DirectMethod = nullptr;
  for (; M; M = M->getNext()) {
    ObjCMethodDecl *Method = M->getMethod();
    if (!Method)
      continue;
    assert(Method->getSelector() == Sel && "Method with wrong selector in method list");
    if (Method->isDirectMethod()) {
      anyDirect = true;
      DirectMethod = Method;
    } else
      onlyDirect = false;
  }

  return DirectMethod;
}

// Search the global pool for (potentially) direct methods matching the given
// selector. If a non-direct method is found, set \param onlyDirect to false. If
// a direct method is found, set \param anyDirect to true. Returns a direct
// method, if any.
static ObjCMethodDecl *LookupDirectMethodInGlobalPool(Sema &S, Selector Sel,
                                                      bool &onlyDirect,
                                                      bool &anyDirect) {
  auto Iter = S.MethodPool.find(Sel);
  if (Iter == S.MethodPool.end())
    return nullptr;

  ObjCMethodDecl *DirectInstance = LookupDirectMethodInMethodList(
      S, Sel, Iter->second.first, onlyDirect, anyDirect);
  ObjCMethodDecl *DirectClass = LookupDirectMethodInMethodList(
      S, Sel, Iter->second.second, onlyDirect, anyDirect);

  return DirectInstance ? DirectInstance : DirectClass;
}

static ObjCMethodDecl *findMethodInCurrentClass(Sema &S, Selector Sel) {
  auto *CurMD = S.getCurMethodDecl();
  if (!CurMD)
    return nullptr;
  ObjCInterfaceDecl *IFace = CurMD->getClassInterface();

  // The language enforce that only one direct method is present in a given
  // class, so we just need to find one method in the current class to know
  // whether Sel is potentially direct in this context.
  if (ObjCMethodDecl *MD = IFace->lookupMethod(Sel, /*isInstance=*/true))
    return MD;
  if (ObjCMethodDecl *MD = IFace->lookupPrivateMethod(Sel, /*isInstance=*/true))
    return MD;
  if (ObjCMethodDecl *MD = IFace->lookupMethod(Sel, /*isInstance=*/false))
    return MD;
  if (ObjCMethodDecl *MD = IFace->lookupPrivateMethod(Sel, /*isInstance=*/false))
    return MD;

  return nullptr;
}

ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
                                             SourceLocation AtLoc,
                                             SourceLocation SelLoc,
                                             SourceLocation LParenLoc,
                                             SourceLocation RParenLoc,
                                             bool WarnMultipleSelectors) {
  ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
                             SourceRange(LParenLoc, RParenLoc));
  if (!Method)
    Method = LookupFactoryMethodInGlobalPool(Sel,
                                          SourceRange(LParenLoc, RParenLoc));
  if (!Method) {
    if (const ObjCMethodDecl *OM = SelectorsForTypoCorrection(Sel)) {
      Selector MatchedSel = OM->getSelector();
      SourceRange SelectorRange(LParenLoc.getLocWithOffset(1),
                                RParenLoc.getLocWithOffset(-1));
      Diag(SelLoc, diag::warn_undeclared_selector_with_typo)
        << Sel << MatchedSel
        << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());

    } else
        Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
  } else {
    DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc,
                                WarnMultipleSelectors);

    bool onlyDirect = true;
    bool anyDirect = false;
    ObjCMethodDecl *GlobalDirectMethod =
        LookupDirectMethodInGlobalPool(*this, Sel, onlyDirect, anyDirect);

    if (onlyDirect) {
      Diag(AtLoc, diag::err_direct_selector_expression)
          << Method->getSelector();
      Diag(Method->getLocation(), diag::note_direct_method_declared_at)
          << Method->getDeclName();
    } else if (anyDirect) {
      // If we saw any direct methods, see if we see a direct member of the
      // current class. If so, the @selector will likely be used to refer to
      // this direct method.
      ObjCMethodDecl *LikelyTargetMethod = findMethodInCurrentClass(*this, Sel);
      if (LikelyTargetMethod && LikelyTargetMethod->isDirectMethod()) {
        Diag(AtLoc, diag::warn_potentially_direct_selector_expression) << Sel;
        Diag(LikelyTargetMethod->getLocation(),
             diag::note_direct_method_declared_at)
            << LikelyTargetMethod->getDeclName();
      } else if (!LikelyTargetMethod) {
        // Otherwise, emit the "strict" variant of this diagnostic, unless
        // LikelyTargetMethod is non-direct.
        Diag(AtLoc, diag::warn_strict_potentially_direct_selector_expression)
            << Sel;
        Diag(GlobalDirectMethod->getLocation(),
             diag::note_direct_method_declared_at)
            << GlobalDirectMethod->getDeclName();
      }
    }
  }

  if (Method &&
      Method->getImplementationControl() != ObjCMethodDecl::Optional &&
      !getSourceManager().isInSystemHeader(Method->getLocation()))
    ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));

  // In ARC, forbid the user from using @selector for
  // retain/release/autorelease/dealloc/retainCount.
  if (getLangOpts().ObjCAutoRefCount) {
    switch (Sel.getMethodFamily()) {
    case OMF_retain:
    case OMF_release:
    case OMF_autorelease:
    case OMF_retainCount:
    case OMF_dealloc:
      Diag(AtLoc, diag::err_arc_illegal_selector) <<
        Sel << SourceRange(LParenLoc, RParenLoc);
      break;

    case OMF_None:
    case OMF_alloc:
    case OMF_copy:
    case OMF_finalize:
    case OMF_init:
    case OMF_mutableCopy:
    case OMF_new:
    case OMF_self:
    case OMF_initialize:
    case OMF_performSelector:
      break;
    }
  }
  QualType Ty = Context.getObjCSelType();
  return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
}

ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
                                             SourceLocation AtLoc,
                                             SourceLocation ProtoLoc,
                                             SourceLocation LParenLoc,
                                             SourceLocation ProtoIdLoc,
                                             SourceLocation RParenLoc) {
  ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoIdLoc);
  if (!PDecl) {
    Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
    return true;
  }
  if (PDecl->isNonRuntimeProtocol())
    Diag(ProtoLoc, diag::err_objc_non_runtime_protocol_in_protocol_expr)
        << PDecl;
  if (!PDecl->hasDefinition()) {
    Diag(ProtoLoc, diag::err_atprotocol_protocol) << PDecl;
    Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
  } else {
    PDecl = PDecl->getDefinition();
  }

  QualType Ty = Context.getObjCProtoType();
  if (Ty.isNull())
    return true;
  Ty = Context.getObjCObjectPointerType(Ty);
  return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, ProtoIdLoc, RParenLoc);
}

/// Try to capture an implicit reference to 'self'.
ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) {
  DeclContext *DC = getFunctionLevelDeclContext();

  // If we're not in an ObjC method, error out.  Note that, unlike the
  // C++ case, we don't require an instance method --- class methods
  // still have a 'self', and we really do still need to capture it!
  ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC);
  if (!method)
    return nullptr;

  tryCaptureVariable(method->getSelfDecl(), Loc);

  return method;
}

static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {
  QualType origType = T;
  if (auto nullability = AttributedType::stripOuterNullability(T)) {
    if (T == Context.getObjCInstanceType()) {
      return Context.getAttributedType(
               AttributedType::getNullabilityAttrKind(*nullability),
               Context.getObjCIdType(),
               Context.getObjCIdType());
    }

    return origType;
  }

  if (T == Context.getObjCInstanceType())
    return Context.getObjCIdType();

  return origType;
}

/// Determine the result type of a message send based on the receiver type,
/// method, and the kind of message send.
///
/// This is the "base" result type, which will still need to be adjusted
/// to account for nullability.
static QualType getBaseMessageSendResultType(Sema &S,
                                             QualType ReceiverType,
                                             ObjCMethodDecl *Method,
                                             bool isClassMessage,
                                             bool isSuperMessage) {
  assert(Method && "Must have a method");
  if (!Method->hasRelatedResultType())
    return Method->getSendResultType(ReceiverType);

  ASTContext &Context = S.Context;

  // Local function that transfers the nullability of the method's
  // result type to the returned result.
  auto transferNullability = [&](QualType type) -> QualType {
    // If the method's result type has nullability, extract it.
    if (auto nullability = Method->getSendResultType(ReceiverType)
                             ->getNullability(Context)){
      // Strip off any outer nullability sugar from the provided type.
      (void)AttributedType::stripOuterNullability(type);

      // Form a new attributed type using the method result type's nullability.
      return Context.getAttributedType(
               AttributedType::getNullabilityAttrKind(*nullability),
               type,
               type);
    }

    return type;
  };

  // If a method has a related return type:
  //   - if the method found is an instance method, but the message send
  //     was a class message send, T is the declared return type of the method
  //     found
  if (Method->isInstanceMethod() && isClassMessage)
    return stripObjCInstanceType(Context,
                                 Method->getSendResultType(ReceiverType));

  //   - if the receiver is super, T is a pointer to the class of the
  //     enclosing method definition
  if (isSuperMessage) {
    if (ObjCMethodDecl *CurMethod = S.getCurMethodDecl())
      if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) {
        return transferNullability(
                 Context.getObjCObjectPointerType(
                   Context.getObjCInterfaceType(Class)));
      }
  }

  //   - if the receiver is the name of a class U, T is a pointer to U
  if (ReceiverType->getAsObjCInterfaceType())
    return transferNullability(Context.getObjCObjectPointerType(ReceiverType));
  //   - if the receiver is of type Class or qualified Class type,
  //     T is the declared return type of the method.
  if (ReceiverType->isObjCClassType() ||
      ReceiverType->isObjCQualifiedClassType())
    return stripObjCInstanceType(Context,
                                 Method->getSendResultType(ReceiverType));

  //   - if the receiver is id, qualified id, Class, or qualified Class, T
  //     is the receiver type, otherwise
  //   - T is the type of the receiver expression.
  return transferNullability(ReceiverType);
}

QualType Sema::getMessageSendResultType(const Expr *Receiver,
                                        QualType ReceiverType,
                                        ObjCMethodDecl *Method,
                                        bool isClassMessage,
                                        bool isSuperMessage) {
  // Produce the result type.
  QualType resultType = getBaseMessageSendResultType(*this, ReceiverType,
                                                     Method,
                                                     isClassMessage,
                                                     isSuperMessage);

  // If this is a class message, ignore the nullability of the receiver.
  if (isClassMessage) {
    // In a class method, class messages to 'self' that return instancetype can
    // be typed as the current class.  We can safely do this in ARC because self
    // can't be reassigned, and we do it unsafely outside of ARC because in
    // practice people never reassign self in class methods and there's some
    // virtue in not being aggressively pedantic.
    if (Receiver && Receiver->isObjCSelfExpr()) {
      assert(ReceiverType->isObjCClassType() && "expected a Class self");
      QualType T = Method->getSendResultType(ReceiverType);
      AttributedType::stripOuterNullability(T);
      if (T == Context.getObjCInstanceType()) {
        const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(
            cast<ImplicitParamDecl>(
                cast<DeclRefExpr>(Receiver->IgnoreParenImpCasts())->getDecl())
                ->getDeclContext());
        assert(MD->isClassMethod() && "expected a class method");
        QualType NewResultType = Context.getObjCObjectPointerType(
            Context.getObjCInterfaceType(MD->getClassInterface()));
        if (auto Nullability = resultType->getNullability(Context))
          NewResultType = Context.getAttributedType(
              AttributedType::getNullabilityAttrKind(*Nullability),
              NewResultType, NewResultType);
        return NewResultType;
      }
    }
    return resultType;
  }

  // There is nothing left to do if the result type cannot have a nullability
  // specifier.
  if (!resultType->canHaveNullability())
    return resultType;

  // Map the nullability of the result into a table index.
  unsigned receiverNullabilityIdx = 0;
  if (Optional<NullabilityKind> nullability =
          ReceiverType->getNullability(Context)) {
    if (*nullability == NullabilityKind::NullableResult)
      nullability = NullabilityKind::Nullable;
    receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
  }

  unsigned resultNullabilityIdx = 0;
  if (Optional<NullabilityKind> nullability =
          resultType->getNullability(Context)) {
    if (*nullability == NullabilityKind::NullableResult)
      nullability = NullabilityKind::Nullable;
    resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
  }

  // The table of nullability mappings, indexed by the receiver's nullability
  // and then the result type's nullability.
  static const uint8_t None = 0;
  static const uint8_t NonNull = 1;
  static const uint8_t Nullable = 2;
  static const uint8_t Unspecified = 3;
  static const uint8_t nullabilityMap[4][4] = {
    //                  None        NonNull       Nullable    Unspecified
    /* None */        { None,       None,         Nullable,   None },
    /* NonNull */     { None,       NonNull,      Nullable,   Unspecified },
    /* Nullable */    { Nullable,   Nullable,     Nullable,   Nullable },
    /* Unspecified */ { None,       Unspecified,  Nullable,   Unspecified }
  };

  unsigned newResultNullabilityIdx
    = nullabilityMap[receiverNullabilityIdx][resultNullabilityIdx];
  if (newResultNullabilityIdx == resultNullabilityIdx)
    return resultType;

  // Strip off the existing nullability. This removes as little type sugar as
  // possible.
  do {
    if (auto attributed = dyn_cast<AttributedType>(resultType.getTypePtr())) {
      resultType = attributed->getModifiedType();
    } else {
      resultType = resultType.getDesugaredType(Context);
    }
  } while (resultType->getNullability(Context));

  // Add nullability back if needed.
  if (newResultNullabilityIdx > 0) {
    auto newNullability
      = static_cast<NullabilityKind>(newResultNullabilityIdx-1);
    return Context.getAttributedType(
             AttributedType::getNullabilityAttrKind(newNullability),
             resultType, resultType);
  }

  return resultType;
}

/// Look for an ObjC method whose result type exactly matches the given type.
static const ObjCMethodDecl *
findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
                                 QualType instancetype) {
  if (MD->getReturnType() == instancetype)
    return MD;

  // For these purposes, a method in an @implementation overrides a
  // declaration in the @interface.
  if (const ObjCImplDecl *impl =
        dyn_cast<ObjCImplDecl>(MD->getDeclContext())) {
    const ObjCContainerDecl *iface;
    if (const ObjCCategoryImplDecl *catImpl =
          dyn_cast<ObjCCategoryImplDecl>(impl)) {
      iface = catImpl->getCategoryDecl();
    } else {
      iface = impl->getClassInterface();
    }

    const ObjCMethodDecl *ifaceMD =
      iface->getMethod(MD->getSelector(), MD->isInstanceMethod());
    if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype);
  }

  SmallVector<const ObjCMethodDecl *, 4> overrides;
  MD->getOverriddenMethods(overrides);
  for (unsigned i = 0, e = overrides.size(); i != e; ++i) {
    if (const ObjCMethodDecl *result =
          findExplicitInstancetypeDeclarer(overrides[i], instancetype))
      return result;
  }

  return nullptr;
}

void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
  // Only complain if we're in an ObjC method and the required return
  // type doesn't match the method's declared return type.
  ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext);
  if (!MD || !MD->hasRelatedResultType() ||
      Context.hasSameUnqualifiedType(destType, MD->getReturnType()))
    return;

  // Look for a method overridden by this method which explicitly uses
  // 'instancetype'.
  if (const ObjCMethodDecl *overridden =
        findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {
    SourceRange range = overridden->getReturnTypeSourceRange();
    SourceLocation loc = range.getBegin();
    if (loc.isInvalid())
      loc = overridden->getLocation();
    Diag(loc, diag::note_related_result_type_explicit)
      << /*current method*/ 1 << range;
    return;
  }

  // Otherwise, if we have an interesting method family, note that.
  // This should always trigger if the above didn't.
  if (ObjCMethodFamily family = MD->getMethodFamily())
    Diag(MD->getLocation(), diag::note_related_result_type_family)
      << /*current method*/ 1
      << family;
}

void Sema::EmitRelatedResultTypeNote(const Expr *E) {
  E = E->IgnoreParenImpCasts();
  const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);
  if (!MsgSend)
    return;

  const ObjCMethodDecl *Method = MsgSend->getMethodDecl();
  if (!Method)
    return;

  if (!Method->hasRelatedResultType())
    return;

  if (Context.hasSameUnqualifiedType(
          Method->getReturnType().getNonReferenceType(), MsgSend->getType()))
    return;

  if (!Context.hasSameUnqualifiedType(Method->getReturnType(),
                                      Context.getObjCInstanceType()))
    return;

  Diag(Method->getLocation(), diag::note_related_result_type_inferred)
    << Method->isInstanceMethod() << Method->getSelector()
    << MsgSend->getType();
}

bool Sema::CheckMessageArgumentTypes(
    const Expr *Receiver, QualType ReceiverType, MultiExprArg Args,
    Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method,
    bool isClassMessage, bool isSuperMessage, SourceLocation lbrac,
    SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType,
    ExprValueKind &VK) {
  SourceLocation SelLoc;
  if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
    SelLoc = SelectorLocs.front();
  else
    SelLoc = lbrac;

  if (!Method) {
    // Apply default argument promotion as for (C99 6.5.2.2p6).
    for (unsigned i = 0, e = Args.size(); i != e; i++) {
      if (Args[i]->isTypeDependent())
        continue;

      ExprResult result;
      if (getLangOpts().DebuggerSupport) {
        QualType paramTy; // ignored
        result = checkUnknownAnyArg(SelLoc, Args[i], paramTy);
      } else {
        result = DefaultArgumentPromotion(Args[i]);
      }
      if (result.isInvalid())
        return true;
      Args[i] = result.get();
    }

    unsigned DiagID;
    if (getLangOpts().ObjCAutoRefCount)
      DiagID = diag::err_arc_method_not_found;
    else
      DiagID = isClassMessage ? diag::warn_class_method_not_found
                              : diag::warn_inst_method_not_found;
    if (!getLangOpts().DebuggerSupport) {
      const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType);
      if (OMD && !OMD->isInvalidDecl()) {
        if (getLangOpts().ObjCAutoRefCount)
          DiagID = diag::err_method_not_found_with_typo;
        else
          DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo
                                  : diag::warn_instance_method_not_found_with_typo;
        Selector MatchedSel = OMD->getSelector();
        SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back());
        if (MatchedSel.isUnarySelector())
          Diag(SelLoc, DiagID)
            << Sel<< isClassMessage << MatchedSel
            << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
        else
          Diag(SelLoc, DiagID) << Sel<< isClassMessage << MatchedSel;
      }
      else
        Diag(SelLoc, DiagID)
          << Sel << isClassMessage << SourceRange(SelectorLocs.front(),
                                                SelectorLocs.back());
      // Find the class to which we are sending this message.
      if (auto *ObjPT = ReceiverType->getAs<ObjCObjectPointerType>()) {
        if (ObjCInterfaceDecl *ThisClass = ObjPT->getInterfaceDecl()) {
          Diag(ThisClass->getLocation(), diag::note_receiver_class_declared);
          if (!RecRange.isInvalid())
            if (ThisClass->lookupClassMethod(Sel))
              Diag(RecRange.getBegin(), diag::note_receiver_expr_here)
                  << FixItHint::CreateReplacement(RecRange,
                                                  ThisClass->getNameAsString());
        }
      }
    }

    // In debuggers, we want to use __unknown_anytype for these
    // results so that clients can cast them.
    if (getLangOpts().DebuggerSupport) {
      ReturnType = Context.UnknownAnyTy;
    } else {
      ReturnType = Context.getObjCIdType();
    }
    VK = VK_PRValue;
    return false;
  }

  ReturnType = getMessageSendResultType(Receiver, ReceiverType, Method,
                                        isClassMessage, isSuperMessage);
  VK = Expr::getValueKindForType(Method->getReturnType());

  unsigned NumNamedArgs = Sel.getNumArgs();
  // Method might have more arguments than selector indicates. This is due
  // to addition of c-style arguments in method.
  if (Method->param_size() > Sel.getNumArgs())
    NumNamedArgs = Method->param_size();
  // FIXME. This need be cleaned up.
  if (Args.size() < NumNamedArgs) {
    Diag(SelLoc, diag::err_typecheck_call_too_few_args)
      << 2 << NumNamedArgs << static_cast<unsigned>(Args.size());
    return false;
  }

  // Compute the set of type arguments to be substituted into each parameter
  // type.
  Optional<ArrayRef<QualType>> typeArgs
    = ReceiverType->getObjCSubstitutions(Method->getDeclContext());
  bool IsError = false;
  for (unsigned i = 0; i < NumNamedArgs; i++) {
    // We can't do any type-checking on a type-dependent argument.
    if (Args[i]->isTypeDependent())
      continue;

    Expr *argExpr = Args[i];

    ParmVarDecl *param = Method->parameters()[i];
    assert(argExpr && "CheckMessageArgumentTypes(): missing expression");

    if (param->hasAttr<NoEscapeAttr>() &&
        param->getType()->isBlockPointerType())
      if (auto *BE = dyn_cast<BlockExpr>(
              argExpr->IgnoreParenNoopCasts(Context)))
        BE->getBlockDecl()->setDoesNotEscape();

    // Strip the unbridged-cast placeholder expression off unless it's
    // a consumed argument.
    if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
        !param->hasAttr<CFConsumedAttr>())
      argExpr = stripARCUnbridgedCast(argExpr);

    // If the parameter is __unknown_anytype, infer its type
    // from the argument.
    if (param->getType() == Context.UnknownAnyTy) {
      QualType paramType;
      ExprResult argE = checkUnknownAnyArg(SelLoc, argExpr, paramType);
      if (argE.isInvalid()) {
        IsError = true;
      } else {
        Args[i] = argE.get();

        // Update the parameter type in-place.
        param->setType(paramType);
      }
      continue;
    }

    QualType origParamType = param->getType();
    QualType paramType = param->getType();
    if (typeArgs)
      paramType = paramType.substObjCTypeArgs(
                    Context,
                    *typeArgs,
                    ObjCSubstitutionContext::Parameter);

    if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
                            paramType,
                            diag::err_call_incomplete_argument, argExpr))
      return true;

    InitializedEntity Entity
      = InitializedEntity::InitializeParameter(Context, param, paramType);
    ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), argExpr);
    if (ArgE.isInvalid())
      IsError = true;
    else {
      Args[i] = ArgE.getAs<Expr>();

      // If we are type-erasing a block to a block-compatible
      // Objective-C pointer type, we may need to extend the lifetime
      // of the block object.
      if (typeArgs && Args[i]->isPRValue() && paramType->isBlockPointerType() &&
          Args[i]->getType()->isBlockPointerType() &&
          origParamType->isObjCObjectPointerType()) {
        ExprResult arg = Args[i];
        maybeExtendBlockObject(arg);
        Args[i] = arg.get();
      }
    }
  }

  // Promote additional arguments to variadic methods.
  if (Method->isVariadic()) {
    for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {
      if (Args[i]->isTypeDependent())
        continue;

      ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
                                                        nullptr);
      IsError |= Arg.isInvalid();
      Args[i] = Arg.get();
    }
  } else {
    // Check for extra arguments to non-variadic methods.
    if (Args.size() != NumNamedArgs) {
      Diag(Args[NumNamedArgs]->getBeginLoc(),
           diag::err_typecheck_call_too_many_args)
          << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size())
          << Method->getSourceRange()
          << SourceRange(Args[NumNamedArgs]->getBeginLoc(),
                         Args.back()->getEndLoc());
    }
  }

  DiagnoseSentinelCalls(Method, SelLoc, Args);

  // Do additional checkings on method.
  IsError |= CheckObjCMethodCall(
      Method, SelLoc, makeArrayRef(Args.data(), Args.size()));

  return IsError;
}

bool Sema::isSelfExpr(Expr *RExpr) {
  // 'self' is objc 'self' in an objc method only.
  ObjCMethodDecl *Method =
      dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
  return isSelfExpr(RExpr, Method);
}

bool Sema::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) {
  if (!method) return false;

  receiver = receiver->IgnoreParenLValueCasts();
  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver))
    if (DRE->getDecl() == method->getSelfDecl())
      return true;
  return false;
}

/// LookupMethodInType - Look up a method in an ObjCObjectType.
ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type,
                                               bool isInstance) {
  const ObjCObjectType *objType = type->castAs<ObjCObjectType>();
  if (ObjCInterfaceDecl *iface = objType->getInterface()) {
    // Look it up in the main interface (and categories, etc.)
    if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance))
      return method;

    // Okay, look for "private" methods declared in any
    // @implementations we've seen.
    if (ObjCMethodDecl *method = iface->lookupPrivateMethod(sel, isInstance))
      return method;
  }

  // Check qualifiers.
  for (const auto *I : objType->quals())
    if (ObjCMethodDecl *method = I->lookupMethod(sel, isInstance))
      return method;

  return nullptr;
}

/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
/// list of a qualified objective pointer type.
ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
                                              const ObjCObjectPointerType *OPT,
                                              bool Instance)
{
  ObjCMethodDecl *MD = nullptr;
  for (const auto *PROTO : OPT->quals()) {
    if ((MD = PROTO->lookupMethod(Sel, Instance))) {
      return MD;
    }
  }
  return nullptr;
}

/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
/// objective C interface.  This is a property reference expression.
ExprResult Sema::
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
                          Expr *BaseExpr, SourceLocation OpLoc,
                          DeclarationName MemberName,
                          SourceLocation MemberLoc,
                          SourceLocation SuperLoc, QualType SuperType,
                          bool Super) {
  const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
  ObjCInterfaceDecl *IFace = IFaceT->getDecl();

  if (!MemberName.isIdentifier()) {
    Diag(MemberLoc, diag::err_invalid_property_name)
      << MemberName << QualType(OPT, 0);
    return ExprError();
  }

  IdentifierInfo *Member = MemberName.getAsIdentifierInfo();

  SourceRange BaseRange = Super? SourceRange(SuperLoc)
                               : BaseExpr->getSourceRange();
  if (RequireCompleteType(MemberLoc, OPT->getPointeeType(),
                          diag::err_property_not_found_forward_class,
                          MemberName, BaseRange))
    return ExprError();

  if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(
          Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
    // Check whether we can reference this property.
    if (DiagnoseUseOfDecl(PD, MemberLoc))
      return ExprError();
    if (Super)
      return new (Context)
          ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
                              OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);
    else
      return new (Context)
          ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
                              OK_ObjCProperty, MemberLoc, BaseExpr);
  }
  // Check protocols on qualified interfaces.
  for (const auto *I : OPT->quals())
    if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(
            Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
      // Check whether we can reference this property.
      if (DiagnoseUseOfDecl(PD, MemberLoc))
        return ExprError();

      if (Super)
        return new (Context) ObjCPropertyRefExpr(
            PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc,
            SuperLoc, SuperType);
      else
        return new (Context)
            ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
                                OK_ObjCProperty, MemberLoc, BaseExpr);
    }
  // If that failed, look for an "implicit" property by seeing if the nullary
  // selector is implemented.

  // FIXME: The logic for looking up nullary and unary selectors should be
  // shared with the code in ActOnInstanceMessage.

  Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
  ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);

  // May be found in property's qualified list.
  if (!Getter)
    Getter = LookupMethodInQualifiedType(Sel, OPT, true);

  // If this reference is in an @implementation, check for 'private' methods.
  if (!Getter)
    Getter = IFace->lookupPrivateMethod(Sel);

  if (Getter) {
    // Check if we can reference this property.
    if (DiagnoseUseOfDecl(Getter, MemberLoc))
      return ExprError();
  }
  // If we found a getter then this may be a valid dot-reference, we
  // will look for the matching setter, in case it is needed.
  Selector SetterSel =
    SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
                                           PP.getSelectorTable(), Member);
  ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);

  // May be found in property's qualified list.
  if (!Setter)
    Setter = LookupMethodInQualifiedType(SetterSel, OPT, true);

  if (!Setter) {
    // If this reference is in an @implementation, also check for 'private'
    // methods.
    Setter = IFace->lookupPrivateMethod(SetterSel);
  }

  if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
    return ExprError();

  // Special warning if member name used in a property-dot for a setter accessor
  // does not use a property with same name; e.g. obj.X = ... for a property with
  // name 'x'.
  if (Setter && Setter->isImplicit() && Setter->isPropertyAccessor() &&
      !IFace->FindPropertyDeclaration(
          Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
      if (const ObjCPropertyDecl *PDecl = Setter->findPropertyDecl()) {
        // Do not warn if user is using property-dot syntax to make call to
        // user named setter.
        if (!(PDecl->getPropertyAttributes() &
              ObjCPropertyAttribute::kind_setter))
          Diag(MemberLoc,
               diag::warn_property_access_suggest)
          << MemberName << QualType(OPT, 0) << PDecl->getName()
          << FixItHint::CreateReplacement(MemberLoc, PDecl->getName());
      }
  }

  if (Getter || Setter) {
    if (Super)
      return new (Context)
          ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
                              OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);
    else
      return new (Context)
          ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
                              OK_ObjCProperty, MemberLoc, BaseExpr);

  }

  // Attempt to correct for typos in property names.
  DeclFilterCCC<ObjCPropertyDecl> CCC{};
  if (TypoCorrection Corrected = CorrectTypo(
          DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName,
          nullptr, nullptr, CCC, CTK_ErrorRecovery, IFace, false, OPT)) {
    DeclarationName TypoResult = Corrected.getCorrection();
    if (TypoResult.isIdentifier() &&
        TypoResult.getAsIdentifierInfo() == Member) {
      // There is no need to try the correction if it is the same.
      NamedDecl *ChosenDecl =
        Corrected.isKeyword() ? nullptr : Corrected.getFoundDecl();
      if (ChosenDecl && isa<ObjCPropertyDecl>(ChosenDecl))
        if (cast<ObjCPropertyDecl>(ChosenDecl)->isClassProperty()) {
          // This is a class property, we should not use the instance to
          // access it.
          Diag(MemberLoc, diag::err_class_property_found) << MemberName
          << OPT->getInterfaceDecl()->getName()
          << FixItHint::CreateReplacement(BaseExpr->getSourceRange(),
                                          OPT->getInterfaceDecl()->getName());
          return ExprError();
        }
    } else {
      diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest)
                                << MemberName << QualType(OPT, 0));
      return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,
                                       TypoResult, MemberLoc,
                                       SuperLoc, SuperType, Super);
    }
  }
  ObjCInterfaceDecl *ClassDeclared;
  if (ObjCIvarDecl *Ivar =
      IFace->lookupInstanceVariable(Member, ClassDeclared)) {
    QualType T = Ivar->getType();
    if (const ObjCObjectPointerType * OBJPT =
        T->getAsObjCInterfacePointerType()) {
      if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(),
                              diag::err_property_not_as_forward_class,
                              MemberName, BaseExpr))
        return ExprError();
    }
    Diag(MemberLoc,
         diag::err_ivar_access_using_property_syntax_suggest)
    << MemberName << QualType(OPT, 0) << Ivar->getDeclName()
    << FixItHint::CreateReplacement(OpLoc, "->");
    return ExprError();
  }

  Diag(MemberLoc, diag::err_property_not_found)
    << MemberName << QualType(OPT, 0);
  if (Setter)
    Diag(Setter->getLocation(), diag::note_getter_unavailable)
          << MemberName << BaseExpr->getSourceRange();
  return ExprError();
}

ExprResult Sema::
ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
                          IdentifierInfo &propertyName,
                          SourceLocation receiverNameLoc,
                          SourceLocation propertyNameLoc) {

  IdentifierInfo *receiverNamePtr = &receiverName;
  ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,
                                                  receiverNameLoc);

  QualType SuperType;
  if (!IFace) {
    // If the "receiver" is 'super' in a method, handle it as an expression-like
    // property reference.
    if (receiverNamePtr->isStr("super")) {
      if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) {
        if (auto classDecl = CurMethod->getClassInterface()) {
          SuperType = QualType(classDecl->getSuperClassType(), 0);
          if (CurMethod->isInstanceMethod()) {
            if (SuperType.isNull()) {
              // The current class does not have a superclass.
              Diag(receiverNameLoc, diag::err_root_class_cannot_use_super)
                << CurMethod->getClassInterface()->getIdentifier();
              return ExprError();
            }
            QualType T = Context.getObjCObjectPointerType(SuperType);

            return HandleExprPropertyRefExpr(T->castAs<ObjCObjectPointerType>(),
                                             /*BaseExpr*/nullptr,
                                             SourceLocation()/*OpLoc*/,
                                             &propertyName,
                                             propertyNameLoc,
                                             receiverNameLoc, T, true);
          }

          // Otherwise, if this is a class method, try dispatching to our
          // superclass.
          IFace = CurMethod->getClassInterface()->getSuperClass();
        }
      }
    }

    if (!IFace) {
      Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier
                                                       << tok::l_paren;
      return ExprError();
    }
  }

  Selector GetterSel;
  Selector SetterSel;
  if (auto PD = IFace->FindPropertyDeclaration(
          &propertyName, ObjCPropertyQueryKind::OBJC_PR_query_class)) {
    GetterSel = PD->getGetterName();
    SetterSel = PD->getSetterName();
  } else {
    GetterSel = PP.getSelectorTable().getNullarySelector(&propertyName);
    SetterSel = SelectorTable::constructSetterSelector(
        PP.getIdentifierTable(), PP.getSelectorTable(), &propertyName);
  }

  // Search for a declared property first.
  ObjCMethodDecl *Getter = IFace->lookupClassMethod(GetterSel);

  // If this reference is in an @implementation, check for 'private' methods.
  if (!Getter)
    Getter = IFace->lookupPrivateClassMethod(GetterSel);

  if (Getter) {
    // FIXME: refactor/share with ActOnMemberReference().
    // Check if we can reference this property.
    if (DiagnoseUseOfDecl(Getter, propertyNameLoc))
      return ExprError();
  }

  // Look for the matching setter, in case it is needed.
  ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
  if (!Setter) {
    // If this reference is in an @implementation, also check for 'private'
    // methods.
    Setter = IFace->lookupPrivateClassMethod(SetterSel);
  }
  // Look through local category implementations associated with the class.
  if (!Setter)
    Setter = IFace->getCategoryClassMethod(SetterSel);

  if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc))
    return ExprError();

  if (Getter || Setter) {
    if (!SuperType.isNull())
      return new (Context)
          ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
                              OK_ObjCProperty, propertyNameLoc, receiverNameLoc,
                              SuperType);

    return new (Context) ObjCPropertyRefExpr(
        Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty,
        propertyNameLoc, receiverNameLoc, IFace);
  }
  return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
                     << &propertyName << Context.getObjCInterfaceType(IFace));
}

namespace {

class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback {
 public:
  ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {
    // Determine whether "super" is acceptable in the current context.
    if (Method && Method->getClassInterface())
      WantObjCSuper = Method->getClassInterface()->getSuperClass();
  }

  bool ValidateCandidate(const TypoCorrection &candidate) override {
    return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
        candidate.isKeyword("super");
  }

  std::unique_ptr<CorrectionCandidateCallback> clone() override {
    return std::make_unique<ObjCInterfaceOrSuperCCC>(*this);
  }
};

} // end anonymous namespace

Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
                                               IdentifierInfo *Name,
                                               SourceLocation NameLoc,
                                               bool IsSuper,
                                               bool HasTrailingDot,
                                               ParsedType &ReceiverType) {
  ReceiverType = nullptr;

  // If the identifier is "super" and there is no trailing dot, we're
  // messaging super. If the identifier is "super" and there is a
  // trailing dot, it's an instance message.
  if (IsSuper && S->isInObjcMethodScope())
    return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage;

  LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
  LookupName(Result, S);

  switch (Result.getResultKind()) {
  case LookupResult::NotFound:
    // Normal name lookup didn't find anything. If we're in an
    // Objective-C method, look for ivars. If we find one, we're done!
    // FIXME: This is a hack. Ivar lookup should be part of normal
    // lookup.
    if (ObjCMethodDecl *Method = getCurMethodDecl()) {
      if (!Method->getClassInterface()) {
        // Fall back: let the parser try to parse it as an instance message.
        return ObjCInstanceMessage;
      }

      ObjCInterfaceDecl *ClassDeclared;
      if (Method->getClassInterface()->lookupInstanceVariable(Name,
                                                              ClassDeclared))
        return ObjCInstanceMessage;
    }

    // Break out; we'll perform typo correction below.
    break;

  case LookupResult::NotFoundInCurrentInstantiation:
  case LookupResult::FoundOverloaded:
  case LookupResult::FoundUnresolvedValue:
  case LookupResult::Ambiguous:
    Result.suppressDiagnostics();
    return ObjCInstanceMessage;

  case LookupResult::Found: {
    // If the identifier is a class or not, and there is a trailing dot,
    // it's an instance message.
    if (HasTrailingDot)
      return ObjCInstanceMessage;
    // We found something. If it's a type, then we have a class
    // message. Otherwise, it's an instance message.
    NamedDecl *ND = Result.getFoundDecl();
    QualType T;
    if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))
      T = Context.getObjCInterfaceType(Class);
    else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) {
      T = Context.getTypeDeclType(Type);
      DiagnoseUseOfDecl(Type, NameLoc);
    }
    else
      return ObjCInstanceMessage;

    //  We have a class message, and T is the type we're
    //  messaging. Build source-location information for it.
    TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
    ReceiverType = CreateParsedType(T, TSInfo);
    return ObjCClassMessage;
  }
  }

  ObjCInterfaceOrSuperCCC CCC(getCurMethodDecl());
  if (TypoCorrection Corrected = CorrectTypo(
          Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, CCC,
          CTK_ErrorRecovery, nullptr, false, nullptr, false)) {
    if (Corrected.isKeyword()) {
      // If we've found the keyword "super" (the only keyword that would be
      // returned by CorrectTypo), this is a send to super.
      diagnoseTypo(Corrected,
                   PDiag(diag::err_unknown_receiver_suggest) << Name);
      return ObjCSuperMessage;
    } else if (ObjCInterfaceDecl *Class =
                   Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
      // If we found a declaration, correct when it refers to an Objective-C
      // class.
      diagnoseTypo(Corrected,
                   PDiag(diag::err_unknown_receiver_suggest) << Name);
      QualType T = Context.getObjCInterfaceType(Class);
      TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
      ReceiverType = CreateParsedType(T, TSInfo);
      return ObjCClassMessage;
    }
  }

  // Fall back: let the parser try to parse it as an instance message.
  return ObjCInstanceMessage;
}

ExprResult Sema::ActOnSuperMessage(Scope *S,
                                   SourceLocation SuperLoc,
                                   Selector Sel,
                                   SourceLocation LBracLoc,
                                   ArrayRef<SourceLocation> SelectorLocs,
                                   SourceLocation RBracLoc,
                                   MultiExprArg Args) {
  // Determine whether we are inside a method or not.
  ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc);
  if (!Method) {
    Diag(SuperLoc, diag::err_invalid_receiver_to_message_super);
    return ExprError();
  }

  ObjCInterfaceDecl *Class = Method->getClassInterface();
  if (!Class) {
    Diag(SuperLoc, diag::err_no_super_class_message)
      << Method->getDeclName();
    return ExprError();
  }

  QualType SuperTy(Class->getSuperClassType(), 0);
  if (SuperTy.isNull()) {
    // The current class does not have a superclass.
    Diag(SuperLoc, diag::err_root_class_cannot_use_super)
      << Class->getIdentifier();
    return ExprError();
  }

  // We are in a method whose class has a superclass, so 'super'
  // is acting as a keyword.
  if (Method->getSelector() == Sel)
    getCurFunction()->ObjCShouldCallSuper = false;

  if (Method->isInstanceMethod()) {
    // Since we are in an instance method, this is an instance
    // message to the superclass instance.
    SuperTy = Context.getObjCObjectPointerType(SuperTy);
    return BuildInstanceMessage(nullptr, SuperTy, SuperLoc,
                                Sel, /*Method=*/nullptr,
                                LBracLoc, SelectorLocs, RBracLoc, Args);
  }

  // Since we are in a class method, this is a class message to
  // the superclass.
  return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,
                           SuperTy,
                           SuperLoc, Sel, /*Method=*/nullptr,
                           LBracLoc, SelectorLocs, RBracLoc, Args);
}

ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType,
                                           bool isSuperReceiver,
                                           SourceLocation Loc,
                                           Selector Sel,
                                           ObjCMethodDecl *Method,
                                           MultiExprArg Args) {
  TypeSourceInfo *receiverTypeInfo = nullptr;
  if (!ReceiverType.isNull())
    receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType);

  return BuildClassMessage(receiverTypeInfo, ReceiverType,
                          /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(),
                           Sel, Method, Loc, Loc, Loc, Args,
                           /*isImplicit=*/true);
}

static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,
                               unsigned DiagID,
                               bool (*refactor)(const ObjCMessageExpr *,
                                              const NSAPI &, edit::Commit &)) {
  SourceLocation MsgLoc = Msg->getExprLoc();
  if (S.Diags.isIgnored(DiagID, MsgLoc))
    return;

  SourceManager &SM = S.SourceMgr;
  edit::Commit ECommit(SM, S.LangOpts);
  if (refactor(Msg,*S.NSAPIObj, ECommit)) {
    auto Builder = S.Diag(MsgLoc, DiagID)
                   << Msg->getSelector() << Msg->getSourceRange();
    // FIXME: Don't emit diagnostic at all if fixits are non-commitable.
    if (!ECommit.isCommitable())
      return;
    for (edit::Commit::edit_iterator
           I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) {
      const edit::Commit::Edit &Edit = *I;
      switch (Edit.Kind) {
      case edit::Commit::Act_Insert:
        Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc,
                                                        Edit.Text,
                                                        Edit.BeforePrev));
        break;
      case edit::Commit::Act_InsertFromRange:
        Builder.AddFixItHint(
            FixItHint::CreateInsertionFromRange(Edit.OrigLoc,
                                                Edit.getInsertFromRange(SM),
                                                Edit.BeforePrev));
        break;
      case edit::Commit::Act_Remove:
        Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM)));
        break;
      }
    }
  }
}

static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) {
  applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use,
                     edit::rewriteObjCRedundantCallWithLiteral);
}

static void checkFoundationAPI(Sema &S, SourceLocation Loc,
                               const ObjCMethodDecl *Method,
                               ArrayRef<Expr *> Args, QualType ReceiverType,
                               bool IsClassObjectCall) {
  // Check if this is a performSelector method that uses a selector that returns
  // a record or a vector type.
  if (Method->getSelector().getMethodFamily() != OMF_performSelector ||
      Args.empty())
    return;
  const auto *SE = dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens());
  if (!SE)
    return;
  ObjCMethodDecl *ImpliedMethod;
  if (!IsClassObjectCall) {
    const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>();
    if (!OPT || !OPT->getInterfaceDecl())
      return;
    ImpliedMethod =
        OPT->getInterfaceDecl()->lookupInstanceMethod(SE->getSelector());
    if (!ImpliedMethod)
      ImpliedMethod =
          OPT->getInterfaceDecl()->lookupPrivateMethod(SE->getSelector());
  } else {
    const auto *IT = ReceiverType->getAs<ObjCInterfaceType>();
    if (!IT)
      return;
    ImpliedMethod = IT->getDecl()->lookupClassMethod(SE->getSelector());
    if (!ImpliedMethod)
      ImpliedMethod =
          IT->getDecl()->lookupPrivateClassMethod(SE->getSelector());
  }
  if (!ImpliedMethod)
    return;
  QualType Ret = ImpliedMethod->getReturnType();
  if (Ret->isRecordType() || Ret->isVectorType() || Ret->isExtVectorType()) {
    S.Diag(Loc, diag::warn_objc_unsafe_perform_selector)
        << Method->getSelector()
        << (!Ret->isRecordType()
                ? /*Vector*/ 2
                : Ret->isUnionType() ? /*Union*/ 1 : /*Struct*/ 0);
    S.Diag(ImpliedMethod->getBeginLoc(),
           diag::note_objc_unsafe_perform_selector_method_declared_here)
        << ImpliedMethod->getSelector() << Ret;
  }
}

/// Diagnose use of %s directive in an NSString which is being passed
/// as formatting string to formatting method.
static void
DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,
                                        ObjCMethodDecl *Method,
                                        Selector Sel,
                                        Expr **Args, unsigned NumArgs) {
  unsigned Idx = 0;
  bool Format = false;
  ObjCStringFormatFamily SFFamily = Sel.getStringFormatFamily();
  if (SFFamily == ObjCStringFormatFamily::SFF_NSString) {
    Idx = 0;
    Format = true;
  }
  else if (Method) {
    for (const auto *I : Method->specific_attrs<FormatAttr>()) {
      if (S.GetFormatNSStringIdx(I, Idx)) {
        Format = true;
        break;
      }
    }
  }
  if (!Format || NumArgs <= Idx)
    return;

  Expr *FormatExpr = Args[Idx];
  if (ObjCStringLiteral *OSL =
      dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts())) {
    StringLiteral *FormatString = OSL->getString();
    if (S.FormatStringHasSArg(FormatString)) {
      S.Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string)
        << "%s" << 0 << 0;
      if (Method)
        S.Diag(Method->getLocation(), diag::note_method_declared_at)
          << Method->getDeclName();
    }
  }
}

/// Build an Objective-C class message expression.
///
/// This routine takes care of both normal class messages and
/// class messages to the superclass.
///
/// \param ReceiverTypeInfo Type source information that describes the
/// receiver of this message. This may be NULL, in which case we are
/// sending to the superclass and \p SuperLoc must be a valid source
/// location.

/// \param ReceiverType The type of the object receiving the
/// message. When \p ReceiverTypeInfo is non-NULL, this is the same
/// type as that refers to. For a superclass send, this is the type of
/// the superclass.
///
/// \param SuperLoc The location of the "super" keyword in a
/// superclass message.
///
/// \param Sel The selector to which the message is being sent.
///
/// \param Method The method that this class message is invoking, if
/// already known.
///
/// \param LBracLoc The location of the opening square bracket ']'.
///
/// \param RBracLoc The location of the closing square bracket ']'.
///
/// \param ArgsIn The message arguments.
ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
                                   QualType ReceiverType,
                                   SourceLocation SuperLoc,
                                   Selector Sel,
                                   ObjCMethodDecl *Method,
                                   SourceLocation LBracLoc,
                                   ArrayRef<SourceLocation> SelectorLocs,
                                   SourceLocation RBracLoc,
                                   MultiExprArg ArgsIn,
                                   bool isImplicit) {
  SourceLocation Loc = SuperLoc.isValid()? SuperLoc
    : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
  if (LBracLoc.isInvalid()) {
    Diag(Loc, diag::err_missing_open_square_message_send)
      << FixItHint::CreateInsertion(Loc, "[");
    LBracLoc = Loc;
  }
  ArrayRef<SourceLocation> SelectorSlotLocs;
  if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
    SelectorSlotLocs = SelectorLocs;
  else
    SelectorSlotLocs = Loc;
  SourceLocation SelLoc = SelectorSlotLocs.front();

  if (ReceiverType->isDependentType()) {
    // If the receiver type is dependent, we can't type-check anything
    // at this point. Build a dependent expression.
    unsigned NumArgs = ArgsIn.size();
    Expr **Args = ArgsIn.data();
    assert(SuperLoc.isInvalid() && "Message to super with dependent type");
    return ObjCMessageExpr::Create(
        Context, ReceiverType, VK_PRValue, LBracLoc, ReceiverTypeInfo, Sel,
        SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs), RBracLoc,
        isImplicit);
  }

  // Find the class to which we are sending this message.
  ObjCInterfaceDecl *Class = nullptr;
  const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
  if (!ClassType || !(Class = ClassType->getInterface())) {
    Diag(Loc, diag::err_invalid_receiver_class_message)
      << ReceiverType;
    return ExprError();
  }
  assert(Class && "We don't know which class we're messaging?");
  // objc++ diagnoses during typename annotation.
  if (!getLangOpts().CPlusPlus)
    (void)DiagnoseUseOfDecl(Class, SelectorSlotLocs);
  // Find the method we are messaging.
  if (!Method) {
    SourceRange TypeRange
      = SuperLoc.isValid()? SourceRange(SuperLoc)
                          : ReceiverTypeInfo->getTypeLoc().getSourceRange();
    if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class),
                            (getLangOpts().ObjCAutoRefCount
                               ? diag::err_arc_receiver_forward_class
                               : diag::warn_receiver_forward_class),
                            TypeRange)) {
      // A forward class used in messaging is treated as a 'Class'
      Method = LookupFactoryMethodInGlobalPool(Sel,
                                               SourceRange(LBracLoc, RBracLoc));
      if (Method && !getLangOpts().ObjCAutoRefCount)
        Diag(Method->getLocation(), diag::note_method_sent_forward_class)
          << Method->getDeclName();
    }
    if (!Method)
      Method = Class->lookupClassMethod(Sel);

    // If we have an implementation in scope, check "private" methods.
    if (!Method)
      Method = Class->lookupPrivateClassMethod(Sel);

    if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs,
                                    nullptr, false, false, Class))
      return ExprError();
  }

  // Check the argument types and determine the result type.
  QualType ReturnType;
  ExprValueKind VK = VK_PRValue;

  unsigned NumArgs = ArgsIn.size();
  Expr **Args = ArgsIn.data();
  if (CheckMessageArgumentTypes(/*Receiver=*/nullptr, ReceiverType,
                                MultiExprArg(Args, NumArgs), Sel, SelectorLocs,
                                Method, true, SuperLoc.isValid(), LBracLoc,
                                RBracLoc, SourceRange(), ReturnType, VK))
    return ExprError();

  if (Method && !Method->getReturnType()->isVoidType() &&
      RequireCompleteType(LBracLoc, Method->getReturnType(),
                          diag::err_illegal_message_expr_incomplete_type))
    return ExprError();

  if (Method && Method->isDirectMethod() && SuperLoc.isValid()) {
    Diag(SuperLoc, diag::err_messaging_super_with_direct_method)
        << FixItHint::CreateReplacement(
               SuperLoc, getLangOpts().ObjCAutoRefCount
                             ? "self"
                             : Method->getClassInterface()->getName());
    Diag(Method->getLocation(), diag::note_direct_method_declared_at)
        << Method->getDeclName();
  }

  // Warn about explicit call of +initialize on its own class. But not on 'super'.
  if (Method && Method->getMethodFamily() == OMF_initialize) {
    if (!SuperLoc.isValid()) {
      const ObjCInterfaceDecl *ID =
        dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext());
      if (ID == Class) {
        Diag(Loc, diag::warn_direct_initialize_call);
        Diag(Method->getLocation(), diag::note_method_declared_at)
          << Method->getDeclName();
      }
    }
    else if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
      // [super initialize] is allowed only within an +initialize implementation
      if (CurMeth->getMethodFamily() != OMF_initialize) {
        Diag(Loc, diag::warn_direct_super_initialize_call);
        Diag(Method->getLocation(), diag::note_method_declared_at)
          << Method->getDeclName();
        Diag(CurMeth->getLocation(), diag::note_method_declared_at)
        << CurMeth->getDeclName();
      }
    }
  }

  DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs);

  // Construct the appropriate ObjCMessageExpr.
  ObjCMessageExpr *Result;
  if (SuperLoc.isValid())
    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
                                     SuperLoc, /*IsInstanceSuper=*/false,
                                     ReceiverType, Sel, SelectorLocs,
                                     Method, makeArrayRef(Args, NumArgs),
                                     RBracLoc, isImplicit);
  else {
    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
                                     ReceiverTypeInfo, Sel, SelectorLocs,
                                     Method, makeArrayRef(Args, NumArgs),
                                     RBracLoc, isImplicit);
    if (!isImplicit)
      checkCocoaAPI(*this, Result);
  }
  if (Method)
    checkFoundationAPI(*this, SelLoc, Method, makeArrayRef(Args, NumArgs),
                       ReceiverType, /*IsClassObjectCall=*/true);
  return MaybeBindToTemporary(Result);
}

// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
ExprResult Sema::ActOnClassMessage(Scope *S,
                                   ParsedType Receiver,
                                   Selector Sel,
                                   SourceLocation LBracLoc,
                                   ArrayRef<SourceLocation> SelectorLocs,
                                   SourceLocation RBracLoc,
                                   MultiExprArg Args) {
  TypeSourceInfo *ReceiverTypeInfo;
  QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo);
  if (ReceiverType.isNull())
    return ExprError();

  if (!ReceiverTypeInfo)
    ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);

  return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
                           /*SuperLoc=*/SourceLocation(), Sel,
                           /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc,
                           Args);
}

ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver,
                                              QualType ReceiverType,
                                              SourceLocation Loc,
                                              Selector Sel,
                                              ObjCMethodDecl *Method,
                                              MultiExprArg Args) {
  return BuildInstanceMessage(Receiver, ReceiverType,
                              /*SuperLoc=*/!Receiver ? Loc : SourceLocation(),
                              Sel, Method, Loc, Loc, Loc, Args,
                              /*isImplicit=*/true);
}

static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) {
  if (!S.NSAPIObj)
    return false;
  const auto *Protocol = dyn_cast<ObjCProtocolDecl>(M->getDeclContext());
  if (!Protocol)
    return false;
  const IdentifierInfo *II = S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);
  if (const auto *RootClass = dyn_cast_or_null<ObjCInterfaceDecl>(
          S.LookupSingleName(S.TUScope, II, Protocol->getBeginLoc(),
                             Sema::LookupOrdinaryName))) {
    for (const ObjCProtocolDecl *P : RootClass->all_referenced_protocols()) {
      if (P->getCanonicalDecl() == Protocol->getCanonicalDecl())
        return true;
    }
  }
  return false;
}

/// Build an Objective-C instance message expression.
///
/// This routine takes care of both normal instance messages and
/// instance messages to the superclass instance.
///
/// \param Receiver The expression that computes the object that will
/// receive this message. This may be empty, in which case we are
/// sending to the superclass instance and \p SuperLoc must be a valid
/// source location.
///
/// \param ReceiverType The (static) type of the object receiving the
/// message. When a \p Receiver expression is provided, this is the
/// same type as that expression. For a superclass instance send, this
/// is a pointer to the type of the superclass.
///
/// \param SuperLoc The location of the "super" keyword in a
/// superclass instance message.
///
/// \param Sel The selector to which the message is being sent.
///
/// \param Method The method that this instance message is invoking, if
/// already known.
///
/// \param LBracLoc The location of the opening square bracket ']'.
///
/// \param RBracLoc The location of the closing square bracket ']'.
///
/// \param ArgsIn The message arguments.
ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
                                      QualType ReceiverType,
                                      SourceLocation SuperLoc,
                                      Selector Sel,
                                      ObjCMethodDecl *Method,
                                      SourceLocation LBracLoc,
                                      ArrayRef<SourceLocation> SelectorLocs,
                                      SourceLocation RBracLoc,
                                      MultiExprArg ArgsIn,
                                      bool isImplicit) {
  assert((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the "
                                             "SuperLoc must be valid so we can "
                                             "use it instead.");

  // The location of the receiver.
  SourceLocation Loc = SuperLoc.isValid() ? SuperLoc : Receiver->getBeginLoc();
  SourceRange RecRange =
      SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
  ArrayRef<SourceLocation> SelectorSlotLocs;
  if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
    SelectorSlotLocs = SelectorLocs;
  else
    SelectorSlotLocs = Loc;
  SourceLocation SelLoc = SelectorSlotLocs.front();

  if (LBracLoc.isInvalid()) {
    Diag(Loc, diag::err_missing_open_square_message_send)
      << FixItHint::CreateInsertion(Loc, "[");
    LBracLoc = Loc;
  }

  // If we have a receiver expression, perform appropriate promotions
  // and determine receiver type.
  if (Receiver) {
    if (Receiver->hasPlaceholderType()) {
      ExprResult Result;
      if (Receiver->getType() == Context.UnknownAnyTy)
        Result = forceUnknownAnyToType(Receiver, Context.getObjCIdType());
      else
        Result = CheckPlaceholderExpr(Receiver);
      if (Result.isInvalid()) return ExprError();
      Receiver = Result.get();
    }

    if (Receiver->isTypeDependent()) {
      // If the receiver is type-dependent, we can't type-check anything
      // at this point. Build a dependent expression.
      unsigned NumArgs = ArgsIn.size();
      Expr **Args = ArgsIn.data();
      assert(SuperLoc.isInvalid() && "Message to super with dependent type");
      return ObjCMessageExpr::Create(
          Context, Context.DependentTy, VK_PRValue, LBracLoc, Receiver, Sel,
          SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs),
          RBracLoc, isImplicit);
    }

    // If necessary, apply function/array conversion to the receiver.
    // C99 6.7.5.3p[7,8].
    ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver);
    if (Result.isInvalid())
      return ExprError();
    Receiver = Result.get();
    ReceiverType = Receiver->getType();

    // If the receiver is an ObjC pointer, a block pointer, or an
    // __attribute__((NSObject)) pointer, we don't need to do any
    // special conversion in order to look up a receiver.
    if (ReceiverType->isObjCRetainableType()) {
      // do nothing
    } else if (!getLangOpts().ObjCAutoRefCount &&
               !Context.getObjCIdType().isNull() &&
               (ReceiverType->isPointerType() ||
                ReceiverType->isIntegerType())) {
      // Implicitly convert integers and pointers to 'id' but emit a warning.
      // But not in ARC.
      Diag(Loc, diag::warn_bad_receiver_type) << ReceiverType << RecRange;
      if (ReceiverType->isPointerType()) {
        Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
                                     CK_CPointerToObjCPointerCast).get();
      } else {
        // TODO: specialized warning on null receivers?
        bool IsNull = Receiver->isNullPointerConstant(Context,
                                              Expr::NPC_ValueDependentIsNull);
        CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;
        Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
                                     Kind).get();
      }
      ReceiverType = Receiver->getType();
    } else if (getLangOpts().CPlusPlus) {
      // The receiver must be a complete type.
      if (RequireCompleteType(Loc, Receiver->getType(),
                              diag::err_incomplete_receiver_type))
        return ExprError();

      ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver);
      if (result.isUsable()) {
        Receiver = result.get();
        ReceiverType = Receiver->getType();
      }
    }
  }

  // There's a somewhat weird interaction here where we assume that we
  // won't actually have a method unless we also don't need to do some
  // of the more detailed type-checking on the receiver.

  if (!Method) {
    // Handle messages to id and __kindof types (where we use the
    // global method pool).
    const ObjCObjectType *typeBound = nullptr;
    bool receiverIsIdLike = ReceiverType->isObjCIdOrObjectKindOfType(Context,
                                                                     typeBound);
    if (receiverIsIdLike || ReceiverType->isBlockPointerType() ||
        (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
      SmallVector<ObjCMethodDecl*, 4> Methods;
      // If we have a type bound, further filter the methods.
      CollectMultipleMethodsInGlobalPool(Sel, Methods, true/*InstanceFirst*/,
                                         true/*CheckTheOther*/, typeBound);
      if (!Methods.empty()) {
        // We choose the first method as the initial candidate, then try to
        // select a better one.
        Method = Methods[0];

        if (ObjCMethodDecl *BestMethod =
            SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(), Methods))
          Method = BestMethod;

        if (!AreMultipleMethodsInGlobalPool(Sel, Method,
                                            SourceRange(LBracLoc, RBracLoc),
                                            receiverIsIdLike, Methods))
          DiagnoseUseOfDecl(Method, SelectorSlotLocs);
      }
    } else if (ReceiverType->isObjCClassOrClassKindOfType() ||
               ReceiverType->isObjCQualifiedClassType()) {
      // Handle messages to Class.
      // We allow sending a message to a qualified Class ("Class<foo>"), which
      // is ok as long as one of the protocols implements the selector (if not,
      // warn).
      if (!ReceiverType->isObjCClassOrClassKindOfType()) {
        const ObjCObjectPointerType *QClassTy
          = ReceiverType->getAsObjCQualifiedClassType();
        // Search protocols for class methods.
        Method = LookupMethodInQualifiedType(Sel, QClassTy, false);
        if (!Method) {
          Method = LookupMethodInQualifiedType(Sel, QClassTy, true);
          // warn if instance method found for a Class message.
          if (Method && !isMethodDeclaredInRootProtocol(*this, Method)) {
            Diag(SelLoc, diag::warn_instance_method_on_class_found)
              << Method->getSelector() << Sel;
            Diag(Method->getLocation(), diag::note_method_declared_at)
              << Method->getDeclName();
          }
        }
      } else {
        if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
          if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
            // As a guess, try looking for the method in the current interface.
            // This very well may not produce the "right" method.

            // First check the public methods in the class interface.
            Method = ClassDecl->lookupClassMethod(Sel);

            if (!Method)
              Method = ClassDecl->lookupPrivateClassMethod(Sel);

            if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
              return ExprError();
          }
        }
        if (!Method) {
          // If not messaging 'self', look for any factory method named 'Sel'.
          if (!Receiver || !isSelfExpr(Receiver)) {
            // If no class (factory) method was found, check if an _instance_
            // method of the same name exists in the root class only.
            SmallVector<ObjCMethodDecl*, 4> Methods;
            CollectMultipleMethodsInGlobalPool(Sel, Methods,
                                               false/*InstanceFirst*/,
                                               true/*CheckTheOther*/);
            if (!Methods.empty()) {
              // We choose the first method as the initial candidate, then try
              // to select a better one.
              Method = Methods[0];

              // If we find an instance method, emit warning.
              if (Method->isInstanceMethod()) {
                if (const ObjCInterfaceDecl *ID =
                    dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
                  if (ID->getSuperClass())
                    Diag(SelLoc, diag::warn_root_inst_method_not_found)
                        << Sel << SourceRange(LBracLoc, RBracLoc);
                }
              }

             if (ObjCMethodDecl *BestMethod =
                 SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(),
                                  Methods))
               Method = BestMethod;
            }
          }
        }
      }
    } else {
      ObjCInterfaceDecl *ClassDecl = nullptr;

      // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
      // long as one of the protocols implements the selector (if not, warn).
      // And as long as message is not deprecated/unavailable (warn if it is).
      if (const ObjCObjectPointerType *QIdTy
                                   = ReceiverType->getAsObjCQualifiedIdType()) {
        // Search protocols for instance methods.
        Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
        if (!Method)
          Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
        if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
          return ExprError();
      } else if (const ObjCObjectPointerType *OCIType
                   = ReceiverType->getAsObjCInterfacePointerType()) {
        // We allow sending a message to a pointer to an interface (an object).
        ClassDecl = OCIType->getInterfaceDecl();

        // Try to complete the type. Under ARC, this is a hard error from which
        // we don't try to recover.
        // FIXME: In the non-ARC case, this will still be a hard error if the
        // definition is found in a module that's not visible.
        const ObjCInterfaceDecl *forwardClass = nullptr;
        if (RequireCompleteType(Loc, OCIType->getPointeeType(),
                                getLangOpts().ObjCAutoRefCount
                                    ? diag::err_arc_receiver_forward_instance
                                    : diag::warn_receiver_forward_instance,
                                RecRange)) {
          if (getLangOpts().ObjCAutoRefCount)
            return ExprError();

          forwardClass = OCIType->getInterfaceDecl();
          Diag(Receiver ? Receiver->getBeginLoc() : SuperLoc,
               diag::note_receiver_is_id);
          Method = nullptr;
        } else {
          Method = ClassDecl->lookupInstanceMethod(Sel);
        }

        if (!Method)
          // Search protocol qualifiers.
          Method = LookupMethodInQualifiedType(Sel, OCIType, true);

        if (!Method) {
          // If we have implementations in scope, check "private" methods.
          Method = ClassDecl->lookupPrivateMethod(Sel);

          if (!Method && getLangOpts().ObjCAutoRefCount) {
            Diag(SelLoc, diag::err_arc_may_not_respond)
              << OCIType->getPointeeType() << Sel << RecRange
              << SourceRange(SelectorLocs.front(), SelectorLocs.back());
            return ExprError();
          }

          if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
            // If we still haven't found a method, look in the global pool. This
            // behavior isn't very desirable, however we need it for GCC
            // compatibility. FIXME: should we deviate??
            if (OCIType->qual_empty()) {
              SmallVector<ObjCMethodDecl*, 4> Methods;
              CollectMultipleMethodsInGlobalPool(Sel, Methods,
                                                 true/*InstanceFirst*/,
                                                 false/*CheckTheOther*/);
              if (!Methods.empty()) {
                // We choose the first method as the initial candidate, then try
                // to select a better one.
                Method = Methods[0];

                if (ObjCMethodDecl *BestMethod =
                    SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(),
                                     Methods))
                  Method = BestMethod;

                AreMultipleMethodsInGlobalPool(Sel, Method,
                                               SourceRange(LBracLoc, RBracLoc),
                                               true/*receiverIdOrClass*/,
                                               Methods);
              }
              if (Method && !forwardClass)
                Diag(SelLoc, diag::warn_maynot_respond)
                  << OCIType->getInterfaceDecl()->getIdentifier()
                  << Sel << RecRange;
            }
          }
        }
        if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, forwardClass))
          return ExprError();
      } else {
        // Reject other random receiver types (e.g. structs).
        Diag(Loc, diag::err_bad_receiver_type) << ReceiverType << RecRange;
        return ExprError();
      }
    }
  }

  FunctionScopeInfo *DIFunctionScopeInfo =
    (Method && Method->getMethodFamily() == OMF_init)
      ? getEnclosingFunction() : nullptr;

  if (Method && Method->isDirectMethod()) {
    if (ReceiverType->isObjCIdType() && !isImplicit) {
      Diag(Receiver->getExprLoc(),
           diag::err_messaging_unqualified_id_with_direct_method);
      Diag(Method->getLocation(), diag::note_direct_method_declared_at)
          << Method->getDeclName();
    }

    // Under ARC, self can't be assigned, and doing a direct call to `self`
    // when it's a Class is hence safe.  For other cases, we can't trust `self`
    // is what we think it is, so we reject it.
    if (ReceiverType->isObjCClassType() && !isImplicit &&
        !(Receiver->isObjCSelfExpr() && getLangOpts().ObjCAutoRefCount)) {
      {
        auto Builder = Diag(Receiver->getExprLoc(),
                            diag::err_messaging_class_with_direct_method);
        if (Receiver->isObjCSelfExpr()) {
          Builder.AddFixItHint(FixItHint::CreateReplacement(
              RecRange, Method->getClassInterface()->getName()));
        }
      }
      Diag(Method->getLocation(), diag::note_direct_method_declared_at)
          << Method->getDeclName();
    }

    if (SuperLoc.isValid()) {
      {
        auto Builder =
            Diag(SuperLoc, diag::err_messaging_super_with_direct_method);
        if (ReceiverType->isObjCClassType()) {
          Builder.AddFixItHint(FixItHint::CreateReplacement(
              SuperLoc, Method->getClassInterface()->getName()));
        } else {
          Builder.AddFixItHint(FixItHint::CreateReplacement(SuperLoc, "self"));
        }
      }
      Diag(Method->getLocation(), diag::note_direct_method_declared_at)
          << Method->getDeclName();
    }
  } else if (ReceiverType->isObjCIdType() && !isImplicit) {
    Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id);
  }

  if (DIFunctionScopeInfo &&
      DIFunctionScopeInfo->ObjCIsDesignatedInit &&
      (SuperLoc.isValid() || isSelfExpr(Receiver))) {
    bool isDesignatedInitChain = false;
    if (SuperLoc.isValid()) {
      if (const ObjCObjectPointerType *
            OCIType = ReceiverType->getAsObjCInterfacePointerType()) {
        if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {
          // Either we know this is a designated initializer or we
          // conservatively assume it because we don't know for sure.
          if (!ID->declaresOrInheritsDesignatedInitializers() ||
              ID->isDesignatedInitializer(Sel)) {
            isDesignatedInitChain = true;
            DIFunctionScopeInfo->ObjCWarnForNoDesignatedInitChain = false;
          }
        }
      }
    }
    if (!isDesignatedInitChain) {
      const ObjCMethodDecl *InitMethod = nullptr;
      bool isDesignated =
        getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod);
      assert(isDesignated && InitMethod);
      (void)isDesignated;
      Diag(SelLoc, SuperLoc.isValid() ?
             diag::warn_objc_designated_init_non_designated_init_call :
             diag::warn_objc_designated_init_non_super_designated_init_call);
      Diag(InitMethod->getLocation(),
           diag::note_objc_designated_init_marked_here);
    }
  }

  if (DIFunctionScopeInfo &&
      DIFunctionScopeInfo->ObjCIsSecondaryInit &&
      (SuperLoc.isValid() || isSelfExpr(Receiver))) {
    if (SuperLoc.isValid()) {
      Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call);
    } else {
      DIFunctionScopeInfo->ObjCWarnForNoInitDelegation = false;
    }
  }

  // Check the message arguments.
  unsigned NumArgs = ArgsIn.size();
  Expr **Args = ArgsIn.data();
  QualType ReturnType;
  ExprValueKind VK = VK_PRValue;
  bool ClassMessage = (ReceiverType->isObjCClassType() ||
                       ReceiverType->isObjCQualifiedClassType());
  if (CheckMessageArgumentTypes(Receiver, ReceiverType,
                                MultiExprArg(Args, NumArgs), Sel, SelectorLocs,
                                Method, ClassMessage, SuperLoc.isValid(),
                                LBracLoc, RBracLoc, RecRange, ReturnType, VK))
    return ExprError();

  if (Method && !Method->getReturnType()->isVoidType() &&
      RequireCompleteType(LBracLoc, Method->getReturnType(),
                          diag::err_illegal_message_expr_incomplete_type))
    return ExprError();

  // In ARC, forbid the user from sending messages to
  // retain/release/autorelease/dealloc/retainCount explicitly.
  if (getLangOpts().ObjCAutoRefCount) {
    ObjCMethodFamily family =
      (Method ? Method->getMethodFamily() : Sel.getMethodFamily());
    switch (family) {
    case OMF_init:
      if (Method)
        checkInitMethod(Method, ReceiverType);
      break;

    case OMF_None:
    case OMF_alloc:
    case OMF_copy:
    case OMF_finalize:
    case OMF_mutableCopy:
    case OMF_new:
    case OMF_self:
    case OMF_initialize:
      break;

    case OMF_dealloc:
    case OMF_retain:
    case OMF_release:
    case OMF_autorelease:
    case OMF_retainCount:
      Diag(SelLoc, diag::err_arc_illegal_explicit_message)
        << Sel << RecRange;
      break;

    case OMF_performSelector:
      if (Method && NumArgs >= 1) {
        if (const auto *SelExp =
                dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens())) {
          Selector ArgSel = SelExp->getSelector();
          ObjCMethodDecl *SelMethod =
            LookupInstanceMethodInGlobalPool(ArgSel,
                                             SelExp->getSourceRange());
          if (!SelMethod)
            SelMethod =
              LookupFactoryMethodInGlobalPool(ArgSel,
                                              SelExp->getSourceRange());
          if (SelMethod) {
            ObjCMethodFamily SelFamily = SelMethod->getMethodFamily();
            switch (SelFamily) {
              case OMF_alloc:
              case OMF_copy:
              case OMF_mutableCopy:
              case OMF_new:
              case OMF_init:
                // Issue error, unless ns_returns_not_retained.
                if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
                  // selector names a +1 method
                  Diag(SelLoc,
                       diag::err_arc_perform_selector_retains);
                  Diag(SelMethod->getLocation(), diag::note_method_declared_at)
                    << SelMethod->getDeclName();
                }
                break;
              default:
                // +0 call. OK. unless ns_returns_retained.
                if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) {
                  // selector names a +1 method
                  Diag(SelLoc,
                       diag::err_arc_perform_selector_retains);
                  Diag(SelMethod->getLocation(), diag::note_method_declared_at)
                    << SelMethod->getDeclName();
                }
                break;
            }
          }
        } else {
          // error (may leak).
          Diag(SelLoc, diag::warn_arc_perform_selector_leaks);
          Diag(Args[0]->getExprLoc(), diag::note_used_here);
        }
      }
      break;
    }
  }

  DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs);

  // Construct the appropriate ObjCMessageExpr instance.
  ObjCMessageExpr *Result;
  if (SuperLoc.isValid())
    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
                                     SuperLoc,  /*IsInstanceSuper=*/true,
                                     ReceiverType, Sel, SelectorLocs, Method,
                                     makeArrayRef(Args, NumArgs), RBracLoc,
                                     isImplicit);
  else {
    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
                                     Receiver, Sel, SelectorLocs, Method,
                                     makeArrayRef(Args, NumArgs), RBracLoc,
                                     isImplicit);
    if (!isImplicit)
      checkCocoaAPI(*this, Result);
  }
  if (Method) {
    bool IsClassObjectCall = ClassMessage;
    // 'self' message receivers in class methods should be treated as message
    // sends to the class object in order for the semantic checks to be
    // performed correctly. Messages to 'super' already count as class messages,
    // so they don't need to be handled here.
    if (Receiver && isSelfExpr(Receiver)) {
      if (const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>()) {
        if (OPT->getObjectType()->isObjCClass()) {
          if (const auto *CurMeth = getCurMethodDecl()) {
            IsClassObjectCall = true;
            ReceiverType =
                Context.getObjCInterfaceType(CurMeth->getClassInterface());
          }
        }
      }
    }
    checkFoundationAPI(*this, SelLoc, Method, makeArrayRef(Args, NumArgs),
                       ReceiverType, IsClassObjectCall);
  }

  if (getLangOpts().ObjCAutoRefCount) {
    // In ARC, annotate delegate init calls.
    if (Result->getMethodFamily() == OMF_init &&
        (SuperLoc.isValid() || isSelfExpr(Receiver))) {
      // Only consider init calls *directly* in init implementations,
      // not within blocks.
      ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(CurContext);
      if (method && method->getMethodFamily() == OMF_init) {
        // The implicit assignment to self means we also don't want to
        // consume the result.
        Result->setDelegateInitCall(true);
        return Result;
      }
    }

    // In ARC, check for message sends which are likely to introduce
    // retain cycles.
    checkRetainCycles(Result);
  }

  if (getLangOpts().ObjCWeak) {
    if (!isImplicit && Method) {
      if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) {
        bool IsWeak =
            Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak;
        if (!IsWeak && Sel.isUnarySelector())
          IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;
        if (IsWeak && !isUnevaluatedContext() &&
            !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, LBracLoc))
          getCurFunction()->recordUseOfWeak(Result, Prop);
      }
    }
  }

  CheckObjCCircularContainer(Result);

  return MaybeBindToTemporary(Result);
}

static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) {
  if (ObjCSelectorExpr *OSE =
      dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) {
    Selector Sel = OSE->getSelector();
    SourceLocation Loc = OSE->getAtLoc();
    auto Pos = S.ReferencedSelectors.find(Sel);
    if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)
      S.ReferencedSelectors.erase(Pos);
  }
}

// ActOnInstanceMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
ExprResult Sema::ActOnInstanceMessage(Scope *S,
                                      Expr *Receiver,
                                      Selector Sel,
                                      SourceLocation LBracLoc,
                                      ArrayRef<SourceLocation> SelectorLocs,
                                      SourceLocation RBracLoc,
                                      MultiExprArg Args) {
  if (!Receiver)
    return ExprError();

  // A ParenListExpr can show up while doing error recovery with invalid code.
  if (isa<ParenListExpr>(Receiver)) {
    ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver);
    if (Result.isInvalid()) return ExprError();
    Receiver = Result.get();
  }

  if (RespondsToSelectorSel.isNull()) {
    IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector");
    RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId);
  }
  if (Sel == RespondsToSelectorSel)
    RemoveSelectorFromWarningCache(*this, Args[0]);

  return BuildInstanceMessage(Receiver, Receiver->getType(),
                              /*SuperLoc=*/SourceLocation(), Sel,
                              /*Method=*/nullptr, LBracLoc, SelectorLocs,
                              RBracLoc, Args);
}

enum ARCConversionTypeClass {
  /// int, void, struct A
  ACTC_none,

  /// id, void (^)()
  ACTC_retainable,

  /// id*, id***, void (^*)(),
  ACTC_indirectRetainable,

  /// void* might be a normal C type, or it might a CF type.
  ACTC_voidPtr,

  /// struct A*
  ACTC_coreFoundation
};

static bool isAnyRetainable(ARCConversionTypeClass ACTC) {
  return (ACTC == ACTC_retainable ||
          ACTC == ACTC_coreFoundation ||
          ACTC == ACTC_voidPtr);
}

static bool isAnyCLike(ARCConversionTypeClass ACTC) {
  return ACTC == ACTC_none ||
         ACTC == ACTC_voidPtr ||
         ACTC == ACTC_coreFoundation;
}

static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) {
  bool isIndirect = false;

  // Ignore an outermost reference type.
  if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
    type = ref->getPointeeType();
    isIndirect = true;
  }

  // Drill through pointers and arrays recursively.
  while (true) {
    if (const PointerType *ptr = type->getAs<PointerType>()) {
      type = ptr->getPointeeType();

      // The first level of pointer may be the innermost pointer on a CF type.
      if (!isIndirect) {
        if (type->isVoidType()) return ACTC_voidPtr;
        if (type->isRecordType()) return ACTC_coreFoundation;
      }
    } else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) {
      type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0);
    } else {
      break;
    }
    isIndirect = true;
  }

  if (isIndirect) {
    if (type->isObjCARCBridgableType())
      return ACTC_indirectRetainable;
    return ACTC_none;
  }

  if (type->isObjCARCBridgableType())
    return ACTC_retainable;

  return ACTC_none;
}

namespace {
  /// A result from the cast checker.
  enum ACCResult {
    /// Cannot be casted.
    ACC_invalid,

    /// Can be safely retained or not retained.
    ACC_bottom,

    /// Can be casted at +0.
    ACC_plusZero,

    /// Can be casted at +1.
    ACC_plusOne
  };
  ACCResult merge(ACCResult left, ACCResult right) {
    if (left == right) return left;
    if (left == ACC_bottom) return right;
    if (right == ACC_bottom) return left;
    return ACC_invalid;
  }

  /// A checker which white-lists certain expressions whose conversion
  /// to or from retainable type would otherwise be forbidden in ARC.
  class ARCCastChecker : public StmtVisitor<ARCCastChecker, ACCResult> {
    typedef StmtVisitor<ARCCastChecker, ACCResult> super;

    ASTContext &Context;
    ARCConversionTypeClass SourceClass;
    ARCConversionTypeClass TargetClass;
    bool Diagnose;

    static bool isCFType(QualType type) {
      // Someday this can use ns_bridged.  For now, it has to do this.
      return type->isCARCBridgableType();
    }

  public:
    ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source,
                   ARCConversionTypeClass target, bool diagnose)
      : Context(Context), SourceClass(source), TargetClass(target),
        Diagnose(diagnose) {}

    using super::Visit;
    ACCResult Visit(Expr *e) {
      return super::Visit(e->IgnoreParens());
    }

    ACCResult VisitStmt(Stmt *s) {
      return ACC_invalid;
    }

    /// Null pointer constants can be casted however you please.
    ACCResult VisitExpr(Expr *e) {
      if (e->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
        return ACC_bottom;
      return ACC_invalid;
    }

    /// Objective-C string literals can be safely casted.
    ACCResult VisitObjCStringLiteral(ObjCStringLiteral *e) {
      // If we're casting to any retainable type, go ahead.  Global
      // strings are immune to retains, so this is bottom.
      if (isAnyRetainable(TargetClass)) return ACC_bottom;

      return ACC_invalid;
    }

    /// Look through certain implicit and explicit casts.
    ACCResult VisitCastExpr(CastExpr *e) {
      switch (e->getCastKind()) {
        case CK_NullToPointer:
          return ACC_bottom;

        case CK_NoOp:
        case CK_LValueToRValue:
        case CK_BitCast:
        case CK_CPointerToObjCPointerCast:
        case CK_BlockPointerToObjCPointerCast:
        case CK_AnyPointerToBlockPointerCast:
          return Visit(e->getSubExpr());

        default:
          return ACC_invalid;
      }
    }

    /// Look through unary extension.
    ACCResult VisitUnaryExtension(UnaryOperator *e) {
      return Visit(e->getSubExpr());
    }

    /// Ignore the LHS of a comma operator.
    ACCResult VisitBinComma(BinaryOperator *e) {
      return Visit(e->getRHS());
    }

    /// Conditional operators are okay if both sides are okay.
    ACCResult VisitConditionalOperator(ConditionalOperator *e) {
      ACCResult left = Visit(e->getTrueExpr());
      if (left == ACC_invalid) return ACC_invalid;
      return merge(left, Visit(e->getFalseExpr()));
    }

    /// Look through pseudo-objects.
    ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) {
      // If we're getting here, we should always have a result.
      return Visit(e->getResultExpr());
    }

    /// Statement expressions are okay if their result expression is okay.
    ACCResult VisitStmtExpr(StmtExpr *e) {
      return Visit(e->getSubStmt()->body_back());
    }

    /// Some declaration references are okay.
    ACCResult VisitDeclRefExpr(DeclRefExpr *e) {
      VarDecl *var = dyn_cast<VarDecl>(e->getDecl());
      // References to global constants are okay.
      if (isAnyRetainable(TargetClass) &&
          isAnyRetainable(SourceClass) &&
          var &&
          !var->hasDefinition(Context) &&
          var->getType().isConstQualified()) {

        // In system headers, they can also be assumed to be immune to retains.
        // These are things like 'kCFStringTransformToLatin'.
        if (Context.getSourceManager().isInSystemHeader(var->getLocation()))
          return ACC_bottom;

        return ACC_plusZero;
      }

      // Nothing else.
      return ACC_invalid;
    }

    /// Some calls are okay.
    ACCResult VisitCallExpr(CallExpr *e) {
      if (FunctionDecl *fn = e->getDirectCallee())
        if (ACCResult result = checkCallToFunction(fn))
          return result;

      return super::VisitCallExpr(e);
    }

    ACCResult checkCallToFunction(FunctionDecl *fn) {
      // Require a CF*Ref return type.
      if (!isCFType(fn->getReturnType()))
        return ACC_invalid;

      if (!isAnyRetainable(TargetClass))
        return ACC_invalid;

      // Honor an explicit 'not retained' attribute.
      if (fn->hasAttr<CFReturnsNotRetainedAttr>())
        return ACC_plusZero;

      // Honor an explicit 'retained' attribute, except that for
      // now we're not going to permit implicit handling of +1 results,
      // because it's a bit frightening.
      if (fn->hasAttr<CFReturnsRetainedAttr>())
        return Diagnose ? ACC_plusOne
                        : ACC_invalid; // ACC_plusOne if we start accepting this

      // Recognize this specific builtin function, which is used by CFSTR.
      unsigned builtinID = fn->getBuiltinID();
      if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString)
        return ACC_bottom;

      // Otherwise, don't do anything implicit with an unaudited function.
      if (!fn->hasAttr<CFAuditedTransferAttr>())
        return ACC_invalid;

      // Otherwise, it's +0 unless it follows the create convention.
      if (ento::coreFoundation::followsCreateRule(fn))
        return Diagnose ? ACC_plusOne
                        : ACC_invalid; // ACC_plusOne if we start accepting this

      return ACC_plusZero;
    }

    ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) {
      return checkCallToMethod(e->getMethodDecl());
    }

    ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) {
      ObjCMethodDecl *method;
      if (e->isExplicitProperty())
        method = e->getExplicitProperty()->getGetterMethodDecl();
      else
        method = e->getImplicitPropertyGetter();
      return checkCallToMethod(method);
    }

    ACCResult checkCallToMethod(ObjCMethodDecl *method) {
      if (!method) return ACC_invalid;

      // Check for message sends to functions returning CF types.  We
      // just obey the Cocoa conventions with these, even though the
      // return type is CF.
      if (!isAnyRetainable(TargetClass) || !isCFType(method->getReturnType()))
        return ACC_invalid;

      // If the method is explicitly marked not-retained, it's +0.
      if (method->hasAttr<CFReturnsNotRetainedAttr>())
        return ACC_plusZero;

      // If the method is explicitly marked as returning retained, or its
      // selector follows a +1 Cocoa convention, treat it as +1.
      if (method->hasAttr<CFReturnsRetainedAttr>())
        return ACC_plusOne;

      switch (method->getSelector().getMethodFamily()) {
      case OMF_alloc:
      case OMF_copy:
      case OMF_mutableCopy:
      case OMF_new:
        return ACC_plusOne;

      default:
        // Otherwise, treat it as +0.
        return ACC_plusZero;
      }
    }
  };
} // end anonymous namespace

bool Sema::isKnownName(StringRef name) {
  if (name.empty())
    return false;
  LookupResult R(*this, &Context.Idents.get(name), SourceLocation(),
                 Sema::LookupOrdinaryName);
  return LookupName(R, TUScope, false);
}

template <typename DiagBuilderT>
static void addFixitForObjCARCConversion(
    Sema &S, DiagBuilderT &DiagB, Sema::CheckedConversionKind CCK,
    SourceLocation afterLParen, QualType castType, Expr *castExpr,
    Expr *realCast, const char *bridgeKeyword, const char *CFBridgeName) {
  // We handle C-style and implicit casts here.
  switch (CCK) {
  case Sema::CCK_ImplicitConversion:
  case Sema::CCK_ForBuiltinOverloadedOp:
  case Sema::CCK_CStyleCast:
  case Sema::CCK_OtherCast:
    break;
  case Sema::CCK_FunctionalCast:
    return;
  }

  if (CFBridgeName) {
    if (CCK == Sema::CCK_OtherCast) {
      if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {
        SourceRange range(NCE->getOperatorLoc(),
                          NCE->getAngleBrackets().getEnd());
        SmallString<32> BridgeCall;

        SourceManager &SM = S.getSourceManager();
        char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));
        if (Lexer::isAsciiIdentifierContinueChar(PrevChar, S.getLangOpts()))
          BridgeCall += ' ';

        BridgeCall += CFBridgeName;
        DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall));
      }
      return;
    }
    Expr *castedE = castExpr;
    if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE))
      castedE = CCE->getSubExpr();
    castedE = castedE->IgnoreImpCasts();
    SourceRange range = castedE->getSourceRange();

    SmallString<32> BridgeCall;

    SourceManager &SM = S.getSourceManager();
    char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));
    if (Lexer::isAsciiIdentifierContinueChar(PrevChar, S.getLangOpts()))
      BridgeCall += ' ';

    BridgeCall += CFBridgeName;

    if (isa<ParenExpr>(castedE)) {
      DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
                         BridgeCall));
    } else {
      BridgeCall += '(';
      DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
                                                    BridgeCall));
      DiagB.AddFixItHint(FixItHint::CreateInsertion(
                                       S.getLocForEndOfToken(range.getEnd()),
                                       ")"));
    }
    return;
  }

  if (CCK == Sema::CCK_CStyleCast) {
    DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword));
  } else if (CCK == Sema::CCK_OtherCast) {
    if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {
      std::string castCode = "(";
      castCode += bridgeKeyword;
      castCode += castType.getAsString();
      castCode += ")";
      SourceRange Range(NCE->getOperatorLoc(),
                        NCE->getAngleBrackets().getEnd());
      DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode));
    }
  } else {
    std::string castCode = "(";
    castCode += bridgeKeyword;
    castCode += castType.getAsString();
    castCode += ")";
    Expr *castedE = castExpr->IgnoreImpCasts();
    SourceRange range = castedE->getSourceRange();
    if (isa<ParenExpr>(castedE)) {
      DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
                         castCode));
    } else {
      castCode += "(";
      DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
                                                    castCode));
      DiagB.AddFixItHint(FixItHint::CreateInsertion(
                                       S.getLocForEndOfToken(range.getEnd()),
                                       ")"));
    }
  }
}

template <typename T>
static inline T *getObjCBridgeAttr(const TypedefType *TD) {
  TypedefNameDecl *TDNDecl = TD->getDecl();
  QualType QT = TDNDecl->getUnderlyingType();
  if (QT->isPointerType()) {
    QT = QT->getPointeeType();
    if (const RecordType *RT = QT->getAs<RecordType>()) {
      for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {
        if (auto *attr = Redecl->getAttr<T>())
          return attr;
      }
    }
  }
  return nullptr;
}

static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T,
                                                            TypedefNameDecl *&TDNDecl) {
  while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
    TDNDecl = TD->getDecl();
    if (ObjCBridgeRelatedAttr *ObjCBAttr =
        getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD))
      return ObjCBAttr;
    T = TDNDecl->getUnderlyingType();
  }
  return nullptr;
}

static void
diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
                          QualType castType, ARCConversionTypeClass castACTC,
                          Expr *castExpr, Expr *realCast,
                          ARCConversionTypeClass exprACTC,
                          Sema::CheckedConversionKind CCK) {
  SourceLocation loc =
    (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());

  if (S.makeUnavailableInSystemHeader(loc,
                                 UnavailableAttr::IR_ARCForbiddenConversion))
    return;

  QualType castExprType = castExpr->getType();
  // Defer emitting a diagnostic for bridge-related casts; that will be
  // handled by CheckObjCBridgeRelatedConversions.
  TypedefNameDecl *TDNDecl = nullptr;
  if ((castACTC == ACTC_coreFoundation &&  exprACTC == ACTC_retainable &&
       ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) ||
      (exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&
       ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl)))
    return;

  unsigned srcKind = 0;
  switch (exprACTC) {
  case ACTC_none:
  case ACTC_coreFoundation:
  case ACTC_voidPtr:
    srcKind = (castExprType->isPointerType() ? 1 : 0);
    break;
  case ACTC_retainable:
    srcKind = (castExprType->isBlockPointerType() ? 2 : 3);
    break;
  case ACTC_indirectRetainable:
    srcKind = 4;
    break;
  }

  // Check whether this could be fixed with a bridge cast.
  SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin());
  SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;

  unsigned convKindForDiag = Sema::isCast(CCK) ? 0 : 1;

  // Bridge from an ARC type to a CF type.
  if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {

    S.Diag(loc, diag::err_arc_cast_requires_bridge)
      << convKindForDiag
      << 2 // of C pointer type
      << castExprType
      << unsigned(castType->isBlockPointerType()) // to ObjC|block type
      << castType
      << castRange
      << castExpr->getSourceRange();
    bool br = S.isKnownName("CFBridgingRelease");
    ACCResult CreateRule =
      ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);
    assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
    if (CreateRule != ACC_plusOne)
    {
      auto DiagB = (CCK != Sema::CCK_OtherCast)
                       ? S.Diag(noteLoc, diag::note_arc_bridge)
                       : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);

      addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
                                   castType, castExpr, realCast, "__bridge ",
                                   nullptr);
    }
    if (CreateRule != ACC_plusZero)
    {
      auto DiagB = (CCK == Sema::CCK_OtherCast && !br)
                       ? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer)
                             << castExprType
                       : S.Diag(br ? castExpr->getExprLoc() : noteLoc,
                                diag::note_arc_bridge_transfer)
                             << castExprType << br;

      addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
                                   castType, castExpr, realCast, "__bridge_transfer ",
                                   br ? "CFBridgingRelease" : nullptr);
    }

    return;
  }

  // Bridge from a CF type to an ARC type.
  if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
    bool br = S.isKnownName("CFBridgingRetain");
    S.Diag(loc, diag::err_arc_cast_requires_bridge)
      << convKindForDiag
      << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type
      << castExprType
      << 2 // to C pointer type
      << castType
      << castRange
      << castExpr->getSourceRange();
    ACCResult CreateRule =
      ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);
    assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
    if (CreateRule != ACC_plusOne)
    {
      auto DiagB = (CCK != Sema::CCK_OtherCast)
                       ? S.Diag(noteLoc, diag::note_arc_bridge)
                       : S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
      addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
                                   castType, castExpr, realCast, "__bridge ",
                                   nullptr);
    }
    if (CreateRule != ACC_plusZero)
    {
      auto DiagB = (CCK == Sema::CCK_OtherCast && !br)
                       ? S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained)
                             << castType
                       : S.Diag(br ? castExpr->getExprLoc() : noteLoc,
                                diag::note_arc_bridge_retained)
                             << castType << br;

      addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
                                   castType, castExpr, realCast, "__bridge_retained ",
                                   br ? "CFBridgingRetain" : nullptr);
    }

    return;
  }

  S.Diag(loc, diag::err_arc_mismatched_cast)
    << !convKindForDiag
    << srcKind << castExprType << castType
    << castRange << castExpr->getSourceRange();
}

template <typename TB>
static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
                                  bool &HadTheAttribute, bool warn) {
  QualType T = castExpr->getType();
  HadTheAttribute = false;
  while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
    TypedefNameDecl *TDNDecl = TD->getDecl();
    if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
      if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
        HadTheAttribute = true;
        if (Parm->isStr("id"))
          return true;

        // Check for an existing type with this name.
        LookupResult R(S, DeclarationName(Parm), SourceLocation(),
                       Sema::LookupOrdinaryName);
        if (S.LookupName(R, S.TUScope)) {
          NamedDecl *Target = R.getFoundDecl();
          if (Target && isa<ObjCInterfaceDecl>(Target)) {
            ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Target);
            if (const ObjCObjectPointerType *InterfacePointerType =
                  castType->getAsObjCInterfacePointerType()) {
              ObjCInterfaceDecl *CastClass
                = InterfacePointerType->getObjectType()->getInterface();
              if ((CastClass == ExprClass) ||
                  (CastClass && CastClass->isSuperClassOf(ExprClass)))
                return true;
              if (warn)
                S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge)
                    << T << Target->getName() << castType->getPointeeType();
              return false;
            } else if (castType->isObjCIdType() ||
                       (S.Context.ObjCObjectAdoptsQTypeProtocols(
                          castType, ExprClass)))
              // ok to cast to 'id'.
              // casting to id<p-list> is ok if bridge type adopts all of
              // p-list protocols.
              return true;
            else {
              if (warn) {
                S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge)
                    << T << Target->getName() << castType;
                S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
                S.Diag(Target->getBeginLoc(), diag::note_declared_at);
              }
              return false;
           }
          }
        } else if (!castType->isObjCIdType()) {
          S.Diag(castExpr->getBeginLoc(),
                 diag::err_objc_cf_bridged_not_interface)
              << castExpr->getType() << Parm;
          S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
        }
        return true;
      }
      return false;
    }
    T = TDNDecl->getUnderlyingType();
  }
  return true;
}

template <typename TB>
static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,
                                  bool &HadTheAttribute, bool warn) {
  QualType T = castType;
  HadTheAttribute = false;
  while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
    TypedefNameDecl *TDNDecl = TD->getDecl();
    if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
      if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
        HadTheAttribute = true;
        if (Parm->isStr("id"))
          return true;

        NamedDecl *Target = nullptr;
        // Check for an existing type with this name.
        LookupResult R(S, DeclarationName(Parm), SourceLocation(),
                       Sema::LookupOrdinaryName);
        if (S.LookupName(R, S.TUScope)) {
          Target = R.getFoundDecl();
          if (Target && isa<ObjCInterfaceDecl>(Target)) {
            ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target);
            if (const ObjCObjectPointerType *InterfacePointerType =
                  castExpr->getType()->getAsObjCInterfacePointerType()) {
              ObjCInterfaceDecl *ExprClass
                = InterfacePointerType->getObjectType()->getInterface();
              if ((CastClass == ExprClass) ||
                  (ExprClass && CastClass->isSuperClassOf(ExprClass)))
                return true;
              if (warn) {
                S.Diag(castExpr->getBeginLoc(),
                       diag::warn_objc_invalid_bridge_to_cf)
                    << castExpr->getType()->getPointeeType() << T;
                S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
              }
              return false;
            } else if (castExpr->getType()->isObjCIdType() ||
                       (S.Context.QIdProtocolsAdoptObjCObjectProtocols(
                          castExpr->getType(), CastClass)))
              // ok to cast an 'id' expression to a CFtype.
              // ok to cast an 'id<plist>' expression to CFtype provided plist
              // adopts all of CFtype's ObjetiveC's class plist.
              return true;
            else {
              if (warn) {
                S.Diag(castExpr->getBeginLoc(),
                       diag::warn_objc_invalid_bridge_to_cf)
                    << castExpr->getType() << castType;
                S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
                S.Diag(Target->getBeginLoc(), diag::note_declared_at);
              }
              return false;
            }
          }
        }
        S.Diag(castExpr->getBeginLoc(),
               diag::err_objc_ns_bridged_invalid_cfobject)
            << castExpr->getType() << castType;
        S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
        if (Target)
          S.Diag(Target->getBeginLoc(), diag::note_declared_at);
        return true;
      }
      return false;
    }
    T = TDNDecl->getUnderlyingType();
  }
  return true;
}

void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
  if (!getLangOpts().ObjC)
    return;
  // warn in presence of __bridge casting to or from a toll free bridge cast.
  ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType());
  ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);
  if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) {
    bool HasObjCBridgeAttr;
    bool ObjCBridgeAttrWillNotWarn =
      CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
                                            false);
    if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)
      return;
    bool HasObjCBridgeMutableAttr;
    bool ObjCBridgeMutableAttrWillNotWarn =
      CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr,
                                                   HasObjCBridgeMutableAttr, false);
    if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)
      return;

    if (HasObjCBridgeAttr)
      CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
                                            true);
    else if (HasObjCBridgeMutableAttr)
      CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr,
                                                   HasObjCBridgeMutableAttr, true);
  }
  else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) {
    bool HasObjCBridgeAttr;
    bool ObjCBridgeAttrWillNotWarn =
      CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
                                            false);
    if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)
      return;
    bool HasObjCBridgeMutableAttr;
    bool ObjCBridgeMutableAttrWillNotWarn =
      CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr,
                                                   HasObjCBridgeMutableAttr, false);
    if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)
      return;

    if (HasObjCBridgeAttr)
      CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr,
                                            true);
    else if (HasObjCBridgeMutableAttr)
      CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr,
                                                   HasObjCBridgeMutableAttr, true);
  }
}

void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) {
  QualType SrcType = castExpr->getType();
  if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(castExpr)) {
    if (PRE->isExplicitProperty()) {
      if (ObjCPropertyDecl *PDecl = PRE->getExplicitProperty())
        SrcType = PDecl->getType();
    }
    else if (PRE->isImplicitProperty()) {
      if (ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter())
        SrcType = Getter->getReturnType();
    }
  }

  ARCConversionTypeClass srcExprACTC = classifyTypeForARCConversion(SrcType);
  ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType);
  if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation)
    return;
  CheckObjCBridgeRelatedConversions(castExpr->getBeginLoc(), castType, SrcType,
                                    castExpr);
}

bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
                                         CastKind &Kind) {
  if (!getLangOpts().ObjC)
    return false;
  ARCConversionTypeClass exprACTC =
    classifyTypeForARCConversion(castExpr->getType());
  ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);
  if ((castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) ||
      (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable)) {
    CheckTollFreeBridgeCast(castType, castExpr);
    Kind = (castACTC == ACTC_coreFoundation) ? CK_BitCast
                                             : CK_CPointerToObjCPointerCast;
    return true;
  }
  return false;
}

bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
                                            QualType DestType, QualType SrcType,
                                            ObjCInterfaceDecl *&RelatedClass,
                                            ObjCMethodDecl *&ClassMethod,
                                            ObjCMethodDecl *&InstanceMethod,
                                            TypedefNameDecl *&TDNDecl,
                                            bool CfToNs, bool Diagnose) {
  QualType T = CfToNs ? SrcType : DestType;
  ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl);
  if (!ObjCBAttr)
    return false;

  IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();
  IdentifierInfo *CMId = ObjCBAttr->getClassMethod();
  IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
  if (!RCId)
    return false;
  NamedDecl *Target = nullptr;
  // Check for an existing type with this name.
  LookupResult R(*this, DeclarationName(RCId), SourceLocation(),
                 Sema::LookupOrdinaryName);
  if (!LookupName(R, TUScope)) {
    if (Diagnose) {
      Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId
            << SrcType << DestType;
      Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
    }
    return false;
  }
  Target = R.getFoundDecl();
  if (Target && isa<ObjCInterfaceDecl>(Target))
    RelatedClass = cast<ObjCInterfaceDecl>(Target);
  else {
    if (Diagnose) {
      Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId
            << SrcType << DestType;
      Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
      if (Target)
        Diag(Target->getBeginLoc(), diag::note_declared_at);
    }
    return false;
  }

  // Check for an existing class method with the given selector name.
  if (CfToNs && CMId) {
    Selector Sel = Context.Selectors.getUnarySelector(CMId);
    ClassMethod = RelatedClass->lookupMethod(Sel, false);
    if (!ClassMethod) {
      if (Diagnose) {
        Diag(Loc, diag::err_objc_bridged_related_known_method)
              << SrcType << DestType << Sel << false;
        Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
      }
      return false;
    }
  }

  // Check for an existing instance method with the given selector name.
  if (!CfToNs && IMId) {
    Selector Sel = Context.Selectors.getNullarySelector(IMId);
    InstanceMethod = RelatedClass->lookupMethod(Sel, true);
    if (!InstanceMethod) {
      if (Diagnose) {
        Diag(Loc, diag::err_objc_bridged_related_known_method)
              << SrcType << DestType << Sel << true;
        Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
      }
      return false;
    }
  }
  return true;
}

bool
Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
                                        QualType DestType, QualType SrcType,
                                        Expr *&SrcExpr, bool Diagnose) {
  ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType);
  ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType);
  bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);
  bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);
  if (!CfToNs && !NsToCf)
    return false;

  ObjCInterfaceDecl *RelatedClass;
  ObjCMethodDecl *ClassMethod = nullptr;
  ObjCMethodDecl *InstanceMethod = nullptr;
  TypedefNameDecl *TDNDecl = nullptr;
  if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,
                                        ClassMethod, InstanceMethod, TDNDecl,
                                        CfToNs, Diagnose))
    return false;

  if (CfToNs) {
    // Implicit conversion from CF to ObjC object is needed.
    if (ClassMethod) {
      if (Diagnose) {
        std::string ExpressionString = "[";
        ExpressionString += RelatedClass->getNameAsString();
        ExpressionString += " ";
        ExpressionString += ClassMethod->getSelector().getAsString();
        SourceLocation SrcExprEndLoc =
            getLocForEndOfToken(SrcExpr->getEndLoc());
        // Provide a fixit: [RelatedClass ClassMethod SrcExpr]
        Diag(Loc, diag::err_objc_bridged_related_known_method)
            << SrcType << DestType << ClassMethod->getSelector() << false
            << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(),
                                          ExpressionString)
            << FixItHint::CreateInsertion(SrcExprEndLoc, "]");
        Diag(RelatedClass->getBeginLoc(), diag::note_declared_at);
        Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);

        QualType receiverType = Context.getObjCInterfaceType(RelatedClass);
        // Argument.
        Expr *args[] = { SrcExpr };
        ExprResult msg = BuildClassMessageImplicit(receiverType, false,
                                      ClassMethod->getLocation(),
                                      ClassMethod->getSelector(), ClassMethod,
                                      MultiExprArg(args, 1));
        SrcExpr = msg.get();
      }
      return true;
    }
  }
  else {
    // Implicit conversion from ObjC type to CF object is needed.
    if (InstanceMethod) {
      if (Diagnose) {
        std::string ExpressionString;
        SourceLocation SrcExprEndLoc =
            getLocForEndOfToken(SrcExpr->getEndLoc());
        if (InstanceMethod->isPropertyAccessor())
          if (const ObjCPropertyDecl *PDecl =
                  InstanceMethod->findPropertyDecl()) {
            // fixit: ObjectExpr.propertyname when it is  aproperty accessor.
            ExpressionString = ".";
            ExpressionString += PDecl->getNameAsString();
            Diag(Loc, diag::err_objc_bridged_related_known_method)
                << SrcType << DestType << InstanceMethod->getSelector() << true
                << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
          }
        if (ExpressionString.empty()) {
          // Provide a fixit: [ObjectExpr InstanceMethod]
          ExpressionString = " ";
          ExpressionString += InstanceMethod->getSelector().getAsString();
          ExpressionString += "]";

          Diag(Loc, diag::err_objc_bridged_related_known_method)
              << SrcType << DestType << InstanceMethod->getSelector() << true
              << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "[")
              << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
        }
        Diag(RelatedClass->getBeginLoc(), diag::note_declared_at);
        Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);

        ExprResult msg =
          BuildInstanceMessageImplicit(SrcExpr, SrcType,
                                       InstanceMethod->getLocation(),
                                       InstanceMethod->getSelector(),
                                       InstanceMethod, None);
        SrcExpr = msg.get();
      }
      return true;
    }
  }
  return false;
}

Sema::ARCConversionResult
Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
                          Expr *&castExpr, CheckedConversionKind CCK,
                          bool Diagnose, bool DiagnoseCFAudited,
                          BinaryOperatorKind Opc) {
  QualType castExprType = castExpr->getType();

  // For the purposes of the classification, we assume reference types
  // will bind to temporaries.
  QualType effCastType = castType;
  if (const ReferenceType *ref = castType->getAs<ReferenceType>())
    effCastType = ref->getPointeeType();

  ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType);
  ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType);
  if (exprACTC == castACTC) {
    // Check for viability and report error if casting an rvalue to a
    // life-time qualifier.
    if (castACTC == ACTC_retainable &&
        (CCK == CCK_CStyleCast || CCK == CCK_OtherCast) &&
        castType != castExprType) {
      const Type *DT = castType.getTypePtr();
      QualType QDT = castType;
      // We desugar some types but not others. We ignore those
      // that cannot happen in a cast; i.e. auto, and those which
      // should not be de-sugared; i.e typedef.
      if (const ParenType *PT = dyn_cast<ParenType>(DT))
        QDT = PT->desugar();
      else if (const TypeOfType *TP = dyn_cast<TypeOfType>(DT))
        QDT = TP->desugar();
      else if (const AttributedType *AT = dyn_cast<AttributedType>(DT))
        QDT = AT->desugar();
      if (QDT != castType &&
          QDT.getObjCLifetime() !=  Qualifiers::OCL_None) {
        if (Diagnose) {
          SourceLocation loc = (castRange.isValid() ? castRange.getBegin()
                                                    : castExpr->getExprLoc());
          Diag(loc, diag::err_arc_nolifetime_behavior);
        }
        return ACR_error;
      }
    }
    return ACR_okay;
  }

  // The life-time qualifier cast check above is all we need for ObjCWeak.
  // ObjCAutoRefCount has more restrictions on what is legal.
  if (!getLangOpts().ObjCAutoRefCount)
    return ACR_okay;

  if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay;

  // Allow all of these types to be cast to integer types (but not
  // vice-versa).
  if (castACTC == ACTC_none && castType->isIntegralType(Context))
    return ACR_okay;

  // Allow casts between pointers to lifetime types (e.g., __strong id*)
  // and pointers to void (e.g., cv void *). Casting from void* to lifetime*
  // must be explicit.
  // Allow conversions between pointers to lifetime types and coreFoundation
  // pointers too, but only when the conversions are explicit.
  if (exprACTC == ACTC_indirectRetainable &&
      (castACTC == ACTC_voidPtr ||
       (castACTC == ACTC_coreFoundation && isCast(CCK))))
    return ACR_okay;
  if (castACTC == ACTC_indirectRetainable &&
      (exprACTC == ACTC_voidPtr || exprACTC == ACTC_coreFoundation) &&
      isCast(CCK))
    return ACR_okay;

  switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
  // For invalid casts, fall through.
  case ACC_invalid:
    break;

  // Do nothing for both bottom and +0.
  case ACC_bottom:
  case ACC_plusZero:
    return ACR_okay;

  // If the result is +1, consume it here.
  case ACC_plusOne:
    castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),
                                        CK_ARCConsumeObject, castExpr, nullptr,
                                        VK_PRValue, FPOptionsOverride());
    Cleanup.setExprNeedsCleanups(true);
    return ACR_okay;
  }

  // If this is a non-implicit cast from id or block type to a
  // CoreFoundation type, delay complaining in case the cast is used
  // in an acceptable context.
  if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && isCast(CCK))
    return ACR_unbridged;

  // Issue a diagnostic about a missing @-sign when implicit casting a cstring
  // to 'NSString *', instead of falling through to report a "bridge cast"
  // diagnostic.
  if (castACTC == ACTC_retainable && exprACTC == ACTC_none &&
      CheckConversionToObjCLiteral(castType, castExpr, Diagnose))
    return ACR_error;

  // Do not issue "bridge cast" diagnostic when implicit casting
  // a retainable object to a CF type parameter belonging to an audited
  // CF API function. Let caller issue a normal type mismatched diagnostic
  // instead.
  if ((!DiagnoseCFAudited || exprACTC != ACTC_retainable ||
       castACTC != ACTC_coreFoundation) &&
      !(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable &&
        (Opc == BO_NE || Opc == BO_EQ))) {
    if (Diagnose)
      diagnoseObjCARCConversion(*this, castRange, castType, castACTC, castExpr,
                                castExpr, exprACTC, CCK);
    return ACR_error;
  }
  return ACR_okay;
}

/// Given that we saw an expression with the ARCUnbridgedCastTy
/// placeholder type, complain bitterly.
void Sema::diagnoseARCUnbridgedCast(Expr *e) {
  // We expect the spurious ImplicitCastExpr to already have been stripped.
  assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
  CastExpr *realCast = cast<CastExpr>(e->IgnoreParens());

  SourceRange castRange;
  QualType castType;
  CheckedConversionKind CCK;

  if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) {
    castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc());
    castType = cast->getTypeAsWritten();
    CCK = CCK_CStyleCast;
  } else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) {
    castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange();
    castType = cast->getTypeAsWritten();
    CCK = CCK_OtherCast;
  } else {
    llvm_unreachable("Unexpected ImplicitCastExpr");
  }

  ARCConversionTypeClass castACTC =
    classifyTypeForARCConversion(castType.getNonReferenceType());

  Expr *castExpr = realCast->getSubExpr();
  assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);

  diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
                            castExpr, realCast, ACTC_retainable, CCK);
}

/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast
/// type, remove the placeholder cast.
Expr *Sema::stripARCUnbridgedCast(Expr *e) {
  assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));

  if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) {
    Expr *sub = stripARCUnbridgedCast(pe->getSubExpr());
    return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub);
  } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {
    assert(uo->getOpcode() == UO_Extension);
    Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
    return UnaryOperator::Create(Context, sub, UO_Extension, sub->getType(),
                                 sub->getValueKind(), sub->getObjectKind(),
                                 uo->getOperatorLoc(), false,
                                 CurFPFeatureOverrides());
  } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
    assert(!gse->isResultDependent());

    unsigned n = gse->getNumAssocs();
    SmallVector<Expr *, 4> subExprs;
    SmallVector<TypeSourceInfo *, 4> subTypes;
    subExprs.reserve(n);
    subTypes.reserve(n);
    for (const GenericSelectionExpr::Association assoc : gse->associations()) {
      subTypes.push_back(assoc.getTypeSourceInfo());
      Expr *sub = assoc.getAssociationExpr();
      if (assoc.isSelected())
        sub = stripARCUnbridgedCast(sub);
      subExprs.push_back(sub);
    }

    return GenericSelectionExpr::Create(
        Context, gse->getGenericLoc(), gse->getControllingExpr(), subTypes,
        subExprs, gse->getDefaultLoc(), gse->getRParenLoc(),
        gse->containsUnexpandedParameterPack(), gse->getResultIndex());
  } else {
    assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!");
    return cast<ImplicitCastExpr>(e)->getSubExpr();
  }
}

bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,
                                                 QualType exprType) {
  QualType canCastType =
    Context.getCanonicalType(castType).getUnqualifiedType();
  QualType canExprType =
    Context.getCanonicalType(exprType).getUnqualifiedType();
  if (isa<ObjCObjectPointerType>(canCastType) &&
      castType.getObjCLifetime() == Qualifiers::OCL_Weak &&
      canExprType->isObjCObjectPointerType()) {
    if (const ObjCObjectPointerType *ObjT =
        canExprType->getAs<ObjCObjectPointerType>())
      if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl())
        return !ObjI->isArcWeakrefUnavailable();
  }
  return true;
}

/// Look for an ObjCReclaimReturnedObject cast and destroy it.
static Expr *maybeUndoReclaimObject(Expr *e) {
  Expr *curExpr = e, *prevExpr = nullptr;

  // Walk down the expression until we hit an implicit cast of kind
  // ARCReclaimReturnedObject or an Expr that is neither a Paren nor a Cast.
  while (true) {
    if (auto *pe = dyn_cast<ParenExpr>(curExpr)) {
      prevExpr = curExpr;
      curExpr = pe->getSubExpr();
      continue;
    }

    if (auto *ce = dyn_cast<CastExpr>(curExpr)) {
      if (auto *ice = dyn_cast<ImplicitCastExpr>(ce))
        if (ice->getCastKind() == CK_ARCReclaimReturnedObject) {
          if (!prevExpr)
            return ice->getSubExpr();
          if (auto *pe = dyn_cast<ParenExpr>(prevExpr))
            pe->setSubExpr(ice->getSubExpr());
          else
            cast<CastExpr>(prevExpr)->setSubExpr(ice->getSubExpr());
          return e;
        }

      prevExpr = curExpr;
      curExpr = ce->getSubExpr();
      continue;
    }

    // Break out of the loop if curExpr is neither a Paren nor a Cast.
    break;
  }

  return e;
}

ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
                                      ObjCBridgeCastKind Kind,
                                      SourceLocation BridgeKeywordLoc,
                                      TypeSourceInfo *TSInfo,
                                      Expr *SubExpr) {
  ExprResult SubResult = UsualUnaryConversions(SubExpr);
  if (SubResult.isInvalid()) return ExprError();
  SubExpr = SubResult.get();

  QualType T = TSInfo->getType();
  QualType FromType = SubExpr->getType();

  CastKind CK;

  bool MustConsume = false;
  if (T->isDependentType() || SubExpr->isTypeDependent()) {
    // Okay: we'll build a dependent expression type.
    CK = CK_Dependent;
  } else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) {
    // Casting CF -> id
    CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast
                                  : CK_CPointerToObjCPointerCast);
    switch (Kind) {
    case OBC_Bridge:
      break;

    case OBC_BridgeRetained: {
      bool br = isKnownName("CFBridgingRelease");
      Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
        << 2
        << FromType
        << (T->isBlockPointerType()? 1 : 0)
        << T
        << SubExpr->getSourceRange()
        << Kind;
      Diag(BridgeKeywordLoc, diag::note_arc_bridge)
        << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge");
      Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer)
        << FromType << br
        << FixItHint::CreateReplacement(BridgeKeywordLoc,
                                        br ? "CFBridgingRelease "
                                           : "__bridge_transfer ");

      Kind = OBC_Bridge;
      break;
    }

    case OBC_BridgeTransfer:
      // We must consume the Objective-C object produced by the cast.
      MustConsume = true;
      break;
    }
  } else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) {
    // Okay: id -> CF
    CK = CK_BitCast;
    switch (Kind) {
    case OBC_Bridge:
      // Reclaiming a value that's going to be __bridge-casted to CF
      // is very dangerous, so we don't do it.
      SubExpr = maybeUndoReclaimObject(SubExpr);
      break;

    case OBC_BridgeRetained:
      // Produce the object before casting it.
      SubExpr = ImplicitCastExpr::Create(Context, FromType, CK_ARCProduceObject,
                                         SubExpr, nullptr, VK_PRValue,
                                         FPOptionsOverride());
      break;

    case OBC_BridgeTransfer: {
      bool br = isKnownName("CFBridgingRetain");
      Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
        << (FromType->isBlockPointerType()? 1 : 0)
        << FromType
        << 2
        << T
        << SubExpr->getSourceRange()
        << Kind;

      Diag(BridgeKeywordLoc, diag::note_arc_bridge)
        << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge ");
      Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained)
        << T << br
        << FixItHint::CreateReplacement(BridgeKeywordLoc,
                          br ? "CFBridgingRetain " : "__bridge_retained");

      Kind = OBC_Bridge;
      break;
    }
    }
  } else {
    Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible)
      << FromType << T << Kind
      << SubExpr->getSourceRange()
      << TSInfo->getTypeLoc().getSourceRange();
    return ExprError();
  }

  Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK,
                                                   BridgeKeywordLoc,
                                                   TSInfo, SubExpr);

  if (MustConsume) {
    Cleanup.setExprNeedsCleanups(true);
    Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,
                                      nullptr, VK_PRValue, FPOptionsOverride());
  }

  return Result;
}

ExprResult Sema::ActOnObjCBridgedCast(Scope *S,
                                      SourceLocation LParenLoc,
                                      ObjCBridgeCastKind Kind,
                                      SourceLocation BridgeKeywordLoc,
                                      ParsedType Type,
                                      SourceLocation RParenLoc,
                                      Expr *SubExpr) {
  TypeSourceInfo *TSInfo = nullptr;
  QualType T = GetTypeFromParser(Type, &TSInfo);
  if (Kind == OBC_Bridge)
    CheckTollFreeBridgeCast(T, SubExpr);
  if (!TSInfo)
    TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc);
  return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,
                              SubExpr);
}
