//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for Objective-C expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#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/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 "llvm/ADT/SmallString.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),
        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,
                               /*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);
      }

      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,
              /*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,
                                               /*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,
          /*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));
}

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,
                           /*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));
  return MaybeBindToTemporary(ObjCDictionaryLiteral::Create(
      Context, Elements, HasPackExpansions, Ty,
      DictionaryWithObjectsMethod, SR));
}

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.CharTy;
    // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
    if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
      StrTy.addConst();
    StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
                                         ArrayType::Normal, 0);
  }

  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;
  }
}

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);

  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->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(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)
    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 (auto nullability = ReceiverType->getNullability(Context))
    receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);

  unsigned resultNullabilityIdx = 0;
  if (auto nullability = resultType->getNullability(Context))
    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(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 (ReceiverType->isObjCObjectPointerType()) {
        if (ObjCInterfaceDecl *ThisClass =
            ReceiverType->getAs<ObjCObjectPointerType>()->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_RValue;
    return false;
  }

  ReturnType = getMessageSendResultType(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>())
      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]->isRValue() && 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() & ObjCPropertyDecl::OBJC_PR_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.
  if (TypoCorrection Corrected =
          CorrectTypo(DeclarationNameInfo(MemberName, MemberLoc),
                      LookupOrdinaryName, nullptr, nullptr,
                      llvm::make_unique<DeclFilterCCC<ObjCPropertyDecl>>(),
                      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 : 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");
  }
};

} // 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;
  }
  }

  if (TypoCorrection Corrected = CorrectTypo(
          Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr,
          llvm::make_unique<ObjCInterfaceOrSuperCCC>(getCurMethodDecl()),
          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)) {
    DiagnosticBuilder 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()) {
    QualType Ret = ImpliedMethod->getReturnType();
    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_RValue, 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_RValue;

  unsigned NumArgs = ArgsIn.size();
  Expr **Args = ArgsIn.data();
  if (CheckMessageArgumentTypes(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();

  // 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_RValue, 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
        << Receiver->getSourceRange();
      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();
      }
    }
  }

  if (ReceiverType->isObjCIdType() && !isImplicit)
    Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id);

  // 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()) {
            // FIXME: Is this correct? Why are we assuming that a message to
            // Class will call a method in the current interface?

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

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

            if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, nullptr,
                                            false, false, ClassDecl))
              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,
                                Receiver? Receiver->getSourceRange()
                                        : SourceRange(SuperLoc))) {
          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 << Receiver->getSourceRange();
        return ExprError();
      }
    }
  }

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

  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_RValue;
  bool ClassMessage = (ReceiverType->isObjCClassType() ||
                       ReceiverType->isObjCQualifiedClassType());
  if (CheckMessageArgumentTypes(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() & ObjCPropertyDecl::OBJC_PR_weak;
        if (!IsWeak && Sel.isUnarySelector())
          IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;
        if (IsWeak &&
            !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);
}

static void addFixitForObjCARCConversion(Sema &S,
                                         DiagnosticBuilder &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::isIdentifierBodyChar(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::isIdentifierBodyChar(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>())
      if (RecordDecl *RD = RT->getDecl()->getMostRecentDecl())
        return RD->getAttr<T>();
  }
  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)
    {
      DiagnosticBuilder 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)
    {
      DiagnosticBuilder 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)
    {
      DiagnosticBuilder 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)
    {
      DiagnosticBuilder 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;

        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 *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);
          if (Target)
            S.Diag(Target->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().ObjC1)
    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().ObjC1)
    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.
  if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr)
    return ACR_okay;
  if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
      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_RValue);
    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 &&
      ConversionToObjCStringLiteralCheck(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 new (Context)
        UnaryOperator(sub, UO_Extension, sub->getType(), sub->getValueKind(),
                      sub->getObjectKind(), uo->getOperatorLoc(), false);
  } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
    assert(!gse->isResultDependent());

    unsigned n = gse->getNumAssocs();
    SmallVector<Expr*, 4> subExprs(n);
    SmallVector<TypeSourceInfo*, 4> subTypes(n);
    for (unsigned i = 0; i != n; ++i) {
      subTypes[i] = gse->getAssocTypeSourceInfo(i);
      Expr *sub = gse->getAssocExpr(i);
      if (i == gse->getResultIndex())
        sub = stripARCUnbridgedCast(sub);
      subExprs[i] = sub;
    }

    return new (Context) GenericSelectionExpr(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_RValue);
      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_RValue);
  }

  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);
}
