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

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

//===----------------------------------------------------------------------===//
// Sema Initialization Checking
//===----------------------------------------------------------------------===//

/// Check whether T is compatible with a wide character type (wchar_t,
/// char16_t or char32_t).
static bool IsWideCharCompatible(QualType T, ASTContext &Context) {
  if (Context.typesAreCompatible(Context.getWideCharType(), T))
    return true;
  if (Context.getLangOpts().CPlusPlus || Context.getLangOpts().C11) {
    return Context.typesAreCompatible(Context.Char16Ty, T) ||
           Context.typesAreCompatible(Context.Char32Ty, T);
  }
  return false;
}

enum StringInitFailureKind {
  SIF_None,
  SIF_NarrowStringIntoWideChar,
  SIF_WideStringIntoChar,
  SIF_IncompatWideStringIntoWideChar,
  SIF_UTF8StringIntoPlainChar,
  SIF_PlainStringIntoUTF8Char,
  SIF_Other
};

/// Check whether the array of type AT can be initialized by the Init
/// expression by means of string initialization. Returns SIF_None if so,
/// otherwise returns a StringInitFailureKind that describes why the
/// initialization would not work.
static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
                                          ASTContext &Context) {
  if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
    return SIF_Other;

  // See if this is a string literal or @encode.
  Init = Init->IgnoreParens();

  // Handle @encode, which is a narrow string.
  if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType())
    return SIF_None;

  // Otherwise we can only handle string literals.
  StringLiteral *SL = dyn_cast<StringLiteral>(Init);
  if (!SL)
    return SIF_Other;

  const QualType ElemTy =
      Context.getCanonicalType(AT->getElementType()).getUnqualifiedType();

  switch (SL->getKind()) {
  case StringLiteral::UTF8:
    // char8_t array can be initialized with a UTF-8 string.
    if (ElemTy->isChar8Type())
      return SIF_None;
    LLVM_FALLTHROUGH;
  case StringLiteral::Ascii:
    // char array can be initialized with a narrow string.
    // Only allow char x[] = "foo";  not char x[] = L"foo";
    if (ElemTy->isCharType())
      return (SL->getKind() == StringLiteral::UTF8 &&
              Context.getLangOpts().Char8)
                 ? SIF_UTF8StringIntoPlainChar
                 : SIF_None;
    if (ElemTy->isChar8Type())
      return SIF_PlainStringIntoUTF8Char;
    if (IsWideCharCompatible(ElemTy, Context))
      return SIF_NarrowStringIntoWideChar;
    return SIF_Other;
  // C99 6.7.8p15 (with correction from DR343), or C11 6.7.9p15:
  // "An array with element type compatible with a qualified or unqualified
  // version of wchar_t, char16_t, or char32_t may be initialized by a wide
  // string literal with the corresponding encoding prefix (L, u, or U,
  // respectively), optionally enclosed in braces.
  case StringLiteral::UTF16:
    if (Context.typesAreCompatible(Context.Char16Ty, ElemTy))
      return SIF_None;
    if (ElemTy->isCharType() || ElemTy->isChar8Type())
      return SIF_WideStringIntoChar;
    if (IsWideCharCompatible(ElemTy, Context))
      return SIF_IncompatWideStringIntoWideChar;
    return SIF_Other;
  case StringLiteral::UTF32:
    if (Context.typesAreCompatible(Context.Char32Ty, ElemTy))
      return SIF_None;
    if (ElemTy->isCharType() || ElemTy->isChar8Type())
      return SIF_WideStringIntoChar;
    if (IsWideCharCompatible(ElemTy, Context))
      return SIF_IncompatWideStringIntoWideChar;
    return SIF_Other;
  case StringLiteral::Wide:
    if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy))
      return SIF_None;
    if (ElemTy->isCharType() || ElemTy->isChar8Type())
      return SIF_WideStringIntoChar;
    if (IsWideCharCompatible(ElemTy, Context))
      return SIF_IncompatWideStringIntoWideChar;
    return SIF_Other;
  }

  llvm_unreachable("missed a StringLiteral kind?");
}

static StringInitFailureKind IsStringInit(Expr *init, QualType declType,
                                          ASTContext &Context) {
  const ArrayType *arrayType = Context.getAsArrayType(declType);
  if (!arrayType)
    return SIF_Other;
  return IsStringInit(init, arrayType, Context);
}

/// Update the type of a string literal, including any surrounding parentheses,
/// to match the type of the object which it is initializing.
static void updateStringLiteralType(Expr *E, QualType Ty) {
  while (true) {
    E->setType(Ty);
    E->setValueKind(VK_RValue);
    if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E)) {
      break;
    } else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
      E = PE->getSubExpr();
    } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
      assert(UO->getOpcode() == UO_Extension);
      E = UO->getSubExpr();
    } else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
      E = GSE->getResultExpr();
    } else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
      E = CE->getChosenSubExpr();
    } else {
      llvm_unreachable("unexpected expr in string literal init");
    }
  }
}

/// Fix a compound literal initializing an array so it's correctly marked
/// as an rvalue.
static void updateGNUCompoundLiteralRValue(Expr *E) {
  while (true) {
    E->setValueKind(VK_RValue);
    if (isa<CompoundLiteralExpr>(E)) {
      break;
    } else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
      E = PE->getSubExpr();
    } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
      assert(UO->getOpcode() == UO_Extension);
      E = UO->getSubExpr();
    } else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
      E = GSE->getResultExpr();
    } else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
      E = CE->getChosenSubExpr();
    } else {
      llvm_unreachable("unexpected expr in array compound literal init");
    }
  }
}

static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
                            Sema &S) {
  // Get the length of the string as parsed.
  auto *ConstantArrayTy =
      cast<ConstantArrayType>(Str->getType()->getAsArrayTypeUnsafe());
  uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue();

  if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
    // C99 6.7.8p14. We have an array of character type with unknown size
    // being initialized to a string literal.
    llvm::APInt ConstVal(32, StrLength);
    // Return a new array type (C99 6.7.8p22).
    DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
                                           ConstVal, nullptr,
                                           ArrayType::Normal, 0);
    updateStringLiteralType(Str, DeclT);
    return;
  }

  const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);

  // We have an array of character type with known size.  However,
  // the size may be smaller or larger than the string we are initializing.
  // FIXME: Avoid truncation for 64-bit length strings.
  if (S.getLangOpts().CPlusPlus) {
    if (StringLiteral *SL = dyn_cast<StringLiteral>(Str->IgnoreParens())) {
      // For Pascal strings it's OK to strip off the terminating null character,
      // so the example below is valid:
      //
      // unsigned char a[2] = "\pa";
      if (SL->isPascal())
        StrLength--;
    }

    // [dcl.init.string]p2
    if (StrLength > CAT->getSize().getZExtValue())
      S.Diag(Str->getBeginLoc(),
             diag::err_initializer_string_for_char_array_too_long)
          << Str->getSourceRange();
  } else {
    // C99 6.7.8p14.
    if (StrLength-1 > CAT->getSize().getZExtValue())
      S.Diag(Str->getBeginLoc(),
             diag::ext_initializer_string_for_char_array_too_long)
          << Str->getSourceRange();
  }

  // Set the type to the actual size that we are initializing.  If we have
  // something like:
  //   char x[1] = "foo";
  // then this will set the string literal's type to char[1].
  updateStringLiteralType(Str, DeclT);
}

//===----------------------------------------------------------------------===//
// Semantic checking for initializer lists.
//===----------------------------------------------------------------------===//

namespace {

/// Semantic checking for initializer lists.
///
/// The InitListChecker class contains a set of routines that each
/// handle the initialization of a certain kind of entity, e.g.,
/// arrays, vectors, struct/union types, scalars, etc. The
/// InitListChecker itself performs a recursive walk of the subobject
/// structure of the type to be initialized, while stepping through
/// the initializer list one element at a time. The IList and Index
/// parameters to each of the Check* routines contain the active
/// (syntactic) initializer list and the index into that initializer
/// list that represents the current initializer. Each routine is
/// responsible for moving that Index forward as it consumes elements.
///
/// Each Check* routine also has a StructuredList/StructuredIndex
/// arguments, which contains the current "structured" (semantic)
/// initializer list and the index into that initializer list where we
/// are copying initializers as we map them over to the semantic
/// list. Once we have completed our recursive walk of the subobject
/// structure, we will have constructed a full semantic initializer
/// list.
///
/// C99 designators cause changes in the initializer list traversal,
/// because they make the initialization "jump" into a specific
/// subobject and then continue the initialization from that
/// point. CheckDesignatedInitializer() recursively steps into the
/// designated subobject and manages backing out the recursion to
/// initialize the subobjects after the one designated.
///
/// If an initializer list contains any designators, we build a placeholder
/// structured list even in 'verify only' mode, so that we can track which
/// elements need 'empty' initializtion.
class InitListChecker {
  Sema &SemaRef;
  bool hadError = false;
  bool VerifyOnly; // No diagnostics.
  bool TreatUnavailableAsInvalid; // Used only in VerifyOnly mode.
  bool InOverloadResolution;
  InitListExpr *FullyStructuredList = nullptr;
  NoInitExpr *DummyExpr = nullptr;

  NoInitExpr *getDummyInit() {
    if (!DummyExpr)
      DummyExpr = new (SemaRef.Context) NoInitExpr(SemaRef.Context.VoidTy);
    return DummyExpr;
  }

  void CheckImplicitInitList(const InitializedEntity &Entity,
                             InitListExpr *ParentIList, QualType T,
                             unsigned &Index, InitListExpr *StructuredList,
                             unsigned &StructuredIndex);
  void CheckExplicitInitList(const InitializedEntity &Entity,
                             InitListExpr *IList, QualType &T,
                             InitListExpr *StructuredList,
                             bool TopLevelObject = false);
  void CheckListElementTypes(const InitializedEntity &Entity,
                             InitListExpr *IList, QualType &DeclType,
                             bool SubobjectIsDesignatorContext,
                             unsigned &Index,
                             InitListExpr *StructuredList,
                             unsigned &StructuredIndex,
                             bool TopLevelObject = false);
  void CheckSubElementType(const InitializedEntity &Entity,
                           InitListExpr *IList, QualType ElemType,
                           unsigned &Index,
                           InitListExpr *StructuredList,
                           unsigned &StructuredIndex);
  void CheckComplexType(const InitializedEntity &Entity,
                        InitListExpr *IList, QualType DeclType,
                        unsigned &Index,
                        InitListExpr *StructuredList,
                        unsigned &StructuredIndex);
  void CheckScalarType(const InitializedEntity &Entity,
                       InitListExpr *IList, QualType DeclType,
                       unsigned &Index,
                       InitListExpr *StructuredList,
                       unsigned &StructuredIndex);
  void CheckReferenceType(const InitializedEntity &Entity,
                          InitListExpr *IList, QualType DeclType,
                          unsigned &Index,
                          InitListExpr *StructuredList,
                          unsigned &StructuredIndex);
  void CheckVectorType(const InitializedEntity &Entity,
                       InitListExpr *IList, QualType DeclType, unsigned &Index,
                       InitListExpr *StructuredList,
                       unsigned &StructuredIndex);
  void CheckStructUnionTypes(const InitializedEntity &Entity,
                             InitListExpr *IList, QualType DeclType,
                             CXXRecordDecl::base_class_range Bases,
                             RecordDecl::field_iterator Field,
                             bool SubobjectIsDesignatorContext, unsigned &Index,
                             InitListExpr *StructuredList,
                             unsigned &StructuredIndex,
                             bool TopLevelObject = false);
  void CheckArrayType(const InitializedEntity &Entity,
                      InitListExpr *IList, QualType &DeclType,
                      llvm::APSInt elementIndex,
                      bool SubobjectIsDesignatorContext, unsigned &Index,
                      InitListExpr *StructuredList,
                      unsigned &StructuredIndex);
  bool CheckDesignatedInitializer(const InitializedEntity &Entity,
                                  InitListExpr *IList, DesignatedInitExpr *DIE,
                                  unsigned DesigIdx,
                                  QualType &CurrentObjectType,
                                  RecordDecl::field_iterator *NextField,
                                  llvm::APSInt *NextElementIndex,
                                  unsigned &Index,
                                  InitListExpr *StructuredList,
                                  unsigned &StructuredIndex,
                                  bool FinishSubobjectInit,
                                  bool TopLevelObject);
  InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
                                           QualType CurrentObjectType,
                                           InitListExpr *StructuredList,
                                           unsigned StructuredIndex,
                                           SourceRange InitRange,
                                           bool IsFullyOverwritten = false);
  void UpdateStructuredListElement(InitListExpr *StructuredList,
                                   unsigned &StructuredIndex,
                                   Expr *expr);
  InitListExpr *createInitListExpr(QualType CurrentObjectType,
                                   SourceRange InitRange,
                                   unsigned ExpectedNumInits);
  int numArrayElements(QualType DeclType);
  int numStructUnionElements(QualType DeclType);

  ExprResult PerformEmptyInit(SourceLocation Loc,
                              const InitializedEntity &Entity);

  /// Diagnose that OldInit (or part thereof) has been overridden by NewInit.
  void diagnoseInitOverride(Expr *OldInit, SourceRange NewInitRange,
                            bool FullyOverwritten = true) {
    // Overriding an initializer via a designator is valid with C99 designated
    // initializers, but ill-formed with C++20 designated initializers.
    unsigned DiagID = SemaRef.getLangOpts().CPlusPlus
                          ? diag::ext_initializer_overrides
                          : diag::warn_initializer_overrides;

    if (InOverloadResolution && SemaRef.getLangOpts().CPlusPlus) {
      // In overload resolution, we have to strictly enforce the rules, and so
      // don't allow any overriding of prior initializers. This matters for a
      // case such as:
      //
      //   union U { int a, b; };
      //   struct S { int a, b; };
      //   void f(U), f(S);
      //
      // Here, f({.a = 1, .b = 2}) is required to call the struct overload. For
      // consistency, we disallow all overriding of prior initializers in
      // overload resolution, not only overriding of union members.
      hadError = true;
    } else if (OldInit->getType().isDestructedType() && !FullyOverwritten) {
      // If we'll be keeping around the old initializer but overwriting part of
      // the object it initialized, and that object is not trivially
      // destructible, this can leak. Don't allow that, not even as an
      // extension.
      //
      // FIXME: It might be reasonable to allow this in cases where the part of
      // the initializer that we're overriding has trivial destruction.
      DiagID = diag::err_initializer_overrides_destructed;
    } else if (!OldInit->getSourceRange().isValid()) {
      // We need to check on source range validity because the previous
      // initializer does not have to be an explicit initializer. e.g.,
      //
      // struct P { int a, b; };
      // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 };
      //
      // There is an overwrite taking place because the first braced initializer
      // list "{ .a = 2 }" already provides value for .p.b (which is zero).
      //
      // Such overwrites are harmless, so we don't diagnose them. (Note that in
      // C++, this cannot be reached unless we've already seen and diagnosed a
      // different conformance issue, such as a mixture of designated and
      // non-designated initializers or a multi-level designator.)
      return;
    }

    if (!VerifyOnly) {
      SemaRef.Diag(NewInitRange.getBegin(), DiagID)
          << NewInitRange << FullyOverwritten << OldInit->getType();
      SemaRef.Diag(OldInit->getBeginLoc(), diag::note_previous_initializer)
          << (OldInit->HasSideEffects(SemaRef.Context) && FullyOverwritten)
          << OldInit->getSourceRange();
    }
  }

  // Explanation on the "FillWithNoInit" mode:
  //
  // Assume we have the following definitions (Case#1):
  // struct P { char x[6][6]; } xp = { .x[1] = "bar" };
  // struct PP { struct P lp; } l = { .lp = xp, .lp.x[1][2] = 'f' };
  //
  // l.lp.x[1][0..1] should not be filled with implicit initializers because the
  // "base" initializer "xp" will provide values for them; l.lp.x[1] will be "baf".
  //
  // But if we have (Case#2):
  // struct PP l = { .lp = xp, .lp.x[1] = { [2] = 'f' } };
  //
  // l.lp.x[1][0..1] are implicitly initialized and do not use values from the
  // "base" initializer; l.lp.x[1] will be "\0\0f\0\0\0".
  //
  // To distinguish Case#1 from Case#2, and also to avoid leaving many "holes"
  // in the InitListExpr, the "holes" in Case#1 are filled not with empty
  // initializers but with special "NoInitExpr" place holders, which tells the
  // CodeGen not to generate any initializers for these parts.
  void FillInEmptyInitForBase(unsigned Init, const CXXBaseSpecifier &Base,
                              const InitializedEntity &ParentEntity,
                              InitListExpr *ILE, bool &RequiresSecondPass,
                              bool FillWithNoInit);
  void FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
                               const InitializedEntity &ParentEntity,
                               InitListExpr *ILE, bool &RequiresSecondPass,
                               bool FillWithNoInit = false);
  void FillInEmptyInitializations(const InitializedEntity &Entity,
                                  InitListExpr *ILE, bool &RequiresSecondPass,
                                  InitListExpr *OuterILE, unsigned OuterIndex,
                                  bool FillWithNoInit = false);
  bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
                              Expr *InitExpr, FieldDecl *Field,
                              bool TopLevelObject);
  void CheckEmptyInitializable(const InitializedEntity &Entity,
                               SourceLocation Loc);

public:
  InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL,
                  QualType &T, bool VerifyOnly, bool TreatUnavailableAsInvalid,
                  bool InOverloadResolution = false);
  bool HadError() { return hadError; }

  // Retrieves the fully-structured initializer list used for
  // semantic analysis and code generation.
  InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
};

} // end anonymous namespace

ExprResult InitListChecker::PerformEmptyInit(SourceLocation Loc,
                                             const InitializedEntity &Entity) {
  InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
                                                            true);
  MultiExprArg SubInit;
  Expr *InitExpr;
  InitListExpr DummyInitList(SemaRef.Context, Loc, None, Loc);

  // C++ [dcl.init.aggr]p7:
  //   If there are fewer initializer-clauses in the list than there are
  //   members in the aggregate, then each member not explicitly initialized
  //   ...
  bool EmptyInitList = SemaRef.getLangOpts().CPlusPlus11 &&
      Entity.getType()->getBaseElementTypeUnsafe()->isRecordType();
  if (EmptyInitList) {
    // C++1y / DR1070:
    //   shall be initialized [...] from an empty initializer list.
    //
    // We apply the resolution of this DR to C++11 but not C++98, since C++98
    // does not have useful semantics for initialization from an init list.
    // We treat this as copy-initialization, because aggregate initialization
    // always performs copy-initialization on its elements.
    //
    // Only do this if we're initializing a class type, to avoid filling in
    // the initializer list where possible.
    InitExpr = VerifyOnly ? &DummyInitList : new (SemaRef.Context)
                   InitListExpr(SemaRef.Context, Loc, None, Loc);
    InitExpr->setType(SemaRef.Context.VoidTy);
    SubInit = InitExpr;
    Kind = InitializationKind::CreateCopy(Loc, Loc);
  } else {
    // C++03:
    //   shall be value-initialized.
  }

  InitializationSequence InitSeq(SemaRef, Entity, Kind, SubInit);
  // libstdc++4.6 marks the vector default constructor as explicit in
  // _GLIBCXX_DEBUG mode, so recover using the C++03 logic in that case.
  // stlport does so too. Look for std::__debug for libstdc++, and for
  // std:: for stlport.  This is effectively a compiler-side implementation of
  // LWG2193.
  if (!InitSeq && EmptyInitList && InitSeq.getFailureKind() ==
          InitializationSequence::FK_ExplicitConstructor) {
    OverloadCandidateSet::iterator Best;
    OverloadingResult O =
        InitSeq.getFailedCandidateSet()
            .BestViableFunction(SemaRef, Kind.getLocation(), Best);
    (void)O;
    assert(O == OR_Success && "Inconsistent overload resolution");
    CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
    CXXRecordDecl *R = CtorDecl->getParent();

    if (CtorDecl->getMinRequiredArguments() == 0 &&
        CtorDecl->isExplicit() && R->getDeclName() &&
        SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) {
      bool IsInStd = false;
      for (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(R->getDeclContext());
           ND && !IsInStd; ND = dyn_cast<NamespaceDecl>(ND->getParent())) {
        if (SemaRef.getStdNamespace()->InEnclosingNamespaceSetOf(ND))
          IsInStd = true;
      }

      if (IsInStd && llvm::StringSwitch<bool>(R->getName())
              .Cases("basic_string", "deque", "forward_list", true)
              .Cases("list", "map", "multimap", "multiset", true)
              .Cases("priority_queue", "queue", "set", "stack", true)
              .Cases("unordered_map", "unordered_set", "vector", true)
              .Default(false)) {
        InitSeq.InitializeFrom(
            SemaRef, Entity,
            InitializationKind::CreateValue(Loc, Loc, Loc, true),
            MultiExprArg(), /*TopLevelOfInitList=*/false,
            TreatUnavailableAsInvalid);
        // Emit a warning for this.  System header warnings aren't shown
        // by default, but people working on system headers should see it.
        if (!VerifyOnly) {
          SemaRef.Diag(CtorDecl->getLocation(),
                       diag::warn_invalid_initializer_from_system_header);
          if (Entity.getKind() == InitializedEntity::EK_Member)
            SemaRef.Diag(Entity.getDecl()->getLocation(),
                         diag::note_used_in_initialization_here);
          else if (Entity.getKind() == InitializedEntity::EK_ArrayElement)
            SemaRef.Diag(Loc, diag::note_used_in_initialization_here);
        }
      }
    }
  }
  if (!InitSeq) {
    if (!VerifyOnly) {
      InitSeq.Diagnose(SemaRef, Entity, Kind, SubInit);
      if (Entity.getKind() == InitializedEntity::EK_Member)
        SemaRef.Diag(Entity.getDecl()->getLocation(),
                     diag::note_in_omitted_aggregate_initializer)
          << /*field*/1 << Entity.getDecl();
      else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) {
        bool IsTrailingArrayNewMember =
            Entity.getParent() &&
            Entity.getParent()->isVariableLengthArrayNew();
        SemaRef.Diag(Loc, diag::note_in_omitted_aggregate_initializer)
          << (IsTrailingArrayNewMember ? 2 : /*array element*/0)
          << Entity.getElementIndex();
      }
    }
    hadError = true;
    return ExprError();
  }

  return VerifyOnly ? ExprResult()
                    : InitSeq.Perform(SemaRef, Entity, Kind, SubInit);
}

void InitListChecker::CheckEmptyInitializable(const InitializedEntity &Entity,
                                              SourceLocation Loc) {
  // If we're building a fully-structured list, we'll check this at the end
  // once we know which elements are actually initialized. Otherwise, we know
  // that there are no designators so we can just check now.
  if (FullyStructuredList)
    return;
  PerformEmptyInit(Loc, Entity);
}

void InitListChecker::FillInEmptyInitForBase(
    unsigned Init, const CXXBaseSpecifier &Base,
    const InitializedEntity &ParentEntity, InitListExpr *ILE,
    bool &RequiresSecondPass, bool FillWithNoInit) {
  InitializedEntity BaseEntity = InitializedEntity::InitializeBase(
      SemaRef.Context, &Base, false, &ParentEntity);

  if (Init >= ILE->getNumInits() || !ILE->getInit(Init)) {
    ExprResult BaseInit = FillWithNoInit
                              ? new (SemaRef.Context) NoInitExpr(Base.getType())
                              : PerformEmptyInit(ILE->getEndLoc(), BaseEntity);
    if (BaseInit.isInvalid()) {
      hadError = true;
      return;
    }

    if (!VerifyOnly) {
      assert(Init < ILE->getNumInits() && "should have been expanded");
      ILE->setInit(Init, BaseInit.getAs<Expr>());
    }
  } else if (InitListExpr *InnerILE =
                 dyn_cast<InitListExpr>(ILE->getInit(Init))) {
    FillInEmptyInitializations(BaseEntity, InnerILE, RequiresSecondPass,
                               ILE, Init, FillWithNoInit);
  } else if (DesignatedInitUpdateExpr *InnerDIUE =
               dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init))) {
    FillInEmptyInitializations(BaseEntity, InnerDIUE->getUpdater(),
                               RequiresSecondPass, ILE, Init,
                               /*FillWithNoInit =*/true);
  }
}

void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
                                        const InitializedEntity &ParentEntity,
                                              InitListExpr *ILE,
                                              bool &RequiresSecondPass,
                                              bool FillWithNoInit) {
  SourceLocation Loc = ILE->getEndLoc();
  unsigned NumInits = ILE->getNumInits();
  InitializedEntity MemberEntity
    = InitializedEntity::InitializeMember(Field, &ParentEntity);

  if (Init >= NumInits || !ILE->getInit(Init)) {
    if (const RecordType *RType = ILE->getType()->getAs<RecordType>())
      if (!RType->getDecl()->isUnion())
        assert((Init < NumInits || VerifyOnly) &&
               "This ILE should have been expanded");

    if (FillWithNoInit) {
      assert(!VerifyOnly && "should not fill with no-init in verify-only mode");
      Expr *Filler = new (SemaRef.Context) NoInitExpr(Field->getType());
      if (Init < NumInits)
        ILE->setInit(Init, Filler);
      else
        ILE->updateInit(SemaRef.Context, Init, Filler);
      return;
    }
    // C++1y [dcl.init.aggr]p7:
    //   If there are fewer initializer-clauses in the list than there are
    //   members in the aggregate, then each member not explicitly initialized
    //   shall be initialized from its brace-or-equal-initializer [...]
    if (Field->hasInClassInitializer()) {
      if (VerifyOnly)
        return;

      ExprResult DIE = SemaRef.BuildCXXDefaultInitExpr(Loc, Field);
      if (DIE.isInvalid()) {
        hadError = true;
        return;
      }
      SemaRef.checkInitializerLifetime(MemberEntity, DIE.get());
      if (Init < NumInits)
        ILE->setInit(Init, DIE.get());
      else {
        ILE->updateInit(SemaRef.Context, Init, DIE.get());
        RequiresSecondPass = true;
      }
      return;
    }

    if (Field->getType()->isReferenceType()) {
      if (!VerifyOnly) {
        // C++ [dcl.init.aggr]p9:
        //   If an incomplete or empty initializer-list leaves a
        //   member of reference type uninitialized, the program is
        //   ill-formed.
        SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
          << Field->getType()
          << ILE->getSyntacticForm()->getSourceRange();
        SemaRef.Diag(Field->getLocation(),
                     diag::note_uninit_reference_member);
      }
      hadError = true;
      return;
    }

    ExprResult MemberInit = PerformEmptyInit(Loc, MemberEntity);
    if (MemberInit.isInvalid()) {
      hadError = true;
      return;
    }

    if (hadError || VerifyOnly) {
      // Do nothing
    } else if (Init < NumInits) {
      ILE->setInit(Init, MemberInit.getAs<Expr>());
    } else if (!isa<ImplicitValueInitExpr>(MemberInit.get())) {
      // Empty initialization requires a constructor call, so
      // extend the initializer list to include the constructor
      // call and make a note that we'll need to take another pass
      // through the initializer list.
      ILE->updateInit(SemaRef.Context, Init, MemberInit.getAs<Expr>());
      RequiresSecondPass = true;
    }
  } else if (InitListExpr *InnerILE
               = dyn_cast<InitListExpr>(ILE->getInit(Init))) {
    FillInEmptyInitializations(MemberEntity, InnerILE,
                               RequiresSecondPass, ILE, Init, FillWithNoInit);
  } else if (DesignatedInitUpdateExpr *InnerDIUE =
                 dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init))) {
    FillInEmptyInitializations(MemberEntity, InnerDIUE->getUpdater(),
                               RequiresSecondPass, ILE, Init,
                               /*FillWithNoInit =*/true);
  }
}

/// Recursively replaces NULL values within the given initializer list
/// with expressions that perform value-initialization of the
/// appropriate type, and finish off the InitListExpr formation.
void
InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
                                            InitListExpr *ILE,
                                            bool &RequiresSecondPass,
                                            InitListExpr *OuterILE,
                                            unsigned OuterIndex,
                                            bool FillWithNoInit) {
  assert((ILE->getType() != SemaRef.Context.VoidTy) &&
         "Should not have void type");

  // We don't need to do any checks when just filling NoInitExprs; that can't
  // fail.
  if (FillWithNoInit && VerifyOnly)
    return;

  // If this is a nested initializer list, we might have changed its contents
  // (and therefore some of its properties, such as instantiation-dependence)
  // while filling it in. Inform the outer initializer list so that its state
  // can be updated to match.
  // FIXME: We should fully build the inner initializers before constructing
  // the outer InitListExpr instead of mutating AST nodes after they have
  // been used as subexpressions of other nodes.
  struct UpdateOuterILEWithUpdatedInit {
    InitListExpr *Outer;
    unsigned OuterIndex;
    ~UpdateOuterILEWithUpdatedInit() {
      if (Outer)
        Outer->setInit(OuterIndex, Outer->getInit(OuterIndex));
    }
  } UpdateOuterRAII = {OuterILE, OuterIndex};

  // A transparent ILE is not performing aggregate initialization and should
  // not be filled in.
  if (ILE->isTransparent())
    return;

  if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
    const RecordDecl *RDecl = RType->getDecl();
    if (RDecl->isUnion() && ILE->getInitializedFieldInUnion())
      FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(),
                              Entity, ILE, RequiresSecondPass, FillWithNoInit);
    else if (RDecl->isUnion() && isa<CXXRecordDecl>(RDecl) &&
             cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) {
      for (auto *Field : RDecl->fields()) {
        if (Field->hasInClassInitializer()) {
          FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass,
                                  FillWithNoInit);
          break;
        }
      }
    } else {
      // The fields beyond ILE->getNumInits() are default initialized, so in
      // order to leave them uninitialized, the ILE is expanded and the extra
      // fields are then filled with NoInitExpr.
      unsigned NumElems = numStructUnionElements(ILE->getType());
      if (RDecl->hasFlexibleArrayMember())
        ++NumElems;
      if (!VerifyOnly && ILE->getNumInits() < NumElems)
        ILE->resizeInits(SemaRef.Context, NumElems);

      unsigned Init = 0;

      if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RDecl)) {
        for (auto &Base : CXXRD->bases()) {
          if (hadError)
            return;

          FillInEmptyInitForBase(Init, Base, Entity, ILE, RequiresSecondPass,
                                 FillWithNoInit);
          ++Init;
        }
      }

      for (auto *Field : RDecl->fields()) {
        if (Field->isUnnamedBitfield())
          continue;

        if (hadError)
          return;

        FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass,
                                FillWithNoInit);
        if (hadError)
          return;

        ++Init;

        // Only look at the first initialization of a union.
        if (RDecl->isUnion())
          break;
      }
    }

    return;
  }

  QualType ElementType;

  InitializedEntity ElementEntity = Entity;
  unsigned NumInits = ILE->getNumInits();
  unsigned NumElements = NumInits;
  if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
    ElementType = AType->getElementType();
    if (const auto *CAType = dyn_cast<ConstantArrayType>(AType))
      NumElements = CAType->getSize().getZExtValue();
    // For an array new with an unknown bound, ask for one additional element
    // in order to populate the array filler.
    if (Entity.isVariableLengthArrayNew())
      ++NumElements;
    ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
                                                         0, Entity);
  } else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
    ElementType = VType->getElementType();
    NumElements = VType->getNumElements();
    ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
                                                         0, Entity);
  } else
    ElementType = ILE->getType();

  bool SkipEmptyInitChecks = false;
  for (unsigned Init = 0; Init != NumElements; ++Init) {
    if (hadError)
      return;

    if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement ||
        ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
      ElementEntity.setElementIndex(Init);

    if (Init >= NumInits && (ILE->hasArrayFiller() || SkipEmptyInitChecks))
      return;

    Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr);
    if (!InitExpr && Init < NumInits && ILE->hasArrayFiller())
      ILE->setInit(Init, ILE->getArrayFiller());
    else if (!InitExpr && !ILE->hasArrayFiller()) {
      // In VerifyOnly mode, there's no point performing empty initialization
      // more than once.
      if (SkipEmptyInitChecks)
        continue;

      Expr *Filler = nullptr;

      if (FillWithNoInit)
        Filler = new (SemaRef.Context) NoInitExpr(ElementType);
      else {
        ExprResult ElementInit =
            PerformEmptyInit(ILE->getEndLoc(), ElementEntity);
        if (ElementInit.isInvalid()) {
          hadError = true;
          return;
        }

        Filler = ElementInit.getAs<Expr>();
      }

      if (hadError) {
        // Do nothing
      } else if (VerifyOnly) {
        SkipEmptyInitChecks = true;
      } else if (Init < NumInits) {
        // For arrays, just set the expression used for value-initialization
        // of the "holes" in the array.
        if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement)
          ILE->setArrayFiller(Filler);
        else
          ILE->setInit(Init, Filler);
      } else {
        // For arrays, just set the expression used for value-initialization
        // of the rest of elements and exit.
        if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) {
          ILE->setArrayFiller(Filler);
          return;
        }

        if (!isa<ImplicitValueInitExpr>(Filler) && !isa<NoInitExpr>(Filler)) {
          // Empty initialization requires a constructor call, so
          // extend the initializer list to include the constructor
          // call and make a note that we'll need to take another pass
          // through the initializer list.
          ILE->updateInit(SemaRef.Context, Init, Filler);
          RequiresSecondPass = true;
        }
      }
    } else if (InitListExpr *InnerILE
                 = dyn_cast_or_null<InitListExpr>(InitExpr)) {
      FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass,
                                 ILE, Init, FillWithNoInit);
    } else if (DesignatedInitUpdateExpr *InnerDIUE =
                   dyn_cast_or_null<DesignatedInitUpdateExpr>(InitExpr)) {
      FillInEmptyInitializations(ElementEntity, InnerDIUE->getUpdater(),
                                 RequiresSecondPass, ILE, Init,
                                 /*FillWithNoInit =*/true);
    }
  }
}

static bool hasAnyDesignatedInits(const InitListExpr *IL) {
  for (const Stmt *Init : *IL)
    if (Init && isa<DesignatedInitExpr>(Init))
      return true;
  return false;
}

InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
                                 InitListExpr *IL, QualType &T, bool VerifyOnly,
                                 bool TreatUnavailableAsInvalid,
                                 bool InOverloadResolution)
    : SemaRef(S), VerifyOnly(VerifyOnly),
      TreatUnavailableAsInvalid(TreatUnavailableAsInvalid),
      InOverloadResolution(InOverloadResolution) {
  if (!VerifyOnly || hasAnyDesignatedInits(IL)) {
    FullyStructuredList =
        createInitListExpr(T, IL->getSourceRange(), IL->getNumInits());

    // FIXME: Check that IL isn't already the semantic form of some other
    // InitListExpr. If it is, we'd create a broken AST.
    if (!VerifyOnly)
      FullyStructuredList->setSyntacticForm(IL);
  }

  CheckExplicitInitList(Entity, IL, T, FullyStructuredList,
                        /*TopLevelObject=*/true);

  if (!hadError && FullyStructuredList) {
    bool RequiresSecondPass = false;
    FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass,
                               /*OuterILE=*/nullptr, /*OuterIndex=*/0);
    if (RequiresSecondPass && !hadError)
      FillInEmptyInitializations(Entity, FullyStructuredList,
                                 RequiresSecondPass, nullptr, 0);
  }
}

int InitListChecker::numArrayElements(QualType DeclType) {
  // FIXME: use a proper constant
  int maxElements = 0x7FFFFFFF;
  if (const ConstantArrayType *CAT =
        SemaRef.Context.getAsConstantArrayType(DeclType)) {
    maxElements = static_cast<int>(CAT->getSize().getZExtValue());
  }
  return maxElements;
}

int InitListChecker::numStructUnionElements(QualType DeclType) {
  RecordDecl *structDecl = DeclType->castAs<RecordType>()->getDecl();
  int InitializableMembers = 0;
  if (auto *CXXRD = dyn_cast<CXXRecordDecl>(structDecl))
    InitializableMembers += CXXRD->getNumBases();
  for (const auto *Field : structDecl->fields())
    if (!Field->isUnnamedBitfield())
      ++InitializableMembers;

  if (structDecl->isUnion())
    return std::min(InitializableMembers, 1);
  return InitializableMembers - structDecl->hasFlexibleArrayMember();
}

/// Determine whether Entity is an entity for which it is idiomatic to elide
/// the braces in aggregate initialization.
static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) {
  // Recursive initialization of the one and only field within an aggregate
  // class is considered idiomatic. This case arises in particular for
  // initialization of std::array, where the C++ standard suggests the idiom of
  //
  //   std::array<T, N> arr = {1, 2, 3};
  //
  // (where std::array is an aggregate struct containing a single array field.

  // FIXME: Should aggregate initialization of a struct with a single
  // base class and no members also suppress the warning?
  if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent())
    return false;

  auto *ParentRD =
      Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
  if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD))
    if (CXXRD->getNumBases())
      return false;

  auto FieldIt = ParentRD->field_begin();
  assert(FieldIt != ParentRD->field_end() &&
         "no fields but have initializer for member?");
  return ++FieldIt == ParentRD->field_end();
}

/// Check whether the range of the initializer \p ParentIList from element
/// \p Index onwards can be used to initialize an object of type \p T. Update
/// \p Index to indicate how many elements of the list were consumed.
///
/// This also fills in \p StructuredList, from element \p StructuredIndex
/// onwards, with the fully-braced, desugared form of the initialization.
void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
                                            InitListExpr *ParentIList,
                                            QualType T, unsigned &Index,
                                            InitListExpr *StructuredList,
                                            unsigned &StructuredIndex) {
  int maxElements = 0;

  if (T->isArrayType())
    maxElements = numArrayElements(T);
  else if (T->isRecordType())
    maxElements = numStructUnionElements(T);
  else if (T->isVectorType())
    maxElements = T->castAs<VectorType>()->getNumElements();
  else
    llvm_unreachable("CheckImplicitInitList(): Illegal type");

  if (maxElements == 0) {
    if (!VerifyOnly)
      SemaRef.Diag(ParentIList->getInit(Index)->getBeginLoc(),
                   diag::err_implicit_empty_initializer);
    ++Index;
    hadError = true;
    return;
  }

  // Build a structured initializer list corresponding to this subobject.
  InitListExpr *StructuredSubobjectInitList = getStructuredSubobjectInit(
      ParentIList, Index, T, StructuredList, StructuredIndex,
      SourceRange(ParentIList->getInit(Index)->getBeginLoc(),
                  ParentIList->getSourceRange().getEnd()));
  unsigned StructuredSubobjectInitIndex = 0;

  // Check the element types and build the structural subobject.
  unsigned StartIndex = Index;
  CheckListElementTypes(Entity, ParentIList, T,
                        /*SubobjectIsDesignatorContext=*/false, Index,
                        StructuredSubobjectInitList,
                        StructuredSubobjectInitIndex);

  if (StructuredSubobjectInitList) {
    StructuredSubobjectInitList->setType(T);

    unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
    // Update the structured sub-object initializer so that it's ending
    // range corresponds with the end of the last initializer it used.
    if (EndIndex < ParentIList->getNumInits() &&
        ParentIList->getInit(EndIndex)) {
      SourceLocation EndLoc
        = ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
      StructuredSubobjectInitList->setRBraceLoc(EndLoc);
    }

    // Complain about missing braces.
    if (!VerifyOnly && (T->isArrayType() || T->isRecordType()) &&
        !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
        !isIdiomaticBraceElisionEntity(Entity)) {
      SemaRef.Diag(StructuredSubobjectInitList->getBeginLoc(),
                   diag::warn_missing_braces)
          << StructuredSubobjectInitList->getSourceRange()
          << FixItHint::CreateInsertion(
                 StructuredSubobjectInitList->getBeginLoc(), "{")
          << FixItHint::CreateInsertion(
                 SemaRef.getLocForEndOfToken(
                     StructuredSubobjectInitList->getEndLoc()),
                 "}");
    }

    // Warn if this type won't be an aggregate in future versions of C++.
    auto *CXXRD = T->getAsCXXRecordDecl();
    if (!VerifyOnly && CXXRD && CXXRD->hasUserDeclaredConstructor()) {
      SemaRef.Diag(StructuredSubobjectInitList->getBeginLoc(),
                   diag::warn_cxx2a_compat_aggregate_init_with_ctors)
          << StructuredSubobjectInitList->getSourceRange() << T;
    }
  }
}

/// Warn that \p Entity was of scalar type and was initialized by a
/// single-element braced initializer list.
static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
                                 SourceRange Braces) {
  // Don't warn during template instantiation. If the initialization was
  // non-dependent, we warned during the initial parse; otherwise, the
  // type might not be scalar in some uses of the template.
  if (S.inTemplateInstantiation())
    return;

  unsigned DiagID = 0;

  switch (Entity.getKind()) {
  case InitializedEntity::EK_VectorElement:
  case InitializedEntity::EK_ComplexElement:
  case InitializedEntity::EK_ArrayElement:
  case InitializedEntity::EK_Parameter:
  case InitializedEntity::EK_Parameter_CF_Audited:
  case InitializedEntity::EK_Result:
    // Extra braces here are suspicious.
    DiagID = diag::warn_braces_around_scalar_init;
    break;

  case InitializedEntity::EK_Member:
    // Warn on aggregate initialization but not on ctor init list or
    // default member initializer.
    if (Entity.getParent())
      DiagID = diag::warn_braces_around_scalar_init;
    break;

  case InitializedEntity::EK_Variable:
  case InitializedEntity::EK_LambdaCapture:
    // No warning, might be direct-list-initialization.
    // FIXME: Should we warn for copy-list-initialization in these cases?
    break;

  case InitializedEntity::EK_New:
  case InitializedEntity::EK_Temporary:
  case InitializedEntity::EK_CompoundLiteralInit:
    // No warning, braces are part of the syntax of the underlying construct.
    break;

  case InitializedEntity::EK_RelatedResult:
    // No warning, we already warned when initializing the result.
    break;

  case InitializedEntity::EK_Exception:
  case InitializedEntity::EK_Base:
  case InitializedEntity::EK_Delegating:
  case InitializedEntity::EK_BlockElement:
  case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
  case InitializedEntity::EK_Binding:
  case InitializedEntity::EK_StmtExprResult:
    llvm_unreachable("unexpected braced scalar init");
  }

  if (DiagID) {
    S.Diag(Braces.getBegin(), DiagID)
      << Braces
      << FixItHint::CreateRemoval(Braces.getBegin())
      << FixItHint::CreateRemoval(Braces.getEnd());
  }
}

/// Check whether the initializer \p IList (that was written with explicit
/// braces) can be used to initialize an object of type \p T.
///
/// This also fills in \p StructuredList with the fully-braced, desugared
/// form of the initialization.
void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
                                            InitListExpr *IList, QualType &T,
                                            InitListExpr *StructuredList,
                                            bool TopLevelObject) {
  unsigned Index = 0, StructuredIndex = 0;
  CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
                        Index, StructuredList, StructuredIndex, TopLevelObject);
  if (StructuredList) {
    QualType ExprTy = T;
    if (!ExprTy->isArrayType())
      ExprTy = ExprTy.getNonLValueExprType(SemaRef.Context);
    if (!VerifyOnly)
      IList->setType(ExprTy);
    StructuredList->setType(ExprTy);
  }
  if (hadError)
    return;

  // Don't complain for incomplete types, since we'll get an error elsewhere.
  if (Index < IList->getNumInits() && !T->isIncompleteType()) {
    // We have leftover initializers
    bool ExtraInitsIsError = SemaRef.getLangOpts().CPlusPlus ||
          (SemaRef.getLangOpts().OpenCL && T->isVectorType());
    hadError = ExtraInitsIsError;
    if (VerifyOnly) {
      return;
    } else if (StructuredIndex == 1 &&
               IsStringInit(StructuredList->getInit(0), T, SemaRef.Context) ==
                   SIF_None) {
      unsigned DK =
          ExtraInitsIsError
              ? diag::err_excess_initializers_in_char_array_initializer
              : diag::ext_excess_initializers_in_char_array_initializer;
      SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
          << IList->getInit(Index)->getSourceRange();
    } else {
      int initKind = T->isArrayType() ? 0 :
                     T->isVectorType() ? 1 :
                     T->isScalarType() ? 2 :
                     T->isUnionType() ? 3 :
                     4;

      unsigned DK = ExtraInitsIsError ? diag::err_excess_initializers
                                      : diag::ext_excess_initializers;
      SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
          << initKind << IList->getInit(Index)->getSourceRange();
    }
  }

  if (!VerifyOnly) {
    if (T->isScalarType() && IList->getNumInits() == 1 &&
        !isa<InitListExpr>(IList->getInit(0)))
      warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange());

    // Warn if this is a class type that won't be an aggregate in future
    // versions of C++.
    auto *CXXRD = T->getAsCXXRecordDecl();
    if (CXXRD && CXXRD->hasUserDeclaredConstructor()) {
      // Don't warn if there's an equivalent default constructor that would be
      // used instead.
      bool HasEquivCtor = false;
      if (IList->getNumInits() == 0) {
        auto *CD = SemaRef.LookupDefaultConstructor(CXXRD);
        HasEquivCtor = CD && !CD->isDeleted();
      }

      if (!HasEquivCtor) {
        SemaRef.Diag(IList->getBeginLoc(),
                     diag::warn_cxx2a_compat_aggregate_init_with_ctors)
            << IList->getSourceRange() << T;
      }
    }
  }
}

void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
                                            InitListExpr *IList,
                                            QualType &DeclType,
                                            bool SubobjectIsDesignatorContext,
                                            unsigned &Index,
                                            InitListExpr *StructuredList,
                                            unsigned &StructuredIndex,
                                            bool TopLevelObject) {
  if (DeclType->isAnyComplexType() && SubobjectIsDesignatorContext) {
    // Explicitly braced initializer for complex type can be real+imaginary
    // parts.
    CheckComplexType(Entity, IList, DeclType, Index,
                     StructuredList, StructuredIndex);
  } else if (DeclType->isScalarType()) {
    CheckScalarType(Entity, IList, DeclType, Index,
                    StructuredList, StructuredIndex);
  } else if (DeclType->isVectorType()) {
    CheckVectorType(Entity, IList, DeclType, Index,
                    StructuredList, StructuredIndex);
  } else if (DeclType->isRecordType()) {
    assert(DeclType->isAggregateType() &&
           "non-aggregate records should be handed in CheckSubElementType");
    RecordDecl *RD = DeclType->castAs<RecordType>()->getDecl();
    auto Bases =
        CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(),
                                        CXXRecordDecl::base_class_iterator());
    if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
      Bases = CXXRD->bases();
    CheckStructUnionTypes(Entity, IList, DeclType, Bases, RD->field_begin(),
                          SubobjectIsDesignatorContext, Index, StructuredList,
                          StructuredIndex, TopLevelObject);
  } else if (DeclType->isArrayType()) {
    llvm::APSInt Zero(
                    SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
                    false);
    CheckArrayType(Entity, IList, DeclType, Zero,
                   SubobjectIsDesignatorContext, Index,
                   StructuredList, StructuredIndex);
  } else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
    // This type is invalid, issue a diagnostic.
    ++Index;
    if (!VerifyOnly)
      SemaRef.Diag(IList->getBeginLoc(), diag::err_illegal_initializer_type)
          << DeclType;
    hadError = true;
  } else if (DeclType->isReferenceType()) {
    CheckReferenceType(Entity, IList, DeclType, Index,
                       StructuredList, StructuredIndex);
  } else if (DeclType->isObjCObjectType()) {
    if (!VerifyOnly)
      SemaRef.Diag(IList->getBeginLoc(), diag::err_init_objc_class) << DeclType;
    hadError = true;
  } else if (DeclType->isOCLIntelSubgroupAVCType()) {
    // Checks for scalar type are sufficient for these types too.
    CheckScalarType(Entity, IList, DeclType, Index, StructuredList,
                    StructuredIndex);
  } else {
    if (!VerifyOnly)
      SemaRef.Diag(IList->getBeginLoc(), diag::err_illegal_initializer_type)
          << DeclType;
    hadError = true;
  }
}

void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
                                          InitListExpr *IList,
                                          QualType ElemType,
                                          unsigned &Index,
                                          InitListExpr *StructuredList,
                                          unsigned &StructuredIndex) {
  Expr *expr = IList->getInit(Index);

  if (ElemType->isReferenceType())
    return CheckReferenceType(Entity, IList, ElemType, Index,
                              StructuredList, StructuredIndex);

  if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
    if (SubInitList->getNumInits() == 1 &&
        IsStringInit(SubInitList->getInit(0), ElemType, SemaRef.Context) ==
        SIF_None) {
      // FIXME: It would be more faithful and no less correct to include an
      // InitListExpr in the semantic form of the initializer list in this case.
      expr = SubInitList->getInit(0);
    }
    // Nested aggregate initialization and C++ initialization are handled later.
  } else if (isa<ImplicitValueInitExpr>(expr)) {
    // This happens during template instantiation when we see an InitListExpr
    // that we've already checked once.
    assert(SemaRef.Context.hasSameType(expr->getType(), ElemType) &&
           "found implicit initialization for the wrong type");
    UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
    ++Index;
    return;
  }

  if (SemaRef.getLangOpts().CPlusPlus || isa<InitListExpr>(expr)) {
    // C++ [dcl.init.aggr]p2:
    //   Each member is copy-initialized from the corresponding
    //   initializer-clause.

    // FIXME: Better EqualLoc?
    InitializationKind Kind =
        InitializationKind::CreateCopy(expr->getBeginLoc(), SourceLocation());

    // Vector elements can be initialized from other vectors in which case
    // we need initialization entity with a type of a vector (and not a vector
    // element!) initializing multiple vector elements.
    auto TmpEntity =
        (ElemType->isExtVectorType() && !Entity.getType()->isExtVectorType())
            ? InitializedEntity::InitializeTemporary(ElemType)
            : Entity;

    InitializationSequence Seq(SemaRef, TmpEntity, Kind, expr,
                               /*TopLevelOfInitList*/ true);

    // C++14 [dcl.init.aggr]p13:
    //   If the assignment-expression can initialize a member, the member is
    //   initialized. Otherwise [...] brace elision is assumed
    //
    // Brace elision is never performed if the element is not an
    // assignment-expression.
    if (Seq || isa<InitListExpr>(expr)) {
      if (!VerifyOnly) {
        ExprResult Result = Seq.Perform(SemaRef, TmpEntity, Kind, expr);
        if (Result.isInvalid())
          hadError = true;

        UpdateStructuredListElement(StructuredList, StructuredIndex,
                                    Result.getAs<Expr>());
      } else if (!Seq) {
        hadError = true;
      } else if (StructuredList) {
        UpdateStructuredListElement(StructuredList, StructuredIndex,
                                    getDummyInit());
      }
      ++Index;
      return;
    }

    // Fall through for subaggregate initialization
  } else if (ElemType->isScalarType() || ElemType->isAtomicType()) {
    // FIXME: Need to handle atomic aggregate types with implicit init lists.
    return CheckScalarType(Entity, IList, ElemType, Index,
                           StructuredList, StructuredIndex);
  } else if (const ArrayType *arrayType =
                 SemaRef.Context.getAsArrayType(ElemType)) {
    // arrayType can be incomplete if we're initializing a flexible
    // array member.  There's nothing we can do with the completed
    // type here, though.

    if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
      // FIXME: Should we do this checking in verify-only mode?
      if (!VerifyOnly)
        CheckStringInit(expr, ElemType, arrayType, SemaRef);
      if (StructuredList)
        UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
      ++Index;
      return;
    }

    // Fall through for subaggregate initialization.

  } else {
    assert((ElemType->isRecordType() || ElemType->isVectorType() ||
            ElemType->isOpenCLSpecificType()) && "Unexpected type");

    // C99 6.7.8p13:
    //
    //   The initializer for a structure or union object that has
    //   automatic storage duration shall be either an initializer
    //   list as described below, or a single expression that has
    //   compatible structure or union type. In the latter case, the
    //   initial value of the object, including unnamed members, is
    //   that of the expression.
    ExprResult ExprRes = expr;
    if (SemaRef.CheckSingleAssignmentConstraints(
            ElemType, ExprRes, !VerifyOnly) != Sema::Incompatible) {
      if (ExprRes.isInvalid())
        hadError = true;
      else {
        ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.get());
        if (ExprRes.isInvalid())
          hadError = true;
      }
      UpdateStructuredListElement(StructuredList, StructuredIndex,
                                  ExprRes.getAs<Expr>());
      ++Index;
      return;
    }
    ExprRes.get();
    // Fall through for subaggregate initialization
  }

  // C++ [dcl.init.aggr]p12:
  //
  //   [...] Otherwise, if the member is itself a non-empty
  //   subaggregate, brace elision is assumed and the initializer is
  //   considered for the initialization of the first member of
  //   the subaggregate.
  // OpenCL vector initializer is handled elsewhere.
  if ((!SemaRef.getLangOpts().OpenCL && ElemType->isVectorType()) ||
      ElemType->isAggregateType()) {
    CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
                          StructuredIndex);
    ++StructuredIndex;
  } else {
    if (!VerifyOnly) {
      // We cannot initialize this element, so let PerformCopyInitialization
      // produce the appropriate diagnostic. We already checked that this
      // initialization will fail.
      ExprResult Copy =
          SemaRef.PerformCopyInitialization(Entity, SourceLocation(), expr,
                                            /*TopLevelOfInitList=*/true);
      (void)Copy;
      assert(Copy.isInvalid() &&
             "expected non-aggregate initialization to fail");
    }
    hadError = true;
    ++Index;
    ++StructuredIndex;
  }
}

void InitListChecker::CheckComplexType(const InitializedEntity &Entity,
                                       InitListExpr *IList, QualType DeclType,
                                       unsigned &Index,
                                       InitListExpr *StructuredList,
                                       unsigned &StructuredIndex) {
  assert(Index == 0 && "Index in explicit init list must be zero");

  // As an extension, clang supports complex initializers, which initialize
  // a complex number component-wise.  When an explicit initializer list for
  // a complex number contains two two initializers, this extension kicks in:
  // it exepcts the initializer list to contain two elements convertible to
  // the element type of the complex type. The first element initializes
  // the real part, and the second element intitializes the imaginary part.

  if (IList->getNumInits() != 2)
    return CheckScalarType(Entity, IList, DeclType, Index, StructuredList,
                           StructuredIndex);

  // This is an extension in C.  (The builtin _Complex type does not exist
  // in the C++ standard.)
  if (!SemaRef.getLangOpts().CPlusPlus && !VerifyOnly)
    SemaRef.Diag(IList->getBeginLoc(), diag::ext_complex_component_init)
        << IList->getSourceRange();

  // Initialize the complex number.
  QualType elementType = DeclType->castAs<ComplexType>()->getElementType();
  InitializedEntity ElementEntity =
    InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);

  for (unsigned i = 0; i < 2; ++i) {
    ElementEntity.setElementIndex(Index);
    CheckSubElementType(ElementEntity, IList, elementType, Index,
                        StructuredList, StructuredIndex);
  }
}

void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
                                      InitListExpr *IList, QualType DeclType,
                                      unsigned &Index,
                                      InitListExpr *StructuredList,
                                      unsigned &StructuredIndex) {
  if (Index >= IList->getNumInits()) {
    if (!VerifyOnly)
      SemaRef.Diag(IList->getBeginLoc(),
                   SemaRef.getLangOpts().CPlusPlus11
                       ? diag::warn_cxx98_compat_empty_scalar_initializer
                       : diag::err_empty_scalar_initializer)
          << IList->getSourceRange();
    hadError = !SemaRef.getLangOpts().CPlusPlus11;
    ++Index;
    ++StructuredIndex;
    return;
  }

  Expr *expr = IList->getInit(Index);
  if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
    // FIXME: This is invalid, and accepting it causes overload resolution
    // to pick the wrong overload in some corner cases.
    if (!VerifyOnly)
      SemaRef.Diag(SubIList->getBeginLoc(),
                   diag::ext_many_braces_around_scalar_init)
          << SubIList->getSourceRange();

    CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
                    StructuredIndex);
    return;
  } else if (isa<DesignatedInitExpr>(expr)) {
    if (!VerifyOnly)
      SemaRef.Diag(expr->getBeginLoc(), diag::err_designator_for_scalar_init)
          << DeclType << expr->getSourceRange();
    hadError = true;
    ++Index;
    ++StructuredIndex;
    return;
  }

  ExprResult Result;
  if (VerifyOnly) {
    if (SemaRef.CanPerformCopyInitialization(Entity, expr))
      Result = getDummyInit();
    else
      Result = ExprError();
  } else {
    Result =
        SemaRef.PerformCopyInitialization(Entity, expr->getBeginLoc(), expr,
                                          /*TopLevelOfInitList=*/true);
  }

  Expr *ResultExpr = nullptr;

  if (Result.isInvalid())
    hadError = true; // types weren't compatible.
  else {
    ResultExpr = Result.getAs<Expr>();

    if (ResultExpr != expr && !VerifyOnly) {
      // The type was promoted, update initializer list.
      // FIXME: Why are we updating the syntactic init list?
      IList->setInit(Index, ResultExpr);
    }
  }
  if (hadError)
    ++StructuredIndex;
  else
    UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
  ++Index;
}

void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
                                         InitListExpr *IList, QualType DeclType,
                                         unsigned &Index,
                                         InitListExpr *StructuredList,
                                         unsigned &StructuredIndex) {
  if (Index >= IList->getNumInits()) {
    // FIXME: It would be wonderful if we could point at the actual member. In
    // general, it would be useful to pass location information down the stack,
    // so that we know the location (or decl) of the "current object" being
    // initialized.
    if (!VerifyOnly)
      SemaRef.Diag(IList->getBeginLoc(),
                   diag::err_init_reference_member_uninitialized)
          << DeclType << IList->getSourceRange();
    hadError = true;
    ++Index;
    ++StructuredIndex;
    return;
  }

  Expr *expr = IList->getInit(Index);
  if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus11) {
    if (!VerifyOnly)
      SemaRef.Diag(IList->getBeginLoc(), diag::err_init_non_aggr_init_list)
          << DeclType << IList->getSourceRange();
    hadError = true;
    ++Index;
    ++StructuredIndex;
    return;
  }

  ExprResult Result;
  if (VerifyOnly) {
    if (SemaRef.CanPerformCopyInitialization(Entity,expr))
      Result = getDummyInit();
    else
      Result = ExprError();
  } else {
    Result =
        SemaRef.PerformCopyInitialization(Entity, expr->getBeginLoc(), expr,
                                          /*TopLevelOfInitList=*/true);
  }

  if (Result.isInvalid())
    hadError = true;

  expr = Result.getAs<Expr>();
  // FIXME: Why are we updating the syntactic init list?
  if (!VerifyOnly)
    IList->setInit(Index, expr);

  if (hadError)
    ++StructuredIndex;
  else
    UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
  ++Index;
}

void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
                                      InitListExpr *IList, QualType DeclType,
                                      unsigned &Index,
                                      InitListExpr *StructuredList,
                                      unsigned &StructuredIndex) {
  const VectorType *VT = DeclType->castAs<VectorType>();
  unsigned maxElements = VT->getNumElements();
  unsigned numEltsInit = 0;
  QualType elementType = VT->getElementType();

  if (Index >= IList->getNumInits()) {
    // Make sure the element type can be value-initialized.
    CheckEmptyInitializable(
        InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity),
        IList->getEndLoc());
    return;
  }

  if (!SemaRef.getLangOpts().OpenCL) {
    // If the initializing element is a vector, try to copy-initialize
    // instead of breaking it apart (which is doomed to failure anyway).
    Expr *Init = IList->getInit(Index);
    if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) {
      ExprResult Result;
      if (VerifyOnly) {
        if (SemaRef.CanPerformCopyInitialization(Entity, Init))
          Result = getDummyInit();
        else
          Result = ExprError();
      } else {
        Result =
            SemaRef.PerformCopyInitialization(Entity, Init->getBeginLoc(), Init,
                                              /*TopLevelOfInitList=*/true);
      }

      Expr *ResultExpr = nullptr;
      if (Result.isInvalid())
        hadError = true; // types weren't compatible.
      else {
        ResultExpr = Result.getAs<Expr>();

        if (ResultExpr != Init && !VerifyOnly) {
          // The type was promoted, update initializer list.
          // FIXME: Why are we updating the syntactic init list?
          IList->setInit(Index, ResultExpr);
        }
      }
      if (hadError)
        ++StructuredIndex;
      else
        UpdateStructuredListElement(StructuredList, StructuredIndex,
                                    ResultExpr);
      ++Index;
      return;
    }

    InitializedEntity ElementEntity =
      InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);

    for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) {
      // Don't attempt to go past the end of the init list
      if (Index >= IList->getNumInits()) {
        CheckEmptyInitializable(ElementEntity, IList->getEndLoc());
        break;
      }

      ElementEntity.setElementIndex(Index);
      CheckSubElementType(ElementEntity, IList, elementType, Index,
                          StructuredList, StructuredIndex);
    }

    if (VerifyOnly)
      return;

    bool isBigEndian = SemaRef.Context.getTargetInfo().isBigEndian();
    const VectorType *T = Entity.getType()->castAs<VectorType>();
    if (isBigEndian && (T->getVectorKind() == VectorType::NeonVector ||
                        T->getVectorKind() == VectorType::NeonPolyVector)) {
      // The ability to use vector initializer lists is a GNU vector extension
      // and is unrelated to the NEON intrinsics in arm_neon.h. On little
      // endian machines it works fine, however on big endian machines it
      // exhibits surprising behaviour:
      //
      //   uint32x2_t x = {42, 64};
      //   return vget_lane_u32(x, 0); // Will return 64.
      //
      // Because of this, explicitly call out that it is non-portable.
      //
      SemaRef.Diag(IList->getBeginLoc(),
                   diag::warn_neon_vector_initializer_non_portable);

      const char *typeCode;
      unsigned typeSize = SemaRef.Context.getTypeSize(elementType);

      if (elementType->isFloatingType())
        typeCode = "f";
      else if (elementType->isSignedIntegerType())
        typeCode = "s";
      else if (elementType->isUnsignedIntegerType())
        typeCode = "u";
      else
        llvm_unreachable("Invalid element type!");

      SemaRef.Diag(IList->getBeginLoc(),
                   SemaRef.Context.getTypeSize(VT) > 64
                       ? diag::note_neon_vector_initializer_non_portable_q
                       : diag::note_neon_vector_initializer_non_portable)
          << typeCode << typeSize;
    }

    return;
  }

  InitializedEntity ElementEntity =
    InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);

  // OpenCL initializers allows vectors to be constructed from vectors.
  for (unsigned i = 0; i < maxElements; ++i) {
    // Don't attempt to go past the end of the init list
    if (Index >= IList->getNumInits())
      break;

    ElementEntity.setElementIndex(Index);

    QualType IType = IList->getInit(Index)->getType();
    if (!IType->isVectorType()) {
      CheckSubElementType(ElementEntity, IList, elementType, Index,
                          StructuredList, StructuredIndex);
      ++numEltsInit;
    } else {
      QualType VecType;
      const VectorType *IVT = IType->castAs<VectorType>();
      unsigned numIElts = IVT->getNumElements();

      if (IType->isExtVectorType())
        VecType = SemaRef.Context.getExtVectorType(elementType, numIElts);
      else
        VecType = SemaRef.Context.getVectorType(elementType, numIElts,
                                                IVT->getVectorKind());
      CheckSubElementType(ElementEntity, IList, VecType, Index,
                          StructuredList, StructuredIndex);
      numEltsInit += numIElts;
    }
  }

  // OpenCL requires all elements to be initialized.
  if (numEltsInit != maxElements) {
    if (!VerifyOnly)
      SemaRef.Diag(IList->getBeginLoc(),
                   diag::err_vector_incorrect_num_initializers)
          << (numEltsInit < maxElements) << maxElements << numEltsInit;
    hadError = true;
  }
}

/// Check if the type of a class element has an accessible destructor, and marks
/// it referenced. Returns true if we shouldn't form a reference to the
/// destructor.
///
/// Aggregate initialization requires a class element's destructor be
/// accessible per 11.6.1 [dcl.init.aggr]:
///
/// The destructor for each element of class type is potentially invoked
/// (15.4 [class.dtor]) from the context where the aggregate initialization
/// occurs.
static bool checkDestructorReference(QualType ElementType, SourceLocation Loc,
                                     Sema &SemaRef) {
  auto *CXXRD = ElementType->getAsCXXRecordDecl();
  if (!CXXRD)
    return false;

  CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD);
  SemaRef.CheckDestructorAccess(Loc, Destructor,
                                SemaRef.PDiag(diag::err_access_dtor_temp)
                                << ElementType);
  SemaRef.MarkFunctionReferenced(Loc, Destructor);
  return SemaRef.DiagnoseUseOfDecl(Destructor, Loc);
}

void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
                                     InitListExpr *IList, QualType &DeclType,
                                     llvm::APSInt elementIndex,
                                     bool SubobjectIsDesignatorContext,
                                     unsigned &Index,
                                     InitListExpr *StructuredList,
                                     unsigned &StructuredIndex) {
  const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType);

  if (!VerifyOnly) {
    if (checkDestructorReference(arrayType->getElementType(),
                                 IList->getEndLoc(), SemaRef)) {
      hadError = true;
      return;
    }
  }

  // Check for the special-case of initializing an array with a string.
  if (Index < IList->getNumInits()) {
    if (IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context) ==
        SIF_None) {
      // We place the string literal directly into the resulting
      // initializer list. This is the only place where the structure
      // of the structured initializer list doesn't match exactly,
      // because doing so would involve allocating one character
      // constant for each string.
      // FIXME: Should we do these checks in verify-only mode too?
      if (!VerifyOnly)
        CheckStringInit(IList->getInit(Index), DeclType, arrayType, SemaRef);
      if (StructuredList) {
        UpdateStructuredListElement(StructuredList, StructuredIndex,
                                    IList->getInit(Index));
        StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
      }
      ++Index;
      return;
    }
  }
  if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(arrayType)) {
    // Check for VLAs; in standard C it would be possible to check this
    // earlier, but I don't know where clang accepts VLAs (gcc accepts
    // them in all sorts of strange places).
    if (!VerifyOnly)
      SemaRef.Diag(VAT->getSizeExpr()->getBeginLoc(),
                   diag::err_variable_object_no_init)
          << VAT->getSizeExpr()->getSourceRange();
    hadError = true;
    ++Index;
    ++StructuredIndex;
    return;
  }

  // We might know the maximum number of elements in advance.
  llvm::APSInt maxElements(elementIndex.getBitWidth(),
                           elementIndex.isUnsigned());
  bool maxElementsKnown = false;
  if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(arrayType)) {
    maxElements = CAT->getSize();
    elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth());
    elementIndex.setIsUnsigned(maxElements.isUnsigned());
    maxElementsKnown = true;
  }

  QualType elementType = arrayType->getElementType();
  while (Index < IList->getNumInits()) {
    Expr *Init = IList->getInit(Index);
    if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
      // If we're not the subobject that matches up with the '{' for
      // the designator, we shouldn't be handling the
      // designator. Return immediately.
      if (!SubobjectIsDesignatorContext)
        return;

      // Handle this designated initializer. elementIndex will be
      // updated to be the next array element we'll initialize.
      if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
                                     DeclType, nullptr, &elementIndex, Index,
                                     StructuredList, StructuredIndex, true,
                                     false)) {
        hadError = true;
        continue;
      }

      if (elementIndex.getBitWidth() > maxElements.getBitWidth())
        maxElements = maxElements.extend(elementIndex.getBitWidth());
      else if (elementIndex.getBitWidth() < maxElements.getBitWidth())
        elementIndex = elementIndex.extend(maxElements.getBitWidth());
      elementIndex.setIsUnsigned(maxElements.isUnsigned());

      // If the array is of incomplete type, keep track of the number of
      // elements in the initializer.
      if (!maxElementsKnown && elementIndex > maxElements)
        maxElements = elementIndex;

      continue;
    }

    // If we know the maximum number of elements, and we've already
    // hit it, stop consuming elements in the initializer list.
    if (maxElementsKnown && elementIndex == maxElements)
      break;

    InitializedEntity ElementEntity =
      InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex,
                                           Entity);
    // Check this element.
    CheckSubElementType(ElementEntity, IList, elementType, Index,
                        StructuredList, StructuredIndex);
    ++elementIndex;

    // If the array is of incomplete type, keep track of the number of
    // elements in the initializer.
    if (!maxElementsKnown && elementIndex > maxElements)
      maxElements = elementIndex;
  }
  if (!hadError && DeclType->isIncompleteArrayType() && !VerifyOnly) {
    // If this is an incomplete array type, the actual type needs to
    // be calculated here.
    llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
    if (maxElements == Zero && !Entity.isVariableLengthArrayNew()) {
      // Sizing an array implicitly to zero is not allowed by ISO C,
      // but is supported by GNU.
      SemaRef.Diag(IList->getBeginLoc(), diag::ext_typecheck_zero_array_size);
    }

    DeclType = SemaRef.Context.getConstantArrayType(
        elementType, maxElements, nullptr, ArrayType::Normal, 0);
  }
  if (!hadError) {
    // If there are any members of the array that get value-initialized, check
    // that is possible. That happens if we know the bound and don't have
    // enough elements, or if we're performing an array new with an unknown
    // bound.
    if ((maxElementsKnown && elementIndex < maxElements) ||
        Entity.isVariableLengthArrayNew())
      CheckEmptyInitializable(
          InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity),
          IList->getEndLoc());
  }
}

bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
                                             Expr *InitExpr,
                                             FieldDecl *Field,
                                             bool TopLevelObject) {
  // Handle GNU flexible array initializers.
  unsigned FlexArrayDiag;
  if (isa<InitListExpr>(InitExpr) &&
      cast<InitListExpr>(InitExpr)->getNumInits() == 0) {
    // Empty flexible array init always allowed as an extension
    FlexArrayDiag = diag::ext_flexible_array_init;
  } else if (SemaRef.getLangOpts().CPlusPlus) {
    // Disallow flexible array init in C++; it is not required for gcc
    // compatibility, and it needs work to IRGen correctly in general.
    FlexArrayDiag = diag::err_flexible_array_init;
  } else if (!TopLevelObject) {
    // Disallow flexible array init on non-top-level object
    FlexArrayDiag = diag::err_flexible_array_init;
  } else if (Entity.getKind() != InitializedEntity::EK_Variable) {
    // Disallow flexible array init on anything which is not a variable.
    FlexArrayDiag = diag::err_flexible_array_init;
  } else if (cast<VarDecl>(Entity.getDecl())->hasLocalStorage()) {
    // Disallow flexible array init on local variables.
    FlexArrayDiag = diag::err_flexible_array_init;
  } else {
    // Allow other cases.
    FlexArrayDiag = diag::ext_flexible_array_init;
  }

  if (!VerifyOnly) {
    SemaRef.Diag(InitExpr->getBeginLoc(), FlexArrayDiag)
        << InitExpr->getBeginLoc();
    SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
      << Field;
  }

  return FlexArrayDiag != diag::ext_flexible_array_init;
}

void InitListChecker::CheckStructUnionTypes(
    const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType,
    CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field,
    bool SubobjectIsDesignatorContext, unsigned &Index,
    InitListExpr *StructuredList, unsigned &StructuredIndex,
    bool TopLevelObject) {
  RecordDecl *structDecl = DeclType->castAs<RecordType>()->getDecl();

  // If the record is invalid, some of it's members are invalid. To avoid
  // confusion, we forgo checking the intializer for the entire record.
  if (structDecl->isInvalidDecl()) {
    // Assume it was supposed to consume a single initializer.
    ++Index;
    hadError = true;
    return;
  }

  if (DeclType->isUnionType() && IList->getNumInits() == 0) {
    RecordDecl *RD = DeclType->castAs<RecordType>()->getDecl();

    if (!VerifyOnly)
      for (FieldDecl *FD : RD->fields()) {
        QualType ET = SemaRef.Context.getBaseElementType(FD->getType());
        if (checkDestructorReference(ET, IList->getEndLoc(), SemaRef)) {
          hadError = true;
          return;
        }
      }

    // If there's a default initializer, use it.
    if (isa<CXXRecordDecl>(RD) &&
        cast<CXXRecordDecl>(RD)->hasInClassInitializer()) {
      if (!StructuredList)
        return;
      for (RecordDecl::field_iterator FieldEnd = RD->field_end();
           Field != FieldEnd; ++Field) {
        if (Field->hasInClassInitializer()) {
          StructuredList->setInitializedFieldInUnion(*Field);
          // FIXME: Actually build a CXXDefaultInitExpr?
          return;
        }
      }
    }

    // Value-initialize the first member of the union that isn't an unnamed
    // bitfield.
    for (RecordDecl::field_iterator FieldEnd = RD->field_end();
         Field != FieldEnd; ++Field) {
      if (!Field->isUnnamedBitfield()) {
        CheckEmptyInitializable(
            InitializedEntity::InitializeMember(*Field, &Entity),
            IList->getEndLoc());
        if (StructuredList)
          StructuredList->setInitializedFieldInUnion(*Field);
        break;
      }
    }
    return;
  }

  bool InitializedSomething = false;

  // If we have any base classes, they are initialized prior to the fields.
  for (auto &Base : Bases) {
    Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr;

    // Designated inits always initialize fields, so if we see one, all
    // remaining base classes have no explicit initializer.
    if (Init && isa<DesignatedInitExpr>(Init))
      Init = nullptr;

    SourceLocation InitLoc = Init ? Init->getBeginLoc() : IList->getEndLoc();
    InitializedEntity BaseEntity = InitializedEntity::InitializeBase(
        SemaRef.Context, &Base, false, &Entity);
    if (Init) {
      CheckSubElementType(BaseEntity, IList, Base.getType(), Index,
                          StructuredList, StructuredIndex);
      InitializedSomething = true;
    } else {
      CheckEmptyInitializable(BaseEntity, InitLoc);
    }

    if (!VerifyOnly)
      if (checkDestructorReference(Base.getType(), InitLoc, SemaRef)) {
        hadError = true;
        return;
      }
  }

  // If structDecl is a forward declaration, this loop won't do
  // anything except look at designated initializers; That's okay,
  // because an error should get printed out elsewhere. It might be
  // worthwhile to skip over the rest of the initializer, though.
  RecordDecl *RD = DeclType->castAs<RecordType>()->getDecl();
  RecordDecl::field_iterator FieldEnd = RD->field_end();
  bool CheckForMissingFields =
    !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
  bool HasDesignatedInit = false;

  while (Index < IList->getNumInits()) {
    Expr *Init = IList->getInit(Index);
    SourceLocation InitLoc = Init->getBeginLoc();

    if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
      // If we're not the subobject that matches up with the '{' for
      // the designator, we shouldn't be handling the
      // designator. Return immediately.
      if (!SubobjectIsDesignatorContext)
        return;

      HasDesignatedInit = true;

      // Handle this designated initializer. Field will be updated to
      // the next field that we'll be initializing.
      if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
                                     DeclType, &Field, nullptr, Index,
                                     StructuredList, StructuredIndex,
                                     true, TopLevelObject))
        hadError = true;
      else if (!VerifyOnly) {
        // Find the field named by the designated initializer.
        RecordDecl::field_iterator F = RD->field_begin();
        while (std::next(F) != Field)
          ++F;
        QualType ET = SemaRef.Context.getBaseElementType(F->getType());
        if (checkDestructorReference(ET, InitLoc, SemaRef)) {
          hadError = true;
          return;
        }
      }

      InitializedSomething = true;

      // Disable check for missing fields when designators are used.
      // This matches gcc behaviour.
      CheckForMissingFields = false;
      continue;
    }

    if (Field == FieldEnd) {
      // We've run out of fields. We're done.
      break;
    }

    // We've already initialized a member of a union. We're done.
    if (InitializedSomething && DeclType->isUnionType())
      break;

    // If we've hit the flexible array member at the end, we're done.
    if (Field->getType()->isIncompleteArrayType())
      break;

    if (Field->isUnnamedBitfield()) {
      // Don't initialize unnamed bitfields, e.g. "int : 20;"
      ++Field;
      continue;
    }

    // Make sure we can use this declaration.
    bool InvalidUse;
    if (VerifyOnly)
      InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid);
    else
      InvalidUse = SemaRef.DiagnoseUseOfDecl(
          *Field, IList->getInit(Index)->getBeginLoc());
    if (InvalidUse) {
      ++Index;
      ++Field;
      hadError = true;
      continue;
    }

    if (!VerifyOnly) {
      QualType ET = SemaRef.Context.getBaseElementType(Field->getType());
      if (checkDestructorReference(ET, InitLoc, SemaRef)) {
        hadError = true;
        return;
      }
    }

    InitializedEntity MemberEntity =
      InitializedEntity::InitializeMember(*Field, &Entity);
    CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
                        StructuredList, StructuredIndex);
    InitializedSomething = true;

    if (DeclType->isUnionType() && StructuredList) {
      // Initialize the first field within the union.
      StructuredList->setInitializedFieldInUnion(*Field);
    }

    ++Field;
  }

  // Emit warnings for missing struct field initializers.
  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
      Field != FieldEnd && !Field->getType()->isIncompleteArrayType() &&
      !DeclType->isUnionType()) {
    // It is possible we have one or more unnamed bitfields remaining.
    // Find first (if any) named field and emit warning.
    for (RecordDecl::field_iterator it = Field, end = RD->field_end();
         it != end; ++it) {
      if (!it->isUnnamedBitfield() && !it->hasInClassInitializer()) {
        SemaRef.Diag(IList->getSourceRange().getEnd(),
                     diag::warn_missing_field_initializers) << *it;
        break;
      }
    }
  }

  // Check that any remaining fields can be value-initialized if we're not
  // building a structured list. (If we are, we'll check this later.)
  if (!StructuredList && Field != FieldEnd && !DeclType->isUnionType() &&
      !Field->getType()->isIncompleteArrayType()) {
    for (; Field != FieldEnd && !hadError; ++Field) {
      if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer())
        CheckEmptyInitializable(
            InitializedEntity::InitializeMember(*Field, &Entity),
            IList->getEndLoc());
    }
  }

  // Check that the types of the remaining fields have accessible destructors.
  if (!VerifyOnly) {
    // If the initializer expression has a designated initializer, check the
    // elements for which a designated initializer is not provided too.
    RecordDecl::field_iterator I = HasDesignatedInit ? RD->field_begin()
                                                     : Field;
    for (RecordDecl::field_iterator E = RD->field_end(); I != E; ++I) {
      QualType ET = SemaRef.Context.getBaseElementType(I->getType());
      if (checkDestructorReference(ET, IList->getEndLoc(), SemaRef)) {
        hadError = true;
        return;
      }
    }
  }

  if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() ||
      Index >= IList->getNumInits())
    return;

  if (CheckFlexibleArrayInit(Entity, IList->getInit(Index), *Field,
                             TopLevelObject)) {
    hadError = true;
    ++Index;
    return;
  }

  InitializedEntity MemberEntity =
    InitializedEntity::InitializeMember(*Field, &Entity);

  if (isa<InitListExpr>(IList->getInit(Index)))
    CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
                        StructuredList, StructuredIndex);
  else
    CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
                          StructuredList, StructuredIndex);
}

/// Expand a field designator that refers to a member of an
/// anonymous struct or union into a series of field designators that
/// refers to the field within the appropriate subobject.
///
static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
                                           DesignatedInitExpr *DIE,
                                           unsigned DesigIdx,
                                           IndirectFieldDecl *IndirectField) {
  typedef DesignatedInitExpr::Designator Designator;

  // Build the replacement designators.
  SmallVector<Designator, 4> Replacements;
  for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
       PE = IndirectField->chain_end(); PI != PE; ++PI) {
    if (PI + 1 == PE)
      Replacements.push_back(Designator((IdentifierInfo *)nullptr,
                                    DIE->getDesignator(DesigIdx)->getDotLoc(),
                                DIE->getDesignator(DesigIdx)->getFieldLoc()));
    else
      Replacements.push_back(Designator((IdentifierInfo *)nullptr,
                                        SourceLocation(), SourceLocation()));
    assert(isa<FieldDecl>(*PI));
    Replacements.back().setField(cast<FieldDecl>(*PI));
  }

  // Expand the current designator into the set of replacement
  // designators, so we have a full subobject path down to where the
  // member of the anonymous struct/union is actually stored.
  DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0],
                        &Replacements[0] + Replacements.size());
}

static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef,
                                                   DesignatedInitExpr *DIE) {
  unsigned NumIndexExprs = DIE->getNumSubExprs() - 1;
  SmallVector<Expr*, 4> IndexExprs(NumIndexExprs);
  for (unsigned I = 0; I < NumIndexExprs; ++I)
    IndexExprs[I] = DIE->getSubExpr(I + 1);
  return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators(),
                                    IndexExprs,
                                    DIE->getEqualOrColonLoc(),
                                    DIE->usesGNUSyntax(), DIE->getInit());
}

namespace {

// Callback to only accept typo corrections that are for field members of
// the given struct or union.
class FieldInitializerValidatorCCC final : public CorrectionCandidateCallback {
 public:
  explicit FieldInitializerValidatorCCC(RecordDecl *RD)
      : Record(RD) {}

  bool ValidateCandidate(const TypoCorrection &candidate) override {
    FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>();
    return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record);
  }

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

 private:
  RecordDecl *Record;
};

} // end anonymous namespace

/// Check the well-formedness of a C99 designated initializer.
///
/// Determines whether the designated initializer @p DIE, which
/// resides at the given @p Index within the initializer list @p
/// IList, is well-formed for a current object of type @p DeclType
/// (C99 6.7.8). The actual subobject that this designator refers to
/// within the current subobject is returned in either
/// @p NextField or @p NextElementIndex (whichever is appropriate).
///
/// @param IList  The initializer list in which this designated
/// initializer occurs.
///
/// @param DIE The designated initializer expression.
///
/// @param DesigIdx  The index of the current designator.
///
/// @param CurrentObjectType The type of the "current object" (C99 6.7.8p17),
/// into which the designation in @p DIE should refer.
///
/// @param NextField  If non-NULL and the first designator in @p DIE is
/// a field, this will be set to the field declaration corresponding
/// to the field named by the designator. On input, this is expected to be
/// the next field that would be initialized in the absence of designation,
/// if the complete object being initialized is a struct.
///
/// @param NextElementIndex  If non-NULL and the first designator in @p
/// DIE is an array designator or GNU array-range designator, this
/// will be set to the last index initialized by this designator.
///
/// @param Index  Index into @p IList where the designated initializer
/// @p DIE occurs.
///
/// @param StructuredList  The initializer list expression that
/// describes all of the subobject initializers in the order they'll
/// actually be initialized.
///
/// @returns true if there was an error, false otherwise.
bool
InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
                                            InitListExpr *IList,
                                            DesignatedInitExpr *DIE,
                                            unsigned DesigIdx,
                                            QualType &CurrentObjectType,
                                          RecordDecl::field_iterator *NextField,
                                            llvm::APSInt *NextElementIndex,
                                            unsigned &Index,
                                            InitListExpr *StructuredList,
                                            unsigned &StructuredIndex,
                                            bool FinishSubobjectInit,
                                            bool TopLevelObject) {
  if (DesigIdx == DIE->size()) {
    // C++20 designated initialization can result in direct-list-initialization
    // of the designated subobject. This is the only way that we can end up
    // performing direct initialization as part of aggregate initialization, so
    // it needs special handling.
    if (DIE->isDirectInit()) {
      Expr *Init = DIE->getInit();
      assert(isa<InitListExpr>(Init) &&
             "designator result in direct non-list initialization?");
      InitializationKind Kind = InitializationKind::CreateDirectList(
          DIE->getBeginLoc(), Init->getBeginLoc(), Init->getEndLoc());
      InitializationSequence Seq(SemaRef, Entity, Kind, Init,
                                 /*TopLevelOfInitList*/ true);
      if (StructuredList) {
        ExprResult Result = VerifyOnly
                                ? getDummyInit()
                                : Seq.Perform(SemaRef, Entity, Kind, Init);
        UpdateStructuredListElement(StructuredList, StructuredIndex,
                                    Result.get());
      }
      ++Index;
      return !Seq;
    }

    // Check the actual initialization for the designated object type.
    bool prevHadError = hadError;

    // Temporarily remove the designator expression from the
    // initializer list that the child calls see, so that we don't try
    // to re-process the designator.
    unsigned OldIndex = Index;
    IList->setInit(OldIndex, DIE->getInit());

    CheckSubElementType(Entity, IList, CurrentObjectType, Index,
                        StructuredList, StructuredIndex);

    // Restore the designated initializer expression in the syntactic
    // form of the initializer list.
    if (IList->getInit(OldIndex) != DIE->getInit())
      DIE->setInit(IList->getInit(OldIndex));
    IList->setInit(OldIndex, DIE);

    return hadError && !prevHadError;
  }

  DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
  bool IsFirstDesignator = (DesigIdx == 0);
  if (IsFirstDesignator ? FullyStructuredList : StructuredList) {
    // Determine the structural initializer list that corresponds to the
    // current subobject.
    if (IsFirstDesignator)
      StructuredList = FullyStructuredList;
    else {
      Expr *ExistingInit = StructuredIndex < StructuredList->getNumInits() ?
          StructuredList->getInit(StructuredIndex) : nullptr;
      if (!ExistingInit && StructuredList->hasArrayFiller())
        ExistingInit = StructuredList->getArrayFiller();

      if (!ExistingInit)
        StructuredList = getStructuredSubobjectInit(
            IList, Index, CurrentObjectType, StructuredList, StructuredIndex,
            SourceRange(D->getBeginLoc(), DIE->getEndLoc()));
      else if (InitListExpr *Result = dyn_cast<InitListExpr>(ExistingInit))
        StructuredList = Result;
      else {
        // We are creating an initializer list that initializes the
        // subobjects of the current object, but there was already an
        // initialization that completely initialized the current
        // subobject, e.g., by a compound literal:
        //
        // struct X { int a, b; };
        // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
        //
        // Here, xs[0].a == 1 and xs[0].b == 3, since the second,
        // designated initializer re-initializes only its current object
        // subobject [0].b.
        diagnoseInitOverride(ExistingInit,
                             SourceRange(D->getBeginLoc(), DIE->getEndLoc()),
                             /*FullyOverwritten=*/false);

        if (!VerifyOnly) {
          if (DesignatedInitUpdateExpr *E =
                  dyn_cast<DesignatedInitUpdateExpr>(ExistingInit))
            StructuredList = E->getUpdater();
          else {
            DesignatedInitUpdateExpr *DIUE = new (SemaRef.Context)
                DesignatedInitUpdateExpr(SemaRef.Context, D->getBeginLoc(),
                                         ExistingInit, DIE->getEndLoc());
            StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE);
            StructuredList = DIUE->getUpdater();
          }
        } else {
          // We don't need to track the structured representation of a
          // designated init update of an already-fully-initialized object in
          // verify-only mode. The only reason we would need the structure is
          // to determine where the uninitialized "holes" are, and in this
          // case, we know there aren't any and we can't introduce any.
          StructuredList = nullptr;
        }
      }
    }
  }

  if (D->isFieldDesignator()) {
    // C99 6.7.8p7:
    //
    //   If a designator has the form
    //
    //      . identifier
    //
    //   then the current object (defined below) shall have
    //   structure or union type and the identifier shall be the
    //   name of a member of that type.
    const RecordType *RT = CurrentObjectType->getAs<RecordType>();
    if (!RT) {
      SourceLocation Loc = D->getDotLoc();
      if (Loc.isInvalid())
        Loc = D->getFieldLoc();
      if (!VerifyOnly)
        SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
          << SemaRef.getLangOpts().CPlusPlus << CurrentObjectType;
      ++Index;
      return true;
    }

    FieldDecl *KnownField = D->getField();
    if (!KnownField) {
      IdentifierInfo *FieldName = D->getFieldName();
      DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
      for (NamedDecl *ND : Lookup) {
        if (auto *FD = dyn_cast<FieldDecl>(ND)) {
          KnownField = FD;
          break;
        }
        if (auto *IFD = dyn_cast<IndirectFieldDecl>(ND)) {
          // In verify mode, don't modify the original.
          if (VerifyOnly)
            DIE = CloneDesignatedInitExpr(SemaRef, DIE);
          ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IFD);
          D = DIE->getDesignator(DesigIdx);
          KnownField = cast<FieldDecl>(*IFD->chain_begin());
          break;
        }
      }
      if (!KnownField) {
        if (VerifyOnly) {
          ++Index;
          return true;  // No typo correction when just trying this out.
        }

        // Name lookup found something, but it wasn't a field.
        if (!Lookup.empty()) {
          SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
            << FieldName;
          SemaRef.Diag(Lookup.front()->getLocation(),
                       diag::note_field_designator_found);
          ++Index;
          return true;
        }

        // Name lookup didn't find anything.
        // Determine whether this was a typo for another field name.
        FieldInitializerValidatorCCC CCC(RT->getDecl());
        if (TypoCorrection Corrected = SemaRef.CorrectTypo(
                DeclarationNameInfo(FieldName, D->getFieldLoc()),
                Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr, CCC,
                Sema::CTK_ErrorRecovery, RT->getDecl())) {
          SemaRef.diagnoseTypo(
              Corrected,
              SemaRef.PDiag(diag::err_field_designator_unknown_suggest)
                << FieldName << CurrentObjectType);
          KnownField = Corrected.getCorrectionDeclAs<FieldDecl>();
          hadError = true;
        } else {
          // Typo correction didn't find anything.
          SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
            << FieldName << CurrentObjectType;
          ++Index;
          return true;
        }
      }
    }

    unsigned NumBases = 0;
    if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
      NumBases = CXXRD->getNumBases();

    unsigned FieldIndex = NumBases;

    for (auto *FI : RT->getDecl()->fields()) {
      if (FI->isUnnamedBitfield())
        continue;
      if (declaresSameEntity(KnownField, FI)) {
        KnownField = FI;
        break;
      }
      ++FieldIndex;
    }

    RecordDecl::field_iterator Field =
        RecordDecl::field_iterator(DeclContext::decl_iterator(KnownField));

    // All of the fields of a union are located at the same place in
    // the initializer list.
    if (RT->getDecl()->isUnion()) {
      FieldIndex = 0;
      if (StructuredList) {
        FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion();
        if (CurrentField && !declaresSameEntity(CurrentField, *Field)) {
          assert(StructuredList->getNumInits() == 1
                 && "A union should never have more than one initializer!");

          Expr *ExistingInit = StructuredList->getInit(0);
          if (ExistingInit) {
            // We're about to throw away an initializer, emit warning.
            diagnoseInitOverride(
                ExistingInit, SourceRange(D->getBeginLoc(), DIE->getEndLoc()));
          }

          // remove existing initializer
          StructuredList->resizeInits(SemaRef.Context, 0);
          StructuredList->setInitializedFieldInUnion(nullptr);
        }

        StructuredList->setInitializedFieldInUnion(*Field);
      }
    }

    // Make sure we can use this declaration.
    bool InvalidUse;
    if (VerifyOnly)
      InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid);
    else
      InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc());
    if (InvalidUse) {
      ++Index;
      return true;
    }

    // C++20 [dcl.init.list]p3:
    //   The ordered identifiers in the designators of the designated-
    //   initializer-list shall form a subsequence of the ordered identifiers
    //   in the direct non-static data members of T.
    //
    // Note that this is not a condition on forming the aggregate
    // initialization, only on actually performing initialization,
    // so it is not checked in VerifyOnly mode.
    //
    // FIXME: This is the only reordering diagnostic we produce, and it only
    // catches cases where we have a top-level field designator that jumps
    // backwards. This is the only such case that is reachable in an
    // otherwise-valid C++20 program, so is the only case that's required for
    // conformance, but for consistency, we should diagnose all the other
    // cases where a designator takes us backwards too.
    if (IsFirstDesignator && !VerifyOnly && SemaRef.getLangOpts().CPlusPlus &&
        NextField &&
        (*NextField == RT->getDecl()->field_end() ||
         (*NextField)->getFieldIndex() > Field->getFieldIndex() + 1)) {
      // Find the field that we just initialized.
      FieldDecl *PrevField = nullptr;
      for (auto FI = RT->getDecl()->field_begin();
           FI != RT->getDecl()->field_end(); ++FI) {
        if (FI->isUnnamedBitfield())
          continue;
        if (*NextField != RT->getDecl()->field_end() &&
            declaresSameEntity(*FI, **NextField))
          break;
        PrevField = *FI;
      }

      if (PrevField &&
          PrevField->getFieldIndex() > KnownField->getFieldIndex()) {
        SemaRef.Diag(DIE->getBeginLoc(), diag::ext_designated_init_reordered)
            << KnownField << PrevField << DIE->getSourceRange();

        unsigned OldIndex = NumBases + PrevField->getFieldIndex();
        if (StructuredList && OldIndex <= StructuredList->getNumInits()) {
          if (Expr *PrevInit = StructuredList->getInit(OldIndex)) {
            SemaRef.Diag(PrevInit->getBeginLoc(),
                         diag::note_previous_field_init)
                << PrevField << PrevInit->getSourceRange();
          }
        }
      }
    }


    // Update the designator with the field declaration.
    if (!VerifyOnly)
      D->setField(*Field);

    // Make sure that our non-designated initializer list has space
    // for a subobject corresponding to this field.
    if (StructuredList && FieldIndex >= StructuredList->getNumInits())
      StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);

    // This designator names a flexible array member.
    if (Field->getType()->isIncompleteArrayType()) {
      bool Invalid = false;
      if ((DesigIdx + 1) != DIE->size()) {
        // We can't designate an object within the flexible array
        // member (because GCC doesn't allow it).
        if (!VerifyOnly) {
          DesignatedInitExpr::Designator *NextD
            = DIE->getDesignator(DesigIdx + 1);
          SemaRef.Diag(NextD->getBeginLoc(),
                       diag::err_designator_into_flexible_array_member)
              << SourceRange(NextD->getBeginLoc(), DIE->getEndLoc());
          SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
            << *Field;
        }
        Invalid = true;
      }

      if (!hadError && !isa<InitListExpr>(DIE->getInit()) &&
          !isa<StringLiteral>(DIE->getInit())) {
        // The initializer is not an initializer list.
        if (!VerifyOnly) {
          SemaRef.Diag(DIE->getInit()->getBeginLoc(),
                       diag::err_flexible_array_init_needs_braces)
              << DIE->getInit()->getSourceRange();
          SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
            << *Field;
        }
        Invalid = true;
      }

      // Check GNU flexible array initializer.
      if (!Invalid && CheckFlexibleArrayInit(Entity, DIE->getInit(), *Field,
                                             TopLevelObject))
        Invalid = true;

      if (Invalid) {
        ++Index;
        return true;
      }

      // Initialize the array.
      bool prevHadError = hadError;
      unsigned newStructuredIndex = FieldIndex;
      unsigned OldIndex = Index;
      IList->setInit(Index, DIE->getInit());

      InitializedEntity MemberEntity =
        InitializedEntity::InitializeMember(*Field, &Entity);
      CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
                          StructuredList, newStructuredIndex);

      IList->setInit(OldIndex, DIE);
      if (hadError && !prevHadError) {
        ++Field;
        ++FieldIndex;
        if (NextField)
          *NextField = Field;
        StructuredIndex = FieldIndex;
        return true;
      }
    } else {
      // Recurse to check later designated subobjects.
      QualType FieldType = Field->getType();
      unsigned newStructuredIndex = FieldIndex;

      InitializedEntity MemberEntity =
        InitializedEntity::InitializeMember(*Field, &Entity);
      if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
                                     FieldType, nullptr, nullptr, Index,
                                     StructuredList, newStructuredIndex,
                                     FinishSubobjectInit, false))
        return true;
    }

    // Find the position of the next field to be initialized in this
    // subobject.
    ++Field;
    ++FieldIndex;

    // If this the first designator, our caller will continue checking
    // the rest of this struct/class/union subobject.
    if (IsFirstDesignator) {
      if (NextField)
        *NextField = Field;
      StructuredIndex = FieldIndex;
      return false;
    }

    if (!FinishSubobjectInit)
      return false;

    // We've already initialized something in the union; we're done.
    if (RT->getDecl()->isUnion())
      return hadError;

    // Check the remaining fields within this class/struct/union subobject.
    bool prevHadError = hadError;

    auto NoBases =
        CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(),
                                        CXXRecordDecl::base_class_iterator());
    CheckStructUnionTypes(Entity, IList, CurrentObjectType, NoBases, Field,
                          false, Index, StructuredList, FieldIndex);
    return hadError && !prevHadError;
  }

  // C99 6.7.8p6:
  //
  //   If a designator has the form
  //
  //      [ constant-expression ]
  //
  //   then the current object (defined below) shall have array
  //   type and the expression shall be an integer constant
  //   expression. If the array is of unknown size, any
  //   nonnegative value is valid.
  //
  // Additionally, cope with the GNU extension that permits
  // designators of the form
  //
  //      [ constant-expression ... constant-expression ]
  const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType);
  if (!AT) {
    if (!VerifyOnly)
      SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
        << CurrentObjectType;
    ++Index;
    return true;
  }

  Expr *IndexExpr = nullptr;
  llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
  if (D->isArrayDesignator()) {
    IndexExpr = DIE->getArrayIndex(*D);
    DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context);
    DesignatedEndIndex = DesignatedStartIndex;
  } else {
    assert(D->isArrayRangeDesignator() && "Need array-range designator");

    DesignatedStartIndex =
      DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context);
    DesignatedEndIndex =
      DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context);
    IndexExpr = DIE->getArrayRangeEnd(*D);

    // Codegen can't handle evaluating array range designators that have side
    // effects, because we replicate the AST value for each initialized element.
    // As such, set the sawArrayRangeDesignator() bit if we initialize multiple
    // elements with something that has a side effect, so codegen can emit an
    // "error unsupported" error instead of miscompiling the app.
    if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&&
        DIE->getInit()->HasSideEffects(SemaRef.Context) && !VerifyOnly)
      FullyStructuredList->sawArrayRangeDesignator();
  }

  if (isa<ConstantArrayType>(AT)) {
    llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
    DesignatedStartIndex
      = DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
    DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
    DesignatedEndIndex
      = DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
    DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
    if (DesignatedEndIndex >= MaxElements) {
      if (!VerifyOnly)
        SemaRef.Diag(IndexExpr->getBeginLoc(),
                     diag::err_array_designator_too_large)
            << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
            << IndexExpr->getSourceRange();
      ++Index;
      return true;
    }
  } else {
    unsigned DesignatedIndexBitWidth =
      ConstantArrayType::getMaxSizeBits(SemaRef.Context);
    DesignatedStartIndex =
      DesignatedStartIndex.extOrTrunc(DesignatedIndexBitWidth);
    DesignatedEndIndex =
      DesignatedEndIndex.extOrTrunc(DesignatedIndexBitWidth);
    DesignatedStartIndex.setIsUnsigned(true);
    DesignatedEndIndex.setIsUnsigned(true);
  }

  bool IsStringLiteralInitUpdate =
      StructuredList && StructuredList->isStringLiteralInit();
  if (IsStringLiteralInitUpdate && VerifyOnly) {
    // We're just verifying an update to a string literal init. We don't need
    // to split the string up into individual characters to do that.
    StructuredList = nullptr;
  } else if (IsStringLiteralInitUpdate) {
    // We're modifying a string literal init; we have to decompose the string
    // so we can modify the individual characters.
    ASTContext &Context = SemaRef.Context;
    Expr *SubExpr = StructuredList->getInit(0)->IgnoreParens();

    // Compute the character type
    QualType CharTy = AT->getElementType();

    // Compute the type of the integer literals.
    QualType PromotedCharTy = CharTy;
    if (CharTy->isPromotableIntegerType())
      PromotedCharTy = Context.getPromotedIntegerType(CharTy);
    unsigned PromotedCharTyWidth = Context.getTypeSize(PromotedCharTy);

    if (StringLiteral *SL = dyn_cast<StringLiteral>(SubExpr)) {
      // Get the length of the string.
      uint64_t StrLen = SL->getLength();
      if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen))
        StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue();
      StructuredList->resizeInits(Context, StrLen);

      // Build a literal for each character in the string, and put them into
      // the init list.
      for (unsigned i = 0, e = StrLen; i != e; ++i) {
        llvm::APInt CodeUnit(PromotedCharTyWidth, SL->getCodeUnit(i));
        Expr *Init = new (Context) IntegerLiteral(
            Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
        if (CharTy != PromotedCharTy)
          Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
                                          Init, nullptr, VK_RValue);
        StructuredList->updateInit(Context, i, Init);
      }
    } else {
      ObjCEncodeExpr *E = cast<ObjCEncodeExpr>(SubExpr);
      std::string Str;
      Context.getObjCEncodingForType(E->getEncodedType(), Str);

      // Get the length of the string.
      uint64_t StrLen = Str.size();
      if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen))
        StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue();
      StructuredList->resizeInits(Context, StrLen);

      // Build a literal for each character in the string, and put them into
      // the init list.
      for (unsigned i = 0, e = StrLen; i != e; ++i) {
        llvm::APInt CodeUnit(PromotedCharTyWidth, Str[i]);
        Expr *Init = new (Context) IntegerLiteral(
            Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
        if (CharTy != PromotedCharTy)
          Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
                                          Init, nullptr, VK_RValue);
        StructuredList->updateInit(Context, i, Init);
      }
    }
  }

  // Make sure that our non-designated initializer list has space
  // for a subobject corresponding to this array element.
  if (StructuredList &&
      DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
    StructuredList->resizeInits(SemaRef.Context,
                                DesignatedEndIndex.getZExtValue() + 1);

  // Repeatedly perform subobject initializations in the range
  // [DesignatedStartIndex, DesignatedEndIndex].

  // Move to the next designator
  unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
  unsigned OldIndex = Index;

  InitializedEntity ElementEntity =
    InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);

  while (DesignatedStartIndex <= DesignatedEndIndex) {
    // Recurse to check later designated subobjects.
    QualType ElementType = AT->getElementType();
    Index = OldIndex;

    ElementEntity.setElementIndex(ElementIndex);
    if (CheckDesignatedInitializer(
            ElementEntity, IList, DIE, DesigIdx + 1, ElementType, nullptr,
            nullptr, Index, StructuredList, ElementIndex,
            FinishSubobjectInit && (DesignatedStartIndex == DesignatedEndIndex),
            false))
      return true;

    // Move to the next index in the array that we'll be initializing.
    ++DesignatedStartIndex;
    ElementIndex = DesignatedStartIndex.getZExtValue();
  }

  // If this the first designator, our caller will continue checking
  // the rest of this array subobject.
  if (IsFirstDesignator) {
    if (NextElementIndex)
      *NextElementIndex = DesignatedStartIndex;
    StructuredIndex = ElementIndex;
    return false;
  }

  if (!FinishSubobjectInit)
    return false;

  // Check the remaining elements within this array subobject.
  bool prevHadError = hadError;
  CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex,
                 /*SubobjectIsDesignatorContext=*/false, Index,
                 StructuredList, ElementIndex);
  return hadError && !prevHadError;
}

// Get the structured initializer list for a subobject of type
// @p CurrentObjectType.
InitListExpr *
InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
                                            QualType CurrentObjectType,
                                            InitListExpr *StructuredList,
                                            unsigned StructuredIndex,
                                            SourceRange InitRange,
                                            bool IsFullyOverwritten) {
  if (!StructuredList)
    return nullptr;

  Expr *ExistingInit = nullptr;
  if (StructuredIndex < StructuredList->getNumInits())
    ExistingInit = StructuredList->getInit(StructuredIndex);

  if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
    // There might have already been initializers for subobjects of the current
    // object, but a subsequent initializer list will overwrite the entirety
    // of the current object. (See DR 253 and C99 6.7.8p21). e.g.,
    //
    // struct P { char x[6]; };
    // struct P l = { .x[2] = 'x', .x = { [0] = 'f' } };
    //
    // The first designated initializer is ignored, and l.x is just "f".
    if (!IsFullyOverwritten)
      return Result;

  if (ExistingInit) {
    // We are creating an initializer list that initializes the
    // subobjects of the current object, but there was already an
    // initialization that completely initialized the current
    // subobject:
    //
    // struct X { int a, b; };
    // struct X xs[] = { [0] = { 1, 2 }, [0].b = 3 };
    //
    // Here, xs[0].a == 1 and xs[0].b == 3, since the second,
    // designated initializer overwrites the [0].b initializer
    // from the prior initialization.
    //
    // When the existing initializer is an expression rather than an
    // initializer list, we cannot decompose and update it in this way.
    // For example:
    //
    // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
    //
    // This case is handled by CheckDesignatedInitializer.
    diagnoseInitOverride(ExistingInit, InitRange);
  }

  unsigned ExpectedNumInits = 0;
  if (Index < IList->getNumInits()) {
    if (auto *Init = dyn_cast_or_null<InitListExpr>(IList->getInit(Index)))
      ExpectedNumInits = Init->getNumInits();
    else
      ExpectedNumInits = IList->getNumInits() - Index;
  }

  InitListExpr *Result =
      createInitListExpr(CurrentObjectType, InitRange, ExpectedNumInits);

  // Link this new initializer list into the structured initializer
  // lists.
  StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result);
  return Result;
}

InitListExpr *
InitListChecker::createInitListExpr(QualType CurrentObjectType,
                                    SourceRange InitRange,
                                    unsigned ExpectedNumInits) {
  InitListExpr *Result
    = new (SemaRef.Context) InitListExpr(SemaRef.Context,
                                         InitRange.getBegin(), None,
                                         InitRange.getEnd());

  QualType ResultType = CurrentObjectType;
  if (!ResultType->isArrayType())
    ResultType = ResultType.getNonLValueExprType(SemaRef.Context);
  Result->setType(ResultType);

  // Pre-allocate storage for the structured initializer list.
  unsigned NumElements = 0;

  if (const ArrayType *AType
      = SemaRef.Context.getAsArrayType(CurrentObjectType)) {
    if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) {
      NumElements = CAType->getSize().getZExtValue();
      // Simple heuristic so that we don't allocate a very large
      // initializer with many empty entries at the end.
      if (NumElements > ExpectedNumInits)
        NumElements = 0;
    }
  } else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>()) {
    NumElements = VType->getNumElements();
  } else if (CurrentObjectType->isRecordType()) {
    NumElements = numStructUnionElements(CurrentObjectType);
  }

  Result->reserveInits(SemaRef.Context, NumElements);

  return Result;
}

/// Update the initializer at index @p StructuredIndex within the
/// structured initializer list to the value @p expr.
void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
                                                  unsigned &StructuredIndex,
                                                  Expr *expr) {
  // No structured initializer list to update
  if (!StructuredList)
    return;

  if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context,
                                                  StructuredIndex, expr)) {
    // This initializer overwrites a previous initializer. Warn.
    diagnoseInitOverride(PrevInit, expr->getSourceRange());
  }

  ++StructuredIndex;
}

/// Determine whether we can perform aggregate initialization for the purposes
/// of overload resolution.
bool Sema::CanPerformAggregateInitializationForOverloadResolution(
    const InitializedEntity &Entity, InitListExpr *From) {
  QualType Type = Entity.getType();
  InitListChecker Check(*this, Entity, From, Type, /*VerifyOnly=*/true,
                        /*TreatUnavailableAsInvalid=*/false,
                        /*InOverloadResolution=*/true);
  return !Check.HadError();
}

/// Check that the given Index expression is a valid array designator
/// value. This is essentially just a wrapper around
/// VerifyIntegerConstantExpression that also checks for negative values
/// and produces a reasonable diagnostic if there is a
/// failure. Returns the index expression, possibly with an implicit cast
/// added, on success.  If everything went okay, Value will receive the
/// value of the constant expression.
static ExprResult
CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
  SourceLocation Loc = Index->getBeginLoc();

  // Make sure this is an integer constant expression.
  ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value);
  if (Result.isInvalid())
    return Result;

  if (Value.isSigned() && Value.isNegative())
    return S.Diag(Loc, diag::err_array_designator_negative)
      << Value.toString(10) << Index->getSourceRange();

  Value.setIsUnsigned(true);
  return Result;
}

ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
                                            SourceLocation EqualOrColonLoc,
                                            bool GNUSyntax,
                                            ExprResult Init) {
  typedef DesignatedInitExpr::Designator ASTDesignator;

  bool Invalid = false;
  SmallVector<ASTDesignator, 32> Designators;
  SmallVector<Expr *, 32> InitExpressions;

  // Build designators and check array designator expressions.
  for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
    const Designator &D = Desig.getDesignator(Idx);
    switch (D.getKind()) {
    case Designator::FieldDesignator:
      Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(),
                                          D.getFieldLoc()));
      break;

    case Designator::ArrayDesignator: {
      Expr *Index = static_cast<Expr *>(D.getArrayIndex());
      llvm::APSInt IndexValue;
      if (!Index->isTypeDependent() && !Index->isValueDependent())
        Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).get();
      if (!Index)
        Invalid = true;
      else {
        Designators.push_back(ASTDesignator(InitExpressions.size(),
                                            D.getLBracketLoc(),
                                            D.getRBracketLoc()));
        InitExpressions.push_back(Index);
      }
      break;
    }

    case Designator::ArrayRangeDesignator: {
      Expr *StartIndex = static_cast<Expr *>(D.getArrayRangeStart());
      Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd());
      llvm::APSInt StartValue;
      llvm::APSInt EndValue;
      bool StartDependent = StartIndex->isTypeDependent() ||
                            StartIndex->isValueDependent();
      bool EndDependent = EndIndex->isTypeDependent() ||
                          EndIndex->isValueDependent();
      if (!StartDependent)
        StartIndex =
            CheckArrayDesignatorExpr(*this, StartIndex, StartValue).get();
      if (!EndDependent)
        EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).get();

      if (!StartIndex || !EndIndex)
        Invalid = true;
      else {
        // Make sure we're comparing values with the same bit width.
        if (StartDependent || EndDependent) {
          // Nothing to compute.
        } else if (StartValue.getBitWidth() > EndValue.getBitWidth())
          EndValue = EndValue.extend(StartValue.getBitWidth());
        else if (StartValue.getBitWidth() < EndValue.getBitWidth())
          StartValue = StartValue.extend(EndValue.getBitWidth());

        if (!StartDependent && !EndDependent && EndValue < StartValue) {
          Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range)
            << StartValue.toString(10) << EndValue.toString(10)
            << StartIndex->getSourceRange() << EndIndex->getSourceRange();
          Invalid = true;
        } else {
          Designators.push_back(ASTDesignator(InitExpressions.size(),
                                              D.getLBracketLoc(),
                                              D.getEllipsisLoc(),
                                              D.getRBracketLoc()));
          InitExpressions.push_back(StartIndex);
          InitExpressions.push_back(EndIndex);
        }
      }
      break;
    }
    }
  }

  if (Invalid || Init.isInvalid())
    return ExprError();

  // Clear out the expressions within the designation.
  Desig.ClearExprs(*this);

  return DesignatedInitExpr::Create(Context, Designators, InitExpressions,
                                    EqualOrColonLoc, GNUSyntax,
                                    Init.getAs<Expr>());
}

//===----------------------------------------------------------------------===//
// Initialization entity
//===----------------------------------------------------------------------===//

InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
                                     const InitializedEntity &Parent)
  : Parent(&Parent), Index(Index)
{
  if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) {
    Kind = EK_ArrayElement;
    Type = AT->getElementType();
  } else if (const VectorType *VT = Parent.getType()->getAs<VectorType>()) {
    Kind = EK_VectorElement;
    Type = VT->getElementType();
  } else {
    const ComplexType *CT = Parent.getType()->getAs<ComplexType>();
    assert(CT && "Unexpected type");
    Kind = EK_ComplexElement;
    Type = CT->getElementType();
  }
}

InitializedEntity
InitializedEntity::InitializeBase(ASTContext &Context,
                                  const CXXBaseSpecifier *Base,
                                  bool IsInheritedVirtualBase,
                                  const InitializedEntity *Parent) {
  InitializedEntity Result;
  Result.Kind = EK_Base;
  Result.Parent = Parent;
  Result.Base = reinterpret_cast<uintptr_t>(Base);
  if (IsInheritedVirtualBase)
    Result.Base |= 0x01;

  Result.Type = Base->getType();
  return Result;
}

DeclarationName InitializedEntity::getName() const {
  switch (getKind()) {
  case EK_Parameter:
  case EK_Parameter_CF_Audited: {
    ParmVarDecl *D = reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
    return (D ? D->getDeclName() : DeclarationName());
  }

  case EK_Variable:
  case EK_Member:
  case EK_Binding:
    return Variable.VariableOrMember->getDeclName();

  case EK_LambdaCapture:
    return DeclarationName(Capture.VarID);

  case EK_Result:
  case EK_StmtExprResult:
  case EK_Exception:
  case EK_New:
  case EK_Temporary:
  case EK_Base:
  case EK_Delegating:
  case EK_ArrayElement:
  case EK_VectorElement:
  case EK_ComplexElement:
  case EK_BlockElement:
  case EK_LambdaToBlockConversionBlockElement:
  case EK_CompoundLiteralInit:
  case EK_RelatedResult:
    return DeclarationName();
  }

  llvm_unreachable("Invalid EntityKind!");
}

ValueDecl *InitializedEntity::getDecl() const {
  switch (getKind()) {
  case EK_Variable:
  case EK_Member:
  case EK_Binding:
    return Variable.VariableOrMember;

  case EK_Parameter:
  case EK_Parameter_CF_Audited:
    return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);

  case EK_Result:
  case EK_StmtExprResult:
  case EK_Exception:
  case EK_New:
  case EK_Temporary:
  case EK_Base:
  case EK_Delegating:
  case EK_ArrayElement:
  case EK_VectorElement:
  case EK_ComplexElement:
  case EK_BlockElement:
  case EK_LambdaToBlockConversionBlockElement:
  case EK_LambdaCapture:
  case EK_CompoundLiteralInit:
  case EK_RelatedResult:
    return nullptr;
  }

  llvm_unreachable("Invalid EntityKind!");
}

bool InitializedEntity::allowsNRVO() const {
  switch (getKind()) {
  case EK_Result:
  case EK_Exception:
    return LocAndNRVO.NRVO;

  case EK_StmtExprResult:
  case EK_Variable:
  case EK_Parameter:
  case EK_Parameter_CF_Audited:
  case EK_Member:
  case EK_Binding:
  case EK_New:
  case EK_Temporary:
  case EK_CompoundLiteralInit:
  case EK_Base:
  case EK_Delegating:
  case EK_ArrayElement:
  case EK_VectorElement:
  case EK_ComplexElement:
  case EK_BlockElement:
  case EK_LambdaToBlockConversionBlockElement:
  case EK_LambdaCapture:
  case EK_RelatedResult:
    break;
  }

  return false;
}

unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
  assert(getParent() != this);
  unsigned Depth = getParent() ? getParent()->dumpImpl(OS) : 0;
  for (unsigned I = 0; I != Depth; ++I)
    OS << "`-";

  switch (getKind()) {
  case EK_Variable: OS << "Variable"; break;
  case EK_Parameter: OS << "Parameter"; break;
  case EK_Parameter_CF_Audited: OS << "CF audited function Parameter";
    break;
  case EK_Result: OS << "Result"; break;
  case EK_StmtExprResult: OS << "StmtExprResult"; break;
  case EK_Exception: OS << "Exception"; break;
  case EK_Member: OS << "Member"; break;
  case EK_Binding: OS << "Binding"; break;
  case EK_New: OS << "New"; break;
  case EK_Temporary: OS << "Temporary"; break;
  case EK_CompoundLiteralInit: OS << "CompoundLiteral";break;
  case EK_RelatedResult: OS << "RelatedResult"; break;
  case EK_Base: OS << "Base"; break;
  case EK_Delegating: OS << "Delegating"; break;
  case EK_ArrayElement: OS << "ArrayElement " << Index; break;
  case EK_VectorElement: OS << "VectorElement " << Index; break;
  case EK_ComplexElement: OS << "ComplexElement " << Index; break;
  case EK_BlockElement: OS << "Block"; break;
  case EK_LambdaToBlockConversionBlockElement:
    OS << "Block (lambda)";
    break;
  case EK_LambdaCapture:
    OS << "LambdaCapture ";
    OS << DeclarationName(Capture.VarID);
    break;
  }

  if (auto *D = getDecl()) {
    OS << " ";
    D->printQualifiedName(OS);
  }

  OS << " '" << getType().getAsString() << "'\n";

  return Depth + 1;
}

LLVM_DUMP_METHOD void InitializedEntity::dump() const {
  dumpImpl(llvm::errs());
}

//===----------------------------------------------------------------------===//
// Initialization sequence
//===----------------------------------------------------------------------===//

void InitializationSequence::Step::Destroy() {
  switch (Kind) {
  case SK_ResolveAddressOfOverloadedFunction:
  case SK_CastDerivedToBaseRValue:
  case SK_CastDerivedToBaseXValue:
  case SK_CastDerivedToBaseLValue:
  case SK_BindReference:
  case SK_BindReferenceToTemporary:
  case SK_FinalCopy:
  case SK_ExtraneousCopyToTemporary:
  case SK_UserConversion:
  case SK_QualificationConversionRValue:
  case SK_QualificationConversionXValue:
  case SK_QualificationConversionLValue:
  case SK_AtomicConversion:
  case SK_ListInitialization:
  case SK_UnwrapInitList:
  case SK_RewrapInitList:
  case SK_ConstructorInitialization:
  case SK_ConstructorInitializationFromList:
  case SK_ZeroInitialization:
  case SK_CAssignment:
  case SK_StringInit:
  case SK_ObjCObjectConversion:
  case SK_ArrayLoopIndex:
  case SK_ArrayLoopInit:
  case SK_ArrayInit:
  case SK_GNUArrayInit:
  case SK_ParenthesizedArrayInit:
  case SK_PassByIndirectCopyRestore:
  case SK_PassByIndirectRestore:
  case SK_ProduceObjCObject:
  case SK_StdInitializerList:
  case SK_StdInitializerListConstructorCall:
  case SK_OCLSamplerInit:
  case SK_OCLZeroOpaqueType:
    break;

  case SK_ConversionSequence:
  case SK_ConversionSequenceNoNarrowing:
    delete ICS;
  }
}

bool InitializationSequence::isDirectReferenceBinding() const {
  // There can be some lvalue adjustments after the SK_BindReference step.
  for (auto I = Steps.rbegin(); I != Steps.rend(); ++I) {
    if (I->Kind == SK_BindReference)
      return true;
    if (I->Kind == SK_BindReferenceToTemporary)
      return false;
  }
  return false;
}

bool InitializationSequence::isAmbiguous() const {
  if (!Failed())
    return false;

  switch (getFailureKind()) {
  case FK_TooManyInitsForReference:
  case FK_ParenthesizedListInitForReference:
  case FK_ArrayNeedsInitList:
  case FK_ArrayNeedsInitListOrStringLiteral:
  case FK_ArrayNeedsInitListOrWideStringLiteral:
  case FK_NarrowStringIntoWideCharArray:
  case FK_WideStringIntoCharArray:
  case FK_IncompatWideStringIntoWideChar:
  case FK_PlainStringIntoUTF8Char:
  case FK_UTF8StringIntoPlainChar:
  case FK_AddressOfOverloadFailed: // FIXME: Could do better
  case FK_NonConstLValueReferenceBindingToTemporary:
  case FK_NonConstLValueReferenceBindingToBitfield:
  case FK_NonConstLValueReferenceBindingToVectorElement:
  case FK_NonConstLValueReferenceBindingToUnrelated:
  case FK_RValueReferenceBindingToLValue:
  case FK_ReferenceAddrspaceMismatchTemporary:
  case FK_ReferenceInitDropsQualifiers:
  case FK_ReferenceInitFailed:
  case FK_ConversionFailed:
  case FK_ConversionFromPropertyFailed:
  case FK_TooManyInitsForScalar:
  case FK_ParenthesizedListInitForScalar:
  case FK_ReferenceBindingToInitList:
  case FK_InitListBadDestinationType:
  case FK_DefaultInitOfConst:
  case FK_Incomplete:
  case FK_ArrayTypeMismatch:
  case FK_NonConstantArrayInit:
  case FK_ListInitializationFailed:
  case FK_VariableLengthArrayHasInitializer:
  case FK_PlaceholderType:
  case FK_ExplicitConstructor:
  case FK_AddressOfUnaddressableFunction:
    return false;

  case FK_ReferenceInitOverloadFailed:
  case FK_UserConversionOverloadFailed:
  case FK_ConstructorOverloadFailed:
  case FK_ListConstructorOverloadFailed:
    return FailedOverloadResult == OR_Ambiguous;
  }

  llvm_unreachable("Invalid EntityKind!");
}

bool InitializationSequence::isConstructorInitialization() const {
  return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization;
}

void
InitializationSequence
::AddAddressOverloadResolutionStep(FunctionDecl *Function,
                                   DeclAccessPair Found,
                                   bool HadMultipleCandidates) {
  Step S;
  S.Kind = SK_ResolveAddressOfOverloadedFunction;
  S.Type = Function->getType();
  S.Function.HadMultipleCandidates = HadMultipleCandidates;
  S.Function.Function = Function;
  S.Function.FoundDecl = Found;
  Steps.push_back(S);
}

void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
                                                      ExprValueKind VK) {
  Step S;
  switch (VK) {
  case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break;
  case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break;
  case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break;
  }
  S.Type = BaseType;
  Steps.push_back(S);
}

void InitializationSequence::AddReferenceBindingStep(QualType T,
                                                     bool BindingTemporary) {
  Step S;
  S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddFinalCopy(QualType T) {
  Step S;
  S.Kind = SK_FinalCopy;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) {
  Step S;
  S.Kind = SK_ExtraneousCopyToTemporary;
  S.Type = T;
  Steps.push_back(S);
}

void
InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
                                              DeclAccessPair FoundDecl,
                                              QualType T,
                                              bool HadMultipleCandidates) {
  Step S;
  S.Kind = SK_UserConversion;
  S.Type = T;
  S.Function.HadMultipleCandidates = HadMultipleCandidates;
  S.Function.Function = Function;
  S.Function.FoundDecl = FoundDecl;
  Steps.push_back(S);
}

void InitializationSequence::AddQualificationConversionStep(QualType Ty,
                                                            ExprValueKind VK) {
  Step S;
  S.Kind = SK_QualificationConversionRValue; // work around a gcc warning
  switch (VK) {
  case VK_RValue:
    S.Kind = SK_QualificationConversionRValue;
    break;
  case VK_XValue:
    S.Kind = SK_QualificationConversionXValue;
    break;
  case VK_LValue:
    S.Kind = SK_QualificationConversionLValue;
    break;
  }
  S.Type = Ty;
  Steps.push_back(S);
}

void InitializationSequence::AddAtomicConversionStep(QualType Ty) {
  Step S;
  S.Kind = SK_AtomicConversion;
  S.Type = Ty;
  Steps.push_back(S);
}

void InitializationSequence::AddConversionSequenceStep(
    const ImplicitConversionSequence &ICS, QualType T,
    bool TopLevelOfInitList) {
  Step S;
  S.Kind = TopLevelOfInitList ? SK_ConversionSequenceNoNarrowing
                              : SK_ConversionSequence;
  S.Type = T;
  S.ICS = new ImplicitConversionSequence(ICS);
  Steps.push_back(S);
}

void InitializationSequence::AddListInitializationStep(QualType T) {
  Step S;
  S.Kind = SK_ListInitialization;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddConstructorInitializationStep(
    DeclAccessPair FoundDecl, CXXConstructorDecl *Constructor, QualType T,
    bool HadMultipleCandidates, bool FromInitList, bool AsInitList) {
  Step S;
  S.Kind = FromInitList ? AsInitList ? SK_StdInitializerListConstructorCall
                                     : SK_ConstructorInitializationFromList
                        : SK_ConstructorInitialization;
  S.Type = T;
  S.Function.HadMultipleCandidates = HadMultipleCandidates;
  S.Function.Function = Constructor;
  S.Function.FoundDecl = FoundDecl;
  Steps.push_back(S);
}

void InitializationSequence::AddZeroInitializationStep(QualType T) {
  Step S;
  S.Kind = SK_ZeroInitialization;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddCAssignmentStep(QualType T) {
  Step S;
  S.Kind = SK_CAssignment;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddStringInitStep(QualType T) {
  Step S;
  S.Kind = SK_StringInit;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
  Step S;
  S.Kind = SK_ObjCObjectConversion;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddArrayInitStep(QualType T, bool IsGNUExtension) {
  Step S;
  S.Kind = IsGNUExtension ? SK_GNUArrayInit : SK_ArrayInit;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddArrayInitLoopStep(QualType T, QualType EltT) {
  Step S;
  S.Kind = SK_ArrayLoopIndex;
  S.Type = EltT;
  Steps.insert(Steps.begin(), S);

  S.Kind = SK_ArrayLoopInit;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddParenthesizedArrayInitStep(QualType T) {
  Step S;
  S.Kind = SK_ParenthesizedArrayInit;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddPassByIndirectCopyRestoreStep(QualType type,
                                                              bool shouldCopy) {
  Step s;
  s.Kind = (shouldCopy ? SK_PassByIndirectCopyRestore
                       : SK_PassByIndirectRestore);
  s.Type = type;
  Steps.push_back(s);
}

void InitializationSequence::AddProduceObjCObjectStep(QualType T) {
  Step S;
  S.Kind = SK_ProduceObjCObject;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) {
  Step S;
  S.Kind = SK_StdInitializerList;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddOCLSamplerInitStep(QualType T) {
  Step S;
  S.Kind = SK_OCLSamplerInit;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::AddOCLZeroOpaqueTypeStep(QualType T) {
  Step S;
  S.Kind = SK_OCLZeroOpaqueType;
  S.Type = T;
  Steps.push_back(S);
}

void InitializationSequence::RewrapReferenceInitList(QualType T,
                                                     InitListExpr *Syntactic) {
  assert(Syntactic->getNumInits() == 1 &&
         "Can only rewrap trivial init lists.");
  Step S;
  S.Kind = SK_UnwrapInitList;
  S.Type = Syntactic->getInit(0)->getType();
  Steps.insert(Steps.begin(), S);

  S.Kind = SK_RewrapInitList;
  S.Type = T;
  S.WrappingSyntacticList = Syntactic;
  Steps.push_back(S);
}

void InitializationSequence::SetOverloadFailure(FailureKind Failure,
                                                OverloadingResult Result) {
  setSequenceKind(FailedSequence);
  this->Failure = Failure;
  this->FailedOverloadResult = Result;
}

//===----------------------------------------------------------------------===//
// Attempt initialization
//===----------------------------------------------------------------------===//

/// Tries to add a zero initializer. Returns true if that worked.
static bool
maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence,
                                   const InitializedEntity &Entity) {
  if (Entity.getKind() != InitializedEntity::EK_Variable)
    return false;

  VarDecl *VD = cast<VarDecl>(Entity.getDecl());
  if (VD->getInit() || VD->getEndLoc().isMacroID())
    return false;

  QualType VariableTy = VD->getType().getCanonicalType();
  SourceLocation Loc = S.getLocForEndOfToken(VD->getEndLoc());
  std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
  if (!Init.empty()) {
    Sequence.AddZeroInitializationStep(Entity.getType());
    Sequence.SetZeroInitializationFixit(Init, Loc);
    return true;
  }
  return false;
}

static void MaybeProduceObjCObject(Sema &S,
                                   InitializationSequence &Sequence,
                                   const InitializedEntity &Entity) {
  if (!S.getLangOpts().ObjCAutoRefCount) return;

  /// When initializing a parameter, produce the value if it's marked
  /// __attribute__((ns_consumed)).
  if (Entity.isParameterKind()) {
    if (!Entity.isParameterConsumed())
      return;

    assert(Entity.getType()->isObjCRetainableType() &&
           "consuming an object of unretainable type?");
    Sequence.AddProduceObjCObjectStep(Entity.getType());

  /// When initializing a return value, if the return type is a
  /// retainable type, then returns need to immediately retain the
  /// object.  If an autorelease is required, it will be done at the
  /// last instant.
  } else if (Entity.getKind() == InitializedEntity::EK_Result ||
             Entity.getKind() == InitializedEntity::EK_StmtExprResult) {
    if (!Entity.getType()->isObjCRetainableType())
      return;

    Sequence.AddProduceObjCObjectStep(Entity.getType());
  }
}

static void TryListInitialization(Sema &S,
                                  const InitializedEntity &Entity,
                                  const InitializationKind &Kind,
                                  InitListExpr *InitList,
                                  InitializationSequence &Sequence,
                                  bool TreatUnavailableAsInvalid);

/// When initializing from init list via constructor, handle
/// initialization of an object of type std::initializer_list<T>.
///
/// \return true if we have handled initialization of an object of type
/// std::initializer_list<T>, false otherwise.
static bool TryInitializerListConstruction(Sema &S,
                                           InitListExpr *List,
                                           QualType DestType,
                                           InitializationSequence &Sequence,
                                           bool TreatUnavailableAsInvalid) {
  QualType E;
  if (!S.isStdInitializerList(DestType, &E))
    return false;

  if (!S.isCompleteType(List->getExprLoc(), E)) {
    Sequence.setIncompleteTypeFailure(E);
    return true;
  }

  // Try initializing a temporary array from the init list.
  QualType ArrayType = S.Context.getConstantArrayType(
      E.withConst(),
      llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
                  List->getNumInits()),
      nullptr, clang::ArrayType::Normal, 0);
  InitializedEntity HiddenArray =
      InitializedEntity::InitializeTemporary(ArrayType);
  InitializationKind Kind = InitializationKind::CreateDirectList(
      List->getExprLoc(), List->getBeginLoc(), List->getEndLoc());
  TryListInitialization(S, HiddenArray, Kind, List, Sequence,
                        TreatUnavailableAsInvalid);
  if (Sequence)
    Sequence.AddStdInitializerListConstructionStep(DestType);
  return true;
}

/// Determine if the constructor has the signature of a copy or move
/// constructor for the type T of the class in which it was found. That is,
/// determine if its first parameter is of type T or reference to (possibly
/// cv-qualified) T.
static bool hasCopyOrMoveCtorParam(ASTContext &Ctx,
                                   const ConstructorInfo &Info) {
  if (Info.Constructor->getNumParams() == 0)
    return false;

  QualType ParmT =
      Info.Constructor->getParamDecl(0)->getType().getNonReferenceType();
  QualType ClassT =
      Ctx.getRecordType(cast<CXXRecordDecl>(Info.FoundDecl->getDeclContext()));

  return Ctx.hasSameUnqualifiedType(ParmT, ClassT);
}

static OverloadingResult
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
                           MultiExprArg Args,
                           OverloadCandidateSet &CandidateSet,
                           QualType DestType,
                           DeclContext::lookup_result Ctors,
                           OverloadCandidateSet::iterator &Best,
                           bool CopyInitializing, bool AllowExplicit,
                           bool OnlyListConstructors, bool IsListInit,
                           bool SecondStepOfCopyInit = false) {
  CandidateSet.clear(OverloadCandidateSet::CSK_InitByConstructor);
  CandidateSet.setDestAS(DestType.getQualifiers().getAddressSpace());

  for (NamedDecl *D : Ctors) {
    auto Info = getConstructorInfo(D);
    if (!Info.Constructor || Info.Constructor->isInvalidDecl())
      continue;

    if (!AllowExplicit && Info.Constructor->isExplicit())
      continue;

    if (OnlyListConstructors && !S.isInitListConstructor(Info.Constructor))
      continue;

    // C++11 [over.best.ics]p4:
    //   ... and the constructor or user-defined conversion function is a
    //   candidate by
    //   - 13.3.1.3, when the argument is the temporary in the second step
    //     of a class copy-initialization, or
    //   - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), [not handled here]
    //   - the second phase of 13.3.1.7 when the initializer list has exactly
    //     one element that is itself an initializer list, and the target is
    //     the first parameter of a constructor of class X, and the conversion
    //     is to X or reference to (possibly cv-qualified X),
    //   user-defined conversion sequences are not considered.
    bool SuppressUserConversions =
        SecondStepOfCopyInit ||
        (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]) &&
         hasCopyOrMoveCtorParam(S.Context, Info));

    if (Info.ConstructorTmpl)
      S.AddTemplateOverloadCandidate(
          Info.ConstructorTmpl, Info.FoundDecl,
          /*ExplicitArgs*/ nullptr, Args, CandidateSet, SuppressUserConversions,
          /*PartialOverloading=*/false, AllowExplicit);
    else {
      // C++ [over.match.copy]p1:
      //   - When initializing a temporary to be bound to the first parameter
      //     of a constructor [for type T] that takes a reference to possibly
      //     cv-qualified T as its first argument, called with a single
      //     argument in the context of direct-initialization, explicit
      //     conversion functions are also considered.
      // FIXME: What if a constructor template instantiates to such a signature?
      bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
                               Args.size() == 1 &&
                               hasCopyOrMoveCtorParam(S.Context, Info);
      S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
                             CandidateSet, SuppressUserConversions,
                             /*PartialOverloading=*/false, AllowExplicit,
                             AllowExplicitConv);
    }
  }

  // FIXME: Work around a bug in C++17 guaranteed copy elision.
  //
  // When initializing an object of class type T by constructor
  // ([over.match.ctor]) or by list-initialization ([over.match.list])
  // from a single expression of class type U, conversion functions of
  // U that convert to the non-reference type cv T are candidates.
  // Explicit conversion functions are only candidates during
  // direct-initialization.
  //
  // Note: SecondStepOfCopyInit is only ever true in this case when
  // evaluating whether to produce a C++98 compatibility warning.
  if (S.getLangOpts().CPlusPlus17 && Args.size() == 1 &&
      !SecondStepOfCopyInit) {
    Expr *Initializer = Args[0];
    auto *SourceRD = Initializer->getType()->getAsCXXRecordDecl();
    if (SourceRD && S.isCompleteType(DeclLoc, Initializer->getType())) {
      const auto &Conversions = SourceRD->getVisibleConversionFunctions();
      for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
        NamedDecl *D = *I;
        CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
        D = D->getUnderlyingDecl();

        FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
        CXXConversionDecl *Conv;
        if (ConvTemplate)
          Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
        else
          Conv = cast<CXXConversionDecl>(D);

        if (AllowExplicit || !Conv->isExplicit()) {
          if (ConvTemplate)
            S.AddTemplateConversionCandidate(
                ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
                CandidateSet, AllowExplicit, AllowExplicit,
                /*AllowResultConversion*/ false);
          else
            S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer,
                                     DestType, CandidateSet, AllowExplicit,
                                     AllowExplicit,
                                     /*AllowResultConversion*/ false);
        }
      }
    }
  }

  // Perform overload resolution and return the result.
  return CandidateSet.BestViableFunction(S, DeclLoc, Best);
}

/// Attempt initialization by constructor (C++ [dcl.init]), which
/// enumerates the constructors of the initialized entity and performs overload
/// resolution to select the best.
/// \param DestType       The destination class type.
/// \param DestArrayType  The destination type, which is either DestType or
///                       a (possibly multidimensional) array of DestType.
/// \param IsListInit     Is this list-initialization?
/// \param IsInitListCopy Is this non-list-initialization resulting from a
///                       list-initialization from {x} where x is the same
///                       type as the entity?
static void TryConstructorInitialization(Sema &S,
                                         const InitializedEntity &Entity,
                                         const InitializationKind &Kind,
                                         MultiExprArg Args, QualType DestType,
                                         QualType DestArrayType,
                                         InitializationSequence &Sequence,
                                         bool IsListInit = false,
                                         bool IsInitListCopy = false) {
  assert(((!IsListInit && !IsInitListCopy) ||
          (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
         "IsListInit/IsInitListCopy must come with a single initializer list "
         "argument.");
  InitListExpr *ILE =
      (IsListInit || IsInitListCopy) ? cast<InitListExpr>(Args[0]) : nullptr;
  MultiExprArg UnwrappedArgs =
      ILE ? MultiExprArg(ILE->getInits(), ILE->getNumInits()) : Args;

  // The type we're constructing needs to be complete.
  if (!S.isCompleteType(Kind.getLocation(), DestType)) {
    Sequence.setIncompleteTypeFailure(DestType);
    return;
  }

  // C++17 [dcl.init]p17:
  //     - If the initializer expression is a prvalue and the cv-unqualified
  //       version of the source type is the same class as the class of the
  //       destination, the initializer expression is used to initialize the
  //       destination object.
  // Per DR (no number yet), this does not apply when initializing a base
  // class or delegating to another constructor from a mem-initializer.
  // ObjC++: Lambda captured by the block in the lambda to block conversion
  // should avoid copy elision.
  if (S.getLangOpts().CPlusPlus17 &&
      Entity.getKind() != InitializedEntity::EK_Base &&
      Entity.getKind() != InitializedEntity::EK_Delegating &&
      Entity.getKind() !=
          InitializedEntity::EK_LambdaToBlockConversionBlockElement &&
      UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() &&
      S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) {
    // Convert qualifications if necessary.
    Sequence.AddQualificationConversionStep(DestType, VK_RValue);
    if (ILE)
      Sequence.RewrapReferenceInitList(DestType, ILE);
    return;
  }

  const RecordType *DestRecordType = DestType->getAs<RecordType>();
  assert(DestRecordType && "Constructor initialization requires record type");
  CXXRecordDecl *DestRecordDecl
    = cast<CXXRecordDecl>(DestRecordType->getDecl());

  // Build the candidate set directly in the initialization sequence
  // structure, so that it will persist if we fail.
  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();

  // Determine whether we are allowed to call explicit constructors or
  // explicit conversion operators.
  bool AllowExplicit = Kind.AllowExplicit() || IsListInit;
  bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy;

  //   - Otherwise, if T is a class type, constructors are considered. The
  //     applicable constructors are enumerated, and the best one is chosen
  //     through overload resolution.
  DeclContext::lookup_result Ctors = S.LookupConstructors(DestRecordDecl);

  OverloadingResult Result = OR_No_Viable_Function;
  OverloadCandidateSet::iterator Best;
  bool AsInitializerList = false;

  // C++11 [over.match.list]p1, per DR1467:
  //   When objects of non-aggregate type T are list-initialized, such that
  //   8.5.4 [dcl.init.list] specifies that overload resolution is performed
  //   according to the rules in this section, overload resolution selects
  //   the constructor in two phases:
  //
  //   - Initially, the candidate functions are the initializer-list
  //     constructors of the class T and the argument list consists of the
  //     initializer list as a single argument.
  if (IsListInit) {
    AsInitializerList = true;

    // If the initializer list has no elements and T has a default constructor,
    // the first phase is omitted.
    if (!(UnwrappedArgs.empty() && DestRecordDecl->hasDefaultConstructor()))
      Result = ResolveConstructorOverload(S, Kind.getLocation(), Args,
                                          CandidateSet, DestType, Ctors, Best,
                                          CopyInitialization, AllowExplicit,
                                          /*OnlyListConstructors=*/true,
                                          IsListInit);
  }

  // C++11 [over.match.list]p1:
  //   - If no viable initializer-list constructor is found, overload resolution
  //     is performed again, where the candidate functions are all the
  //     constructors of the class T and the argument list consists of the
  //     elements of the initializer list.
  if (Result == OR_No_Viable_Function) {
    AsInitializerList = false;
    Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs,
                                        CandidateSet, DestType, Ctors, Best,
                                        CopyInitialization, AllowExplicit,
                                        /*OnlyListConstructors=*/false,
                                        IsListInit);
  }
  if (Result) {
    Sequence.SetOverloadFailure(IsListInit ?
                      InitializationSequence::FK_ListConstructorOverloadFailed :
                      InitializationSequence::FK_ConstructorOverloadFailed,
                                Result);
    return;
  }

  bool HadMultipleCandidates = (CandidateSet.size() > 1);

  // In C++17, ResolveConstructorOverload can select a conversion function
  // instead of a constructor.
  if (auto *CD = dyn_cast<CXXConversionDecl>(Best->Function)) {
    // Add the user-defined conversion step that calls the conversion function.
    QualType ConvType = CD->getConversionType();
    assert(S.Context.hasSameUnqualifiedType(ConvType, DestType) &&
           "should not have selected this conversion function");
    Sequence.AddUserConversionStep(CD, Best->FoundDecl, ConvType,
                                   HadMultipleCandidates);
    if (!S.Context.hasSameType(ConvType, DestType))
      Sequence.AddQualificationConversionStep(DestType, VK_RValue);
    if (IsListInit)
      Sequence.RewrapReferenceInitList(Entity.getType(), ILE);
    return;
  }

  // C++11 [dcl.init]p6:
  //   If a program calls for the default initialization of an object
  //   of a const-qualified type T, T shall be a class type with a
  //   user-provided default constructor.
  // C++ core issue 253 proposal:
  //   If the implicit default constructor initializes all subobjects, no
  //   initializer should be required.
  // The 253 proposal is for example needed to process libstdc++ headers in 5.x.
  CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
  if (Kind.getKind() == InitializationKind::IK_Default &&
      Entity.getType().isConstQualified()) {
    if (!CtorDecl->getParent()->allowConstDefaultInit()) {
      if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
        Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
      return;
    }
  }

  // C++11 [over.match.list]p1:
  //   In copy-list-initialization, if an explicit constructor is chosen, the
  //   initializer is ill-formed.
  if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
    Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
    return;
  }

  // Add the constructor initialization step. Any cv-qualification conversion is
  // subsumed by the initialization.
  Sequence.AddConstructorInitializationStep(
      Best->FoundDecl, CtorDecl, DestArrayType, HadMultipleCandidates,
      IsListInit | IsInitListCopy, AsInitializerList);
}

static bool
ResolveOverloadedFunctionForReferenceBinding(Sema &S,
                                             Expr *Initializer,
                                             QualType &SourceType,
                                             QualType &UnqualifiedSourceType,
                                             QualType UnqualifiedTargetType,
                                             InitializationSequence &Sequence) {
  if (S.Context.getCanonicalType(UnqualifiedSourceType) ==
        S.Context.OverloadTy) {
    DeclAccessPair Found;
    bool HadMultipleCandidates = false;
    if (FunctionDecl *Fn
        = S.ResolveAddressOfOverloadedFunction(Initializer,
                                               UnqualifiedTargetType,
                                               false, Found,
                                               &HadMultipleCandidates)) {
      Sequence.AddAddressOverloadResolutionStep(Fn, Found,
                                                HadMultipleCandidates);
      SourceType = Fn->getType();
      UnqualifiedSourceType = SourceType.getUnqualifiedType();
    } else if (!UnqualifiedTargetType->isRecordType()) {
      Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
      return true;
    }
  }
  return false;
}

static void TryReferenceInitializationCore(Sema &S,
                                           const InitializedEntity &Entity,
                                           const InitializationKind &Kind,
                                           Expr *Initializer,
                                           QualType cv1T1, QualType T1,
                                           Qualifiers T1Quals,
                                           QualType cv2T2, QualType T2,
                                           Qualifiers T2Quals,
                                           InitializationSequence &Sequence);

static void TryValueInitialization(Sema &S,
                                   const InitializedEntity &Entity,
                                   const InitializationKind &Kind,
                                   InitializationSequence &Sequence,
                                   InitListExpr *InitList = nullptr);

/// Attempt list initialization of a reference.
static void TryReferenceListInitialization(Sema &S,
                                           const InitializedEntity &Entity,
                                           const InitializationKind &Kind,
                                           InitListExpr *InitList,
                                           InitializationSequence &Sequence,
                                           bool TreatUnavailableAsInvalid) {
  // First, catch C++03 where this isn't possible.
  if (!S.getLangOpts().CPlusPlus11) {
    Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
    return;
  }
  // Can't reference initialize a compound literal.
  if (Entity.getKind() == InitializedEntity::EK_CompoundLiteralInit) {
    Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
    return;
  }

  QualType DestType = Entity.getType();
  QualType cv1T1 = DestType->castAs<ReferenceType>()->getPointeeType();
  Qualifiers T1Quals;
  QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);

  // Reference initialization via an initializer list works thus:
  // If the initializer list consists of a single element that is
  // reference-related to the referenced type, bind directly to that element
  // (possibly creating temporaries).
  // Otherwise, initialize a temporary with the initializer list and
  // bind to that.
  if (InitList->getNumInits() == 1) {
    Expr *Initializer = InitList->getInit(0);
    QualType cv2T2 = Initializer->getType();
    Qualifiers T2Quals;
    QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);

    // If this fails, creating a temporary wouldn't work either.
    if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2,
                                                     T1, Sequence))
      return;

    SourceLocation DeclLoc = Initializer->getBeginLoc();
    bool dummy1, dummy2, dummy3, dummy4;
    Sema::ReferenceCompareResult RefRelationship
      = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1,
                                       dummy2, dummy3, dummy4);
    if (RefRelationship >= Sema::Ref_Related) {
      // Try to bind the reference here.
      TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1,
                                     T1Quals, cv2T2, T2, T2Quals, Sequence);
      if (Sequence)
        Sequence.RewrapReferenceInitList(cv1T1, InitList);
      return;
    }

    // Update the initializer if we've resolved an overloaded function.
    if (Sequence.step_begin() != Sequence.step_end())
      Sequence.RewrapReferenceInitList(cv1T1, InitList);
  }

  // Not reference-related. Create a temporary and bind to that.
  InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);

  TryListInitialization(S, TempEntity, Kind, InitList, Sequence,
                        TreatUnavailableAsInvalid);
  if (Sequence) {
    if (DestType->isRValueReferenceType() ||
        (T1Quals.hasConst() && !T1Quals.hasVolatile()))
      Sequence.AddReferenceBindingStep(cv1T1, /*BindingTemporary=*/true);
    else
      Sequence.SetFailed(
          InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
  }
}

/// Attempt list initialization (C++0x [dcl.init.list])
static void TryListInitialization(Sema &S,
                                  const InitializedEntity &Entity,
                                  const InitializationKind &Kind,
                                  InitListExpr *InitList,
                                  InitializationSequence &Sequence,
                                  bool TreatUnavailableAsInvalid) {
  QualType DestType = Entity.getType();

  // C++ doesn't allow scalar initialization with more than one argument.
  // But C99 complex numbers are scalars and it makes sense there.
  if (S.getLangOpts().CPlusPlus && DestType->isScalarType() &&
      !DestType->isAnyComplexType() && InitList->getNumInits() > 1) {
    Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
    return;
  }
  if (DestType->isReferenceType()) {
    TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence,
                                   TreatUnavailableAsInvalid);
    return;
  }

  if (DestType->isRecordType() &&
      !S.isCompleteType(InitList->getBeginLoc(), DestType)) {
    Sequence.setIncompleteTypeFailure(DestType);
    return;
  }

  // C++11 [dcl.init.list]p3, per DR1467:
  // - If T is a class type and the initializer list has a single element of
  //   type cv U, where U is T or a class derived from T, the object is
  //   initialized from that element (by copy-initialization for
  //   copy-list-initialization, or by direct-initialization for
  //   direct-list-initialization).
  // - Otherwise, if T is a character array and the initializer list has a
  //   single element that is an appropriately-typed string literal
  //   (8.5.2 [dcl.init.string]), initialization is performed as described
  //   in that section.
  // - Otherwise, if T is an aggregate, [...] (continue below).
  if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1) {
    if (DestType->isRecordType()) {
      QualType InitType = InitList->getInit(0)->getType();
      if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
          S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
        Expr *InitListAsExpr = InitList;
        TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
                                     DestType, Sequence,
                                     /*InitListSyntax*/false,
                                     /*IsInitListCopy*/true);
        return;
      }
    }
    if (const ArrayType *DestAT = S.Context.getAsArrayType(DestType)) {
      Expr *SubInit[1] = {InitList->getInit(0)};
      if (!isa<VariableArrayType>(DestAT) &&
          IsStringInit(SubInit[0], DestAT, S.Context) == SIF_None) {
        InitializationKind SubKind =
            Kind.getKind() == InitializationKind::IK_DirectList
                ? InitializationKind::CreateDirect(Kind.getLocation(),
                                                   InitList->getLBraceLoc(),
                                                   InitList->getRBraceLoc())
                : Kind;
        Sequence.InitializeFrom(S, Entity, SubKind, SubInit,
                                /*TopLevelOfInitList*/ true,
                                TreatUnavailableAsInvalid);

        // TryStringLiteralInitialization() (in InitializeFrom()) will fail if
        // the element is not an appropriately-typed string literal, in which
        // case we should proceed as in C++11 (below).
        if (Sequence) {
          Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
          return;
        }
      }
    }
  }

  // C++11 [dcl.init.list]p3:
  //   - If T is an aggregate, aggregate initialization is performed.
  if ((DestType->isRecordType() && !DestType->isAggregateType()) ||
      (S.getLangOpts().CPlusPlus11 &&
       S.isStdInitializerList(DestType, nullptr))) {
    if (S.getLangOpts().CPlusPlus11) {
      //   - Otherwise, if the initializer list has no elements and T is a
      //     class type with a default constructor, the object is
      //     value-initialized.
      if (InitList->getNumInits() == 0) {
        CXXRecordDecl *RD = DestType->getAsCXXRecordDecl();
        if (RD->hasDefaultConstructor()) {
          TryValueInitialization(S, Entity, Kind, Sequence, InitList);
          return;
        }
      }

      //   - Otherwise, if T is a specialization of std::initializer_list<E>,
      //     an initializer_list object constructed [...]
      if (TryInitializerListConstruction(S, InitList, DestType, Sequence,
                                         TreatUnavailableAsInvalid))
        return;

      //   - Otherwise, if T is a class type, constructors are considered.
      Expr *InitListAsExpr = InitList;
      TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
                                   DestType, Sequence, /*InitListSyntax*/true);
    } else
      Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
    return;
  }

  if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() &&
      InitList->getNumInits() == 1) {
    Expr *E = InitList->getInit(0);

    //   - Otherwise, if T is an enumeration with a fixed underlying type,
    //     the initializer-list has a single element v, and the initialization
    //     is direct-list-initialization, the object is initialized with the
    //     value T(v); if a narrowing conversion is required to convert v to
    //     the underlying type of T, the program is ill-formed.
    auto *ET = DestType->getAs<EnumType>();
    if (S.getLangOpts().CPlusPlus17 &&
        Kind.getKind() == InitializationKind::IK_DirectList &&
        ET && ET->getDecl()->isFixed() &&
        !S.Context.hasSameUnqualifiedType(E->getType(), DestType) &&
        (E->getType()->isIntegralOrEnumerationType() ||
         E->getType()->isFloatingType())) {
      // There are two ways that T(v) can work when T is an enumeration type.
      // If there is either an implicit conversion sequence from v to T or
      // a conversion function that can convert from v to T, then we use that.
      // Otherwise, if v is of integral, enumeration, or floating-point type,
      // it is converted to the enumeration type via its underlying type.
      // There is no overlap possible between these two cases (except when the
      // source value is already of the destination type), and the first
      // case is handled by the general case for single-element lists below.
      ImplicitConversionSequence ICS;
      ICS.setStandard();
      ICS.Standard.setAsIdentityConversion();
      if (!E->isRValue())
        ICS.Standard.First = ICK_Lvalue_To_Rvalue;
      // If E is of a floating-point type, then the conversion is ill-formed
      // due to narrowing, but go through the motions in order to produce the
      // right diagnostic.
      ICS.Standard.Second = E->getType()->isFloatingType()
                                ? ICK_Floating_Integral
                                : ICK_Integral_Conversion;
      ICS.Standard.setFromType(E->getType());
      ICS.Standard.setToType(0, E->getType());
      ICS.Standard.setToType(1, DestType);
      ICS.Standard.setToType(2, DestType);
      Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2),
                                         /*TopLevelOfInitList*/true);
      Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
      return;
    }

    //   - Otherwise, if the initializer list has a single element of type E
    //     [...references are handled above...], the object or reference is
    //     initialized from that element (by copy-initialization for
    //     copy-list-initialization, or by direct-initialization for
    //     direct-list-initialization); if a narrowing conversion is required
    //     to convert the element to T, the program is ill-formed.
    //
    // Per core-24034, this is direct-initialization if we were performing
    // direct-list-initialization and copy-initialization otherwise.
    // We can't use InitListChecker for this, because it always performs
    // copy-initialization. This only matters if we might use an 'explicit'
    // conversion operator, so we only need to handle the cases where the source
    // is of record type.
    if (InitList->getInit(0)->getType()->isRecordType()) {
      InitializationKind SubKind =
          Kind.getKind() == InitializationKind::IK_DirectList
              ? InitializationKind::CreateDirect(Kind.getLocation(),
                                                 InitList->getLBraceLoc(),
                                                 InitList->getRBraceLoc())
              : Kind;
      Expr *SubInit[1] = { InitList->getInit(0) };
      Sequence.InitializeFrom(S, Entity, SubKind, SubInit,
                              /*TopLevelOfInitList*/true,
                              TreatUnavailableAsInvalid);
      if (Sequence)
        Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
      return;
    }
  }

  InitListChecker CheckInitList(S, Entity, InitList,
          DestType, /*VerifyOnly=*/true, TreatUnavailableAsInvalid);
  if (CheckInitList.HadError()) {
    Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
    return;
  }

  // Add the list initialization step with the built init list.
  Sequence.AddListInitializationStep(DestType);
}

/// Try a reference initialization that involves calling a conversion
/// function.
static OverloadingResult TryRefInitWithConversionFunction(
    Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
    Expr *Initializer, bool AllowRValues, bool IsLValueRef,
    InitializationSequence &Sequence) {
  QualType DestType = Entity.getType();
  QualType cv1T1 = DestType->castAs<ReferenceType>()->getPointeeType();
  QualType T1 = cv1T1.getUnqualifiedType();
  QualType cv2T2 = Initializer->getType();
  QualType T2 = cv2T2.getUnqualifiedType();

  bool DerivedToBase;
  bool ObjCConversion;
  bool ObjCLifetimeConversion;
  bool FunctionConversion;
  assert(!S.CompareReferenceRelationship(
             Initializer->getBeginLoc(), T1, T2, DerivedToBase, ObjCConversion,
             ObjCLifetimeConversion, FunctionConversion) &&
         "Must have incompatible references when binding via conversion");
  (void)DerivedToBase;
  (void)ObjCConversion;
  (void)ObjCLifetimeConversion;
  (void)FunctionConversion;

  // Build the candidate set directly in the initialization sequence
  // structure, so that it will persist if we fail.
  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
  CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);

  // Determine whether we are allowed to call explicit conversion operators.
  // Note that none of [over.match.copy], [over.match.conv], nor
  // [over.match.ref] permit an explicit constructor to be chosen when
  // initializing a reference, not even for direct-initialization.
  bool AllowExplicitCtors = false;
  bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding();

  const RecordType *T1RecordType = nullptr;
  if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
      S.isCompleteType(Kind.getLocation(), T1)) {
    // The type we're converting to is a class type. Enumerate its constructors
    // to see if there is a suitable conversion.
    CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());

    for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) {
      auto Info = getConstructorInfo(D);
      if (!Info.Constructor)
        continue;

      if (!Info.Constructor->isInvalidDecl() &&
          Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) {
        if (Info.ConstructorTmpl)
          S.AddTemplateOverloadCandidate(
              Info.ConstructorTmpl, Info.FoundDecl,
              /*ExplicitArgs*/ nullptr, Initializer, CandidateSet,
              /*SuppressUserConversions=*/true,
              /*PartialOverloading*/ false, AllowExplicitCtors);
        else
          S.AddOverloadCandidate(
              Info.Constructor, Info.FoundDecl, Initializer, CandidateSet,
              /*SuppressUserConversions=*/true,
              /*PartialOverloading*/ false, AllowExplicitCtors);
      }
    }
  }
  if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
    return OR_No_Viable_Function;

  const RecordType *T2RecordType = nullptr;
  if ((T2RecordType = T2->getAs<RecordType>()) &&
      S.isCompleteType(Kind.getLocation(), T2)) {
    // The type we're converting from is a class type, enumerate its conversion
    // functions.
    CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());

    const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions();
    for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
      NamedDecl *D = *I;
      CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
      if (isa<UsingShadowDecl>(D))
        D = cast<UsingShadowDecl>(D)->getTargetDecl();

      FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
      CXXConversionDecl *Conv;
      if (ConvTemplate)
        Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
      else
        Conv = cast<CXXConversionDecl>(D);

      // If the conversion function doesn't return a reference type,
      // it can't be considered for this conversion unless we're allowed to
      // consider rvalues.
      // FIXME: Do we need to make sure that we only consider conversion
      // candidates with reference-compatible results? That might be needed to
      // break recursion.
      if ((AllowExplicitConvs || !Conv->isExplicit()) &&
          (AllowRValues ||
           Conv->getConversionType()->isLValueReferenceType())) {
        if (ConvTemplate)
          S.AddTemplateConversionCandidate(
              ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
              CandidateSet,
              /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs);
        else
          S.AddConversionCandidate(
              Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet,
              /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs);
      }
    }
  }
  if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
    return OR_No_Viable_Function;

  SourceLocation DeclLoc = Initializer->getBeginLoc();

  // Perform overload resolution. If it fails, return the failed result.
  OverloadCandidateSet::iterator Best;
  if (OverloadingResult Result
        = CandidateSet.BestViableFunction(S, DeclLoc, Best))
    return Result;

  FunctionDecl *Function = Best->Function;
  // This is the overload that will be used for this initialization step if we
  // use this initialization. Mark it as referenced.
  Function->setReferenced();

  // Compute the returned type and value kind of the conversion.
  QualType cv3T3;
  if (isa<CXXConversionDecl>(Function))
    cv3T3 = Function->getReturnType();
  else
    cv3T3 = T1;

  ExprValueKind VK = VK_RValue;
  if (cv3T3->isLValueReferenceType())
    VK = VK_LValue;
  else if (const auto *RRef = cv3T3->getAs<RValueReferenceType>())
    VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue;
  cv3T3 = cv3T3.getNonLValueExprType(S.Context);

  // Add the user-defined conversion step.
  bool HadMultipleCandidates = (CandidateSet.size() > 1);
  Sequence.AddUserConversionStep(Function, Best->FoundDecl, cv3T3,
                                 HadMultipleCandidates);

  // Determine whether we'll need to perform derived-to-base adjustments or
  // other conversions.
  bool NewDerivedToBase = false;
  bool NewObjCConversion = false;
  bool NewObjCLifetimeConversion = false;
  bool NewFunctionConversion = false;
  Sema::ReferenceCompareResult NewRefRelationship =
      S.CompareReferenceRelationship(
          DeclLoc, T1, cv3T3, NewDerivedToBase, NewObjCConversion,
          NewObjCLifetimeConversion, NewFunctionConversion);

  // Add the final conversion sequence, if necessary.
  if (NewRefRelationship == Sema::Ref_Incompatible) {
    assert(!isa<CXXConstructorDecl>(Function) &&
           "should not have conversion after constructor");

    ImplicitConversionSequence ICS;
    ICS.setStandard();
    ICS.Standard = Best->FinalConversion;
    Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2));

    // Every implicit conversion results in a prvalue, except for a glvalue
    // derived-to-base conversion, which we handle below.
    cv3T3 = ICS.Standard.getToType(2);
    VK = VK_RValue;
  }

  //   If the converted initializer is a prvalue, its type T4 is adjusted to
  //   type "cv1 T4" and the temporary materialization conversion is applied.
  //
  // We adjust the cv-qualifications to match the reference regardless of
  // whether we have a prvalue so that the AST records the change. In this
  // case, T4 is "cv3 T3".
  QualType cv1T4 = S.Context.getQualifiedType(cv3T3, cv1T1.getQualifiers());
  if (cv1T4.getQualifiers() != cv3T3.getQualifiers())
    Sequence.AddQualificationConversionStep(cv1T4, VK);
  Sequence.AddReferenceBindingStep(cv1T4, VK == VK_RValue);
  VK = IsLValueRef ? VK_LValue : VK_XValue;

  if (NewDerivedToBase)
    Sequence.AddDerivedToBaseCastStep(cv1T1, VK);
  else if (NewObjCConversion)
    Sequence.AddObjCObjectConversionStep(cv1T1);
  else if (NewFunctionConversion)
    Sequence.AddQualificationConversionStep(cv1T1, VK);

  return OR_Success;
}

static void CheckCXX98CompatAccessibleCopy(Sema &S,
                                           const InitializedEntity &Entity,
                                           Expr *CurInitExpr);

/// Attempt reference initialization (C++0x [dcl.init.ref])
static void TryReferenceInitialization(Sema &S,
                                       const InitializedEntity &Entity,
                                       const InitializationKind &Kind,
                                       Expr *Initializer,
                                       InitializationSequence &Sequence) {
  QualType DestType = Entity.getType();
  QualType cv1T1 = DestType->castAs<ReferenceType>()->getPointeeType();
  Qualifiers T1Quals;
  QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);
  QualType cv2T2 = Initializer->getType();
  Qualifiers T2Quals;
  QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);

  // If the initializer is the address of an overloaded function, try
  // to resolve the overloaded function. If all goes well, T2 is the
  // type of the resulting function.
  if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2,
                                                   T1, Sequence))
    return;

  // Delegate everything else to a subfunction.
  TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1,
                                 T1Quals, cv2T2, T2, T2Quals, Sequence);
}

/// Determine whether an expression is a non-referenceable glvalue (one to
/// which a reference can never bind). Attempting to bind a reference to
/// such a glvalue will always create a temporary.
static bool isNonReferenceableGLValue(Expr *E) {
  return E->refersToBitField() || E->refersToVectorElement();
}

/// Reference initialization without resolving overloaded functions.
static void TryReferenceInitializationCore(Sema &S,
                                           const InitializedEntity &Entity,
                                           const InitializationKind &Kind,
                                           Expr *Initializer,
                                           QualType cv1T1, QualType T1,
                                           Qualifiers T1Quals,
                                           QualType cv2T2, QualType T2,
                                           Qualifiers T2Quals,
                                           InitializationSequence &Sequence) {
  QualType DestType = Entity.getType();
  SourceLocation DeclLoc = Initializer->getBeginLoc();
  // Compute some basic properties of the types and the initializer.
  bool isLValueRef = DestType->isLValueReferenceType();
  bool isRValueRef = !isLValueRef;
  bool DerivedToBase = false;
  bool ObjCConversion = false;
  bool ObjCLifetimeConversion = false;
  bool FunctionConversion = false;
  Expr::Classification InitCategory = Initializer->Classify(S.Context);
  Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(
      DeclLoc, cv1T1, cv2T2, DerivedToBase, ObjCConversion,
      ObjCLifetimeConversion, FunctionConversion);

  // C++0x [dcl.init.ref]p5:
  //   A reference to type "cv1 T1" is initialized by an expression of type
  //   "cv2 T2" as follows:
  //
  //     - If the reference is an lvalue reference and the initializer
  //       expression
  // Note the analogous bullet points for rvalue refs to functions. Because
  // there are no function rvalues in C++, rvalue refs to functions are treated
  // like lvalue refs.
  OverloadingResult ConvOvlResult = OR_Success;
  bool T1Function = T1->isFunctionType();
  if (isLValueRef || T1Function) {
    if (InitCategory.isLValue() && !isNonReferenceableGLValue(Initializer) &&
        (RefRelationship == Sema::Ref_Compatible ||
         (Kind.isCStyleOrFunctionalCast() &&
          RefRelationship == Sema::Ref_Related))) {
      //   - is an lvalue (but is not a bit-field), and "cv1 T1" is
      //     reference-compatible with "cv2 T2," or
      if (T1Quals != T2Quals)
        // Convert to cv1 T2. This should only add qualifiers unless this is a
        // c-style cast. The removal of qualifiers in that case notionally
        // happens after the reference binding, but that doesn't matter.
        Sequence.AddQualificationConversionStep(
            S.Context.getQualifiedType(T2, T1Quals),
            Initializer->getValueKind());
      if (DerivedToBase)
        Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue);
      else if (ObjCConversion)
        Sequence.AddObjCObjectConversionStep(cv1T1);
      else if (FunctionConversion)
        Sequence.AddQualificationConversionStep(cv1T1, VK_LValue);

      // We only create a temporary here when binding a reference to a
      // bit-field or vector element. Those cases are't supposed to be
      // handled by this bullet, but the outcome is the same either way.
      Sequence.AddReferenceBindingStep(cv1T1, false);
      return;
    }

    //     - has a class type (i.e., T2 is a class type), where T1 is not
    //       reference-related to T2, and can be implicitly converted to an
    //       lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible
    //       with "cv3 T3" (this conversion is selected by enumerating the
    //       applicable conversion functions (13.3.1.6) and choosing the best
    //       one through overload resolution (13.3)),
    // If we have an rvalue ref to function type here, the rhs must be
    // an rvalue. DR1287 removed the "implicitly" here.
    if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() &&
        (isLValueRef || InitCategory.isRValue())) {
      ConvOvlResult = TryRefInitWithConversionFunction(
          S, Entity, Kind, Initializer, /*AllowRValues*/ isRValueRef,
          /*IsLValueRef*/ isLValueRef, Sequence);
      if (ConvOvlResult == OR_Success)
        return;
      if (ConvOvlResult != OR_No_Viable_Function)
        Sequence.SetOverloadFailure(
            InitializationSequence::FK_ReferenceInitOverloadFailed,
            ConvOvlResult);
    }
  }

  //     - Otherwise, the reference shall be an lvalue reference to a
  //       non-volatile const type (i.e., cv1 shall be const), or the reference
  //       shall be an rvalue reference.
  //       For address spaces, we interpret this to mean that an addr space
  //       of a reference "cv1 T1" is a superset of addr space of "cv2 T2".
  if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile() &&
                       T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
    if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
      Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
    else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
      Sequence.SetOverloadFailure(
                        InitializationSequence::FK_ReferenceInitOverloadFailed,
                                  ConvOvlResult);
    else if (!InitCategory.isLValue())
      Sequence.SetFailed(
          T1Quals.isAddressSpaceSupersetOf(T2Quals)
              ? InitializationSequence::
                    FK_NonConstLValueReferenceBindingToTemporary
              : InitializationSequence::FK_ReferenceInitDropsQualifiers);
    else {
      InitializationSequence::FailureKind FK;
      switch (RefRelationship) {
      case Sema::Ref_Compatible:
        if (Initializer->refersToBitField())
          FK = InitializationSequence::
              FK_NonConstLValueReferenceBindingToBitfield;
        else if (Initializer->refersToVectorElement())
          FK = InitializationSequence::
              FK_NonConstLValueReferenceBindingToVectorElement;
        else
          llvm_unreachable("unexpected kind of compatible initializer");
        break;
      case Sema::Ref_Related:
        FK = InitializationSequence::FK_ReferenceInitDropsQualifiers;
        break;
      case Sema::Ref_Incompatible:
        FK = InitializationSequence::
            FK_NonConstLValueReferenceBindingToUnrelated;
        break;
      }
      Sequence.SetFailed(FK);
    }
    return;
  }

  //    - If the initializer expression
  //      - is an
  // [<=14] xvalue (but not a bit-field), class prvalue, array prvalue, or
  // [1z]   rvalue (but not a bit-field) or
  //        function lvalue and "cv1 T1" is reference-compatible with "cv2 T2"
  //
  // Note: functions are handled above and below rather than here...
  if (!T1Function &&
      (RefRelationship == Sema::Ref_Compatible ||
       (Kind.isCStyleOrFunctionalCast() &&
        RefRelationship == Sema::Ref_Related)) &&
      ((InitCategory.isXValue() && !isNonReferenceableGLValue(Initializer)) ||
       (InitCategory.isPRValue() &&
        (S.getLangOpts().CPlusPlus17 || T2->isRecordType() ||
         T2->isArrayType())))) {
    ExprValueKind ValueKind = InitCategory.isXValue() ? VK_XValue : VK_RValue;
    if (InitCategory.isPRValue() && T2->isRecordType()) {
      // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
      // compiler the freedom to perform a copy here or bind to the
      // object, while C++0x requires that we bind directly to the
      // object. Hence, we always bind to the object without making an
      // extra copy. However, in C++03 requires that we check for the
      // presence of a suitable copy constructor:
      //
      //   The constructor that would be used to make the copy shall
      //   be callable whether or not the copy is actually done.
      if (!S.getLangOpts().CPlusPlus11 && !S.getLangOpts().MicrosoftExt)
        Sequence.AddExtraneousCopyToTemporary(cv2T2);
      else if (S.getLangOpts().CPlusPlus11)
        CheckCXX98CompatAccessibleCopy(S, Entity, Initializer);
    }

    // C++1z [dcl.init.ref]/5.2.1.2:
    //   If the converted initializer is a prvalue, its type T4 is adjusted
    //   to type "cv1 T4" and the temporary materialization conversion is
    //   applied.
    // Postpone address space conversions to after the temporary materialization
    // conversion to allow creating temporaries in the alloca address space.
    auto T1QualsIgnoreAS = T1Quals;
    auto T2QualsIgnoreAS = T2Quals;
    if (T1Quals.getAddressSpace() != T2Quals.getAddressSpace()) {
      T1QualsIgnoreAS.removeAddressSpace();
      T2QualsIgnoreAS.removeAddressSpace();
    }
    QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1QualsIgnoreAS);
    if (T1QualsIgnoreAS != T2QualsIgnoreAS)
      Sequence.AddQualificationConversionStep(cv1T4, ValueKind);
    Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue);
    ValueKind = isLValueRef ? VK_LValue : VK_XValue;
    // Add addr space conversion if required.
    if (T1Quals.getAddressSpace() != T2Quals.getAddressSpace()) {
      auto T4Quals = cv1T4.getQualifiers();
      T4Quals.addAddressSpace(T1Quals.getAddressSpace());
      QualType cv1T4WithAS = S.Context.getQualifiedType(T2, T4Quals);
      Sequence.AddQualificationConversionStep(cv1T4WithAS, ValueKind);
    }

    //   In any case, the reference is bound to the resulting glvalue (or to
    //   an appropriate base class subobject).
    if (DerivedToBase)
      Sequence.AddDerivedToBaseCastStep(cv1T1, ValueKind);
    else if (ObjCConversion)
      Sequence.AddObjCObjectConversionStep(cv1T1);
    return;
  }

  //       - has a class type (i.e., T2 is a class type), where T1 is not
  //         reference-related to T2, and can be implicitly converted to an
  //         xvalue, class prvalue, or function lvalue of type "cv3 T3",
  //         where "cv1 T1" is reference-compatible with "cv3 T3",
  //
  // DR1287 removes the "implicitly" here.
  if (T2->isRecordType()) {
    if (RefRelationship == Sema::Ref_Incompatible) {
      ConvOvlResult = TryRefInitWithConversionFunction(
          S, Entity, Kind, Initializer, /*AllowRValues*/ true,
          /*IsLValueRef*/ isLValueRef, Sequence);
      if (ConvOvlResult)
        Sequence.SetOverloadFailure(
            InitializationSequence::FK_ReferenceInitOverloadFailed,
            ConvOvlResult);

      return;
    }

    if (RefRelationship == Sema::Ref_Compatible &&
        isRValueRef && InitCategory.isLValue()) {
      Sequence.SetFailed(
        InitializationSequence::FK_RValueReferenceBindingToLValue);
      return;
    }

    Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
    return;
  }

  //      - Otherwise, a temporary of type "cv1 T1" is created and initialized
  //        from the initializer expression using the rules for a non-reference
  //        copy-initialization (8.5). The reference is then bound to the
  //        temporary. [...]

  // Ignore address space of reference type at this point and perform address
  // space conversion after the reference binding step.
  QualType cv1T1IgnoreAS =
      T1Quals.hasAddressSpace()
          ? S.Context.getQualifiedType(T1, T1Quals.withoutAddressSpace())
          : cv1T1;

  InitializedEntity TempEntity =
      InitializedEntity::InitializeTemporary(cv1T1IgnoreAS);

  // FIXME: Why do we use an implicit conversion here rather than trying
  // copy-initialization?
  ImplicitConversionSequence ICS
    = S.TryImplicitConversion(Initializer, TempEntity.getType(),
                              /*SuppressUserConversions=*/false,
                              /*AllowExplicit=*/false,
                              /*FIXME:InOverloadResolution=*/false,
                              /*CStyle=*/Kind.isCStyleOrFunctionalCast(),
                              /*AllowObjCWritebackConversion=*/false);

  if (ICS.isBad()) {
    // FIXME: Use the conversion function set stored in ICS to turn
    // this into an overloading ambiguity diagnostic. However, we need
    // to keep that set as an OverloadCandidateSet rather than as some
    // other kind of set.
    if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
      Sequence.SetOverloadFailure(
                        InitializationSequence::FK_ReferenceInitOverloadFailed,
                                  ConvOvlResult);
    else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
      Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
    else
      Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
    return;
  } else {
    Sequence.AddConversionSequenceStep(ICS, TempEntity.getType());
  }

  //        [...] If T1 is reference-related to T2, cv1 must be the
  //        same cv-qualification as, or greater cv-qualification
  //        than, cv2; otherwise, the program is ill-formed.
  unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
  unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
  if ((RefRelationship == Sema::Ref_Related &&
       (T1CVRQuals | T2CVRQuals) != T1CVRQuals) ||
      !T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
    Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
    return;
  }

  //   [...] If T1 is reference-related to T2 and the reference is an rvalue
  //   reference, the initializer expression shall not be an lvalue.
  if (RefRelationship >= Sema::Ref_Related && !isLValueRef &&
      InitCategory.isLValue()) {
    Sequence.SetFailed(
                    InitializationSequence::FK_RValueReferenceBindingToLValue);
    return;
  }

  Sequence.AddReferenceBindingStep(cv1T1IgnoreAS, /*BindingTemporary=*/true);

  if (T1Quals.hasAddressSpace()) {
    if (!Qualifiers::isAddressSpaceSupersetOf(T1Quals.getAddressSpace(),
                                              LangAS::Default)) {
      Sequence.SetFailed(
          InitializationSequence::FK_ReferenceAddrspaceMismatchTemporary);
      return;
    }
    Sequence.AddQualificationConversionStep(cv1T1, isLValueRef ? VK_LValue
                                                               : VK_XValue);
  }
}

/// Attempt character array initialization from a string literal
/// (C++ [dcl.init.string], C99 6.7.8).
static void TryStringLiteralInitialization(Sema &S,
                                           const InitializedEntity &Entity,
                                           const InitializationKind &Kind,
                                           Expr *Initializer,
                                       InitializationSequence &Sequence) {
  Sequence.AddStringInitStep(Entity.getType());
}

/// Attempt value initialization (C++ [dcl.init]p7).
static void TryValueInitialization(Sema &S,
                                   const InitializedEntity &Entity,
                                   const InitializationKind &Kind,
                                   InitializationSequence &Sequence,
                                   InitListExpr *InitList) {
  assert((!InitList || InitList->getNumInits() == 0) &&
         "Shouldn't use value-init for non-empty init lists");

  // C++98 [dcl.init]p5, C++11 [dcl.init]p7:
  //
  //   To value-initialize an object of type T means:
  QualType T = Entity.getType();

  //     -- if T is an array type, then each element is value-initialized;
  T = S.Context.getBaseElementType(T);

  if (const RecordType *RT = T->getAs<RecordType>()) {
    if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
      bool NeedZeroInitialization = true;
      // C++98:
      // -- if T is a class type (clause 9) with a user-declared constructor
      //    (12.1), then the default constructor for T is called (and the
      //    initialization is ill-formed if T has no accessible default
      //    constructor);
      // C++11:
      // -- if T is a class type (clause 9) with either no default constructor
      //    (12.1 [class.ctor]) or a default constructor that is user-provided
      //    or deleted, then the object is default-initialized;
      //
      // Note that the C++11 rule is the same as the C++98 rule if there are no
      // defaulted or deleted constructors, so we just use it unconditionally.
      CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl);
      if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted())
        NeedZeroInitialization = false;

      // -- if T is a (possibly cv-qualified) non-union class type without a
      //    user-provided or deleted default constructor, then the object is
      //    zero-initialized and, if T has a non-trivial default constructor,
      //    default-initialized;
      // The 'non-union' here was removed by DR1502. The 'non-trivial default
      // constructor' part was removed by DR1507.
      if (NeedZeroInitialization)
        Sequence.AddZeroInitializationStep(Entity.getType());

      // C++03:
      // -- if T is a non-union class type without a user-declared constructor,
      //    then every non-static data member and base class component of T is
      //    value-initialized;
      // [...] A program that calls for [...] value-initialization of an
      // entity of reference type is ill-formed.
      //
      // C++11 doesn't need this handling, because value-initialization does not
      // occur recursively there, and the implicit default constructor is
      // defined as deleted in the problematic cases.
      if (!S.getLangOpts().CPlusPlus11 &&
          ClassDecl->hasUninitializedReferenceMember()) {
        Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference);
        return;
      }

      // If this is list-value-initialization, pass the empty init list on when
      // building the constructor call. This affects the semantics of a few
      // things (such as whether an explicit default constructor can be called).
      Expr *InitListAsExpr = InitList;
      MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0);
      bool InitListSyntax = InitList;

      // FIXME: Instead of creating a CXXConstructExpr of array type here,
      // wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr.
      return TryConstructorInitialization(
          S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax);
    }
  }

  Sequence.AddZeroInitializationStep(Entity.getType());
}

/// Attempt default initialization (C++ [dcl.init]p6).
static void TryDefaultInitialization(Sema &S,
                                     const InitializedEntity &Entity,
                                     const InitializationKind &Kind,
                                     InitializationSequence &Sequence) {
  assert(Kind.getKind() == InitializationKind::IK_Default);

  // C++ [dcl.init]p6:
  //   To default-initialize an object of type T means:
  //     - if T is an array type, each element is default-initialized;
  QualType DestType = S.Context.getBaseElementType(Entity.getType());

  //     - if T is a (possibly cv-qualified) class type (Clause 9), the default
  //       constructor for T is called (and the initialization is ill-formed if
  //       T has no accessible default constructor);
  if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) {
    TryConstructorInitialization(S, Entity, Kind, None, DestType,
                                 Entity.getType(), Sequence);
    return;
  }

  //     - otherwise, no initialization is performed.

  //   If a program calls for the default initialization of an object of
  //   a const-qualified type T, T shall be a class type with a user-provided
  //   default constructor.
  if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) {
    if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
      Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
    return;
  }

  // If the destination type has a lifetime property, zero-initialize it.
  if (DestType.getQualifiers().hasObjCLifetime()) {
    Sequence.AddZeroInitializationStep(Entity.getType());
    return;
  }
}

/// Attempt a user-defined conversion between two types (C++ [dcl.init]),
/// which enumerates all conversion functions and performs overload resolution
/// to select the best.
static void TryUserDefinedConversion(Sema &S,
                                     QualType DestType,
                                     const InitializationKind &Kind,
                                     Expr *Initializer,
                                     InitializationSequence &Sequence,
                                     bool TopLevelOfInitList) {
  assert(!DestType->isReferenceType() && "References are handled elsewhere");
  QualType SourceType = Initializer->getType();
  assert((DestType->isRecordType() || SourceType->isRecordType()) &&
         "Must have a class type to perform a user-defined conversion");

  // Build the candidate set directly in the initialization sequence
  // structure, so that it will persist if we fail.
  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
  CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
  CandidateSet.setDestAS(DestType.getQualifiers().getAddressSpace());

  // Determine whether we are allowed to call explicit constructors or
  // explicit conversion operators.
  bool AllowExplicit = Kind.AllowExplicit();

  if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) {
    // The type we're converting to is a class type. Enumerate its constructors
    // to see if there is a suitable conversion.
    CXXRecordDecl *DestRecordDecl
      = cast<CXXRecordDecl>(DestRecordType->getDecl());

    // Try to complete the type we're converting to.
    if (S.isCompleteType(Kind.getLocation(), DestType)) {
      for (NamedDecl *D : S.LookupConstructors(DestRecordDecl)) {
        auto Info = getConstructorInfo(D);
        if (!Info.Constructor)
          continue;

        if (!Info.Constructor->isInvalidDecl() &&
            Info.Constructor->isConvertingConstructor(AllowExplicit)) {
          if (Info.ConstructorTmpl)
            S.AddTemplateOverloadCandidate(
                Info.ConstructorTmpl, Info.FoundDecl,
                /*ExplicitArgs*/ nullptr, Initializer, CandidateSet,
                /*SuppressUserConversions=*/true,
                /*PartialOverloading*/ false, AllowExplicit);
          else
            S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
                                   Initializer, CandidateSet,
                                   /*SuppressUserConversions=*/true,
                                   /*PartialOverloading*/ false, AllowExplicit);
        }
      }
    }
  }

  SourceLocation DeclLoc = Initializer->getBeginLoc();

  if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
    // The type we're converting from is a class type, enumerate its conversion
    // functions.

    // We can only enumerate the conversion functions for a complete type; if
    // the type isn't complete, simply skip this step.
    if (S.isCompleteType(DeclLoc, SourceType)) {
      CXXRecordDecl *SourceRecordDecl
        = cast<CXXRecordDecl>(SourceRecordType->getDecl());

      const auto &Conversions =
          SourceRecordDecl->getVisibleConversionFunctions();
      for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
        NamedDecl *D = *I;
        CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
        if (isa<UsingShadowDecl>(D))
          D = cast<UsingShadowDecl>(D)->getTargetDecl();

        FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
        CXXConversionDecl *Conv;
        if (ConvTemplate)
          Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
        else
          Conv = cast<CXXConversionDecl>(D);

        if (AllowExplicit || !Conv->isExplicit()) {
          if (ConvTemplate)
            S.AddTemplateConversionCandidate(
                ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
                CandidateSet, AllowExplicit, AllowExplicit);
          else
            S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer,
                                     DestType, CandidateSet, AllowExplicit,
                                     AllowExplicit);
        }
      }
    }
  }

  // Perform overload resolution. If it fails, return the failed result.
  OverloadCandidateSet::iterator Best;
  if (OverloadingResult Result
        = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
    Sequence.SetOverloadFailure(
                        InitializationSequence::FK_UserConversionOverloadFailed,
                                Result);
    return;
  }

  FunctionDecl *Function = Best->Function;
  Function->setReferenced();
  bool HadMultipleCandidates = (CandidateSet.size() > 1);

  if (isa<CXXConstructorDecl>(Function)) {
    // Add the user-defined conversion step. Any cv-qualification conversion is
    // subsumed by the initialization. Per DR5, the created temporary is of the
    // cv-unqualified type of the destination.
    Sequence.AddUserConversionStep(Function, Best->FoundDecl,
                                   DestType.getUnqualifiedType(),
                                   HadMultipleCandidates);

    // C++14 and before:
    //   - if the function is a constructor, the call initializes a temporary
    //     of the cv-unqualified version of the destination type. The [...]
    //     temporary [...] is then used to direct-initialize, according to the
    //     rules above, the object that is the destination of the
    //     copy-initialization.
    // Note that this just performs a simple object copy from the temporary.
    //
    // C++17:
    //   - if the function is a constructor, the call is a prvalue of the
    //     cv-unqualified version of the destination type whose return object
    //     is initialized by the constructor. The call is used to
    //     direct-initialize, according to the rules above, the object that
    //     is the destination of the copy-initialization.
    // Therefore we need to do nothing further.
    //
    // FIXME: Mark this copy as extraneous.
    if (!S.getLangOpts().CPlusPlus17)
      Sequence.AddFinalCopy(DestType);
    else if (DestType.hasQualifiers())
      Sequence.AddQualificationConversionStep(DestType, VK_RValue);
    return;
  }

  // Add the user-defined conversion step that calls the conversion function.
  QualType ConvType = Function->getCallResultType();
  Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType,
                                 HadMultipleCandidates);

  if (ConvType->getAs<RecordType>()) {
    //   The call is used to direct-initialize [...] the object that is the
    //   destination of the copy-initialization.
    //
    // In C++17, this does not call a constructor if we enter /17.6.1:
    //   - If the initializer expression is a prvalue and the cv-unqualified
    //     version of the source type is the same as the class of the
    //     destination [... do not make an extra copy]
    //
    // FIXME: Mark this copy as extraneous.
    if (!S.getLangOpts().CPlusPlus17 ||
        Function->getReturnType()->isReferenceType() ||
        !S.Context.hasSameUnqualifiedType(ConvType, DestType))
      Sequence.AddFinalCopy(DestType);
    else if (!S.Context.hasSameType(ConvType, DestType))
      Sequence.AddQualificationConversionStep(DestType, VK_RValue);
    return;
  }

  // If the conversion following the call to the conversion function
  // is interesting, add it as a separate step.
  if (Best->FinalConversion.First || Best->FinalConversion.Second ||
      Best->FinalConversion.Third) {
    ImplicitConversionSequence ICS;
    ICS.setStandard();
    ICS.Standard = Best->FinalConversion;
    Sequence.AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList);
  }
}

/// An egregious hack for compatibility with libstdc++-4.2: in <tr1/hashtable>,
/// a function with a pointer return type contains a 'return false;' statement.
/// In C++11, 'false' is not a null pointer, so this breaks the build of any
/// code using that header.
///
/// Work around this by treating 'return false;' as zero-initializing the result
/// if it's used in a pointer-returning function in a system header.
static bool isLibstdcxxPointerReturnFalseHack(Sema &S,
                                              const InitializedEntity &Entity,
                                              const Expr *Init) {
  return S.getLangOpts().CPlusPlus11 &&
         Entity.getKind() == InitializedEntity::EK_Result &&
         Entity.getType()->isPointerType() &&
         isa<CXXBoolLiteralExpr>(Init) &&
         !cast<CXXBoolLiteralExpr>(Init)->getValue() &&
         S.getSourceManager().isInSystemHeader(Init->getExprLoc());
}

/// The non-zero enum values here are indexes into diagnostic alternatives.
enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar };

/// Determines whether this expression is an acceptable ICR source.
static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
                                         bool isAddressOf, bool &isWeakAccess) {
  // Skip parens.
  e = e->IgnoreParens();

  // Skip address-of nodes.
  if (UnaryOperator *op = dyn_cast<UnaryOperator>(e)) {
    if (op->getOpcode() == UO_AddrOf)
      return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true,
                                isWeakAccess);

  // Skip certain casts.
  } else if (CastExpr *ce = dyn_cast<CastExpr>(e)) {
    switch (ce->getCastKind()) {
    case CK_Dependent:
    case CK_BitCast:
    case CK_LValueBitCast:
    case CK_NoOp:
      return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf, isWeakAccess);

    case CK_ArrayToPointerDecay:
      return IIK_nonscalar;

    case CK_NullToPointer:
      return IIK_okay;

    default:
      break;
    }

  // If we have a declaration reference, it had better be a local variable.
  } else if (isa<DeclRefExpr>(e)) {
    // set isWeakAccess to true, to mean that there will be an implicit
    // load which requires a cleanup.
    if (e->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
      isWeakAccess = true;

    if (!isAddressOf) return IIK_nonlocal;

    VarDecl *var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl());
    if (!var) return IIK_nonlocal;

    return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal);

  // If we have a conditional operator, check both sides.
  } else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) {
    if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf,
                                                isWeakAccess))
      return iik;

    return isInvalidICRSource(C, cond->getRHS(), isAddressOf, isWeakAccess);

  // These are never scalar.
  } else if (isa<ArraySubscriptExpr>(e)) {
    return IIK_nonscalar;

  // Otherwise, it needs to be a null pointer constant.
  } else {
    return (e->isNullPointerConstant(C, Expr::NPC_ValueDependentIsNull)
            ? IIK_okay : IIK_nonlocal);
  }

  return IIK_nonlocal;
}

/// Check whether the given expression is a valid operand for an
/// indirect copy/restore.
static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
  assert(src->isRValue());
  bool isWeakAccess = false;
  InvalidICRKind iik = isInvalidICRSource(S.Context, src, false, isWeakAccess);
  // If isWeakAccess to true, there will be an implicit
  // load which requires a cleanup.
  if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess)
    S.Cleanup.setExprNeedsCleanups(true);

  if (iik == IIK_okay) return;

  S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback)
    << ((unsigned) iik - 1)  // shift index into diagnostic explanations
    << src->getSourceRange();
}

/// Determine whether we have compatible array types for the
/// purposes of GNU by-copy array initialization.
static bool hasCompatibleArrayTypes(ASTContext &Context, const ArrayType *Dest,
                                    const ArrayType *Source) {
  // If the source and destination array types are equivalent, we're
  // done.
  if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0)))
    return true;

  // Make sure that the element types are the same.
  if (!Context.hasSameType(Dest->getElementType(), Source->getElementType()))
    return false;

  // The only mismatch we allow is when the destination is an
  // incomplete array type and the source is a constant array type.
  return Source->isConstantArrayType() && Dest->isIncompleteArrayType();
}

static bool tryObjCWritebackConversion(Sema &S,
                                       InitializationSequence &Sequence,
                                       const InitializedEntity &Entity,
                                       Expr *Initializer) {
  bool ArrayDecay = false;
  QualType ArgType = Initializer->getType();
  QualType ArgPointee;
  if (const ArrayType *ArgArrayType = S.Context.getAsArrayType(ArgType)) {
    ArrayDecay = true;
    ArgPointee = ArgArrayType->getElementType();
    ArgType = S.Context.getPointerType(ArgPointee);
  }

  // Handle write-back conversion.
  QualType ConvertedArgType;
  if (!S.isObjCWritebackConversion(ArgType, Entity.getType(),
                                   ConvertedArgType))
    return false;

  // We should copy unless we're passing to an argument explicitly
  // marked 'out'.
  bool ShouldCopy = true;
  if (ParmVarDecl *param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
    ShouldCopy = (param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);

  // Do we need an lvalue conversion?
  if (ArrayDecay || Initializer->isGLValue()) {
    ImplicitConversionSequence ICS;
    ICS.setStandard();
    ICS.Standard.setAsIdentityConversion();

    QualType ResultType;
    if (ArrayDecay) {
      ICS.Standard.First = ICK_Array_To_Pointer;
      ResultType = S.Context.getPointerType(ArgPointee);
    } else {
      ICS.Standard.First = ICK_Lvalue_To_Rvalue;
      ResultType = Initializer->getType().getNonLValueExprType(S.Context);
    }

    Sequence.AddConversionSequenceStep(ICS, ResultType);
  }

  Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
  return true;
}

static bool TryOCLSamplerInitialization(Sema &S,
                                        InitializationSequence &Sequence,
                                        QualType DestType,
                                        Expr *Initializer) {
  if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() ||
      (!Initializer->isIntegerConstantExpr(S.Context) &&
      !Initializer->getType()->isSamplerT()))
    return false;

  Sequence.AddOCLSamplerInitStep(DestType);
  return true;
}

static bool IsZeroInitializer(Expr *Initializer, Sema &S) {
  return Initializer->isIntegerConstantExpr(S.getASTContext()) &&
    (Initializer->EvaluateKnownConstInt(S.getASTContext()) == 0);
}

static bool TryOCLZeroOpaqueTypeInitialization(Sema &S,
                                               InitializationSequence &Sequence,
                                               QualType DestType,
                                               Expr *Initializer) {
  if (!S.getLangOpts().OpenCL)
    return false;

  //
  // OpenCL 1.2 spec, s6.12.10
  //
  // The event argument can also be used to associate the
  // async_work_group_copy with a previous async copy allowing
  // an event to be shared by multiple async copies; otherwise
  // event should be zero.
  //
  if (DestType->isEventT() || DestType->isQueueT()) {
    if (!IsZeroInitializer(Initializer, S))
      return false;

    Sequence.AddOCLZeroOpaqueTypeStep(DestType);
    return true;
  }

  // We should allow zero initialization for all types defined in the
  // cl_intel_device_side_avc_motion_estimation extension, except
  // intel_sub_group_avc_mce_payload_t and intel_sub_group_avc_mce_result_t.
  if (S.getOpenCLOptions().isEnabled(
          "cl_intel_device_side_avc_motion_estimation") &&
      DestType->isOCLIntelSubgroupAVCType()) {
    if (DestType->isOCLIntelSubgroupAVCMcePayloadType() ||
        DestType->isOCLIntelSubgroupAVCMceResultType())
      return false;
    if (!IsZeroInitializer(Initializer, S))
      return false;

    Sequence.AddOCLZeroOpaqueTypeStep(DestType);
    return true;
  }

  return false;
}

InitializationSequence::InitializationSequence(Sema &S,
                                               const InitializedEntity &Entity,
                                               const InitializationKind &Kind,
                                               MultiExprArg Args,
                                               bool TopLevelOfInitList,
                                               bool TreatUnavailableAsInvalid)
    : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) {
  InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList,
                 TreatUnavailableAsInvalid);
}

/// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the
/// address of that function, this returns true. Otherwise, it returns false.
static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) {
  auto *DRE = dyn_cast<DeclRefExpr>(E);
  if (!DRE || !isa<FunctionDecl>(DRE->getDecl()))
    return false;

  return !S.checkAddressOfFunctionIsAvailable(
      cast<FunctionDecl>(DRE->getDecl()));
}

/// Determine whether we can perform an elementwise array copy for this kind
/// of entity.
static bool canPerformArrayCopy(const InitializedEntity &Entity) {
  switch (Entity.getKind()) {
  case InitializedEntity::EK_LambdaCapture:
    // C++ [expr.prim.lambda]p24:
    //   For array members, the array elements are direct-initialized in
    //   increasing subscript order.
    return true;

  case InitializedEntity::EK_Variable:
    // C++ [dcl.decomp]p1:
    //   [...] each element is copy-initialized or direct-initialized from the
    //   corresponding element of the assignment-expression [...]
    return isa<DecompositionDecl>(Entity.getDecl());

  case InitializedEntity::EK_Member:
    // C++ [class.copy.ctor]p14:
    //   - if the member is an array, each element is direct-initialized with
    //     the corresponding subobject of x
    return Entity.isImplicitMemberInitializer();

  case InitializedEntity::EK_ArrayElement:
    // All the above cases are intended to apply recursively, even though none
    // of them actually say that.
    if (auto *E = Entity.getParent())
      return canPerformArrayCopy(*E);
    break;

  default:
    break;
  }

  return false;
}

void InitializationSequence::InitializeFrom(Sema &S,
                                            const InitializedEntity &Entity,
                                            const InitializationKind &Kind,
                                            MultiExprArg Args,
                                            bool TopLevelOfInitList,
                                            bool TreatUnavailableAsInvalid) {
  ASTContext &Context = S.Context;

  // Eliminate non-overload placeholder types in the arguments.  We
  // need to do this before checking whether types are dependent
  // because lowering a pseudo-object expression might well give us
  // something of dependent type.
  for (unsigned I = 0, E = Args.size(); I != E; ++I)
    if (Args[I]->getType()->isNonOverloadPlaceholderType()) {
      // FIXME: should we be doing this here?
      ExprResult result = S.CheckPlaceholderExpr(Args[I]);
      if (result.isInvalid()) {
        SetFailed(FK_PlaceholderType);
        return;
      }
      Args[I] = result.get();
    }

  // C++0x [dcl.init]p16:
  //   The semantics of initializers are as follows. The destination type is
  //   the type of the object or reference being initialized and the source
  //   type is the type of the initializer expression. The source type is not
  //   defined when the initializer is a braced-init-list or when it is a
  //   parenthesized list of expressions.
  QualType DestType = Entity.getType();

  if (DestType->isDependentType() ||
      Expr::hasAnyTypeDependentArguments(Args)) {
    SequenceKind = DependentSequence;
    return;
  }

  // Almost everything is a normal sequence.
  setSequenceKind(NormalSequence);

  QualType SourceType;
  Expr *Initializer = nullptr;
  if (Args.size() == 1) {
    Initializer = Args[0];
    if (S.getLangOpts().ObjC) {
      if (S.CheckObjCBridgeRelatedConversions(Initializer->getBeginLoc(),
                                              DestType, Initializer->getType(),
                                              Initializer) ||
          S.ConversionToObjCStringLiteralCheck(DestType, Initializer))
        Args[0] = Initializer;
    }
    if (!isa<InitListExpr>(Initializer))
      SourceType = Initializer->getType();
  }

  //     - If the initializer is a (non-parenthesized) braced-init-list, the
  //       object is list-initialized (8.5.4).
  if (Kind.getKind() != InitializationKind::IK_Direct) {
    if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
      TryListInitialization(S, Entity, Kind, InitList, *this,
                            TreatUnavailableAsInvalid);
      return;
    }
  }

  //     - If the destination type is a reference type, see 8.5.3.
  if (DestType->isReferenceType()) {
    // C++0x [dcl.init.ref]p1:
    //   A variable declared to be a T& or T&&, that is, "reference to type T"
    //   (8.3.2), shall be initialized by an object, or function, of type T or
    //   by an object that can be converted into a T.
    // (Therefore, multiple arguments are not permitted.)
    if (Args.size() != 1)
      SetFailed(FK_TooManyInitsForReference);
    // C++17 [dcl.init.ref]p5:
    //   A reference [...] is initialized by an expression [...] as follows:
    // If the initializer is not an expression, presumably we should reject,
    // but the standard fails to actually say so.
    else if (isa<InitListExpr>(Args[0]))
      SetFailed(FK_ParenthesizedListInitForReference);
    else
      TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
    return;
  }

  //     - If the initializer is (), the object is value-initialized.
  if (Kind.getKind() == InitializationKind::IK_Value ||
      (Kind.getKind() == InitializationKind::IK_Direct && Args.empty())) {
    TryValueInitialization(S, Entity, Kind, *this);
    return;
  }

  // Handle default initialization.
  if (Kind.getKind() == InitializationKind::IK_Default) {
    TryDefaultInitialization(S, Entity, Kind, *this);
    return;
  }

  //     - If the destination type is an array of characters, an array of
  //       char16_t, an array of char32_t, or an array of wchar_t, and the
  //       initializer is a string literal, see 8.5.2.
  //     - Otherwise, if the destination type is an array, the program is
  //       ill-formed.
  if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) {
    if (Initializer && isa<VariableArrayType>(DestAT)) {
      SetFailed(FK_VariableLengthArrayHasInitializer);
      return;
    }

    if (Initializer) {
      switch (IsStringInit(Initializer, DestAT, Context)) {
      case SIF_None:
        TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
        return;
      case SIF_NarrowStringIntoWideChar:
        SetFailed(FK_NarrowStringIntoWideCharArray);
        return;
      case SIF_WideStringIntoChar:
        SetFailed(FK_WideStringIntoCharArray);
        return;
      case SIF_IncompatWideStringIntoWideChar:
        SetFailed(FK_IncompatWideStringIntoWideChar);
        return;
      case SIF_PlainStringIntoUTF8Char:
        SetFailed(FK_PlainStringIntoUTF8Char);
        return;
      case SIF_UTF8StringIntoPlainChar:
        SetFailed(FK_UTF8StringIntoPlainChar);
        return;
      case SIF_Other:
        break;
      }
    }

    // Some kinds of initialization permit an array to be initialized from
    // another array of the same type, and perform elementwise initialization.
    if (Initializer && isa<ConstantArrayType>(DestAT) &&
        S.Context.hasSameUnqualifiedType(Initializer->getType(),
                                         Entity.getType()) &&
        canPerformArrayCopy(Entity)) {
      // If source is a prvalue, use it directly.
      if (Initializer->getValueKind() == VK_RValue) {
        AddArrayInitStep(DestType, /*IsGNUExtension*/false);
        return;
      }

      // Emit element-at-a-time copy loop.
      InitializedEntity Element =
          InitializedEntity::InitializeElement(S.Context, 0, Entity);
      QualType InitEltT =
          Context.getAsArrayType(Initializer->getType())->getElementType();
      OpaqueValueExpr OVE(Initializer->getExprLoc(), InitEltT,
                          Initializer->getValueKind(),
                          Initializer->getObjectKind());
      Expr *OVEAsExpr = &OVE;
      InitializeFrom(S, Element, Kind, OVEAsExpr, TopLevelOfInitList,
                     TreatUnavailableAsInvalid);
      if (!Failed())
        AddArrayInitLoopStep(Entity.getType(), InitEltT);
      return;
    }

    // Note: as an GNU C extension, we allow initialization of an
    // array from a compound literal that creates an array of the same
    // type, so long as the initializer has no side effects.
    if (!S.getLangOpts().CPlusPlus && Initializer &&
        isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
        Initializer->getType()->isArrayType()) {
      const ArrayType *SourceAT
        = Context.getAsArrayType(Initializer->getType());
      if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT))
        SetFailed(FK_ArrayTypeMismatch);
      else if (Initializer->HasSideEffects(S.Context))
        SetFailed(FK_NonConstantArrayInit);
      else {
        AddArrayInitStep(DestType, /*IsGNUExtension*/true);
      }
    }
    // Note: as a GNU C++ extension, we allow list-initialization of a
    // class member of array type from a parenthesized initializer list.
    else if (S.getLangOpts().CPlusPlus &&
             Entity.getKind() == InitializedEntity::EK_Member &&
             Initializer && isa<InitListExpr>(Initializer)) {
      TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer),
                            *this, TreatUnavailableAsInvalid);
      AddParenthesizedArrayInitStep(DestType);
    } else if (DestAT->getElementType()->isCharType())
      SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
    else if (IsWideCharCompatible(DestAT->getElementType(), Context))
      SetFailed(FK_ArrayNeedsInitListOrWideStringLiteral);
    else
      SetFailed(FK_ArrayNeedsInitList);

    return;
  }

  // Determine whether we should consider writeback conversions for
  // Objective-C ARC.
  bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount &&
         Entity.isParameterKind();

  if (TryOCLSamplerInitialization(S, *this, DestType, Initializer))
    return;

  // We're at the end of the line for C: it's either a write-back conversion
  // or it's a C assignment. There's no need to check anything else.
  if (!S.getLangOpts().CPlusPlus) {
    // If allowed, check whether this is an Objective-C writeback conversion.
    if (allowObjCWritebackConversion &&
        tryObjCWritebackConversion(S, *this, Entity, Initializer)) {
      return;
    }

    if (TryOCLZeroOpaqueTypeInitialization(S, *this, DestType, Initializer))
      return;

    // Handle initialization in C
    AddCAssignmentStep(DestType);
    MaybeProduceObjCObject(S, *this, Entity);
    return;
  }

  assert(S.getLangOpts().CPlusPlus);

  //     - If the destination type is a (possibly cv-qualified) class type:
  if (DestType->isRecordType()) {
    //     - If the initialization is direct-initialization, or if it is
    //       copy-initialization where the cv-unqualified version of the
    //       source type is the same class as, or a derived class of, the
    //       class of the destination, constructors are considered. [...]
    if (Kind.getKind() == InitializationKind::IK_Direct ||
        (Kind.getKind() == InitializationKind::IK_Copy &&
         (Context.hasSameUnqualifiedType(SourceType, DestType) ||
          S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType, DestType))))
      TryConstructorInitialization(S, Entity, Kind, Args,
                                   DestType, DestType, *this);
    //     - Otherwise (i.e., for the remaining copy-initialization cases),
    //       user-defined conversion sequences that can convert from the source
    //       type to the destination type or (when a conversion function is
    //       used) to a derived class thereof are enumerated as described in
    //       13.3.1.4, and the best one is chosen through overload resolution
    //       (13.3).
    else
      TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,
                               TopLevelOfInitList);
    return;
  }

  assert(Args.size() >= 1 && "Zero-argument case handled above");

  // The remaining cases all need a source type.
  if (Args.size() > 1) {
    SetFailed(FK_TooManyInitsForScalar);
    return;
  } else if (isa<InitListExpr>(Args[0])) {
    SetFailed(FK_ParenthesizedListInitForScalar);
    return;
  }

  //    - Otherwise, if the source type is a (possibly cv-qualified) class
  //      type, conversion functions are considered.
  if (!SourceType.isNull() && SourceType->isRecordType()) {
    // For a conversion to _Atomic(T) from either T or a class type derived
    // from T, initialize the T object then convert to _Atomic type.
    bool NeedAtomicConversion = false;
    if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) {
      if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) ||
          S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType,
                          Atomic->getValueType())) {
        DestType = Atomic->getValueType();
        NeedAtomicConversion = true;
      }
    }

    TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,
                             TopLevelOfInitList);
    MaybeProduceObjCObject(S, *this, Entity);
    if (!Failed() && NeedAtomicConversion)
      AddAtomicConversionStep(Entity.getType());
    return;
  }

  //    - Otherwise, the initial value of the object being initialized is the
  //      (possibly converted) value of the initializer expression. Standard
  //      conversions (Clause 4) will be used, if necessary, to convert the
  //      initializer expression to the cv-unqualified version of the
  //      destination type; no user-defined conversions are considered.

  ImplicitConversionSequence ICS
    = S.TryImplicitConversion(Initializer, DestType,
                              /*SuppressUserConversions*/true,
                              /*AllowExplicitConversions*/ false,
                              /*InOverloadResolution*/ false,
                              /*CStyle=*/Kind.isCStyleOrFunctionalCast(),
                              allowObjCWritebackConversion);

  if (ICS.isStandard() &&
      ICS.Standard.Second == ICK_Writeback_Conversion) {
    // Objective-C ARC writeback conversion.

    // We should copy unless we're passing to an argument explicitly
    // marked 'out'.
    bool ShouldCopy = true;
    if (ParmVarDecl *Param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
      ShouldCopy = (Param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);

    // If there was an lvalue adjustment, add it as a separate conversion.
    if (ICS.Standard.First == ICK_Array_To_Pointer ||
        ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
      ImplicitConversionSequence LvalueICS;
      LvalueICS.setStandard();
      LvalueICS.Standard.setAsIdentityConversion();
      LvalueICS.Standard.setAllToTypes(ICS.Standard.getToType(0));
      LvalueICS.Standard.First = ICS.Standard.First;
      AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
    }

    AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy);
  } else if (ICS.isBad()) {
    DeclAccessPair dap;
    if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) {
      AddZeroInitializationStep(Entity.getType());
    } else if (Initializer->getType() == Context.OverloadTy &&
               !S.ResolveAddressOfOverloadedFunction(Initializer, DestType,
                                                     false, dap))
      SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
    else if (Initializer->getType()->isFunctionType() &&
             isExprAnUnaddressableFunction(S, Initializer))
      SetFailed(InitializationSequence::FK_AddressOfUnaddressableFunction);
    else
      SetFailed(InitializationSequence::FK_ConversionFailed);
  } else {
    AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList);

    MaybeProduceObjCObject(S, *this, Entity);
  }
}

InitializationSequence::~InitializationSequence() {
  for (auto &S : Steps)
    S.Destroy();
}

//===----------------------------------------------------------------------===//
// Perform initialization
//===----------------------------------------------------------------------===//
static Sema::AssignmentAction
getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
  switch(Entity.getKind()) {
  case InitializedEntity::EK_Variable:
  case InitializedEntity::EK_New:
  case InitializedEntity::EK_Exception:
  case InitializedEntity::EK_Base:
  case InitializedEntity::EK_Delegating:
    return Sema::AA_Initializing;

  case InitializedEntity::EK_Parameter:
    if (Entity.getDecl() &&
        isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
      return Sema::AA_Sending;

    return Sema::AA_Passing;

  case InitializedEntity::EK_Parameter_CF_Audited:
    if (Entity.getDecl() &&
      isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
      return Sema::AA_Sending;

    return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited;

  case InitializedEntity::EK_Result:
  case InitializedEntity::EK_StmtExprResult: // FIXME: Not quite right.
    return Sema::AA_Returning;

  case InitializedEntity::EK_Temporary:
  case InitializedEntity::EK_RelatedResult:
    // FIXME: Can we tell apart casting vs. converting?
    return Sema::AA_Casting;

  case InitializedEntity::EK_Member:
  case InitializedEntity::EK_Binding:
  case InitializedEntity::EK_ArrayElement:
  case InitializedEntity::EK_VectorElement:
  case InitializedEntity::EK_ComplexElement:
  case InitializedEntity::EK_BlockElement:
  case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
  case InitializedEntity::EK_LambdaCapture:
  case InitializedEntity::EK_CompoundLiteralInit:
    return Sema::AA_Initializing;
  }

  llvm_unreachable("Invalid EntityKind!");
}

/// Whether we should bind a created object as a temporary when
/// initializing the given entity.
static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
  switch (Entity.getKind()) {
  case InitializedEntity::EK_ArrayElement:
  case InitializedEntity::EK_Member:
  case InitializedEntity::EK_Result:
  case InitializedEntity::EK_StmtExprResult:
  case InitializedEntity::EK_New:
  case InitializedEntity::EK_Variable:
  case InitializedEntity::EK_Base:
  case InitializedEntity::EK_Delegating:
  case InitializedEntity::EK_VectorElement:
  case InitializedEntity::EK_ComplexElement:
  case InitializedEntity::EK_Exception:
  case InitializedEntity::EK_BlockElement:
  case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
  case InitializedEntity::EK_LambdaCapture:
  case InitializedEntity::EK_CompoundLiteralInit:
    return false;

  case InitializedEntity::EK_Parameter:
  case InitializedEntity::EK_Parameter_CF_Audited:
  case InitializedEntity::EK_Temporary:
  case InitializedEntity::EK_RelatedResult:
  case InitializedEntity::EK_Binding:
    return true;
  }

  llvm_unreachable("missed an InitializedEntity kind?");
}

/// Whether the given entity, when initialized with an object
/// created for that initialization, requires destruction.
static bool shouldDestroyEntity(const InitializedEntity &Entity) {
  switch (Entity.getKind()) {
    case InitializedEntity::EK_Result:
    case InitializedEntity::EK_StmtExprResult:
    case InitializedEntity::EK_New:
    case InitializedEntity::EK_Base:
    case InitializedEntity::EK_Delegating:
    case InitializedEntity::EK_VectorElement:
    case InitializedEntity::EK_ComplexElement:
    case InitializedEntity::EK_BlockElement:
    case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
    case InitializedEntity::EK_LambdaCapture:
      return false;

    case InitializedEntity::EK_Member:
    case InitializedEntity::EK_Binding:
    case InitializedEntity::EK_Variable:
    case InitializedEntity::EK_Parameter:
    case InitializedEntity::EK_Parameter_CF_Audited:
    case InitializedEntity::EK_Temporary:
    case InitializedEntity::EK_ArrayElement:
    case InitializedEntity::EK_Exception:
    case InitializedEntity::EK_CompoundLiteralInit:
    case InitializedEntity::EK_RelatedResult:
      return true;
  }

  llvm_unreachable("missed an InitializedEntity kind?");
}

/// Get the location at which initialization diagnostics should appear.
static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
                                           Expr *Initializer) {
  switch (Entity.getKind()) {
  case InitializedEntity::EK_Result:
  case InitializedEntity::EK_StmtExprResult:
    return Entity.getReturnLoc();

  case InitializedEntity::EK_Exception:
    return Entity.getThrowLoc();

  case InitializedEntity::EK_Variable:
  case InitializedEntity::EK_Binding:
    return Entity.getDecl()->getLocation();

  case InitializedEntity::EK_LambdaCapture:
    return Entity.getCaptureLoc();

  case InitializedEntity::EK_ArrayElement:
  case InitializedEntity::EK_Member:
  case InitializedEntity::EK_Parameter:
  case InitializedEntity::EK_Parameter_CF_Audited:
  case InitializedEntity::EK_Temporary:
  case InitializedEntity::EK_New:
  case InitializedEntity::EK_Base:
  case InitializedEntity::EK_Delegating:
  case InitializedEntity::EK_VectorElement:
  case InitializedEntity::EK_ComplexElement:
  case InitializedEntity::EK_BlockElement:
  case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
  case InitializedEntity::EK_CompoundLiteralInit:
  case InitializedEntity::EK_RelatedResult:
    return Initializer->getBeginLoc();
  }
  llvm_unreachable("missed an InitializedEntity kind?");
}

/// Make a (potentially elidable) temporary copy of the object
/// provided by the given initializer by calling the appropriate copy
/// constructor.
///
/// \param S The Sema object used for type-checking.
///
/// \param T The type of the temporary object, which must either be
/// the type of the initializer expression or a superclass thereof.
///
/// \param Entity The entity being initialized.
///
/// \param CurInit The initializer expression.
///
/// \param IsExtraneousCopy Whether this is an "extraneous" copy that
/// is permitted in C++03 (but not C++0x) when binding a reference to
/// an rvalue.
///
/// \returns An expression that copies the initializer expression into
/// a temporary object, or an error expression if a copy could not be
/// created.
static ExprResult CopyObject(Sema &S,
                             QualType T,
                             const InitializedEntity &Entity,
                             ExprResult CurInit,
                             bool IsExtraneousCopy) {
  if (CurInit.isInvalid())
    return CurInit;
  // Determine which class type we're copying to.
  Expr *CurInitExpr = (Expr *)CurInit.get();
  CXXRecordDecl *Class = nullptr;
  if (const RecordType *Record = T->getAs<RecordType>())
    Class = cast<CXXRecordDecl>(Record->getDecl());
  if (!Class)
    return CurInit;

  SourceLocation Loc = getInitializationLoc(Entity, CurInit.get());

  // Make sure that the type we are copying is complete.
  if (S.RequireCompleteType(Loc, T, diag::err_temp_copy_incomplete))
    return CurInit;

  // Perform overload resolution using the class's constructors. Per
  // C++11 [dcl.init]p16, second bullet for class types, this initialization
  // is direct-initialization.
  OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
  DeclContext::lookup_result Ctors = S.LookupConstructors(Class);

  OverloadCandidateSet::iterator Best;
  switch (ResolveConstructorOverload(
      S, Loc, CurInitExpr, CandidateSet, T, Ctors, Best,
      /*CopyInitializing=*/false, /*AllowExplicit=*/true,
      /*OnlyListConstructors=*/false, /*IsListInit=*/false,
      /*SecondStepOfCopyInit=*/true)) {
  case OR_Success:
    break;

  case OR_No_Viable_Function:
    CandidateSet.NoteCandidates(
        PartialDiagnosticAt(
            Loc, S.PDiag(IsExtraneousCopy && !S.isSFINAEContext()
                             ? diag::ext_rvalue_to_reference_temp_copy_no_viable
                             : diag::err_temp_copy_no_viable)
                     << (int)Entity.getKind() << CurInitExpr->getType()
                     << CurInitExpr->getSourceRange()),
        S, OCD_AllCandidates, CurInitExpr);
    if (!IsExtraneousCopy || S.isSFINAEContext())
      return ExprError();
    return CurInit;

  case OR_Ambiguous:
    CandidateSet.NoteCandidates(
        PartialDiagnosticAt(Loc, S.PDiag(diag::err_temp_copy_ambiguous)
                                     << (int)Entity.getKind()
                                     << CurInitExpr->getType()
                                     << CurInitExpr->getSourceRange()),
        S, OCD_ViableCandidates, CurInitExpr);
    return ExprError();

  case OR_Deleted:
    S.Diag(Loc, diag::err_temp_copy_deleted)
      << (int)Entity.getKind() << CurInitExpr->getType()
      << CurInitExpr->getSourceRange();
    S.NoteDeletedFunction(Best->Function);
    return ExprError();
  }

  bool HadMultipleCandidates = CandidateSet.size() > 1;

  CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
  SmallVector<Expr*, 8> ConstructorArgs;
  CurInit.get(); // Ownership transferred into MultiExprArg, below.

  S.CheckConstructorAccess(Loc, Constructor, Best->FoundDecl, Entity,
                           IsExtraneousCopy);

  if (IsExtraneousCopy) {
    // If this is a totally extraneous copy for C++03 reference
    // binding purposes, just return the original initialization
    // expression. We don't generate an (elided) copy operation here
    // because doing so would require us to pass down a flag to avoid
    // infinite recursion, where each step adds another extraneous,
    // elidable copy.

    // Instantiate the default arguments of any extra parameters in
    // the selected copy constructor, as if we were going to create a
    // proper call to the copy constructor.
    for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) {
      ParmVarDecl *Parm = Constructor->getParamDecl(I);
      if (S.RequireCompleteType(Loc, Parm->getType(),
                                diag::err_call_incomplete_argument))
        break;

      // Build the default argument expression; we don't actually care
      // if this succeeds or not, because this routine will complain
      // if there was a problem.
      S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm);
    }

    return CurInitExpr;
  }

  // Determine the arguments required to actually perform the
  // constructor call (we might have derived-to-base conversions, or
  // the copy constructor may have default arguments).
  if (S.CompleteConstructorCall(Constructor, CurInitExpr, Loc, ConstructorArgs))
    return ExprError();

  // C++0x [class.copy]p32:
  //   When certain criteria are met, an implementation is allowed to
  //   omit the copy/move construction of a class object, even if the
  //   copy/move constructor and/or destructor for the object have
  //   side effects. [...]
  //     - when a temporary class object that has not been bound to a
  //       reference (12.2) would be copied/moved to a class object
  //       with the same cv-unqualified type, the copy/move operation
  //       can be omitted by constructing the temporary object
  //       directly into the target of the omitted copy/move
  //
  // Note that the other three bullets are handled elsewhere. Copy
  // elision for return statements and throw expressions are handled as part
  // of constructor initialization, while copy elision for exception handlers
  // is handled by the run-time.
  //
  // FIXME: If the function parameter is not the same type as the temporary, we
  // should still be able to elide the copy, but we don't have a way to
  // represent in the AST how much should be elided in this case.
  bool Elidable =
      CurInitExpr->isTemporaryObject(S.Context, Class) &&
      S.Context.hasSameUnqualifiedType(
          Best->Function->getParamDecl(0)->getType().getNonReferenceType(),
          CurInitExpr->getType());

  // Actually perform the constructor call.
  CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor,
                                    Elidable,
                                    ConstructorArgs,
                                    HadMultipleCandidates,
                                    /*ListInit*/ false,
                                    /*StdInitListInit*/ false,
                                    /*ZeroInit*/ false,
                                    CXXConstructExpr::CK_Complete,
                                    SourceRange());

  // If we're supposed to bind temporaries, do so.
  if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity))
    CurInit = S.MaybeBindToTemporary(CurInit.getAs<Expr>());
  return CurInit;
}

/// Check whether elidable copy construction for binding a reference to
/// a temporary would have succeeded if we were building in C++98 mode, for
/// -Wc++98-compat.
static void CheckCXX98CompatAccessibleCopy(Sema &S,
                                           const InitializedEntity &Entity,
                                           Expr *CurInitExpr) {
  assert(S.getLangOpts().CPlusPlus11);

  const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>();
  if (!Record)
    return;

  SourceLocation Loc = getInitializationLoc(Entity, CurInitExpr);
  if (S.Diags.isIgnored(diag::warn_cxx98_compat_temp_copy, Loc))
    return;

  // Find constructors which would have been considered.
  OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
  DeclContext::lookup_result Ctors =
      S.LookupConstructors(cast<CXXRecordDecl>(Record->getDecl()));

  // Perform overload resolution.
  OverloadCandidateSet::iterator Best;
  OverloadingResult OR = ResolveConstructorOverload(
      S, Loc, CurInitExpr, CandidateSet, CurInitExpr->getType(), Ctors, Best,
      /*CopyInitializing=*/false, /*AllowExplicit=*/true,
      /*OnlyListConstructors=*/false, /*IsListInit=*/false,
      /*SecondStepOfCopyInit=*/true);

  PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy)
    << OR << (int)Entity.getKind() << CurInitExpr->getType()
    << CurInitExpr->getSourceRange();

  switch (OR) {
  case OR_Success:
    S.CheckConstructorAccess(Loc, cast<CXXConstructorDecl>(Best->Function),
                             Best->FoundDecl, Entity, Diag);
    // FIXME: Check default arguments as far as that's possible.
    break;

  case OR_No_Viable_Function:
    CandidateSet.NoteCandidates(PartialDiagnosticAt(Loc, Diag), S,
                                OCD_AllCandidates, CurInitExpr);
    break;

  case OR_Ambiguous:
    CandidateSet.NoteCandidates(PartialDiagnosticAt(Loc, Diag), S,
                                OCD_ViableCandidates, CurInitExpr);
    break;

  case OR_Deleted:
    S.Diag(Loc, Diag);
    S.NoteDeletedFunction(Best->Function);
    break;
  }
}

void InitializationSequence::PrintInitLocationNote(Sema &S,
                                              const InitializedEntity &Entity) {
  if (Entity.isParameterKind() && Entity.getDecl()) {
    if (Entity.getDecl()->getLocation().isInvalid())
      return;

    if (Entity.getDecl()->getDeclName())
      S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here)
        << Entity.getDecl()->getDeclName();
    else
      S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here);
  }
  else if (Entity.getKind() == InitializedEntity::EK_RelatedResult &&
           Entity.getMethodDecl())
    S.Diag(Entity.getMethodDecl()->getLocation(),
           diag::note_method_return_type_change)
      << Entity.getMethodDecl()->getDeclName();
}

/// Returns true if the parameters describe a constructor initialization of
/// an explicit temporary object, e.g. "Point(x, y)".
static bool isExplicitTemporary(const InitializedEntity &Entity,
                                const InitializationKind &Kind,
                                unsigned NumArgs) {
  switch (Entity.getKind()) {
  case InitializedEntity::EK_Temporary:
  case InitializedEntity::EK_CompoundLiteralInit:
  case InitializedEntity::EK_RelatedResult:
    break;
  default:
    return false;
  }

  switch (Kind.getKind()) {
  case InitializationKind::IK_DirectList:
    return true;
  // FIXME: Hack to work around cast weirdness.
  case InitializationKind::IK_Direct:
  case InitializationKind::IK_Value:
    return NumArgs != 1;
  default:
    return false;
  }
}

static ExprResult
PerformConstructorInitialization(Sema &S,
                                 const InitializedEntity &Entity,
                                 const InitializationKind &Kind,
                                 MultiExprArg Args,
                                 const InitializationSequence::Step& Step,
                                 bool &ConstructorInitRequiresZeroInit,
                                 bool IsListInitialization,
                                 bool IsStdInitListInitialization,
                                 SourceLocation LBraceLoc,
                                 SourceLocation RBraceLoc) {
  unsigned NumArgs = Args.size();
  CXXConstructorDecl *Constructor
    = cast<CXXConstructorDecl>(Step.Function.Function);
  bool HadMultipleCandidates = Step.Function.HadMultipleCandidates;

  // Build a call to the selected constructor.
  SmallVector<Expr*, 8> ConstructorArgs;
  SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
                         ? Kind.getEqualLoc()
                         : Kind.getLocation();

  if (Kind.getKind() == InitializationKind::IK_Default) {
    // Force even a trivial, implicit default constructor to be
    // semantically checked. We do this explicitly because we don't build
    // the definition for completely trivial constructors.
    assert(Constructor->getParent() && "No parent class for constructor.");
    if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
        Constructor->isTrivial() && !Constructor->isUsed(false)) {
      S.runWithSufficientStackSpace(Loc, [&] {
        S.DefineImplicitDefaultConstructor(Loc, Constructor);
      });
    }
  }

  ExprResult CurInit((Expr *)nullptr);

  // C++ [over.match.copy]p1:
  //   - When initializing a temporary to be bound to the first parameter
  //     of a constructor that takes a reference to possibly cv-qualified
  //     T as its first argument, called with a single argument in the
  //     context of direct-initialization, explicit conversion functions
  //     are also considered.
  bool AllowExplicitConv =
      Kind.AllowExplicit() && !Kind.isCopyInit() && Args.size() == 1 &&
      hasCopyOrMoveCtorParam(S.Context,
                             getConstructorInfo(Step.Function.FoundDecl));

  // Determine the arguments required to actually perform the constructor
  // call.
  if (S.CompleteConstructorCall(Constructor, Args,
                                Loc, ConstructorArgs,
                                AllowExplicitConv,
                                IsListInitialization))
    return ExprError();


  if (isExplicitTemporary(Entity, Kind, NumArgs)) {
    // An explicitly-constructed temporary, e.g., X(1, 2).
    if (S.DiagnoseUseOfDecl(Constructor, Loc))
      return ExprError();

    TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
    if (!TSInfo)
      TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
    SourceRange ParenOrBraceRange =
        (Kind.getKind() == InitializationKind::IK_DirectList)
        ? SourceRange(LBraceLoc, RBraceLoc)
        : Kind.getParenOrBraceRange();

    if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
            Step.Function.FoundDecl.getDecl())) {
      Constructor = S.findInheritingConstructor(Loc, Constructor, Shadow);
      if (S.DiagnoseUseOfDecl(Constructor, Loc))
        return ExprError();
    }
    S.MarkFunctionReferenced(Loc, Constructor);

    CurInit = CXXTemporaryObjectExpr::Create(
        S.Context, Constructor,
        Entity.getType().getNonLValueExprType(S.Context), TSInfo,
        ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates,
        IsListInitialization, IsStdInitListInitialization,
        ConstructorInitRequiresZeroInit);
  } else {
    CXXConstructExpr::ConstructionKind ConstructKind =
      CXXConstructExpr::CK_Complete;

    if (Entity.getKind() == InitializedEntity::EK_Base) {
      ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
        CXXConstructExpr::CK_VirtualBase :
        CXXConstructExpr::CK_NonVirtualBase;
    } else if (Entity.getKind() == InitializedEntity::EK_Delegating) {
      ConstructKind = CXXConstructExpr::CK_Delegating;
    }

    // Only get the parenthesis or brace range if it is a list initialization or
    // direct construction.
    SourceRange ParenOrBraceRange;
    if (IsListInitialization)
      ParenOrBraceRange = SourceRange(LBraceLoc, RBraceLoc);
    else if (Kind.getKind() == InitializationKind::IK_Direct)
      ParenOrBraceRange = Kind.getParenOrBraceRange();

    // If the entity allows NRVO, mark the construction as elidable
    // unconditionally.
    if (Entity.allowsNRVO())
      CurInit = S.BuildCXXConstructExpr(Loc, Step.Type,
                                        Step.Function.FoundDecl,
                                        Constructor, /*Elidable=*/true,
                                        ConstructorArgs,
                                        HadMultipleCandidates,
                                        IsListInitialization,
                                        IsStdInitListInitialization,
                                        ConstructorInitRequiresZeroInit,
                                        ConstructKind,
                                        ParenOrBraceRange);
    else
      CurInit = S.BuildCXXConstructExpr(Loc, Step.Type,
                                        Step.Function.FoundDecl,
                                        Constructor,
                                        ConstructorArgs,
                                        HadMultipleCandidates,
                                        IsListInitialization,
                                        IsStdInitListInitialization,
                                        ConstructorInitRequiresZeroInit,
                                        ConstructKind,
                                        ParenOrBraceRange);
  }
  if (CurInit.isInvalid())
    return ExprError();

  // Only check access if all of that succeeded.
  S.CheckConstructorAccess(Loc, Constructor, Step.Function.FoundDecl, Entity);
  if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc))
    return ExprError();

  if (const ArrayType *AT = S.Context.getAsArrayType(Entity.getType()))
    if (checkDestructorReference(S.Context.getBaseElementType(AT), Loc, S))
      return ExprError();

  if (shouldBindAsTemporary(Entity))
    CurInit = S.MaybeBindToTemporary(CurInit.get());

  return CurInit;
}

namespace {
enum LifetimeKind {
  /// The lifetime of a temporary bound to this entity ends at the end of the
  /// full-expression, and that's (probably) fine.
  LK_FullExpression,

  /// The lifetime of a temporary bound to this entity is extended to the
  /// lifeitme of the entity itself.
  LK_Extended,

  /// The lifetime of a temporary bound to this entity probably ends too soon,
  /// because the entity is allocated in a new-expression.
  LK_New,

  /// The lifetime of a temporary bound to this entity ends too soon, because
  /// the entity is a return object.
  LK_Return,

  /// The lifetime of a temporary bound to this entity ends too soon, because
  /// the entity is the result of a statement expression.
  LK_StmtExprResult,

  /// This is a mem-initializer: if it would extend a temporary (other than via
  /// a default member initializer), the program is ill-formed.
  LK_MemInitializer,
};
using LifetimeResult =
    llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
}

/// Determine the declaration which an initialized entity ultimately refers to,
/// for the purpose of lifetime-extending a temporary bound to a reference in
/// the initialization of \p Entity.
static LifetimeResult getEntityLifetime(
    const InitializedEntity *Entity,
    const InitializedEntity *InitField = nullptr) {
  // C++11 [class.temporary]p5:
  switch (Entity->getKind()) {
  case InitializedEntity::EK_Variable:
    //   The temporary [...] persists for the lifetime of the reference
    return {Entity, LK_Extended};

  case InitializedEntity::EK_Member:
    // For subobjects, we look at the complete object.
    if (Entity->getParent())
      return getEntityLifetime(Entity->getParent(), Entity);

    //   except:
    // C++17 [class.base.init]p8:
    //   A temporary expression bound to a reference member in a
    //   mem-initializer is ill-formed.
    // C++17 [class.base.init]p11:
    //   A temporary expression bound to a reference member from a
    //   default member initializer is ill-formed.
    //
    // The context of p11 and its example suggest that it's only the use of a
    // default member initializer from a constructor that makes the program
    // ill-formed, not its mere existence, and that it can even be used by
    // aggregate initialization.
    return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
                                                         : LK_MemInitializer};

  case InitializedEntity::EK_Binding:
    // Per [dcl.decomp]p3, the binding is treated as a variable of reference
    // type.
    return {Entity, LK_Extended};

  case InitializedEntity::EK_Parameter:
  case InitializedEntity::EK_Parameter_CF_Audited:
    //   -- A temporary bound to a reference parameter in a function call
    //      persists until the completion of the full-expression containing
    //      the call.
    return {nullptr, LK_FullExpression};

  case InitializedEntity::EK_Result:
    //   -- The lifetime of a temporary bound to the returned value in a
    //      function return statement is not extended; the temporary is
    //      destroyed at the end of the full-expression in the return statement.
    return {nullptr, LK_Return};

  case InitializedEntity::EK_StmtExprResult:
    // FIXME: Should we lifetime-extend through the result of a statement
    // expression?
    return {nullptr, LK_StmtExprResult};

  case InitializedEntity::EK_New:
    //   -- A temporary bound to a reference in a new-initializer persists
    //      until the completion of the full-expression containing the
    //      new-initializer.
    return {nullptr, LK_New};

  case InitializedEntity::EK_Temporary:
  case InitializedEntity::EK_CompoundLiteralInit:
  case InitializedEntity::EK_RelatedResult:
    // We don't yet know the storage duration of the surrounding temporary.
    // Assume it's got full-expression duration for now, it will patch up our
    // storage duration if that's not correct.
    return {nullptr, LK_FullExpression};

  case InitializedEntity::EK_ArrayElement:
    // For subobjects, we look at the complete object.
    return getEntityLifetime(Entity->getParent(), InitField);

  case InitializedEntity::EK_Base:
    // For subobjects, we look at the complete object.
    if (Entity->getParent())
      return getEntityLifetime(Entity->getParent(), InitField);
    return {InitField, LK_MemInitializer};

  case InitializedEntity::EK_Delegating:
    // We can reach this case for aggregate initialization in a constructor:
    //   struct A { int &&r; };
    //   struct B : A { B() : A{0} {} };
    // In this case, use the outermost field decl as the context.
    return {InitField, LK_MemInitializer};

  case InitializedEntity::EK_BlockElement:
  case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
  case InitializedEntity::EK_LambdaCapture:
  case InitializedEntity::EK_VectorElement:
  case InitializedEntity::EK_ComplexElement:
    return {nullptr, LK_FullExpression};

  case InitializedEntity::EK_Exception:
    // FIXME: Can we diagnose lifetime problems with exceptions?
    return {nullptr, LK_FullExpression};
  }
  llvm_unreachable("unknown entity kind");
}

namespace {
enum ReferenceKind {
  /// Lifetime would be extended by a reference binding to a temporary.
  RK_ReferenceBinding,
  /// Lifetime would be extended by a std::initializer_list object binding to
  /// its backing array.
  RK_StdInitializerList,
};

/// A temporary or local variable. This will be one of:
///  * A MaterializeTemporaryExpr.
///  * A DeclRefExpr whose declaration is a local.
///  * An AddrLabelExpr.
///  * A BlockExpr for a block with captures.
using Local = Expr*;

/// Expressions we stepped over when looking for the local state. Any steps
/// that would inhibit lifetime extension or take us out of subexpressions of
/// the initializer are included.
struct IndirectLocalPathEntry {
  enum EntryKind {
    DefaultInit,
    AddressOf,
    VarInit,
    LValToRVal,
    LifetimeBoundCall,
    GslPointerInit
  } Kind;
  Expr *E;
  const Decl *D = nullptr;
  IndirectLocalPathEntry() {}
  IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
  IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
      : Kind(K), E(E), D(D) {}
};

using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;

struct RevertToOldSizeRAII {
  IndirectLocalPath &Path;
  unsigned OldSize = Path.size();
  RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
  ~RevertToOldSizeRAII() { Path.resize(OldSize); }
};

using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
                                             ReferenceKind RK)>;
}

static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
  for (auto E : Path)
    if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
      return true;
  return false;
}

static bool pathContainsInit(IndirectLocalPath &Path) {
  return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
    return E.Kind == IndirectLocalPathEntry::DefaultInit ||
           E.Kind == IndirectLocalPathEntry::VarInit;
  });
}

static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
                                             Expr *Init, LocalVisitor Visit,
                                             bool RevisitSubinits,
                                             bool EnableLifetimeWarnings);

static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
                                                  Expr *Init, ReferenceKind RK,
                                                  LocalVisitor Visit,
                                                  bool EnableLifetimeWarnings);

template <typename T> static bool isRecordWithAttr(QualType Type) {
  if (auto *RD = Type->getAsCXXRecordDecl())
    return RD->hasAttr<T>();
  return false;
}

// Decl::isInStdNamespace will return false for iterators in some STL
// implementations due to them being defined in a namespace outside of the std
// namespace.
static bool isInStlNamespace(const Decl *D) {
  const DeclContext *DC = D->getDeclContext();
  if (!DC)
    return false;
  if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
    if (const IdentifierInfo *II = ND->getIdentifier()) {
      StringRef Name = II->getName();
      if (Name.size() >= 2 && Name.front() == '_' &&
          (Name[1] == '_' || isUppercase(Name[1])))
        return true;
    }

  return DC->isStdNamespace();
}

static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
  if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
    if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
      return true;
  if (!isInStlNamespace(Callee->getParent()))
    return false;
  if (!isRecordWithAttr<PointerAttr>(Callee->getThisObjectType()) &&
      !isRecordWithAttr<OwnerAttr>(Callee->getThisObjectType()))
    return false;
  if (Callee->getReturnType()->isPointerType() ||
      isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {
    if (!Callee->getIdentifier())
      return false;
    return llvm::StringSwitch<bool>(Callee->getName())
        .Cases("begin", "rbegin", "cbegin", "crbegin", true)
        .Cases("end", "rend", "cend", "crend", true)
        .Cases("c_str", "data", "get", true)
        // Map and set types.
        .Cases("find", "equal_range", "lower_bound", "upper_bound", true)
        .Default(false);
  } else if (Callee->getReturnType()->isReferenceType()) {
    if (!Callee->getIdentifier()) {
      auto OO = Callee->getOverloadedOperator();
      return OO == OverloadedOperatorKind::OO_Subscript ||
             OO == OverloadedOperatorKind::OO_Star;
    }
    return llvm::StringSwitch<bool>(Callee->getName())
        .Cases("front", "back", "at", "top", "value", true)
        .Default(false);
  }
  return false;
}

static bool shouldTrackFirstArgument(const FunctionDecl *FD) {
  if (!FD->getIdentifier() || FD->getNumParams() != 1)
    return false;
  const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
  if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
    return false;
  if (!isRecordWithAttr<PointerAttr>(QualType(RD->getTypeForDecl(), 0)) &&
      !isRecordWithAttr<OwnerAttr>(QualType(RD->getTypeForDecl(), 0)))
    return false;
  if (FD->getReturnType()->isPointerType() ||
      isRecordWithAttr<PointerAttr>(FD->getReturnType())) {
    return llvm::StringSwitch<bool>(FD->getName())
        .Cases("begin", "rbegin", "cbegin", "crbegin", true)
        .Cases("end", "rend", "cend", "crend", true)
        .Case("data", true)
        .Default(false);
  } else if (FD->getReturnType()->isReferenceType()) {
    return llvm::StringSwitch<bool>(FD->getName())
        .Cases("get", "any_cast", true)
        .Default(false);
  }
  return false;
}

static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
                                    LocalVisitor Visit) {
  auto VisitPointerArg = [&](const Decl *D, Expr *Arg) {
    // We are not interested in the temporary base objects of gsl Pointers:
    //   Temp().ptr; // Here ptr might not dangle.
    if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
      return;
    Path.push_back({IndirectLocalPathEntry::GslPointerInit, Arg, D});
    if (Arg->isGLValue())
      visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
                                            Visit,
                                            /*EnableLifetimeWarnings=*/true);
    else
      visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
                                       /*EnableLifetimeWarnings=*/true);
    Path.pop_back();
  };

  if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
    const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());
    if (MD && shouldTrackImplicitObjectArg(MD))
      VisitPointerArg(MD, MCE->getImplicitObjectArgument());
    return;
  } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
    FunctionDecl *Callee = OCE->getDirectCallee();
    if (Callee && Callee->isCXXInstanceMember() &&
        shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
      VisitPointerArg(Callee, OCE->getArg(0));
    return;
  } else if (auto *CE = dyn_cast<CallExpr>(Call)) {
    FunctionDecl *Callee = CE->getDirectCallee();
    if (Callee && shouldTrackFirstArgument(Callee))
      VisitPointerArg(Callee, CE->getArg(0));
    return;
  }

  if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {
    const auto *Ctor = CCE->getConstructor();
    const CXXRecordDecl *RD = Ctor->getParent();
    if (CCE->getNumArgs() > 0 && RD->hasAttr<PointerAttr>())
      VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0]);
  }
}

static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
  const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
  if (!TSI)
    return false;
  // Don't declare this variable in the second operand of the for-statement;
  // GCC miscompiles that by ending its lifetime before evaluating the
  // third operand. See gcc.gnu.org/PR86769.
  AttributedTypeLoc ATL;
  for (TypeLoc TL = TSI->getTypeLoc();
       (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
       TL = ATL.getModifiedLoc()) {
    if (ATL.getAttrAs<LifetimeBoundAttr>())
      return true;
  }
  return false;
}

static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
                                        LocalVisitor Visit) {
  const FunctionDecl *Callee;
  ArrayRef<Expr*> Args;

  if (auto *CE = dyn_cast<CallExpr>(Call)) {
    Callee = CE->getDirectCallee();
    Args = llvm::makeArrayRef(CE->getArgs(), CE->getNumArgs());
  } else {
    auto *CCE = cast<CXXConstructExpr>(Call);
    Callee = CCE->getConstructor();
    Args = llvm::makeArrayRef(CCE->getArgs(), CCE->getNumArgs());
  }
  if (!Callee)
    return;

  Expr *ObjectArg = nullptr;
  if (isa<CXXOperatorCallExpr>(Call) && Callee->isCXXInstanceMember()) {
    ObjectArg = Args[0];
    Args = Args.slice(1);
  } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
    ObjectArg = MCE->getImplicitObjectArgument();
  }

  auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
    Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
    if (Arg->isGLValue())
      visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding,
                                            Visit,
                                            /*EnableLifetimeWarnings=*/false);
    else
      visitLocalsRetainedByInitializer(Path, Arg, Visit, true,
                                       /*EnableLifetimeWarnings=*/false);
    Path.pop_back();
  };

  if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee))
    VisitLifetimeBoundArg(Callee, ObjectArg);

  for (unsigned I = 0,
                N = std::min<unsigned>(Callee->getNumParams(), Args.size());
       I != N; ++I) {
    if (Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
      VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
  }
}

/// Visit the locals that would be reachable through a reference bound to the
/// glvalue expression \c Init.
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
                                                  Expr *Init, ReferenceKind RK,
                                                  LocalVisitor Visit,
                                                  bool EnableLifetimeWarnings) {
  RevertToOldSizeRAII RAII(Path);

  // Walk past any constructs which we can lifetime-extend across.
  Expr *Old;
  do {
    Old = Init;

    if (auto *FE = dyn_cast<FullExpr>(Init))
      Init = FE->getSubExpr();

    if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
      // If this is just redundant braces around an initializer, step over it.
      if (ILE->isTransparent())
        Init = ILE->getInit(0);
    }

    // Step over any subobject adjustments; we may have a materialized
    // temporary inside them.
    Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());

    // Per current approach for DR1376, look through casts to reference type
    // when performing lifetime extension.
    if (CastExpr *CE = dyn_cast<CastExpr>(Init))
      if (CE->getSubExpr()->isGLValue())
        Init = CE->getSubExpr();

    // Per the current approach for DR1299, look through array element access
    // on array glvalues when performing lifetime extension.
    if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) {
      Init = ASE->getBase();
      auto *ICE = dyn_cast<ImplicitCastExpr>(Init);
      if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
        Init = ICE->getSubExpr();
      else
        // We can't lifetime extend through this but we might still find some
        // retained temporaries.
        return visitLocalsRetainedByInitializer(Path, Init, Visit, true,
                                                EnableLifetimeWarnings);
    }

    // Step into CXXDefaultInitExprs so we can diagnose cases where a
    // constructor inherits one as an implicit mem-initializer.
    if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
      Path.push_back(
          {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
      Init = DIE->getExpr();
    }
  } while (Init != Old);

  if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
    if (Visit(Path, Local(MTE), RK))
      visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit,
                                       true, EnableLifetimeWarnings);
  }

  if (isa<CallExpr>(Init)) {
    if (EnableLifetimeWarnings)
      handleGslAnnotatedTypes(Path, Init, Visit);
    return visitLifetimeBoundArguments(Path, Init, Visit);
  }

  switch (Init->getStmtClass()) {
  case Stmt::DeclRefExprClass: {
    // If we find the name of a local non-reference parameter, we could have a
    // lifetime problem.
    auto *DRE = cast<DeclRefExpr>(Init);
    auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
    if (VD && VD->hasLocalStorage() &&
        !DRE->refersToEnclosingVariableOrCapture()) {
      if (!VD->getType()->isReferenceType()) {
        Visit(Path, Local(DRE), RK);
      } else if (isa<ParmVarDecl>(DRE->getDecl())) {
        // The lifetime of a reference parameter is unknown; assume it's OK
        // for now.
        break;
      } else if (VD->getInit() && !isVarOnPath(Path, VD)) {
        Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
        visitLocalsRetainedByReferenceBinding(Path, VD->getInit(),
                                              RK_ReferenceBinding, Visit,
                                              EnableLifetimeWarnings);
      }
    }
    break;
  }

  case Stmt::UnaryOperatorClass: {
    // The only unary operator that make sense to handle here
    // is Deref.  All others don't resolve to a "name."  This includes
    // handling all sorts of rvalues passed to a unary operator.
    const UnaryOperator *U = cast<UnaryOperator>(Init);
    if (U->getOpcode() == UO_Deref)
      visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true,
                                       EnableLifetimeWarnings);
    break;
  }

  case Stmt::OMPArraySectionExprClass: {
    visitLocalsRetainedByInitializer(Path,
                                     cast<OMPArraySectionExpr>(Init)->getBase(),
                                     Visit, true, EnableLifetimeWarnings);
    break;
  }

  case Stmt::ConditionalOperatorClass:
  case Stmt::BinaryConditionalOperatorClass: {
    auto *C = cast<AbstractConditionalOperator>(Init);
    if (!C->getTrueExpr()->getType()->isVoidType())
      visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit,
                                            EnableLifetimeWarnings);
    if (!C->getFalseExpr()->getType()->isVoidType())
      visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit,
                                            EnableLifetimeWarnings);
    break;
  }

  // FIXME: Visit the left-hand side of an -> or ->*.

  default:
    break;
  }
}

/// Visit the locals that would be reachable through an object initialized by
/// the prvalue expression \c Init.
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
                                             Expr *Init, LocalVisitor Visit,
                                             bool RevisitSubinits,
                                             bool EnableLifetimeWarnings) {
  RevertToOldSizeRAII RAII(Path);

  Expr *Old;
  do {
    Old = Init;

    // Step into CXXDefaultInitExprs so we can diagnose cases where a
    // constructor inherits one as an implicit mem-initializer.
    if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
      Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
      Init = DIE->getExpr();
    }

    if (auto *FE = dyn_cast<FullExpr>(Init))
      Init = FE->getSubExpr();

    // Dig out the expression which constructs the extended temporary.
    Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());

    if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
      Init = BTE->getSubExpr();

    Init = Init->IgnoreParens();

    // Step over value-preserving rvalue casts.
    if (auto *CE = dyn_cast<CastExpr>(Init)) {
      switch (CE->getCastKind()) {
      case CK_LValueToRValue:
        // If we can match the lvalue to a const object, we can look at its
        // initializer.
        Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
        return visitLocalsRetainedByReferenceBinding(
            Path, Init, RK_ReferenceBinding,
            [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
          if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
            auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
            if (VD && VD->getType().isConstQualified() && VD->getInit() &&
                !isVarOnPath(Path, VD)) {
              Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
              visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, true,
                                               EnableLifetimeWarnings);
            }
          } else if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
            if (MTE->getType().isConstQualified())
              visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(),
                                               Visit, true,
                                               EnableLifetimeWarnings);
          }
          return false;
        }, EnableLifetimeWarnings);

        // We assume that objects can be retained by pointers cast to integers,
        // but not if the integer is cast to floating-point type or to _Complex.
        // We assume that casts to 'bool' do not preserve enough information to
        // retain a local object.
      case CK_NoOp:
      case CK_BitCast:
      case CK_BaseToDerived:
      case CK_DerivedToBase:
      case CK_UncheckedDerivedToBase:
      case CK_Dynamic:
      case CK_ToUnion:
      case CK_UserDefinedConversion:
      case CK_ConstructorConversion:
      case CK_IntegralToPointer:
      case CK_PointerToIntegral:
      case CK_VectorSplat:
      case CK_IntegralCast:
      case CK_CPointerToObjCPointerCast:
      case CK_BlockPointerToObjCPointerCast:
      case CK_AnyPointerToBlockPointerCast:
      case CK_AddressSpaceConversion:
        break;

      case CK_ArrayToPointerDecay:
        // Model array-to-pointer decay as taking the address of the array
        // lvalue.
        Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
        return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(),
                                                     RK_ReferenceBinding, Visit,
                                                     EnableLifetimeWarnings);

      default:
        return;
      }

      Init = CE->getSubExpr();
    }
  } while (Old != Init);

  // C++17 [dcl.init.list]p6:
  //   initializing an initializer_list object from the array extends the
  //   lifetime of the array exactly like binding a reference to a temporary.
  if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
    return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
                                                 RK_StdInitializerList, Visit,
                                                 EnableLifetimeWarnings);

  if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
    // We already visited the elements of this initializer list while
    // performing the initialization. Don't visit them again unless we've
    // changed the lifetime of the initialized entity.
    if (!RevisitSubinits)
      return;

    if (ILE->isTransparent())
      return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit,
                                              RevisitSubinits,
                                              EnableLifetimeWarnings);

    if (ILE->getType()->isArrayType()) {
      for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
        visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
                                         RevisitSubinits,
                                         EnableLifetimeWarnings);
      return;
    }

    if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
      assert(RD->isAggregate() && "aggregate init on non-aggregate");

      // If we lifetime-extend a braced initializer which is initializing an
      // aggregate, and that aggregate contains reference members which are
      // bound to temporaries, those temporaries are also lifetime-extended.
      if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
          ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
        visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
                                              RK_ReferenceBinding, Visit,
                                              EnableLifetimeWarnings);
      else {
        unsigned Index = 0;
        for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
          visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,
                                           RevisitSubinits,
                                           EnableLifetimeWarnings);
        for (const auto *I : RD->fields()) {
          if (Index >= ILE->getNumInits())
            break;
          if (I->isUnnamedBitfield())
            continue;
          Expr *SubInit = ILE->getInit(Index);
          if (I->getType()->isReferenceType())
            visitLocalsRetainedByReferenceBinding(Path, SubInit,
                                                  RK_ReferenceBinding, Visit,
                                                  EnableLifetimeWarnings);
          else
            // This might be either aggregate-initialization of a member or
            // initialization of a std::initializer_list object. Regardless,
            // we should recursively lifetime-extend that initializer.
            visitLocalsRetainedByInitializer(Path, SubInit, Visit,
                                             RevisitSubinits,
                                             EnableLifetimeWarnings);
          ++Index;
        }
      }
    }
    return;
  }

  // The lifetime of an init-capture is that of the closure object constructed
  // by a lambda-expression.
  if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
    for (Expr *E : LE->capture_inits()) {
      if (!E)
        continue;
      if (E->isGLValue())
        visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
                                              Visit, EnableLifetimeWarnings);
      else
        visitLocalsRetainedByInitializer(Path, E, Visit, true,
                                         EnableLifetimeWarnings);
    }
  }

  if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init)) {
    if (EnableLifetimeWarnings)
      handleGslAnnotatedTypes(Path, Init, Visit);
    return visitLifetimeBoundArguments(Path, Init, Visit);
  }

  switch (Init->getStmtClass()) {
  case Stmt::UnaryOperatorClass: {
    auto *UO = cast<UnaryOperator>(Init);
    // If the initializer is the address of a local, we could have a lifetime
    // problem.
    if (UO->getOpcode() == UO_AddrOf) {
      // If this is &rvalue, then it's ill-formed and we have already diagnosed
      // it. Don't produce a redundant warning about the lifetime of the
      // temporary.
      if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
        return;

      Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
      visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(),
                                            RK_ReferenceBinding, Visit,
                                            EnableLifetimeWarnings);
    }
    break;
  }

  case Stmt::BinaryOperatorClass: {
    // Handle pointer arithmetic.
    auto *BO = cast<BinaryOperator>(Init);
    BinaryOperatorKind BOK = BO->getOpcode();
    if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
      break;

    if (BO->getLHS()->getType()->isPointerType())
      visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true,
                                       EnableLifetimeWarnings);
    else if (BO->getRHS()->getType()->isPointerType())
      visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true,
                                       EnableLifetimeWarnings);
    break;
  }

  case Stmt::ConditionalOperatorClass:
  case Stmt::BinaryConditionalOperatorClass: {
    auto *C = cast<AbstractConditionalOperator>(Init);
    // In C++, we can have a throw-expression operand, which has 'void' type
    // and isn't interesting from a lifetime perspective.
    if (!C->getTrueExpr()->getType()->isVoidType())
      visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true,
                                       EnableLifetimeWarnings);
    if (!C->getFalseExpr()->getType()->isVoidType())
      visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true,
                                       EnableLifetimeWarnings);
    break;
  }

  case Stmt::BlockExprClass:
    if (cast<BlockExpr>(Init)->getBlockDecl()->hasCaptures()) {
      // This is a local block, whose lifetime is that of the function.
      Visit(Path, Local(cast<BlockExpr>(Init)), RK_ReferenceBinding);
    }
    break;

  case Stmt::AddrLabelExprClass:
    // We want to warn if the address of a label would escape the function.
    Visit(Path, Local(cast<AddrLabelExpr>(Init)), RK_ReferenceBinding);
    break;

  default:
    break;
  }
}

/// Determine whether this is an indirect path to a temporary that we are
/// supposed to lifetime-extend along (but don't).
static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
  for (auto Elem : Path) {
    if (Elem.Kind != IndirectLocalPathEntry::DefaultInit)
      return false;
  }
  return true;
}

/// Find the range for the first interesting entry in the path at or after I.
static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
                                      Expr *E) {
  for (unsigned N = Path.size(); I != N; ++I) {
    switch (Path[I].Kind) {
    case IndirectLocalPathEntry::AddressOf:
    case IndirectLocalPathEntry::LValToRVal:
    case IndirectLocalPathEntry::LifetimeBoundCall:
    case IndirectLocalPathEntry::GslPointerInit:
      // These exist primarily to mark the path as not permitting or
      // supporting lifetime extension.
      break;

    case IndirectLocalPathEntry::VarInit:
      if (cast<VarDecl>(Path[I].D)->isImplicit())
        return SourceRange();
      LLVM_FALLTHROUGH;
    case IndirectLocalPathEntry::DefaultInit:
      return Path[I].E->getSourceRange();
    }
  }
  return E->getSourceRange();
}

static bool pathOnlyInitializesGslPointer(IndirectLocalPath &Path) {
  for (auto It = Path.rbegin(), End = Path.rend(); It != End; ++It) {
    if (It->Kind == IndirectLocalPathEntry::VarInit)
      continue;
    if (It->Kind == IndirectLocalPathEntry::AddressOf)
      continue;
    return It->Kind == IndirectLocalPathEntry::GslPointerInit;
  }
  return false;
}

void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
                                    Expr *Init) {
  LifetimeResult LR = getEntityLifetime(&Entity);
  LifetimeKind LK = LR.getInt();
  const InitializedEntity *ExtendingEntity = LR.getPointer();

  // If this entity doesn't have an interesting lifetime, don't bother looking
  // for temporaries within its initializer.
  if (LK == LK_FullExpression)
    return;

  auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
                              ReferenceKind RK) -> bool {
    SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
    SourceLocation DiagLoc = DiagRange.getBegin();

    auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);

    bool IsGslPtrInitWithGslTempOwner = false;
    bool IsLocalGslOwner = false;
    if (pathOnlyInitializesGslPointer(Path)) {
      if (isa<DeclRefExpr>(L)) {
        // We do not want to follow the references when returning a pointer originating
        // from a local owner to avoid the following false positive:
        //   int &p = *localUniquePtr;
        //   someContainer.add(std::move(localUniquePtr));
        //   return p;
        IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
        if (pathContainsInit(Path) || !IsLocalGslOwner)
          return false;
      } else {
        IsGslPtrInitWithGslTempOwner = MTE && !MTE->getExtendingDecl() &&
                            isRecordWithAttr<OwnerAttr>(MTE->getType());
        // Skipping a chain of initializing gsl::Pointer annotated objects.
        // We are looking only for the final source to find out if it was
        // a local or temporary owner or the address of a local variable/param.
        if (!IsGslPtrInitWithGslTempOwner)
          return true;
      }
    }

    switch (LK) {
    case LK_FullExpression:
      llvm_unreachable("already handled this");

    case LK_Extended: {
      if (!MTE) {
        // The initialized entity has lifetime beyond the full-expression,
        // and the local entity does too, so don't warn.
        //
        // FIXME: We should consider warning if a static / thread storage
        // duration variable retains an automatic storage duration local.
        return false;
      }

      if (IsGslPtrInitWithGslTempOwner && DiagLoc.isValid()) {
        Diag(DiagLoc, diag::warn_dangling_lifetime_pointer) << DiagRange;
        return false;
      }

      // Lifetime-extend the temporary.
      if (Path.empty()) {
        // Update the storage duration of the materialized temporary.
        // FIXME: Rebuild the expression instead of mutating it.
        MTE->setExtendingDecl(ExtendingEntity->getDecl(),
                              ExtendingEntity->allocateManglingNumber());
        // Also visit the temporaries lifetime-extended by this initializer.
        return true;
      }

      if (shouldLifetimeExtendThroughPath(Path)) {
        // We're supposed to lifetime-extend the temporary along this path (per
        // the resolution of DR1815), but we don't support that yet.
        //
        // FIXME: Properly handle this situation. Perhaps the easiest approach
        // would be to clone the initializer expression on each use that would
        // lifetime extend its temporaries.
        Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
            << RK << DiagRange;
      } else {
        // If the path goes through the initialization of a variable or field,
        // it can't possibly reach a temporary created in this full-expression.
        // We will have already diagnosed any problems with the initializer.
        if (pathContainsInit(Path))
          return false;

        Diag(DiagLoc, diag::warn_dangling_variable)
            << RK << !Entity.getParent()
            << ExtendingEntity->getDecl()->isImplicit()
            << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
      }
      break;
    }

    case LK_MemInitializer: {
      if (isa<MaterializeTemporaryExpr>(L)) {
        // Under C++ DR1696, if a mem-initializer (or a default member
        // initializer used by the absence of one) would lifetime-extend a
        // temporary, the program is ill-formed.
        if (auto *ExtendingDecl =
                ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
          if (IsGslPtrInitWithGslTempOwner) {
            Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
                << ExtendingDecl << DiagRange;
            Diag(ExtendingDecl->getLocation(),
                 diag::note_ref_or_ptr_member_declared_here)
                << true;
            return false;
          }
          bool IsSubobjectMember = ExtendingEntity != &Entity;
          Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path)
                            ? diag::err_dangling_member
                            : diag::warn_dangling_member)
              << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
          // Don't bother adding a note pointing to the field if we're inside
          // its default member initializer; our primary diagnostic points to
          // the same place in that case.
          if (Path.empty() ||
              Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
            Diag(ExtendingDecl->getLocation(),
                 diag::note_lifetime_extending_member_declared_here)
                << RK << IsSubobjectMember;
          }
        } else {
          // We have a mem-initializer but no particular field within it; this
          // is either a base class or a delegating initializer directly
          // initializing the base-class from something that doesn't live long
          // enough.
          //
          // FIXME: Warn on this.
          return false;
        }
      } else {
        // Paths via a default initializer can only occur during error recovery
        // (there's no other way that a default initializer can refer to a
        // local). Don't produce a bogus warning on those cases.
        if (pathContainsInit(Path))
          return false;

        // Suppress false positives for code like the one below:
        //   Ctor(unique_ptr<T> up) : member(*up), member2(move(up)) {}
        if (IsLocalGslOwner && pathOnlyInitializesGslPointer(Path))
          return false;

        auto *DRE = dyn_cast<DeclRefExpr>(L);
        auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
        if (!VD) {
          // A member was initialized to a local block.
          // FIXME: Warn on this.
          return false;
        }

        if (auto *Member =
                ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
          bool IsPointer = !Member->getType()->isReferenceType();
          Diag(DiagLoc, IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
                                  : diag::warn_bind_ref_member_to_parameter)
              << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
          Diag(Member->getLocation(),
               diag::note_ref_or_ptr_member_declared_here)
              << (unsigned)IsPointer;
        }
      }
      break;
    }

    case LK_New:
      if (isa<MaterializeTemporaryExpr>(L)) {
        if (IsGslPtrInitWithGslTempOwner)
          Diag(DiagLoc, diag::warn_dangling_lifetime_pointer) << DiagRange;
        else
          Diag(DiagLoc, RK == RK_ReferenceBinding
                            ? diag::warn_new_dangling_reference
                            : diag::warn_new_dangling_initializer_list)
              << !Entity.getParent() << DiagRange;
      } else {
        // We can't determine if the allocation outlives the local declaration.
        return false;
      }
      break;

    case LK_Return:
    case LK_StmtExprResult:
      if (auto *DRE = dyn_cast<DeclRefExpr>(L)) {
        // We can't determine if the local variable outlives the statement
        // expression.
        if (LK == LK_StmtExprResult)
          return false;
        Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
            << Entity.getType()->isReferenceType() << DRE->getDecl()
            << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;
      } else if (isa<BlockExpr>(L)) {
        Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
      } else if (isa<AddrLabelExpr>(L)) {
        // Don't warn when returning a label from a statement expression.
        // Leaving the scope doesn't end its lifetime.
        if (LK == LK_StmtExprResult)
          return false;
        Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
      } else {
        Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
         << Entity.getType()->isReferenceType() << DiagRange;
      }
      break;
    }

    for (unsigned I = 0; I != Path.size(); ++I) {
      auto Elem = Path[I];

      switch (Elem.Kind) {
      case IndirectLocalPathEntry::AddressOf:
      case IndirectLocalPathEntry::LValToRVal:
        // These exist primarily to mark the path as not permitting or
        // supporting lifetime extension.
        break;

      case IndirectLocalPathEntry::LifetimeBoundCall:
      case IndirectLocalPathEntry::GslPointerInit:
        // FIXME: Consider adding a note for these.
        break;

      case IndirectLocalPathEntry::DefaultInit: {
        auto *FD = cast<FieldDecl>(Elem.D);
        Diag(FD->getLocation(), diag::note_init_with_default_member_initalizer)
            << FD << nextPathEntryRange(Path, I + 1, L);
        break;
      }

      case IndirectLocalPathEntry::VarInit:
        const VarDecl *VD = cast<VarDecl>(Elem.D);
        Diag(VD->getLocation(), diag::note_local_var_initializer)
            << VD->getType()->isReferenceType()
            << VD->isImplicit() << VD->getDeclName()
            << nextPathEntryRange(Path, I + 1, L);
        break;
      }
    }

    // We didn't lifetime-extend, so don't go any further; we don't need more
    // warnings or errors on inner temporaries within this one's initializer.
    return false;
  };

  bool EnableLifetimeWarnings = !getDiagnostics().isIgnored(
      diag::warn_dangling_lifetime_pointer, SourceLocation());
  llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
  if (Init->isGLValue())
    visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding,
                                          TemporaryVisitor,
                                          EnableLifetimeWarnings);
  else
    visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false,
                                     EnableLifetimeWarnings);
}

static void DiagnoseNarrowingInInitList(Sema &S,
                                        const ImplicitConversionSequence &ICS,
                                        QualType PreNarrowingType,
                                        QualType EntityType,
                                        const Expr *PostInit);

/// Provide warnings when std::move is used on construction.
static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
                                    bool IsReturnStmt) {
  if (!InitExpr)
    return;

  if (S.inTemplateInstantiation())
    return;

  QualType DestType = InitExpr->getType();
  if (!DestType->isRecordType())
    return;

  unsigned DiagID = 0;
  if (IsReturnStmt) {
    const CXXConstructExpr *CCE =
        dyn_cast<CXXConstructExpr>(InitExpr->IgnoreParens());
    if (!CCE || CCE->getNumArgs() != 1)
      return;

    if (!CCE->getConstructor()->isCopyOrMoveConstructor())
      return;

    InitExpr = CCE->getArg(0)->IgnoreImpCasts();
  }

  // Find the std::move call and get the argument.
  const CallExpr *CE = dyn_cast<CallExpr>(InitExpr->IgnoreParens());
  if (!CE || !CE->isCallToStdMove())
    return;

  const Expr *Arg = CE->getArg(0)->IgnoreImplicit();

  if (IsReturnStmt) {
    const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts());
    if (!DRE || DRE->refersToEnclosingVariableOrCapture())
      return;

    const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
    if (!VD || !VD->hasLocalStorage())
      return;

    // __block variables are not moved implicitly.
    if (VD->hasAttr<BlocksAttr>())
      return;

    QualType SourceType = VD->getType();
    if (!SourceType->isRecordType())
      return;

    if (!S.Context.hasSameUnqualifiedType(DestType, SourceType)) {
      return;
    }

    // If we're returning a function parameter, copy elision
    // is not possible.
    if (isa<ParmVarDecl>(VD))
      DiagID = diag::warn_redundant_move_on_return;
    else
      DiagID = diag::warn_pessimizing_move_on_return;
  } else {
    DiagID = diag::warn_pessimizing_move_on_initialization;
    const Expr *ArgStripped = Arg->IgnoreImplicit()->IgnoreParens();
    if (!ArgStripped->isRValue() || !ArgStripped->getType()->isRecordType())
      return;
  }

  S.Diag(CE->getBeginLoc(), DiagID);

  // Get all the locations for a fix-it.  Don't emit the fix-it if any location
  // is within a macro.
  SourceLocation CallBegin = CE->getCallee()->getBeginLoc();
  if (CallBegin.isMacroID())
    return;
  SourceLocation RParen = CE->getRParenLoc();
  if (RParen.isMacroID())
    return;
  SourceLocation LParen;
  SourceLocation ArgLoc = Arg->getBeginLoc();

  // Special testing for the argument location.  Since the fix-it needs the
  // location right before the argument, the argument location can be in a
  // macro only if it is at the beginning of the macro.
  while (ArgLoc.isMacroID() &&
         S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) {
    ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).getBegin();
  }

  if (LParen.isMacroID())
    return;

  LParen = ArgLoc.getLocWithOffset(-1);

  S.Diag(CE->getBeginLoc(), diag::note_remove_move)
      << FixItHint::CreateRemoval(SourceRange(CallBegin, LParen))
      << FixItHint::CreateRemoval(SourceRange(RParen, RParen));
}

static void CheckForNullPointerDereference(Sema &S, const Expr *E) {
  // Check to see if we are dereferencing a null pointer.  If so, this is
  // undefined behavior, so warn about it.  This only handles the pattern
  // "*null", which is a very syntactic check.
  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts()))
    if (UO->getOpcode() == UO_Deref &&
        UO->getSubExpr()->IgnoreParenCasts()->
        isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) {
    S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
                          S.PDiag(diag::warn_binding_null_to_reference)
                            << UO->getSubExpr()->getSourceRange());
  }
}

MaterializeTemporaryExpr *
Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
                                     bool BoundToLvalueReference) {
  auto MTE = new (Context)
      MaterializeTemporaryExpr(T, Temporary, BoundToLvalueReference);

  // Order an ExprWithCleanups for lifetime marks.
  //
  // TODO: It'll be good to have a single place to check the access of the
  // destructor and generate ExprWithCleanups for various uses. Currently these
  // are done in both CreateMaterializeTemporaryExpr and MaybeBindToTemporary,
  // but there may be a chance to merge them.
  Cleanup.setExprNeedsCleanups(false);
  return MTE;
}

ExprResult Sema::TemporaryMaterializationConversion(Expr *E) {
  // In C++98, we don't want to implicitly create an xvalue.
  // FIXME: This means that AST consumers need to deal with "prvalues" that
  // denote materialized temporaries. Maybe we should add another ValueKind
  // for "xvalue pretending to be a prvalue" for C++98 support.
  if (!E->isRValue() || !getLangOpts().CPlusPlus11)
    return E;

  // C++1z [conv.rval]/1: T shall be a complete type.
  // FIXME: Does this ever matter (can we form a prvalue of incomplete type)?
  // If so, we should check for a non-abstract class type here too.
  QualType T = E->getType();
  if (RequireCompleteType(E->getExprLoc(), T, diag::err_incomplete_type))
    return ExprError();

  return CreateMaterializeTemporaryExpr(E->getType(), E, false);
}

ExprResult Sema::PerformQualificationConversion(Expr *E, QualType Ty,
                                                ExprValueKind VK,
                                                CheckedConversionKind CCK) {

  CastKind CK = CK_NoOp;

  if (VK == VK_RValue) {
    auto PointeeTy = Ty->getPointeeType();
    auto ExprPointeeTy = E->getType()->getPointeeType();
    if (!PointeeTy.isNull() &&
        PointeeTy.getAddressSpace() != ExprPointeeTy.getAddressSpace())
      CK = CK_AddressSpaceConversion;
  } else if (Ty.getAddressSpace() != E->getType().getAddressSpace()) {
    CK = CK_AddressSpaceConversion;
  }

  return ImpCastExprToType(E, Ty, CK, VK, /*BasePath=*/nullptr, CCK);
}

ExprResult InitializationSequence::Perform(Sema &S,
                                           const InitializedEntity &Entity,
                                           const InitializationKind &Kind,
                                           MultiExprArg Args,
                                           QualType *ResultType) {
  if (Failed()) {
    Diagnose(S, Entity, Kind, Args);
    return ExprError();
  }
  if (!ZeroInitializationFixit.empty()) {
    unsigned DiagID = diag::err_default_init_const;
    if (Decl *D = Entity.getDecl())
      if (S.getLangOpts().MSVCCompat && D->hasAttr<SelectAnyAttr>())
        DiagID = diag::ext_default_init_const;

    // The initialization would have succeeded with this fixit. Since the fixit
    // is on the error, we need to build a valid AST in this case, so this isn't
    // handled in the Failed() branch above.
    QualType DestType = Entity.getType();
    S.Diag(Kind.getLocation(), DiagID)
        << DestType << (bool)DestType->getAs<RecordType>()
        << FixItHint::CreateInsertion(ZeroInitializationFixitLoc,
                                      ZeroInitializationFixit);
  }

  if (getKind() == DependentSequence) {
    // If the declaration is a non-dependent, incomplete array type
    // that has an initializer, then its type will be completed once
    // the initializer is instantiated.
    if (ResultType && !Entity.getType()->isDependentType() &&
        Args.size() == 1) {
      QualType DeclType = Entity.getType();
      if (const IncompleteArrayType *ArrayT
                           = S.Context.getAsIncompleteArrayType(DeclType)) {
        // FIXME: We don't currently have the ability to accurately
        // compute the length of an initializer list without
        // performing full type-checking of the initializer list
        // (since we have to determine where braces are implicitly
        // introduced and such).  So, we fall back to making the array
        // type a dependently-sized array type with no specified
        // bound.
        if (isa<InitListExpr>((Expr *)Args[0])) {
          SourceRange Brackets;

          // Scavange the location of the brackets from the entity, if we can.
          if (auto *DD = dyn_cast_or_null<DeclaratorDecl>(Entity.getDecl())) {
            if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
              TypeLoc TL = TInfo->getTypeLoc();
              if (IncompleteArrayTypeLoc ArrayLoc =
                      TL.getAs<IncompleteArrayTypeLoc>())
                Brackets = ArrayLoc.getBracketsRange();
            }
          }

          *ResultType
            = S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
                                                   /*NumElts=*/nullptr,
                                                   ArrayT->getSizeModifier(),
                                       ArrayT->getIndexTypeCVRQualifiers(),
                                                   Brackets);
        }

      }
    }
    if (Kind.getKind() == InitializationKind::IK_Direct &&
        !Kind.isExplicitCast()) {
      // Rebuild the ParenListExpr.
      SourceRange ParenRange = Kind.getParenOrBraceRange();
      return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(),
                                  Args);
    }
    assert(Kind.getKind() == InitializationKind::IK_Copy ||
           Kind.isExplicitCast() ||
           Kind.getKind() == InitializationKind::IK_DirectList);
    return ExprResult(Args[0]);
  }

  // No steps means no initialization.
  if (Steps.empty())
    return ExprResult((Expr *)nullptr);

  if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() &&
      Args.size() == 1 && isa<InitListExpr>(Args[0]) &&
      !Entity.isParameterKind()) {
    // Produce a C++98 compatibility warning if we are initializing a reference
    // from an initializer list. For parameters, we produce a better warning
    // elsewhere.
    Expr *Init = Args[0];
    S.Diag(Init->getBeginLoc(), diag::warn_cxx98_compat_reference_list_init)
        << Init->getSourceRange();
  }

  // OpenCL v2.0 s6.13.11.1. atomic variables can be initialized in global scope
  QualType ETy = Entity.getType();
  Qualifiers TyQualifiers = ETy.getQualifiers();
  bool HasGlobalAS = TyQualifiers.hasAddressSpace() &&
                     TyQualifiers.getAddressSpace() == LangAS::opencl_global;

  if (S.getLangOpts().OpenCLVersion >= 200 &&
      ETy->isAtomicType() && !HasGlobalAS &&
      Entity.getKind() == InitializedEntity::EK_Variable && Args.size() > 0) {
    S.Diag(Args[0]->getBeginLoc(), diag::err_opencl_atomic_init)
        << 1
        << SourceRange(Entity.getDecl()->getBeginLoc(), Args[0]->getEndLoc());
    return ExprError();
  }

  QualType DestType = Entity.getType().getNonReferenceType();
  // FIXME: Ugly hack around the fact that Entity.getType() is not
  // the same as Entity.getDecl()->getType() in cases involving type merging,
  //  and we want latter when it makes sense.
  if (ResultType)
    *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
                                     Entity.getType();

  ExprResult CurInit((Expr *)nullptr);
  SmallVector<Expr*, 4> ArrayLoopCommonExprs;

  // For initialization steps that start with a single initializer,
  // grab the only argument out the Args and place it into the "current"
  // initializer.
  switch (Steps.front().Kind) {
  case SK_ResolveAddressOfOverloadedFunction:
  case SK_CastDerivedToBaseRValue:
  case SK_CastDerivedToBaseXValue:
  case SK_CastDerivedToBaseLValue:
  case SK_BindReference:
  case SK_BindReferenceToTemporary:
  case SK_FinalCopy:
  case SK_ExtraneousCopyToTemporary:
  case SK_UserConversion:
  case SK_QualificationConversionLValue:
  case SK_QualificationConversionXValue:
  case SK_QualificationConversionRValue:
  case SK_AtomicConversion:
  case SK_ConversionSequence:
  case SK_ConversionSequenceNoNarrowing:
  case SK_ListInitialization:
  case SK_UnwrapInitList:
  case SK_RewrapInitList:
  case SK_CAssignment:
  case SK_StringInit:
  case SK_ObjCObjectConversion:
  case SK_ArrayLoopIndex:
  case SK_ArrayLoopInit:
  case SK_ArrayInit:
  case SK_GNUArrayInit:
  case SK_ParenthesizedArrayInit:
  case SK_PassByIndirectCopyRestore:
  case SK_PassByIndirectRestore:
  case SK_ProduceObjCObject:
  case SK_StdInitializerList:
  case SK_OCLSamplerInit:
  case SK_OCLZeroOpaqueType: {
    assert(Args.size() == 1);
    CurInit = Args[0];
    if (!CurInit.get()) return ExprError();
    break;
  }

  case SK_ConstructorInitialization:
  case SK_ConstructorInitializationFromList:
  case SK_StdInitializerListConstructorCall:
  case SK_ZeroInitialization:
    break;
  }

  // Promote from an unevaluated context to an unevaluated list context in
  // C++11 list-initialization; we need to instantiate entities usable in
  // constant expressions here in order to perform narrowing checks =(
  EnterExpressionEvaluationContext Evaluated(
      S, EnterExpressionEvaluationContext::InitList,
      CurInit.get() && isa<InitListExpr>(CurInit.get()));

  // C++ [class.abstract]p2:
  //   no objects of an abstract class can be created except as subobjects
  //   of a class derived from it
  auto checkAbstractType = [&](QualType T) -> bool {
    if (Entity.getKind() == InitializedEntity::EK_Base ||
        Entity.getKind() == InitializedEntity::EK_Delegating)
      return false;
    return S.RequireNonAbstractType(Kind.getLocation(), T,
                                    diag::err_allocation_of_abstract_type);
  };

  // Walk through the computed steps for the initialization sequence,
  // performing the specified conversions along the way.
  bool ConstructorInitRequiresZeroInit = false;
  for (step_iterator Step = step_begin(), StepEnd = step_end();
       Step != StepEnd; ++Step) {
    if (CurInit.isInvalid())
      return ExprError();

    QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType();

    switch (Step->Kind) {
    case SK_ResolveAddressOfOverloadedFunction:
      // Overload resolution determined which function invoke; update the
      // initializer to reflect that choice.
      S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl);
      if (S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()))
        return ExprError();
      CurInit = S.FixOverloadedFunctionReference(CurInit,
                                                 Step->Function.FoundDecl,
                                                 Step->Function.Function);
      break;

    case SK_CastDerivedToBaseRValue:
    case SK_CastDerivedToBaseXValue:
    case SK_CastDerivedToBaseLValue: {
      // We have a derived-to-base cast that produces either an rvalue or an
      // lvalue. Perform that cast.

      CXXCastPath BasePath;

      // Casts to inaccessible base classes are allowed with C-style casts.
      bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
      if (S.CheckDerivedToBaseConversion(
              SourceType, Step->Type, CurInit.get()->getBeginLoc(),
              CurInit.get()->getSourceRange(), &BasePath, IgnoreBaseAccess))
        return ExprError();

      ExprValueKind VK =
          Step->Kind == SK_CastDerivedToBaseLValue ?
              VK_LValue :
              (Step->Kind == SK_CastDerivedToBaseXValue ?
                   VK_XValue :
                   VK_RValue);
      CurInit =
          ImplicitCastExpr::Create(S.Context, Step->Type, CK_DerivedToBase,
                                   CurInit.get(), &BasePath, VK);
      break;
    }

    case SK_BindReference:
      // Reference binding does not have any corresponding ASTs.

      // Check exception specifications
      if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
        return ExprError();

      // We don't check for e.g. function pointers here, since address
      // availability checks should only occur when the function first decays
      // into a pointer or reference.
      if (CurInit.get()->getType()->isFunctionProtoType()) {
        if (auto *DRE = dyn_cast<DeclRefExpr>(CurInit.get()->IgnoreParens())) {
          if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
            if (!S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
                                                     DRE->getBeginLoc()))
              return ExprError();
          }
        }
      }

      CheckForNullPointerDereference(S, CurInit.get());
      break;

    case SK_BindReferenceToTemporary: {
      // Make sure the "temporary" is actually an rvalue.
      assert(CurInit.get()->isRValue() && "not a temporary");

      // Check exception specifications
      if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
        return ExprError();

      // Materialize the temporary into memory.
      MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
          Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());
      CurInit = MTE;

      // If we're extending this temporary to automatic storage duration -- we
      // need to register its cleanup during the full-expression's cleanups.
      if (MTE->getStorageDuration() == SD_Automatic &&
          MTE->getType().isDestructedType())
        S.Cleanup.setExprNeedsCleanups(true);
      break;
    }

    case SK_FinalCopy:
      if (checkAbstractType(Step->Type))
        return ExprError();

      // If the overall initialization is initializing a temporary, we already
      // bound our argument if it was necessary to do so. If not (if we're
      // ultimately initializing a non-temporary), our argument needs to be
      // bound since it's initializing a function parameter.
      // FIXME: This is a mess. Rationalize temporary destruction.
      if (!shouldBindAsTemporary(Entity))
        CurInit = S.MaybeBindToTemporary(CurInit.get());
      CurInit = CopyObject(S, Step->Type, Entity, CurInit,
                           /*IsExtraneousCopy=*/false);
      break;

    case SK_ExtraneousCopyToTemporary:
      CurInit = CopyObject(S, Step->Type, Entity, CurInit,
                           /*IsExtraneousCopy=*/true);
      break;

    case SK_UserConversion: {
      // We have a user-defined conversion that invokes either a constructor
      // or a conversion function.
      CastKind CastKind;
      FunctionDecl *Fn = Step->Function.Function;
      DeclAccessPair FoundFn = Step->Function.FoundDecl;
      bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
      bool CreatedObject = false;
      if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
        // Build a call to the selected constructor.
        SmallVector<Expr*, 8> ConstructorArgs;
        SourceLocation Loc = CurInit.get()->getBeginLoc();

        // Determine the arguments required to actually perform the constructor
        // call.
        Expr *Arg = CurInit.get();
        if (S.CompleteConstructorCall(Constructor,
                                      MultiExprArg(&Arg, 1),
                                      Loc, ConstructorArgs))
          return ExprError();

        // Build an expression that constructs a temporary.
        CurInit = S.BuildCXXConstructExpr(Loc, Step->Type,
                                          FoundFn, Constructor,
                                          ConstructorArgs,
                                          HadMultipleCandidates,
                                          /*ListInit*/ false,
                                          /*StdInitListInit*/ false,
                                          /*ZeroInit*/ false,
                                          CXXConstructExpr::CK_Complete,
                                          SourceRange());
        if (CurInit.isInvalid())
          return ExprError();

        S.CheckConstructorAccess(Kind.getLocation(), Constructor, FoundFn,
                                 Entity);
        if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
          return ExprError();

        CastKind = CK_ConstructorConversion;
        CreatedObject = true;
      } else {
        // Build a call to the conversion function.
        CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
        S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), nullptr,
                                    FoundFn);
        if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
          return ExprError();

        CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion,
                                           HadMultipleCandidates);
        if (CurInit.isInvalid())
          return ExprError();

        CastKind = CK_UserDefinedConversion;
        CreatedObject = Conversion->getReturnType()->isRecordType();
      }

      if (CreatedObject && checkAbstractType(CurInit.get()->getType()))
        return ExprError();

      CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(),
                                         CastKind, CurInit.get(), nullptr,
                                         CurInit.get()->getValueKind());

      if (shouldBindAsTemporary(Entity))
        // The overall entity is temporary, so this expression should be
        // destroyed at the end of its full-expression.
        CurInit = S.MaybeBindToTemporary(CurInit.getAs<Expr>());
      else if (CreatedObject && shouldDestroyEntity(Entity)) {
        // The object outlasts the full-expression, but we need to prepare for
        // a destructor being run on it.
        // FIXME: It makes no sense to do this here. This should happen
        // regardless of how we initialized the entity.
        QualType T = CurInit.get()->getType();
        if (const RecordType *Record = T->getAs<RecordType>()) {
          CXXDestructorDecl *Destructor
            = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
          S.CheckDestructorAccess(CurInit.get()->getBeginLoc(), Destructor,
                                  S.PDiag(diag::err_access_dtor_temp) << T);
          S.MarkFunctionReferenced(CurInit.get()->getBeginLoc(), Destructor);
          if (S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getBeginLoc()))
            return ExprError();
        }
      }
      break;
    }

    case SK_QualificationConversionLValue:
    case SK_QualificationConversionXValue:
    case SK_QualificationConversionRValue: {
      // Perform a qualification conversion; these can never go wrong.
      ExprValueKind VK =
          Step->Kind == SK_QualificationConversionLValue
              ? VK_LValue
              : (Step->Kind == SK_QualificationConversionXValue ? VK_XValue
                                                                : VK_RValue);
      CurInit = S.PerformQualificationConversion(CurInit.get(), Step->Type, VK);
      break;
    }

    case SK_AtomicConversion: {
      assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic");
      CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
                                    CK_NonAtomicToAtomic, VK_RValue);
      break;
    }

    case SK_ConversionSequence:
    case SK_ConversionSequenceNoNarrowing: {
      if (const auto *FromPtrType =
              CurInit.get()->getType()->getAs<PointerType>()) {
        if (const auto *ToPtrType = Step->Type->getAs<PointerType>()) {
          if (FromPtrType->getPointeeType()->hasAttr(attr::NoDeref) &&
              !ToPtrType->getPointeeType()->hasAttr(attr::NoDeref)) {
            S.Diag(CurInit.get()->getExprLoc(),
                   diag::warn_noderef_to_dereferenceable_pointer)
                << CurInit.get()->getSourceRange();
          }
        }
      }

      Sema::CheckedConversionKind CCK
        = Kind.isCStyleCast()? Sema::CCK_CStyleCast
        : Kind.isFunctionalCast()? Sema::CCK_FunctionalCast
        : Kind.isExplicitCast()? Sema::CCK_OtherCast
        : Sema::CCK_ImplicitConversion;
      ExprResult CurInitExprRes =
        S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS,
                                    getAssignmentAction(Entity), CCK);
      if (CurInitExprRes.isInvalid())
        return ExprError();

      S.DiscardMisalignedMemberAddress(Step->Type.getTypePtr(), CurInit.get());

      CurInit = CurInitExprRes;

      if (Step->Kind == SK_ConversionSequenceNoNarrowing &&
          S.getLangOpts().CPlusPlus)
        DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(),
                                    CurInit.get());

      break;
    }

    case SK_ListInitialization: {
      if (checkAbstractType(Step->Type))
        return ExprError();

      InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
      // If we're not initializing the top-level entity, we need to create an
      // InitializeTemporary entity for our target type.
      QualType Ty = Step->Type;
      bool IsTemporary = !S.Context.hasSameType(Entity.getType(), Ty);
      InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty);
      InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity;
      InitListChecker PerformInitList(S, InitEntity,
          InitList, Ty, /*VerifyOnly=*/false,
          /*TreatUnavailableAsInvalid=*/false);
      if (PerformInitList.HadError())
        return ExprError();

      // Hack: We must update *ResultType if available in order to set the
      // bounds of arrays, e.g. in 'int ar[] = {1, 2, 3};'.
      // Worst case: 'const int (&arref)[] = {1, 2, 3};'.
      if (ResultType &&
          ResultType->getNonReferenceType()->isIncompleteArrayType()) {
        if ((*ResultType)->isRValueReferenceType())
          Ty = S.Context.getRValueReferenceType(Ty);
        else if ((*ResultType)->isLValueReferenceType())
          Ty = S.Context.getLValueReferenceType(Ty,
            (*ResultType)->castAs<LValueReferenceType>()->isSpelledAsLValue());
        *ResultType = Ty;
      }

      InitListExpr *StructuredInitList =
          PerformInitList.getFullyStructuredList();
      CurInit.get();
      CurInit = shouldBindAsTemporary(InitEntity)
          ? S.MaybeBindToTemporary(StructuredInitList)
          : StructuredInitList;
      break;
    }

    case SK_ConstructorInitializationFromList: {
      if (checkAbstractType(Step->Type))
        return ExprError();

      // When an initializer list is passed for a parameter of type "reference
      // to object", we don't get an EK_Temporary entity, but instead an
      // EK_Parameter entity with reference type.
      // FIXME: This is a hack. What we really should do is create a user
      // conversion step for this case, but this makes it considerably more
      // complicated. For now, this will do.
      InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
                                        Entity.getType().getNonReferenceType());
      bool UseTemporary = Entity.getType()->isReferenceType();
      assert(Args.size() == 1 && "expected a single argument for list init");
      InitListExpr *InitList = cast<InitListExpr>(Args[0]);
      S.Diag(InitList->getExprLoc(), diag::warn_cxx98_compat_ctor_list_init)
        << InitList->getSourceRange();
      MultiExprArg Arg(InitList->getInits(), InitList->getNumInits());
      CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity :
                                                                   Entity,
                                                 Kind, Arg, *Step,
                                               ConstructorInitRequiresZeroInit,
                                               /*IsListInitialization*/true,
                                               /*IsStdInitListInit*/false,
                                               InitList->getLBraceLoc(),
                                               InitList->getRBraceLoc());
      break;
    }

    case SK_UnwrapInitList:
      CurInit = cast<InitListExpr>(CurInit.get())->getInit(0);
      break;

    case SK_RewrapInitList: {
      Expr *E = CurInit.get();
      InitListExpr *Syntactic = Step->WrappingSyntacticList;
      InitListExpr *ILE = new (S.Context) InitListExpr(S.Context,
          Syntactic->getLBraceLoc(), E, Syntactic->getRBraceLoc());
      ILE->setSyntacticForm(Syntactic);
      ILE->setType(E->getType());
      ILE->setValueKind(E->getValueKind());
      CurInit = ILE;
      break;
    }

    case SK_ConstructorInitialization:
    case SK_StdInitializerListConstructorCall: {
      if (checkAbstractType(Step->Type))
        return ExprError();

      // When an initializer list is passed for a parameter of type "reference
      // to object", we don't get an EK_Temporary entity, but instead an
      // EK_Parameter entity with reference type.
      // FIXME: This is a hack. What we really should do is create a user
      // conversion step for this case, but this makes it considerably more
      // complicated. For now, this will do.
      InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
                                        Entity.getType().getNonReferenceType());
      bool UseTemporary = Entity.getType()->isReferenceType();
      bool IsStdInitListInit =
          Step->Kind == SK_StdInitializerListConstructorCall;
      Expr *Source = CurInit.get();
      SourceRange Range = Kind.hasParenOrBraceRange()
                              ? Kind.getParenOrBraceRange()
                              : SourceRange();
      CurInit = PerformConstructorInitialization(
          S, UseTemporary ? TempEntity : Entity, Kind,
          Source ? MultiExprArg(Source) : Args, *Step,
          ConstructorInitRequiresZeroInit,
          /*IsListInitialization*/ IsStdInitListInit,
          /*IsStdInitListInitialization*/ IsStdInitListInit,
          /*LBraceLoc*/ Range.getBegin(),
          /*RBraceLoc*/ Range.getEnd());
      break;
    }

    case SK_ZeroInitialization: {
      step_iterator NextStep = Step;
      ++NextStep;
      if (NextStep != StepEnd &&
          (NextStep->Kind == SK_ConstructorInitialization ||
           NextStep->Kind == SK_ConstructorInitializationFromList)) {
        // The need for zero-initialization is recorded directly into
        // the call to the object's constructor within the next step.
        ConstructorInitRequiresZeroInit = true;
      } else if (Kind.getKind() == InitializationKind::IK_Value &&
                 S.getLangOpts().CPlusPlus &&
                 !Kind.isImplicitValueInit()) {
        TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
        if (!TSInfo)
          TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type,
                                                    Kind.getRange().getBegin());

        CurInit = new (S.Context) CXXScalarValueInitExpr(
            Entity.getType().getNonLValueExprType(S.Context), TSInfo,
            Kind.getRange().getEnd());
      } else {
        CurInit = new (S.Context) ImplicitValueInitExpr(Step->Type);
      }
      break;
    }

    case SK_CAssignment: {
      QualType SourceType = CurInit.get()->getType();

      // Save off the initial CurInit in case we need to emit a diagnostic
      ExprResult InitialCurInit = CurInit;
      ExprResult Result = CurInit;
      Sema::AssignConvertType ConvTy =
        S.CheckSingleAssignmentConstraints(Step->Type, Result, true,
            Entity.getKind() == InitializedEntity::EK_Parameter_CF_Audited);
      if (Result.isInvalid())
        return ExprError();
      CurInit = Result;

      // If this is a call, allow conversion to a transparent union.
      ExprResult CurInitExprRes = CurInit;
      if (ConvTy != Sema::Compatible &&
          Entity.isParameterKind() &&
          S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes)
            == Sema::Compatible)
        ConvTy = Sema::Compatible;
      if (CurInitExprRes.isInvalid())
        return ExprError();
      CurInit = CurInitExprRes;

      bool Complained;
      if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
                                     Step->Type, SourceType,
                                     InitialCurInit.get(),
                                     getAssignmentAction(Entity, true),
                                     &Complained)) {
        PrintInitLocationNote(S, Entity);
        return ExprError();
      } else if (Complained)
        PrintInitLocationNote(S, Entity);
      break;
    }

    case SK_StringInit: {
      QualType Ty = Step->Type;
      CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty,
                      S.Context.getAsArrayType(Ty), S);
      break;
    }

    case SK_ObjCObjectConversion:
      CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
                          CK_ObjCObjectLValueCast,
                          CurInit.get()->getValueKind());
      break;

    case SK_ArrayLoopIndex: {
      Expr *Cur = CurInit.get();
      Expr *BaseExpr = new (S.Context)
          OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(),
                          Cur->getValueKind(), Cur->getObjectKind(), Cur);
      Expr *IndexExpr =
          new (S.Context) ArrayInitIndexExpr(S.Context.getSizeType());
      CurInit = S.CreateBuiltinArraySubscriptExpr(
          BaseExpr, Kind.getLocation(), IndexExpr, Kind.getLocation());
      ArrayLoopCommonExprs.push_back(BaseExpr);
      break;
    }

    case SK_ArrayLoopInit: {
      assert(!ArrayLoopCommonExprs.empty() &&
             "mismatched SK_ArrayLoopIndex and SK_ArrayLoopInit");
      Expr *Common = ArrayLoopCommonExprs.pop_back_val();
      CurInit = new (S.Context) ArrayInitLoopExpr(Step->Type, Common,
                                                  CurInit.get());
      break;
    }

    case SK_GNUArrayInit:
      // Okay: we checked everything before creating this step. Note that
      // this is a GNU extension.
      S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
        << Step->Type << CurInit.get()->getType()
        << CurInit.get()->getSourceRange();
      updateGNUCompoundLiteralRValue(CurInit.get());
      LLVM_FALLTHROUGH;
    case SK_ArrayInit:
      // If the destination type is an incomplete array type, update the
      // type accordingly.
      if (ResultType) {
        if (const IncompleteArrayType *IncompleteDest
                           = S.Context.getAsIncompleteArrayType(Step->Type)) {
          if (const ConstantArrayType *ConstantSource
                 = S.Context.getAsConstantArrayType(CurInit.get()->getType())) {
            *ResultType = S.Context.getConstantArrayType(
                                             IncompleteDest->getElementType(),
                                             ConstantSource->getSize(),
                                             ConstantSource->getSizeExpr(),
                                             ArrayType::Normal, 0);
          }
        }
      }
      break;

    case SK_ParenthesizedArrayInit:
      // Okay: we checked everything before creating this step. Note that
      // this is a GNU extension.
      S.Diag(Kind.getLocation(), diag::ext_array_init_parens)
        << CurInit.get()->getSourceRange();
      break;

    case SK_PassByIndirectCopyRestore:
    case SK_PassByIndirectRestore:
      checkIndirectCopyRestoreSource(S, CurInit.get());
      CurInit = new (S.Context) ObjCIndirectCopyRestoreExpr(
          CurInit.get(), Step->Type,
          Step->Kind == SK_PassByIndirectCopyRestore);
      break;

    case SK_ProduceObjCObject:
      CurInit =
          ImplicitCastExpr::Create(S.Context, Step->Type, CK_ARCProduceObject,
                                   CurInit.get(), nullptr, VK_RValue);
      break;

    case SK_StdInitializerList: {
      S.Diag(CurInit.get()->getExprLoc(),
             diag::warn_cxx98_compat_initializer_list_init)
        << CurInit.get()->getSourceRange();

      // Materialize the temporary into memory.
      MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
          CurInit.get()->getType(), CurInit.get(),
          /*BoundToLvalueReference=*/false);

      // Wrap it in a construction of a std::initializer_list<T>.
      CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);

      // Bind the result, in case the library has given initializer_list a
      // non-trivial destructor.
      if (shouldBindAsTemporary(Entity))
        CurInit = S.MaybeBindToTemporary(CurInit.get());
      break;
    }

    case SK_OCLSamplerInit: {
      // Sampler initialization have 5 cases:
      //   1. function argument passing
      //      1a. argument is a file-scope variable
      //      1b. argument is a function-scope variable
      //      1c. argument is one of caller function's parameters
      //   2. variable initialization
      //      2a. initializing a file-scope variable
      //      2b. initializing a function-scope variable
      //
      // For file-scope variables, since they cannot be initialized by function
      // call of __translate_sampler_initializer in LLVM IR, their references
      // need to be replaced by a cast from their literal initializers to
      // sampler type. Since sampler variables can only be used in function
      // calls as arguments, we only need to replace them when handling the
      // argument passing.
      assert(Step->Type->isSamplerT() &&
             "Sampler initialization on non-sampler type.");
      Expr *Init = CurInit.get()->IgnoreParens();
      QualType SourceType = Init->getType();
      // Case 1
      if (Entity.isParameterKind()) {
        if (!SourceType->isSamplerT() && !SourceType->isIntegerType()) {
          S.Diag(Kind.getLocation(), diag::err_sampler_argument_required)
            << SourceType;
          break;
        } else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init)) {
          auto Var = cast<VarDecl>(DRE->getDecl());
          // Case 1b and 1c
          // No cast from integer to sampler is needed.
          if (!Var->hasGlobalStorage()) {
            CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
                                               CK_LValueToRValue, Init,
                                               /*BasePath=*/nullptr, VK_RValue);
            break;
          }
          // Case 1a
          // For function call with a file-scope sampler variable as argument,
          // get the integer literal.
          // Do not diagnose if the file-scope variable does not have initializer
          // since this has already been diagnosed when parsing the variable
          // declaration.
          if (!Var->getInit() || !isa<ImplicitCastExpr>(Var->getInit()))
            break;
          Init = cast<ImplicitCastExpr>(const_cast<Expr*>(
            Var->getInit()))->getSubExpr();
          SourceType = Init->getType();
        }
      } else {
        // Case 2
        // Check initializer is 32 bit integer constant.
        // If the initializer is taken from global variable, do not diagnose since
        // this has already been done when parsing the variable declaration.
        if (!Init->isConstantInitializer(S.Context, false))
          break;

        if (!SourceType->isIntegerType() ||
            32 != S.Context.getIntWidth(SourceType)) {
          S.Diag(Kind.getLocation(), diag::err_sampler_initializer_not_integer)
            << SourceType;
          break;
        }

        Expr::EvalResult EVResult;
        Init->EvaluateAsInt(EVResult, S.Context);
        llvm::APSInt Result = EVResult.Val.getInt();
        const uint64_t SamplerValue = Result.getLimitedValue();
        // 32-bit value of sampler's initializer is interpreted as
        // bit-field with the following structure:
        // |unspecified|Filter|Addressing Mode| Normalized Coords|
        // |31        6|5    4|3             1|                 0|
        // This structure corresponds to enum values of sampler properties
        // defined in SPIR spec v1.2 and also opencl-c.h
        unsigned AddressingMode  = (0x0E & SamplerValue) >> 1;
        unsigned FilterMode      = (0x30 & SamplerValue) >> 4;
        if (FilterMode != 1 && FilterMode != 2 &&
            !S.getOpenCLOptions().isEnabled(
                "cl_intel_device_side_avc_motion_estimation"))
          S.Diag(Kind.getLocation(),
                 diag::warn_sampler_initializer_invalid_bits)
                 << "Filter Mode";
        if (AddressingMode > 4)
          S.Diag(Kind.getLocation(),
                 diag::warn_sampler_initializer_invalid_bits)
                 << "Addressing Mode";
      }

      // Cases 1a, 2a and 2b
      // Insert cast from integer to sampler.
      CurInit = S.ImpCastExprToType(Init, S.Context.OCLSamplerTy,
                                      CK_IntToOCLSampler);
      break;
    }
    case SK_OCLZeroOpaqueType: {
      assert((Step->Type->isEventT() || Step->Type->isQueueT() ||
              Step->Type->isOCLIntelSubgroupAVCType()) &&
             "Wrong type for initialization of OpenCL opaque type.");

      CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
                                    CK_ZeroToOCLOpaqueType,
                                    CurInit.get()->getValueKind());
      break;
    }
    }
  }

  // Check whether the initializer has a shorter lifetime than the initialized
  // entity, and if not, either lifetime-extend or warn as appropriate.
  if (auto *Init = CurInit.get())
    S.checkInitializerLifetime(Entity, Init);

  // Diagnose non-fatal problems with the completed initialization.
  if (Entity.getKind() == InitializedEntity::EK_Member &&
      cast<FieldDecl>(Entity.getDecl())->isBitField())
    S.CheckBitFieldInitialization(Kind.getLocation(),
                                  cast<FieldDecl>(Entity.getDecl()),
                                  CurInit.get());

  // Check for std::move on construction.
  if (const Expr *E = CurInit.get()) {
    CheckMoveOnConstruction(S, E,
                            Entity.getKind() == InitializedEntity::EK_Result);
  }

  return CurInit;
}

/// Somewhere within T there is an uninitialized reference subobject.
/// Dig it out and diagnose it.
static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc,
                                           QualType T) {
  if (T->isReferenceType()) {
    S.Diag(Loc, diag::err_reference_without_init)
      << T.getNonReferenceType();
    return true;
  }

  CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
  if (!RD || !RD->hasUninitializedReferenceMember())
    return false;

  for (const auto *FI : RD->fields()) {
    if (FI->isUnnamedBitfield())
      continue;

    if (DiagnoseUninitializedReference(S, FI->getLocation(), FI->getType())) {
      S.Diag(Loc, diag::note_value_initialization_here) << RD;
      return true;
    }
  }

  for (const auto &BI : RD->bases()) {
    if (DiagnoseUninitializedReference(S, BI.getBeginLoc(), BI.getType())) {
      S.Diag(Loc, diag::note_value_initialization_here) << RD;
      return true;
    }
  }

  return false;
}


//===----------------------------------------------------------------------===//
// Diagnose initialization failures
//===----------------------------------------------------------------------===//

/// Emit notes associated with an initialization that failed due to a
/// "simple" conversion failure.
static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity,
                                   Expr *op) {
  QualType destType = entity.getType();
  if (destType.getNonReferenceType()->isObjCObjectPointerType() &&
      op->getType()->isObjCObjectPointerType()) {

    // Emit a possible note about the conversion failing because the
    // operand is a message send with a related result type.
    S.EmitRelatedResultTypeNote(op);

    // Emit a possible note about a return failing because we're
    // expecting a related result type.
    if (entity.getKind() == InitializedEntity::EK_Result)
      S.EmitRelatedResultTypeNoteForReturn(destType);
  }
}

static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
                             InitListExpr *InitList) {
  QualType DestType = Entity.getType();

  QualType E;
  if (S.getLangOpts().CPlusPlus11 && S.isStdInitializerList(DestType, &E)) {
    QualType ArrayType = S.Context.getConstantArrayType(
        E.withConst(),
        llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
                    InitList->getNumInits()),
        nullptr, clang::ArrayType::Normal, 0);
    InitializedEntity HiddenArray =
        InitializedEntity::InitializeTemporary(ArrayType);
    return diagnoseListInit(S, HiddenArray, InitList);
  }

  if (DestType->isReferenceType()) {
    // A list-initialization failure for a reference means that we tried to
    // create a temporary of the inner type (per [dcl.init.list]p3.6) and the
    // inner initialization failed.
    QualType T = DestType->castAs<ReferenceType>()->getPointeeType();
    diagnoseListInit(S, InitializedEntity::InitializeTemporary(T), InitList);
    SourceLocation Loc = InitList->getBeginLoc();
    if (auto *D = Entity.getDecl())
      Loc = D->getLocation();
    S.Diag(Loc, diag::note_in_reference_temporary_list_initializer) << T;
    return;
  }

  InitListChecker DiagnoseInitList(S, Entity, InitList, DestType,
                                   /*VerifyOnly=*/false,
                                   /*TreatUnavailableAsInvalid=*/false);
  assert(DiagnoseInitList.HadError() &&
         "Inconsistent init list check result.");
}

bool InitializationSequence::Diagnose(Sema &S,
                                      const InitializedEntity &Entity,
                                      const InitializationKind &Kind,
                                      ArrayRef<Expr *> Args) {
  if (!Failed())
    return false;

  // When we want to diagnose only one element of a braced-init-list,
  // we need to factor it out.
  Expr *OnlyArg;
  if (Args.size() == 1) {
    auto *List = dyn_cast<InitListExpr>(Args[0]);
    if (List && List->getNumInits() == 1)
      OnlyArg = List->getInit(0);
    else
      OnlyArg = Args[0];
  }
  else
    OnlyArg = nullptr;

  QualType DestType = Entity.getType();
  switch (Failure) {
  case FK_TooManyInitsForReference:
    // FIXME: Customize for the initialized entity?
    if (Args.empty()) {
      // Dig out the reference subobject which is uninitialized and diagnose it.
      // If this is value-initialization, this could be nested some way within
      // the target type.
      assert(Kind.getKind() == InitializationKind::IK_Value ||
             DestType->isReferenceType());
      bool Diagnosed =
        DiagnoseUninitializedReference(S, Kind.getLocation(), DestType);
      assert(Diagnosed && "couldn't find uninitialized reference to diagnose");
      (void)Diagnosed;
    } else  // FIXME: diagnostic below could be better!
      S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
          << SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc());
    break;
  case FK_ParenthesizedListInitForReference:
    S.Diag(Kind.getLocation(), diag::err_list_init_in_parens)
      << 1 << Entity.getType() << Args[0]->getSourceRange();
    break;

  case FK_ArrayNeedsInitList:
    S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0;
    break;
  case FK_ArrayNeedsInitListOrStringLiteral:
    S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 1;
    break;
  case FK_ArrayNeedsInitListOrWideStringLiteral:
    S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 2;
    break;
  case FK_NarrowStringIntoWideCharArray:
    S.Diag(Kind.getLocation(), diag::err_array_init_narrow_string_into_wchar);
    break;
  case FK_WideStringIntoCharArray:
    S.Diag(Kind.getLocation(), diag::err_array_init_wide_string_into_char);
    break;
  case FK_IncompatWideStringIntoWideChar:
    S.Diag(Kind.getLocation(),
           diag::err_array_init_incompat_wide_string_into_wchar);
    break;
  case FK_PlainStringIntoUTF8Char:
    S.Diag(Kind.getLocation(),
           diag::err_array_init_plain_string_into_char8_t);
    S.Diag(Args.front()->getBeginLoc(),
           diag::note_array_init_plain_string_into_char8_t)
        << FixItHint::CreateInsertion(Args.front()->getBeginLoc(), "u8");
    break;
  case FK_UTF8StringIntoPlainChar:
    S.Diag(Kind.getLocation(),
           diag::err_array_init_utf8_string_into_char)
      << S.getLangOpts().CPlusPlus2a;
    break;
  case FK_ArrayTypeMismatch:
  case FK_NonConstantArrayInit:
    S.Diag(Kind.getLocation(),
           (Failure == FK_ArrayTypeMismatch
              ? diag::err_array_init_different_type
              : diag::err_array_init_non_constant_array))
      << DestType.getNonReferenceType()
      << OnlyArg->getType()
      << Args[0]->getSourceRange();
    break;

  case FK_VariableLengthArrayHasInitializer:
    S.Diag(Kind.getLocation(), diag::err_variable_object_no_init)
      << Args[0]->getSourceRange();
    break;

  case FK_AddressOfOverloadFailed: {
    DeclAccessPair Found;
    S.ResolveAddressOfOverloadedFunction(OnlyArg,
                                         DestType.getNonReferenceType(),
                                         true,
                                         Found);
    break;
  }

  case FK_AddressOfUnaddressableFunction: {
    auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(OnlyArg)->getDecl());
    S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
                                        OnlyArg->getBeginLoc());
    break;
  }

  case FK_ReferenceInitOverloadFailed:
  case FK_UserConversionOverloadFailed:
    switch (FailedOverloadResult) {
    case OR_Ambiguous:

      FailedCandidateSet.NoteCandidates(
          PartialDiagnosticAt(
              Kind.getLocation(),
              Failure == FK_UserConversionOverloadFailed
                  ? (S.PDiag(diag::err_typecheck_ambiguous_condition)
                     << OnlyArg->getType() << DestType
                     << Args[0]->getSourceRange())
                  : (S.PDiag(diag::err_ref_init_ambiguous)
                     << DestType << OnlyArg->getType()
                     << Args[0]->getSourceRange())),
          S, OCD_ViableCandidates, Args);
      break;

    case OR_No_Viable_Function: {
      auto Cands = FailedCandidateSet.CompleteCandidates(S, OCD_AllCandidates, Args);
      if (!S.RequireCompleteType(Kind.getLocation(),
                                 DestType.getNonReferenceType(),
                          diag::err_typecheck_nonviable_condition_incomplete,
                               OnlyArg->getType(), Args[0]->getSourceRange()))
        S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
          << (Entity.getKind() == InitializedEntity::EK_Result)
          << OnlyArg->getType() << Args[0]->getSourceRange()
          << DestType.getNonReferenceType();

      FailedCandidateSet.NoteCandidates(S, Args, Cands);
      break;
    }
    case OR_Deleted: {
      S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
        << OnlyArg->getType() << DestType.getNonReferenceType()
        << Args[0]->getSourceRange();
      OverloadCandidateSet::iterator Best;
      OverloadingResult Ovl
        = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
      if (Ovl == OR_Deleted) {
        S.NoteDeletedFunction(Best->Function);
      } else {
        llvm_unreachable("Inconsistent overload resolution?");
      }
      break;
    }

    case OR_Success:
      llvm_unreachable("Conversion did not fail!");
    }
    break;

  case FK_NonConstLValueReferenceBindingToTemporary:
    if (isa<InitListExpr>(Args[0])) {
      S.Diag(Kind.getLocation(),
             diag::err_lvalue_reference_bind_to_initlist)
      << DestType.getNonReferenceType().isVolatileQualified()
      << DestType.getNonReferenceType()
      << Args[0]->getSourceRange();
      break;
    }
    LLVM_FALLTHROUGH;

  case FK_NonConstLValueReferenceBindingToUnrelated:
    S.Diag(Kind.getLocation(),
           Failure == FK_NonConstLValueReferenceBindingToTemporary
             ? diag::err_lvalue_reference_bind_to_temporary
             : diag::err_lvalue_reference_bind_to_unrelated)
      << DestType.getNonReferenceType().isVolatileQualified()
      << DestType.getNonReferenceType()
      << OnlyArg->getType()
      << Args[0]->getSourceRange();
    break;

  case FK_NonConstLValueReferenceBindingToBitfield: {
    // We don't necessarily have an unambiguous source bit-field.
    FieldDecl *BitField = Args[0]->getSourceBitField();
    S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
      << DestType.isVolatileQualified()
      << (BitField ? BitField->getDeclName() : DeclarationName())
      << (BitField != nullptr)
      << Args[0]->getSourceRange();
    if (BitField)
      S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
    break;
  }

  case FK_NonConstLValueReferenceBindingToVectorElement:
    S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
      << DestType.isVolatileQualified()
      << Args[0]->getSourceRange();
    break;

  case FK_RValueReferenceBindingToLValue:
    S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
      << DestType.getNonReferenceType() << OnlyArg->getType()
      << Args[0]->getSourceRange();
    break;

  case FK_ReferenceAddrspaceMismatchTemporary:
    S.Diag(Kind.getLocation(), diag::err_reference_bind_temporary_addrspace)
        << DestType << Args[0]->getSourceRange();
    break;

  case FK_ReferenceInitDropsQualifiers: {
    QualType SourceType = OnlyArg->getType();
    QualType NonRefType = DestType.getNonReferenceType();
    Qualifiers DroppedQualifiers =
        SourceType.getQualifiers() - NonRefType.getQualifiers();

    if (!NonRefType.getQualifiers().isAddressSpaceSupersetOf(
            SourceType.getQualifiers()))
      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
          << NonRefType << SourceType << 1 /*addr space*/
          << Args[0]->getSourceRange();
    else
      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
          << NonRefType << SourceType << 0 /*cv quals*/
          << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers())
          << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange();
    break;
  }

  case FK_ReferenceInitFailed:
    S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
      << DestType.getNonReferenceType()
      << DestType.getNonReferenceType()->isIncompleteType()
      << OnlyArg->isLValue()
      << OnlyArg->getType()
      << Args[0]->getSourceRange();
    emitBadConversionNotes(S, Entity, Args[0]);
    break;

  case FK_ConversionFailed: {
    QualType FromType = OnlyArg->getType();
    PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
      << (int)Entity.getKind()
      << DestType
      << OnlyArg->isLValue()
      << FromType
      << Args[0]->getSourceRange();
    S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
    S.Diag(Kind.getLocation(), PDiag);
    emitBadConversionNotes(S, Entity, Args[0]);
    break;
  }

  case FK_ConversionFromPropertyFailed:
    // No-op. This error has already been reported.
    break;

  case FK_TooManyInitsForScalar: {
    SourceRange R;

    auto *InitList = dyn_cast<InitListExpr>(Args[0]);
    if (InitList && InitList->getNumInits() >= 1) {
      R = SourceRange(InitList->getInit(0)->getEndLoc(), InitList->getEndLoc());
    } else {
      assert(Args.size() > 1 && "Expected multiple initializers!");
      R = SourceRange(Args.front()->getEndLoc(), Args.back()->getEndLoc());
    }

    R.setBegin(S.getLocForEndOfToken(R.getBegin()));
    if (Kind.isCStyleOrFunctionalCast())
      S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
        << R;
    else
      S.Diag(Kind.getLocation(), diag::err_excess_initializers)
        << /*scalar=*/2 << R;
    break;
  }

  case FK_ParenthesizedListInitForScalar:
    S.Diag(Kind.getLocation(), diag::err_list_init_in_parens)
      << 0 << Entity.getType() << Args[0]->getSourceRange();
    break;

  case FK_ReferenceBindingToInitList:
    S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
      << DestType.getNonReferenceType() << Args[0]->getSourceRange();
    break;

  case FK_InitListBadDestinationType:
    S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
      << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
    break;

  case FK_ListConstructorOverloadFailed:
  case FK_ConstructorOverloadFailed: {
    SourceRange ArgsRange;
    if (Args.size())
      ArgsRange =
          SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc());

    if (Failure == FK_ListConstructorOverloadFailed) {
      assert(Args.size() == 1 &&
             "List construction from other than 1 argument.");
      InitListExpr *InitList = cast<InitListExpr>(Args[0]);
      Args = MultiExprArg(InitList->getInits(), InitList->getNumInits());
    }

    // FIXME: Using "DestType" for the entity we're printing is probably
    // bad.
    switch (FailedOverloadResult) {
      case OR_Ambiguous:
        FailedCandidateSet.NoteCandidates(
            PartialDiagnosticAt(Kind.getLocation(),
                                S.PDiag(diag::err_ovl_ambiguous_init)
                                    << DestType << ArgsRange),
            S, OCD_ViableCandidates, Args);
        break;

      case OR_No_Viable_Function:
        if (Kind.getKind() == InitializationKind::IK_Default &&
            (Entity.getKind() == InitializedEntity::EK_Base ||
             Entity.getKind() == InitializedEntity::EK_Member) &&
            isa<CXXConstructorDecl>(S.CurContext)) {
          // This is implicit default initialization of a member or
          // base within a constructor. If no viable function was
          // found, notify the user that they need to explicitly
          // initialize this base/member.
          CXXConstructorDecl *Constructor
            = cast<CXXConstructorDecl>(S.CurContext);
          const CXXRecordDecl *InheritedFrom = nullptr;
          if (auto Inherited = Constructor->getInheritedConstructor())
            InheritedFrom = Inherited.getShadowDecl()->getNominatedBaseClass();
          if (Entity.getKind() == InitializedEntity::EK_Base) {
            S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
              << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
              << S.Context.getTypeDeclType(Constructor->getParent())
              << /*base=*/0
              << Entity.getType()
              << InheritedFrom;

            RecordDecl *BaseDecl
              = Entity.getBaseSpecifier()->getType()->castAs<RecordType>()
                                                                  ->getDecl();
            S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
              << S.Context.getTagDeclType(BaseDecl);
          } else {
            S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
              << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
              << S.Context.getTypeDeclType(Constructor->getParent())
              << /*member=*/1
              << Entity.getName()
              << InheritedFrom;
            S.Diag(Entity.getDecl()->getLocation(),
                   diag::note_member_declared_at);

            if (const RecordType *Record
                                 = Entity.getType()->getAs<RecordType>())
              S.Diag(Record->getDecl()->getLocation(),
                     diag::note_previous_decl)
                << S.Context.getTagDeclType(Record->getDecl());
          }
          break;
        }

        FailedCandidateSet.NoteCandidates(
            PartialDiagnosticAt(
                Kind.getLocation(),
                S.PDiag(diag::err_ovl_no_viable_function_in_init)
                    << DestType << ArgsRange),
            S, OCD_AllCandidates, Args);
        break;

      case OR_Deleted: {
        OverloadCandidateSet::iterator Best;
        OverloadingResult Ovl
          = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
        if (Ovl != OR_Deleted) {
          S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
              << DestType << ArgsRange;
          llvm_unreachable("Inconsistent overload resolution?");
          break;
        }

        // If this is a defaulted or implicitly-declared function, then
        // it was implicitly deleted. Make it clear that the deletion was
        // implicit.
        if (S.isImplicitlyDeleted(Best->Function))
          S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init)
            << S.getSpecialMember(cast<CXXMethodDecl>(Best->Function))
            << DestType << ArgsRange;
        else
          S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
              << DestType << ArgsRange;

        S.NoteDeletedFunction(Best->Function);
        break;
      }

      case OR_Success:
        llvm_unreachable("Conversion did not fail!");
    }
  }
  break;

  case FK_DefaultInitOfConst:
    if (Entity.getKind() == InitializedEntity::EK_Member &&
        isa<CXXConstructorDecl>(S.CurContext)) {
      // This is implicit default-initialization of a const member in
      // a constructor. Complain that it needs to be explicitly
      // initialized.
      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
      S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
        << (Constructor->getInheritedConstructor() ? 2 :
            Constructor->isImplicit() ? 1 : 0)
        << S.Context.getTypeDeclType(Constructor->getParent())
        << /*const=*/1
        << Entity.getName();
      S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
        << Entity.getName();
    } else {
      S.Diag(Kind.getLocation(), diag::err_default_init_const)
          << DestType << (bool)DestType->getAs<RecordType>();
    }
    break;

  case FK_Incomplete:
    S.RequireCompleteType(Kind.getLocation(), FailedIncompleteType,
                          diag::err_init_incomplete_type);
    break;

  case FK_ListInitializationFailed: {
    // Run the init list checker again to emit diagnostics.
    InitListExpr *InitList = cast<InitListExpr>(Args[0]);
    diagnoseListInit(S, Entity, InitList);
    break;
  }

  case FK_PlaceholderType: {
    // FIXME: Already diagnosed!
    break;
  }

  case FK_ExplicitConstructor: {
    S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor)
      << Args[0]->getSourceRange();
    OverloadCandidateSet::iterator Best;
    OverloadingResult Ovl
      = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
    (void)Ovl;
    assert(Ovl == OR_Success && "Inconsistent overload resolution");
    CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
    S.Diag(CtorDecl->getLocation(),
           diag::note_explicit_ctor_deduction_guide_here) << false;
    break;
  }
  }

  PrintInitLocationNote(S, Entity);
  return true;
}

void InitializationSequence::dump(raw_ostream &OS) const {
  switch (SequenceKind) {
  case FailedSequence: {
    OS << "Failed sequence: ";
    switch (Failure) {
    case FK_TooManyInitsForReference:
      OS << "too many initializers for reference";
      break;

    case FK_ParenthesizedListInitForReference:
      OS << "parenthesized list init for reference";
      break;

    case FK_ArrayNeedsInitList:
      OS << "array requires initializer list";
      break;

    case FK_AddressOfUnaddressableFunction:
      OS << "address of unaddressable function was taken";
      break;

    case FK_ArrayNeedsInitListOrStringLiteral:
      OS << "array requires initializer list or string literal";
      break;

    case FK_ArrayNeedsInitListOrWideStringLiteral:
      OS << "array requires initializer list or wide string literal";
      break;

    case FK_NarrowStringIntoWideCharArray:
      OS << "narrow string into wide char array";
      break;

    case FK_WideStringIntoCharArray:
      OS << "wide string into char array";
      break;

    case FK_IncompatWideStringIntoWideChar:
      OS << "incompatible wide string into wide char array";
      break;

    case FK_PlainStringIntoUTF8Char:
      OS << "plain string literal into char8_t array";
      break;

    case FK_UTF8StringIntoPlainChar:
      OS << "u8 string literal into char array";
      break;

    case FK_ArrayTypeMismatch:
      OS << "array type mismatch";
      break;

    case FK_NonConstantArrayInit:
      OS << "non-constant array initializer";
      break;

    case FK_AddressOfOverloadFailed:
      OS << "address of overloaded function failed";
      break;

    case FK_ReferenceInitOverloadFailed:
      OS << "overload resolution for reference initialization failed";
      break;

    case FK_NonConstLValueReferenceBindingToTemporary:
      OS << "non-const lvalue reference bound to temporary";
      break;

    case FK_NonConstLValueReferenceBindingToBitfield:
      OS << "non-const lvalue reference bound to bit-field";
      break;

    case FK_NonConstLValueReferenceBindingToVectorElement:
      OS << "non-const lvalue reference bound to vector element";
      break;

    case FK_NonConstLValueReferenceBindingToUnrelated:
      OS << "non-const lvalue reference bound to unrelated type";
      break;

    case FK_RValueReferenceBindingToLValue:
      OS << "rvalue reference bound to an lvalue";
      break;

    case FK_ReferenceInitDropsQualifiers:
      OS << "reference initialization drops qualifiers";
      break;

    case FK_ReferenceAddrspaceMismatchTemporary:
      OS << "reference with mismatching address space bound to temporary";
      break;

    case FK_ReferenceInitFailed:
      OS << "reference initialization failed";
      break;

    case FK_ConversionFailed:
      OS << "conversion failed";
      break;

    case FK_ConversionFromPropertyFailed:
      OS << "conversion from property failed";
      break;

    case FK_TooManyInitsForScalar:
      OS << "too many initializers for scalar";
      break;

    case FK_ParenthesizedListInitForScalar:
      OS << "parenthesized list init for reference";
      break;

    case FK_ReferenceBindingToInitList:
      OS << "referencing binding to initializer list";
      break;

    case FK_InitListBadDestinationType:
      OS << "initializer list for non-aggregate, non-scalar type";
      break;

    case FK_UserConversionOverloadFailed:
      OS << "overloading failed for user-defined conversion";
      break;

    case FK_ConstructorOverloadFailed:
      OS << "constructor overloading failed";
      break;

    case FK_DefaultInitOfConst:
      OS << "default initialization of a const variable";
      break;

    case FK_Incomplete:
      OS << "initialization of incomplete type";
      break;

    case FK_ListInitializationFailed:
      OS << "list initialization checker failure";
      break;

    case FK_VariableLengthArrayHasInitializer:
      OS << "variable length array has an initializer";
      break;

    case FK_PlaceholderType:
      OS << "initializer expression isn't contextually valid";
      break;

    case FK_ListConstructorOverloadFailed:
      OS << "list constructor overloading failed";
      break;

    case FK_ExplicitConstructor:
      OS << "list copy initialization chose explicit constructor";
      break;
    }
    OS << '\n';
    return;
  }

  case DependentSequence:
    OS << "Dependent sequence\n";
    return;

  case NormalSequence:
    OS << "Normal sequence: ";
    break;
  }

  for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
    if (S != step_begin()) {
      OS << " -> ";
    }

    switch (S->Kind) {
    case SK_ResolveAddressOfOverloadedFunction:
      OS << "resolve address of overloaded function";
      break;

    case SK_CastDerivedToBaseRValue:
      OS << "derived-to-base (rvalue)";
      break;

    case SK_CastDerivedToBaseXValue:
      OS << "derived-to-base (xvalue)";
      break;

    case SK_CastDerivedToBaseLValue:
      OS << "derived-to-base (lvalue)";
      break;

    case SK_BindReference:
      OS << "bind reference to lvalue";
      break;

    case SK_BindReferenceToTemporary:
      OS << "bind reference to a temporary";
      break;

    case SK_FinalCopy:
      OS << "final copy in class direct-initialization";
      break;

    case SK_ExtraneousCopyToTemporary:
      OS << "extraneous C++03 copy to temporary";
      break;

    case SK_UserConversion:
      OS << "user-defined conversion via " << *S->Function.Function;
      break;

    case SK_QualificationConversionRValue:
      OS << "qualification conversion (rvalue)";
      break;

    case SK_QualificationConversionXValue:
      OS << "qualification conversion (xvalue)";
      break;

    case SK_QualificationConversionLValue:
      OS << "qualification conversion (lvalue)";
      break;

    case SK_AtomicConversion:
      OS << "non-atomic-to-atomic conversion";
      break;

    case SK_ConversionSequence:
      OS << "implicit conversion sequence (";
      S->ICS->dump(); // FIXME: use OS
      OS << ")";
      break;

    case SK_ConversionSequenceNoNarrowing:
      OS << "implicit conversion sequence with narrowing prohibited (";
      S->ICS->dump(); // FIXME: use OS
      OS << ")";
      break;

    case SK_ListInitialization:
      OS << "list aggregate initialization";
      break;

    case SK_UnwrapInitList:
      OS << "unwrap reference initializer list";
      break;

    case SK_RewrapInitList:
      OS << "rewrap reference initializer list";
      break;

    case SK_ConstructorInitialization:
      OS << "constructor initialization";
      break;

    case SK_ConstructorInitializationFromList:
      OS << "list initialization via constructor";
      break;

    case SK_ZeroInitialization:
      OS << "zero initialization";
      break;

    case SK_CAssignment:
      OS << "C assignment";
      break;

    case SK_StringInit:
      OS << "string initialization";
      break;

    case SK_ObjCObjectConversion:
      OS << "Objective-C object conversion";
      break;

    case SK_ArrayLoopIndex:
      OS << "indexing for array initialization loop";
      break;

    case SK_ArrayLoopInit:
      OS << "array initialization loop";
      break;

    case SK_ArrayInit:
      OS << "array initialization";
      break;

    case SK_GNUArrayInit:
      OS << "array initialization (GNU extension)";
      break;

    case SK_ParenthesizedArrayInit:
      OS << "parenthesized array initialization";
      break;

    case SK_PassByIndirectCopyRestore:
      OS << "pass by indirect copy and restore";
      break;

    case SK_PassByIndirectRestore:
      OS << "pass by indirect restore";
      break;

    case SK_ProduceObjCObject:
      OS << "Objective-C object retension";
      break;

    case SK_StdInitializerList:
      OS << "std::initializer_list from initializer list";
      break;

    case SK_StdInitializerListConstructorCall:
      OS << "list initialization from std::initializer_list";
      break;

    case SK_OCLSamplerInit:
      OS << "OpenCL sampler_t from integer constant";
      break;

    case SK_OCLZeroOpaqueType:
      OS << "OpenCL opaque type from zero";
      break;
    }

    OS << " [" << S->Type.getAsString() << ']';
  }

  OS << '\n';
}

void InitializationSequence::dump() const {
  dump(llvm::errs());
}

static bool NarrowingErrs(const LangOptions &L) {
  return L.CPlusPlus11 &&
         (!L.MicrosoftExt || L.isCompatibleWithMSVC(LangOptions::MSVC2015));
}

static void DiagnoseNarrowingInInitList(Sema &S,
                                        const ImplicitConversionSequence &ICS,
                                        QualType PreNarrowingType,
                                        QualType EntityType,
                                        const Expr *PostInit) {
  const StandardConversionSequence *SCS = nullptr;
  switch (ICS.getKind()) {
  case ImplicitConversionSequence::StandardConversion:
    SCS = &ICS.Standard;
    break;
  case ImplicitConversionSequence::UserDefinedConversion:
    SCS = &ICS.UserDefined.After;
    break;
  case ImplicitConversionSequence::AmbiguousConversion:
  case ImplicitConversionSequence::EllipsisConversion:
  case ImplicitConversionSequence::BadConversion:
    return;
  }

  // C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion.
  APValue ConstantValue;
  QualType ConstantType;
  switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue,
                                ConstantType)) {
  case NK_Not_Narrowing:
  case NK_Dependent_Narrowing:
    // No narrowing occurred.
    return;

  case NK_Type_Narrowing:
    // This was a floating-to-integer conversion, which is always considered a
    // narrowing conversion even if the value is a constant and can be
    // represented exactly as an integer.
    S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts())
                                        ? diag::ext_init_list_type_narrowing
                                        : diag::warn_init_list_type_narrowing)
        << PostInit->getSourceRange()
        << PreNarrowingType.getLocalUnqualifiedType()
        << EntityType.getLocalUnqualifiedType();
    break;

  case NK_Constant_Narrowing:
    // A constant value was narrowed.
    S.Diag(PostInit->getBeginLoc(),
           NarrowingErrs(S.getLangOpts())
               ? diag::ext_init_list_constant_narrowing
               : diag::warn_init_list_constant_narrowing)
        << PostInit->getSourceRange()
        << ConstantValue.getAsString(S.getASTContext(), ConstantType)
        << EntityType.getLocalUnqualifiedType();
    break;

  case NK_Variable_Narrowing:
    // A variable's value may have been narrowed.
    S.Diag(PostInit->getBeginLoc(),
           NarrowingErrs(S.getLangOpts())
               ? diag::ext_init_list_variable_narrowing
               : diag::warn_init_list_variable_narrowing)
        << PostInit->getSourceRange()
        << PreNarrowingType.getLocalUnqualifiedType()
        << EntityType.getLocalUnqualifiedType();
    break;
  }

  SmallString<128> StaticCast;
  llvm::raw_svector_ostream OS(StaticCast);
  OS << "static_cast<";
  if (const TypedefType *TT = EntityType->getAs<TypedefType>()) {
    // It's important to use the typedef's name if there is one so that the
    // fixit doesn't break code using types like int64_t.
    //
    // FIXME: This will break if the typedef requires qualification.  But
    // getQualifiedNameAsString() includes non-machine-parsable components.
    OS << *TT->getDecl();
  } else if (const BuiltinType *BT = EntityType->getAs<BuiltinType>())
    OS << BT->getName(S.getLangOpts());
  else {
    // Oops, we didn't find the actual type of the variable.  Don't emit a fixit
    // with a broken cast.
    return;
  }
  OS << ">(";
  S.Diag(PostInit->getBeginLoc(), diag::note_init_list_narrowing_silence)
      << PostInit->getSourceRange()
      << FixItHint::CreateInsertion(PostInit->getBeginLoc(), OS.str())
      << FixItHint::CreateInsertion(
             S.getLocForEndOfToken(PostInit->getEndLoc()), ")");
}

//===----------------------------------------------------------------------===//
// Initialization helper functions
//===----------------------------------------------------------------------===//
bool
Sema::CanPerformCopyInitialization(const InitializedEntity &Entity,
                                   ExprResult Init) {
  if (Init.isInvalid())
    return false;

  Expr *InitE = Init.get();
  assert(InitE && "No initialization expression");

  InitializationKind Kind =
      InitializationKind::CreateCopy(InitE->getBeginLoc(), SourceLocation());
  InitializationSequence Seq(*this, Entity, Kind, InitE);
  return !Seq.Failed();
}

ExprResult
Sema::PerformCopyInitialization(const InitializedEntity &Entity,
                                SourceLocation EqualLoc,
                                ExprResult Init,
                                bool TopLevelOfInitList,
                                bool AllowExplicit) {
  if (Init.isInvalid())
    return ExprError();

  Expr *InitE = Init.get();
  assert(InitE && "No initialization expression?");

  if (EqualLoc.isInvalid())
    EqualLoc = InitE->getBeginLoc();

  InitializationKind Kind = InitializationKind::CreateCopy(
      InitE->getBeginLoc(), EqualLoc, AllowExplicit);
  InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList);

  // Prevent infinite recursion when performing parameter copy-initialization.
  const bool ShouldTrackCopy =
      Entity.isParameterKind() && Seq.isConstructorInitialization();
  if (ShouldTrackCopy) {
    if (llvm::find(CurrentParameterCopyTypes, Entity.getType()) !=
        CurrentParameterCopyTypes.end()) {
      Seq.SetOverloadFailure(
          InitializationSequence::FK_ConstructorOverloadFailed,
          OR_No_Viable_Function);

      // Try to give a meaningful diagnostic note for the problematic
      // constructor.
      const auto LastStep = Seq.step_end() - 1;
      assert(LastStep->Kind ==
             InitializationSequence::SK_ConstructorInitialization);
      const FunctionDecl *Function = LastStep->Function.Function;
      auto Candidate =
          llvm::find_if(Seq.getFailedCandidateSet(),
                        [Function](const OverloadCandidate &Candidate) -> bool {
                          return Candidate.Viable &&
                                 Candidate.Function == Function &&
                                 Candidate.Conversions.size() > 0;
                        });
      if (Candidate != Seq.getFailedCandidateSet().end() &&
          Function->getNumParams() > 0) {
        Candidate->Viable = false;
        Candidate->FailureKind = ovl_fail_bad_conversion;
        Candidate->Conversions[0].setBad(BadConversionSequence::no_conversion,
                                         InitE,
                                         Function->getParamDecl(0)->getType());
      }
    }
    CurrentParameterCopyTypes.push_back(Entity.getType());
  }

  ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE);

  if (ShouldTrackCopy)
    CurrentParameterCopyTypes.pop_back();

  return Result;
}

/// Determine whether RD is, or is derived from, a specialization of CTD.
static bool isOrIsDerivedFromSpecializationOf(CXXRecordDecl *RD,
                                              ClassTemplateDecl *CTD) {
  auto NotSpecialization = [&] (const CXXRecordDecl *Candidate) {
    auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Candidate);
    return !CTSD || !declaresSameEntity(CTSD->getSpecializedTemplate(), CTD);
  };
  return !(NotSpecialization(RD) && RD->forallBases(NotSpecialization));
}

QualType Sema::DeduceTemplateSpecializationFromInitializer(
    TypeSourceInfo *TSInfo, const InitializedEntity &Entity,
    const InitializationKind &Kind, MultiExprArg Inits) {
  auto *DeducedTST = dyn_cast<DeducedTemplateSpecializationType>(
      TSInfo->getType()->getContainedDeducedType());
  assert(DeducedTST && "not a deduced template specialization type");

  auto TemplateName = DeducedTST->getTemplateName();
  if (TemplateName.isDependent())
    return Context.DependentTy;

  // We can only perform deduction for class templates.
  auto *Template =
      dyn_cast_or_null<ClassTemplateDecl>(TemplateName.getAsTemplateDecl());
  if (!Template) {
    Diag(Kind.getLocation(),
         diag::err_deduced_non_class_template_specialization_type)
      << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName;
    if (auto *TD = TemplateName.getAsTemplateDecl())
      Diag(TD->getLocation(), diag::note_template_decl_here);
    return QualType();
  }

  // Can't deduce from dependent arguments.
  if (Expr::hasAnyTypeDependentArguments(Inits)) {
    Diag(TSInfo->getTypeLoc().getBeginLoc(),
         diag::warn_cxx14_compat_class_template_argument_deduction)
        << TSInfo->getTypeLoc().getSourceRange() << 0;
    return Context.DependentTy;
  }

  // FIXME: Perform "exact type" matching first, per CWG discussion?
  //        Or implement this via an implied 'T(T) -> T' deduction guide?

  // FIXME: Do we need/want a std::initializer_list<T> special case?

  // Look up deduction guides, including those synthesized from constructors.
  //
  // C++1z [over.match.class.deduct]p1:
  //   A set of functions and function templates is formed comprising:
  //   - For each constructor of the class template designated by the
  //     template-name, a function template [...]
  //  - For each deduction-guide, a function or function template [...]
  DeclarationNameInfo NameInfo(
      Context.DeclarationNames.getCXXDeductionGuideName(Template),
      TSInfo->getTypeLoc().getEndLoc());
  LookupResult Guides(*this, NameInfo, LookupOrdinaryName);
  LookupQualifiedName(Guides, Template->getDeclContext());

  // FIXME: Do not diagnose inaccessible deduction guides. The standard isn't
  // clear on this, but they're not found by name so access does not apply.
  Guides.suppressDiagnostics();

  // Figure out if this is list-initialization.
  InitListExpr *ListInit =
      (Inits.size() == 1 && Kind.getKind() != InitializationKind::IK_Direct)
          ? dyn_cast<InitListExpr>(Inits[0])
          : nullptr;

  // C++1z [over.match.class.deduct]p1:
  //   Initialization and overload resolution are performed as described in
  //   [dcl.init] and [over.match.ctor], [over.match.copy], or [over.match.list]
  //   (as appropriate for the type of initialization performed) for an object
  //   of a hypothetical class type, where the selected functions and function
  //   templates are considered to be the constructors of that class type
  //
  // Since we know we're initializing a class type of a type unrelated to that
  // of the initializer, this reduces to something fairly reasonable.
  OverloadCandidateSet Candidates(Kind.getLocation(),
                                  OverloadCandidateSet::CSK_Normal);
  OverloadCandidateSet::iterator Best;

  bool HasAnyDeductionGuide = false;
  bool AllowExplicit = !Kind.isCopyInit() || ListInit;

  auto tryToResolveOverload =
      [&](bool OnlyListConstructors) -> OverloadingResult {
    Candidates.clear(OverloadCandidateSet::CSK_Normal);
    HasAnyDeductionGuide = false;

    for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) {
      NamedDecl *D = (*I)->getUnderlyingDecl();
      if (D->isInvalidDecl())
        continue;

      auto *TD = dyn_cast<FunctionTemplateDecl>(D);
      auto *GD = dyn_cast_or_null<CXXDeductionGuideDecl>(
          TD ? TD->getTemplatedDecl() : dyn_cast<FunctionDecl>(D));
      if (!GD)
        continue;

      if (!GD->isImplicit())
        HasAnyDeductionGuide = true;

      // C++ [over.match.ctor]p1: (non-list copy-initialization from non-class)
      //   For copy-initialization, the candidate functions are all the
      //   converting constructors (12.3.1) of that class.
      // C++ [over.match.copy]p1: (non-list copy-initialization from class)
      //   The converting constructors of T are candidate functions.
      if (!AllowExplicit) {
        // Only consider converting constructors.
        if (GD->isExplicit())
          continue;

        // When looking for a converting constructor, deduction guides that
        // could never be called with one argument are not interesting to
        // check or note.
        if (GD->getMinRequiredArguments() > 1 ||
            (GD->getNumParams() == 0 && !GD->isVariadic()))
          continue;
      }

      // C++ [over.match.list]p1.1: (first phase list initialization)
      //   Initially, the candidate functions are the initializer-list
      //   constructors of the class T
      if (OnlyListConstructors && !isInitListConstructor(GD))
        continue;

      // C++ [over.match.list]p1.2: (second phase list initialization)
      //   the candidate functions are all the constructors of the class T
      // C++ [over.match.ctor]p1: (all other cases)
      //   the candidate functions are all the constructors of the class of
      //   the object being initialized

      // C++ [over.best.ics]p4:
      //   When [...] the constructor [...] is a candidate by
      //    - [over.match.copy] (in all cases)
      // FIXME: The "second phase of [over.match.list] case can also
      // theoretically happen here, but it's not clear whether we can
      // ever have a parameter of the right type.
      bool SuppressUserConversions = Kind.isCopyInit();

      if (TD)
        AddTemplateOverloadCandidate(TD, I.getPair(), /*ExplicitArgs*/ nullptr,
                                     Inits, Candidates, SuppressUserConversions,
                                     /*PartialOverloading*/ false,
                                     AllowExplicit);
      else
        AddOverloadCandidate(GD, I.getPair(), Inits, Candidates,
                             SuppressUserConversions,
                             /*PartialOverloading*/ false, AllowExplicit);
    }
    return Candidates.BestViableFunction(*this, Kind.getLocation(), Best);
  };

  OverloadingResult Result = OR_No_Viable_Function;

  // C++11 [over.match.list]p1, per DR1467: for list-initialization, first
  // try initializer-list constructors.
  if (ListInit) {
    bool TryListConstructors = true;

    // Try list constructors unless the list is empty and the class has one or
    // more default constructors, in which case those constructors win.
    if (!ListInit->getNumInits()) {
      for (NamedDecl *D : Guides) {
        auto *FD = dyn_cast<FunctionDecl>(D->getUnderlyingDecl());
        if (FD && FD->getMinRequiredArguments() == 0) {
          TryListConstructors = false;
          break;
        }
      }
    } else if (ListInit->getNumInits() == 1) {
      // C++ [over.match.class.deduct]:
      //   As an exception, the first phase in [over.match.list] (considering
      //   initializer-list constructors) is omitted if the initializer list
      //   consists of a single expression of type cv U, where U is a
      //   specialization of C or a class derived from a specialization of C.
      Expr *E = ListInit->getInit(0);
      auto *RD = E->getType()->getAsCXXRecordDecl();
      if (!isa<InitListExpr>(E) && RD &&
          isCompleteType(Kind.getLocation(), E->getType()) &&
          isOrIsDerivedFromSpecializationOf(RD, Template))
        TryListConstructors = false;
    }

    if (TryListConstructors)
      Result = tryToResolveOverload(/*OnlyListConstructor*/true);
    // Then unwrap the initializer list and try again considering all
    // constructors.
    Inits = MultiExprArg(ListInit->getInits(), ListInit->getNumInits());
  }

  // If list-initialization fails, or if we're doing any other kind of
  // initialization, we (eventually) consider constructors.
  if (Result == OR_No_Viable_Function)
    Result = tryToResolveOverload(/*OnlyListConstructor*/false);

  switch (Result) {
  case OR_Ambiguous:
    // FIXME: For list-initialization candidates, it'd usually be better to
    // list why they were not viable when given the initializer list itself as
    // an argument.
    Candidates.NoteCandidates(
        PartialDiagnosticAt(
            Kind.getLocation(),
            PDiag(diag::err_deduced_class_template_ctor_ambiguous)
                << TemplateName),
        *this, OCD_ViableCandidates, Inits);
    return QualType();

  case OR_No_Viable_Function: {
    CXXRecordDecl *Primary =
        cast<ClassTemplateDecl>(Template)->getTemplatedDecl();
    bool Complete =
        isCompleteType(Kind.getLocation(), Context.getTypeDeclType(Primary));
    Candidates.NoteCandidates(
        PartialDiagnosticAt(
            Kind.getLocation(),
            PDiag(Complete ? diag::err_deduced_class_template_ctor_no_viable
                           : diag::err_deduced_class_template_incomplete)
                << TemplateName << !Guides.empty()),
        *this, OCD_AllCandidates, Inits);
    return QualType();
  }

  case OR_Deleted: {
    Diag(Kind.getLocation(), diag::err_deduced_class_template_deleted)
      << TemplateName;
    NoteDeletedFunction(Best->Function);
    return QualType();
  }

  case OR_Success:
    // C++ [over.match.list]p1:
    //   In copy-list-initialization, if an explicit constructor is chosen, the
    //   initialization is ill-formed.
    if (Kind.isCopyInit() && ListInit &&
        cast<CXXDeductionGuideDecl>(Best->Function)->isExplicit()) {
      bool IsDeductionGuide = !Best->Function->isImplicit();
      Diag(Kind.getLocation(), diag::err_deduced_class_template_explicit)
          << TemplateName << IsDeductionGuide;
      Diag(Best->Function->getLocation(),
           diag::note_explicit_ctor_deduction_guide_here)
          << IsDeductionGuide;
      return QualType();
    }

    // Make sure we didn't select an unusable deduction guide, and mark it
    // as referenced.
    DiagnoseUseOfDecl(Best->Function, Kind.getLocation());
    MarkFunctionReferenced(Kind.getLocation(), Best->Function);
    break;
  }

  // C++ [dcl.type.class.deduct]p1:
  //  The placeholder is replaced by the return type of the function selected
  //  by overload resolution for class template deduction.
  QualType DeducedType =
      SubstAutoType(TSInfo->getType(), Best->Function->getReturnType());
  Diag(TSInfo->getTypeLoc().getBeginLoc(),
       diag::warn_cxx14_compat_class_template_argument_deduction)
      << TSInfo->getTypeLoc().getSourceRange() << 1 << DeducedType;

  // Warn if CTAD was used on a type that does not have any user-defined
  // deduction guides.
  if (!HasAnyDeductionGuide) {
    Diag(TSInfo->getTypeLoc().getBeginLoc(),
         diag::warn_ctad_maybe_unsupported)
        << TemplateName;
    Diag(Template->getLocation(), diag::note_suppress_ctad_maybe_unsupported);
  }

  return DeducedType;
}
