//===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===//
//
// 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 C++ lambda expressions.
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaLambda.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/MangleNumberingContext.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaARM.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include <optional>
using namespace clang;
using namespace sema;

/// Examines the FunctionScopeInfo stack to determine the nearest
/// enclosing lambda (to the current lambda) that is 'capture-ready' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
/// of the capture-ready lambda's LambdaScopeInfo.
///
/// Climbs down the stack of lambdas (deepest nested lambda - i.e. current
/// lambda - is on top) to determine the index of the nearest enclosing/outer
/// lambda that is ready to capture the \p VarToCapture being referenced in
/// the current lambda.
/// As we climb down the stack, we want the index of the first such lambda -
/// that is the lambda with the highest index that is 'capture-ready'.
///
/// A lambda 'L' is capture-ready for 'V' (var or this) if:
///  - its enclosing context is non-dependent
///  - and if the chain of lambdas between L and the lambda in which
///    V is potentially used (i.e. the lambda at the top of the scope info
///    stack), can all capture or have already captured V.
/// If \p VarToCapture is 'null' then we are trying to capture 'this'.
///
/// Note that a lambda that is deemed 'capture-ready' still needs to be checked
/// for whether it is 'capture-capable' (see
/// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly
/// capture.
///
/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a
///  LambdaScopeInfo inherits from).  The current/deepest/innermost lambda
///  is at the top of the stack and has the highest index.
/// \param VarToCapture - the variable to capture.  If NULL, capture 'this'.
///
/// \returns An UnsignedOrNone Index that if evaluates to 'true'
/// contains the index (into Sema's FunctionScopeInfo stack) of the innermost
/// lambda which is capture-ready.  If the return value evaluates to 'false'
/// then no lambda is capture-ready for \p VarToCapture.

static inline UnsignedOrNone getStackIndexOfNearestEnclosingCaptureReadyLambda(
    ArrayRef<const clang::sema::FunctionScopeInfo *> FunctionScopes,
    ValueDecl *VarToCapture) {
  // Label failure to capture.
  const UnsignedOrNone NoLambdaIsCaptureReady = std::nullopt;

  // Ignore all inner captured regions.
  unsigned CurScopeIndex = FunctionScopes.size() - 1;
  while (CurScopeIndex > 0 && isa<clang::sema::CapturedRegionScopeInfo>(
                                  FunctionScopes[CurScopeIndex]))
    --CurScopeIndex;
  assert(
      isa<clang::sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]) &&
      "The function on the top of sema's function-info stack must be a lambda");

  // If VarToCapture is null, we are attempting to capture 'this'.
  const bool IsCapturingThis = !VarToCapture;
  const bool IsCapturingVariable = !IsCapturingThis;

  // Start with the current lambda at the top of the stack (highest index).
  DeclContext *EnclosingDC =
      cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex])->CallOperator;

  do {
    const clang::sema::LambdaScopeInfo *LSI =
        cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]);
    // IF we have climbed down to an intervening enclosing lambda that contains
    // the variable declaration - it obviously can/must not capture the
    // variable.
    // Since its enclosing DC is dependent, all the lambdas between it and the
    // innermost nested lambda are dependent (otherwise we wouldn't have
    // arrived here) - so we don't yet have a lambda that can capture the
    // variable.
    if (IsCapturingVariable &&
        VarToCapture->getDeclContext()->Equals(EnclosingDC))
      return NoLambdaIsCaptureReady;

    // For an enclosing lambda to be capture ready for an entity, all
    // intervening lambda's have to be able to capture that entity. If even
    // one of the intervening lambda's is not capable of capturing the entity
    // then no enclosing lambda can ever capture that entity.
    // For e.g.
    // const int x = 10;
    // [=](auto a) {    #1
    //   [](auto b) {   #2 <-- an intervening lambda that can never capture 'x'
    //    [=](auto c) { #3
    //       f(x, c);  <-- can not lead to x's speculative capture by #1 or #2
    //    }; }; };
    // If they do not have a default implicit capture, check to see
    // if the entity has already been explicitly captured.
    // If even a single dependent enclosing lambda lacks the capability
    // to ever capture this variable, there is no further enclosing
    // non-dependent lambda that can capture this variable.
    if (LSI->ImpCaptureStyle == sema::LambdaScopeInfo::ImpCap_None) {
      if (IsCapturingVariable && !LSI->isCaptured(VarToCapture))
        return NoLambdaIsCaptureReady;
      if (IsCapturingThis && !LSI->isCXXThisCaptured())
        return NoLambdaIsCaptureReady;
    }
    EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC);

    assert(CurScopeIndex);
    --CurScopeIndex;
  } while (!EnclosingDC->isTranslationUnit() &&
           EnclosingDC->isDependentContext() &&
           isLambdaCallOperator(EnclosingDC));

  assert(CurScopeIndex < (FunctionScopes.size() - 1));
  // If the enclosingDC is not dependent, then the immediately nested lambda
  // (one index above) is capture-ready.
  if (!EnclosingDC->isDependentContext())
    return CurScopeIndex + 1;
  return NoLambdaIsCaptureReady;
}

/// Examines the FunctionScopeInfo stack to determine the nearest
/// enclosing lambda (to the current lambda) that is 'capture-capable' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
/// of the capture-capable lambda's LambdaScopeInfo.
///
/// Given the current stack of lambdas being processed by Sema and
/// the variable of interest, to identify the nearest enclosing lambda (to the
/// current lambda at the top of the stack) that can truly capture
/// a variable, it has to have the following two properties:
///  a) 'capture-ready' - be the innermost lambda that is 'capture-ready':
///     - climb down the stack (i.e. starting from the innermost and examining
///       each outer lambda step by step) checking if each enclosing
///       lambda can either implicitly or explicitly capture the variable.
///       Record the first such lambda that is enclosed in a non-dependent
///       context. If no such lambda currently exists return failure.
///  b) 'capture-capable' - make sure the 'capture-ready' lambda can truly
///  capture the variable by checking all its enclosing lambdas:
///     - check if all outer lambdas enclosing the 'capture-ready' lambda
///       identified above in 'a' can also capture the variable (this is done
///       via tryCaptureVariable for variables and CheckCXXThisCapture for
///       'this' by passing in the index of the Lambda identified in step 'a')
///
/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a
/// LambdaScopeInfo inherits from).  The current/deepest/innermost lambda
/// is at the top of the stack.
///
/// \param VarToCapture - the variable to capture.  If NULL, capture 'this'.
///
///
/// \returns An UnsignedOrNone Index that if evaluates to 'true'
/// contains the index (into Sema's FunctionScopeInfo stack) of the innermost
/// lambda which is capture-capable.  If the return value evaluates to 'false'
/// then no lambda is capture-capable for \p VarToCapture.

UnsignedOrNone clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
    ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes,
    ValueDecl *VarToCapture, Sema &S) {

  const UnsignedOrNone NoLambdaIsCaptureCapable = std::nullopt;

  const UnsignedOrNone OptionalStackIndex =
      getStackIndexOfNearestEnclosingCaptureReadyLambda(FunctionScopes,
                                                        VarToCapture);
  if (!OptionalStackIndex)
    return NoLambdaIsCaptureCapable;

  const unsigned IndexOfCaptureReadyLambda = *OptionalStackIndex;
  assert(((IndexOfCaptureReadyLambda != (FunctionScopes.size() - 1)) ||
          S.getCurGenericLambda()) &&
         "The capture ready lambda for a potential capture can only be the "
         "current lambda if it is a generic lambda");

  const sema::LambdaScopeInfo *const CaptureReadyLambdaLSI =
      cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambda]);

  // If VarToCapture is null, we are attempting to capture 'this'
  const bool IsCapturingThis = !VarToCapture;
  const bool IsCapturingVariable = !IsCapturingThis;

  if (IsCapturingVariable) {
    // Check if the capture-ready lambda can truly capture the variable, by
    // checking whether all enclosing lambdas of the capture-ready lambda allow
    // the capture - i.e. make sure it is capture-capable.
    QualType CaptureType, DeclRefType;
    const bool CanCaptureVariable = !S.tryCaptureVariable(
        VarToCapture,
        /*ExprVarIsUsedInLoc*/ SourceLocation(), TryCaptureKind::Implicit,
        /*EllipsisLoc*/ SourceLocation(),
        /*BuildAndDiagnose*/ false, CaptureType, DeclRefType,
        &IndexOfCaptureReadyLambda);
    if (!CanCaptureVariable)
      return NoLambdaIsCaptureCapable;
  } else {
    // Check if the capture-ready lambda can truly capture 'this' by checking
    // whether all enclosing lambdas of the capture-ready lambda can capture
    // 'this'.
    const bool CanCaptureThis =
        !S.CheckCXXThisCapture(
             CaptureReadyLambdaLSI->PotentialThisCaptureLocation,
             /*Explicit*/ false, /*BuildAndDiagnose*/ false,
             &IndexOfCaptureReadyLambda);
    if (!CanCaptureThis)
      return NoLambdaIsCaptureCapable;
  }
  return IndexOfCaptureReadyLambda;
}

static inline TemplateParameterList *
getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
  if (!LSI->GLTemplateParameterList && !LSI->TemplateParams.empty()) {
    LSI->GLTemplateParameterList = TemplateParameterList::Create(
        SemaRef.Context,
        /*Template kw loc*/ SourceLocation(),
        /*L angle loc*/ LSI->ExplicitTemplateParamsRange.getBegin(),
        LSI->TemplateParams,
        /*R angle loc*/LSI->ExplicitTemplateParamsRange.getEnd(),
        LSI->RequiresClause.get());
  }
  return LSI->GLTemplateParameterList;
}

CXXRecordDecl *
Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info,
                              unsigned LambdaDependencyKind,
                              LambdaCaptureDefault CaptureDefault) {
  DeclContext *DC = CurContext;
  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
    DC = DC->getParent();

  bool IsGenericLambda =
      Info && getGenericLambdaTemplateParameterList(getCurLambda(), *this);
  // Start constructing the lambda class.
  CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(
      Context, DC, Info, IntroducerRange.getBegin(), LambdaDependencyKind,
      IsGenericLambda, CaptureDefault);
  DC->addDecl(Class);

  return Class;
}

/// Determine whether the given context is or is enclosed in an inline
/// function.
static bool isInInlineFunction(const DeclContext *DC) {
  while (!DC->isFileContext()) {
    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
      if (FD->isInlined())
        return true;

    DC = DC->getLexicalParent();
  }

  return false;
}

std::tuple<MangleNumberingContext *, Decl *>
Sema::getCurrentMangleNumberContext(const DeclContext *DC) {
  // Compute the context for allocating mangling numbers in the current
  // expression, if the ABI requires them.
  Decl *ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl;

  enum ContextKind {
    Normal,
    DefaultArgument,
    DataMember,
    InlineVariable,
    TemplatedVariable,
    Concept,
    NonInlineInModulePurview
  } Kind = Normal;

  bool IsInNonspecializedTemplate =
      inTemplateInstantiation() || CurContext->isDependentContext();

  // Default arguments of member function parameters that appear in a class
  // definition, as well as the initializers of data members, receive special
  // treatment. Identify them.
  Kind = [&]() {
    if (!ManglingContextDecl)
      return Normal;

    if (auto *ND = dyn_cast<NamedDecl>(ManglingContextDecl)) {
      // See discussion in https://github.com/itanium-cxx-abi/cxx-abi/issues/186
      //
      // zygoloid:
      //    Yeah, I think the only cases left where lambdas don't need a
      //    mangling are when they have (effectively) internal linkage or appear
      //    in a non-inline function in a non-module translation unit.
      Module *M = ManglingContextDecl->getOwningModule();
      if (M && M->getTopLevelModule()->isNamedModuleUnit() &&
          ND->isExternallyVisible())
        return NonInlineInModulePurview;
    }

    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) {
      if (const DeclContext *LexicalDC
          = Param->getDeclContext()->getLexicalParent())
        if (LexicalDC->isRecord())
          return DefaultArgument;
    } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {
      if (Var->getMostRecentDecl()->isInline())
        return InlineVariable;

      if (Var->getDeclContext()->isRecord() && IsInNonspecializedTemplate)
        return TemplatedVariable;

      if (Var->getDescribedVarTemplate())
        return TemplatedVariable;

      if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
        if (!VTS->isExplicitSpecialization())
          return TemplatedVariable;
      }
    } else if (isa<FieldDecl>(ManglingContextDecl)) {
      return DataMember;
    } else if (isa<ImplicitConceptSpecializationDecl>(ManglingContextDecl)) {
      return Concept;
    }

    return Normal;
  }();

  // Itanium ABI [5.1.7]:
  //   In the following contexts [...] the one-definition rule requires closure
  //   types in different translation units to "correspond":
  switch (Kind) {
  case Normal: {
    //  -- the bodies of inline or templated functions
    if ((IsInNonspecializedTemplate &&
         !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) ||
        isInInlineFunction(CurContext)) {
      while (auto *CD = dyn_cast<CapturedDecl>(DC))
        DC = CD->getParent();
      return std::make_tuple(&Context.getManglingNumberContext(DC), nullptr);
    }

    return std::make_tuple(nullptr, nullptr);
  }

  case NonInlineInModulePurview:
  case Concept:
    // Concept definitions aren't code generated and thus aren't mangled,
    // however the ManglingContextDecl is important for the purposes of
    // re-forming the template argument list of the lambda for constraint
    // evaluation.
  case DataMember:
    //  -- default member initializers
  case DefaultArgument:
    //  -- default arguments appearing in class definitions
  case InlineVariable:
  case TemplatedVariable:
    //  -- the initializers of inline or templated variables
    return std::make_tuple(
        &Context.getManglingNumberContext(ASTContext::NeedExtraManglingDecl,
                                          ManglingContextDecl),
        ManglingContextDecl);
  }

  llvm_unreachable("unexpected context");
}

static QualType
buildTypeForLambdaCallOperator(Sema &S, clang::CXXRecordDecl *Class,
                               TemplateParameterList *TemplateParams,
                               TypeSourceInfo *MethodTypeInfo) {
  assert(MethodTypeInfo && "expected a non null type");

  QualType MethodType = MethodTypeInfo->getType();
  // If a lambda appears in a dependent context or is a generic lambda (has
  // template parameters) and has an 'auto' return type, deduce it to a
  // dependent type.
  if (Class->isDependentContext() || TemplateParams) {
    const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
    QualType Result = FPT->getReturnType();
    if (Result->isUndeducedType()) {
      Result = S.SubstAutoTypeDependent(Result);
      MethodType = S.Context.getFunctionType(Result, FPT->getParamTypes(),
                                             FPT->getExtProtoInfo());
    }
  }
  return MethodType;
}

// [C++2b] [expr.prim.lambda.closure] p4
//  Given a lambda with a lambda-capture, the type of the explicit object
//  parameter, if any, of the lambda's function call operator (possibly
//  instantiated from a function call operator template) shall be either:
//  - the closure type,
//  - class type publicly and unambiguously derived from the closure type, or
//  - a reference to a possibly cv-qualified such type.
bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
    CXXMethodDecl *Method, SourceLocation CallLoc) {
  if (!isLambdaCallWithExplicitObjectParameter(Method))
    return false;
  CXXRecordDecl *RD = Method->getParent();
  if (Method->getType()->isDependentType())
    return false;
  if (RD->isCapturelessLambda())
    return false;

  ParmVarDecl *Param = Method->getParamDecl(0);
  QualType ExplicitObjectParameterType = Param->getType()
                                             .getNonReferenceType()
                                             .getUnqualifiedType()
                                             .getDesugaredType(getASTContext());
  QualType LambdaType = getASTContext().getRecordType(RD);
  if (LambdaType == ExplicitObjectParameterType)
    return false;

  // Don't check the same instantiation twice.
  //
  // If this call operator is ill-formed, there is no point in issuing
  // a diagnostic every time it is called because the problem is in the
  // definition of the derived type, not at the call site.
  //
  // FIXME: Move this check to where we instantiate the method? This should
  // be possible, but the naive approach of just marking the method as invalid
  // leads to us emitting more diagnostics than we should have to for this case
  // (1 error here *and* 1 error about there being no matching overload at the
  // call site). It might be possible to avoid that by also checking if there
  // is an empty cast path for the method stored in the context (signalling that
  // we've already diagnosed it) and then just not building the call, but that
  // doesn't really seem any simpler than diagnosing it at the call site...
  auto [It, Inserted] = Context.LambdaCastPaths.try_emplace(Method);
  if (!Inserted)
    return It->second.empty();

  CXXCastPath &Path = It->second;
  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                     /*DetectVirtual=*/false);
  if (!IsDerivedFrom(RD->getLocation(), ExplicitObjectParameterType, LambdaType,
                     Paths)) {
    Diag(Param->getLocation(), diag::err_invalid_explicit_object_type_in_lambda)
        << ExplicitObjectParameterType;
    return true;
  }

  if (Paths.isAmbiguous(LambdaType->getCanonicalTypeUnqualified())) {
    std::string PathsDisplay = getAmbiguousPathsDisplayString(Paths);
    Diag(CallLoc, diag::err_explicit_object_lambda_ambiguous_base)
        << LambdaType << PathsDisplay;
    return true;
  }

  if (CheckBaseClassAccess(CallLoc, LambdaType, ExplicitObjectParameterType,
                           Paths.front(),
                           diag::err_explicit_object_lambda_inaccessible_base))
    return true;

  BuildBasePathArray(Paths, Path);
  return false;
}

void Sema::handleLambdaNumbering(
    CXXRecordDecl *Class, CXXMethodDecl *Method,
    std::optional<CXXRecordDecl::LambdaNumbering> NumberingOverride) {
  if (NumberingOverride) {
    Class->setLambdaNumbering(*NumberingOverride);
    return;
  }

  ContextRAII ManglingContext(*this, Class->getDeclContext());

  auto getMangleNumberingContext =
      [this](CXXRecordDecl *Class,
             Decl *ManglingContextDecl) -> MangleNumberingContext * {
    // Get mangle numbering context if there's any extra decl context.
    if (ManglingContextDecl)
      return &Context.getManglingNumberContext(
          ASTContext::NeedExtraManglingDecl, ManglingContextDecl);
    // Otherwise, from that lambda's decl context.
    auto DC = Class->getDeclContext();
    while (auto *CD = dyn_cast<CapturedDecl>(DC))
      DC = CD->getParent();
    return &Context.getManglingNumberContext(DC);
  };

  CXXRecordDecl::LambdaNumbering Numbering;
  MangleNumberingContext *MCtx;
  std::tie(MCtx, Numbering.ContextDecl) =
      getCurrentMangleNumberContext(Class->getDeclContext());
  if (!MCtx && (getLangOpts().CUDA || getLangOpts().SYCLIsDevice ||
                getLangOpts().SYCLIsHost)) {
    // Force lambda numbering in CUDA/HIP as we need to name lambdas following
    // ODR. Both device- and host-compilation need to have a consistent naming
    // on kernel functions. As lambdas are potential part of these `__global__`
    // function names, they needs numbering following ODR.
    // Also force for SYCL, since we need this for the
    // __builtin_sycl_unique_stable_name implementation, which depends on lambda
    // mangling.
    MCtx = getMangleNumberingContext(Class, Numbering.ContextDecl);
    assert(MCtx && "Retrieving mangle numbering context failed!");
    Numbering.HasKnownInternalLinkage = true;
  }
  if (MCtx) {
    Numbering.IndexInContext = MCtx->getNextLambdaIndex();
    Numbering.ManglingNumber = MCtx->getManglingNumber(Method);
    Numbering.DeviceManglingNumber = MCtx->getDeviceManglingNumber(Method);
    Class->setLambdaNumbering(Numbering);

    if (auto *Source =
            dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
      Source->AssignedLambdaNumbering(Class);
  }
}

static void buildLambdaScopeReturnType(Sema &S, LambdaScopeInfo *LSI,
                                       CXXMethodDecl *CallOperator,
                                       bool ExplicitResultType) {
  if (ExplicitResultType) {
    LSI->HasImplicitReturnType = false;
    LSI->ReturnType = CallOperator->getReturnType();
    if (!LSI->ReturnType->isDependentType() && !LSI->ReturnType->isVoidType())
      S.RequireCompleteType(CallOperator->getBeginLoc(), LSI->ReturnType,
                            diag::err_lambda_incomplete_result);
  } else {
    LSI->HasImplicitReturnType = true;
  }
}

void Sema::buildLambdaScope(LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
                            SourceRange IntroducerRange,
                            LambdaCaptureDefault CaptureDefault,
                            SourceLocation CaptureDefaultLoc,
                            bool ExplicitParams, bool Mutable) {
  LSI->CallOperator = CallOperator;
  CXXRecordDecl *LambdaClass = CallOperator->getParent();
  LSI->Lambda = LambdaClass;
  if (CaptureDefault == LCD_ByCopy)
    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
  else if (CaptureDefault == LCD_ByRef)
    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
  LSI->CaptureDefaultLoc = CaptureDefaultLoc;
  LSI->IntroducerRange = IntroducerRange;
  LSI->ExplicitParams = ExplicitParams;
  LSI->Mutable = Mutable;
}

void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
  LSI->finishedExplicitCaptures();
}

void Sema::ActOnLambdaExplicitTemplateParameterList(
    LambdaIntroducer &Intro, SourceLocation LAngleLoc,
    ArrayRef<NamedDecl *> TParams, SourceLocation RAngleLoc,
    ExprResult RequiresClause) {
  LambdaScopeInfo *LSI = getCurLambda();
  assert(LSI && "Expected a lambda scope");
  assert(LSI->NumExplicitTemplateParams == 0 &&
         "Already acted on explicit template parameters");
  assert(LSI->TemplateParams.empty() &&
         "Explicit template parameters should come "
         "before invented (auto) ones");
  assert(!TParams.empty() &&
         "No template parameters to act on");
  LSI->TemplateParams.append(TParams.begin(), TParams.end());
  LSI->NumExplicitTemplateParams = TParams.size();
  LSI->ExplicitTemplateParamsRange = {LAngleLoc, RAngleLoc};
  LSI->RequiresClause = RequiresClause;
}

/// If this expression is an enumerator-like expression of some type
/// T, return the type T; otherwise, return null.
///
/// Pointer comparisons on the result here should always work because
/// it's derived from either the parent of an EnumConstantDecl
/// (i.e. the definition) or the declaration returned by
/// EnumType::getDecl() (i.e. the definition).
static EnumDecl *findEnumForBlockReturn(Expr *E) {
  // An expression is an enumerator-like expression of type T if,
  // ignoring parens and parens-like expressions:
  E = E->IgnoreParens();

  //  - it is an enumerator whose enum type is T or
  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
    if (EnumConstantDecl *D
          = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
      return cast<EnumDecl>(D->getDeclContext());
    }
    return nullptr;
  }

  //  - it is a comma expression whose RHS is an enumerator-like
  //    expression of type T or
  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
    if (BO->getOpcode() == BO_Comma)
      return findEnumForBlockReturn(BO->getRHS());
    return nullptr;
  }

  //  - it is a statement-expression whose value expression is an
  //    enumerator-like expression of type T or
  if (StmtExpr *SE = dyn_cast<StmtExpr>(E)) {
    if (Expr *last = dyn_cast_or_null<Expr>(SE->getSubStmt()->body_back()))
      return findEnumForBlockReturn(last);
    return nullptr;
  }

  //   - it is a ternary conditional operator (not the GNU ?:
  //     extension) whose second and third operands are
  //     enumerator-like expressions of type T or
  if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
    if (EnumDecl *ED = findEnumForBlockReturn(CO->getTrueExpr()))
      if (ED == findEnumForBlockReturn(CO->getFalseExpr()))
        return ED;
    return nullptr;
  }

  // (implicitly:)
  //   - it is an implicit integral conversion applied to an
  //     enumerator-like expression of type T or
  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
    // We can sometimes see integral conversions in valid
    // enumerator-like expressions.
    if (ICE->getCastKind() == CK_IntegralCast)
      return findEnumForBlockReturn(ICE->getSubExpr());

    // Otherwise, just rely on the type.
  }

  //   - it is an expression of that formal enum type.
  if (const EnumType *ET = E->getType()->getAs<EnumType>()) {
    return ET->getDecl();
  }

  // Otherwise, nope.
  return nullptr;
}

/// Attempt to find a type T for which the returned expression of the
/// given statement is an enumerator-like expression of that type.
static EnumDecl *findEnumForBlockReturn(ReturnStmt *ret) {
  if (Expr *retValue = ret->getRetValue())
    return findEnumForBlockReturn(retValue);
  return nullptr;
}

/// Attempt to find a common type T for which all of the returned
/// expressions in a block are enumerator-like expressions of that
/// type.
static EnumDecl *findCommonEnumForBlockReturns(ArrayRef<ReturnStmt*> returns) {
  ArrayRef<ReturnStmt*>::iterator i = returns.begin(), e = returns.end();

  // Try to find one for the first return.
  EnumDecl *ED = findEnumForBlockReturn(*i);
  if (!ED) return nullptr;

  // Check that the rest of the returns have the same enum.
  for (++i; i != e; ++i) {
    if (findEnumForBlockReturn(*i) != ED)
      return nullptr;
  }

  // Never infer an anonymous enum type.
  if (!ED->hasNameForLinkage()) return nullptr;

  return ED;
}

/// Adjust the given return statements so that they formally return
/// the given type.  It should require, at most, an IntegralCast.
static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
                                     QualType returnType) {
  for (ArrayRef<ReturnStmt*>::iterator
         i = returns.begin(), e = returns.end(); i != e; ++i) {
    ReturnStmt *ret = *i;
    Expr *retValue = ret->getRetValue();
    if (S.Context.hasSameType(retValue->getType(), returnType))
      continue;

    // Right now we only support integral fixup casts.
    assert(returnType->isIntegralOrUnscopedEnumerationType());
    assert(retValue->getType()->isIntegralOrUnscopedEnumerationType());

    ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(retValue);

    Expr *E = (cleanups ? cleanups->getSubExpr() : retValue);
    E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, E,
                                 /*base path*/ nullptr, VK_PRValue,
                                 FPOptionsOverride());
    if (cleanups) {
      cleanups->setSubExpr(E);
    } else {
      ret->setRetValue(E);
    }
  }
}

void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
  assert(CSI.HasImplicitReturnType);
  // If it was ever a placeholder, it had to been deduced to DependentTy.
  assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
  assert((!isa<LambdaScopeInfo>(CSI) || !getLangOpts().CPlusPlus14) &&
         "lambda expressions use auto deduction in C++14 onwards");

  // C++ core issue 975:
  //   If a lambda-expression does not include a trailing-return-type,
  //   it is as if the trailing-return-type denotes the following type:
  //     - if there are no return statements in the compound-statement,
  //       or all return statements return either an expression of type
  //       void or no expression or braced-init-list, the type void;
  //     - otherwise, if all return statements return an expression
  //       and the types of the returned expressions after
  //       lvalue-to-rvalue conversion (4.1 [conv.lval]),
  //       array-to-pointer conversion (4.2 [conv.array]), and
  //       function-to-pointer conversion (4.3 [conv.func]) are the
  //       same, that common type;
  //     - otherwise, the program is ill-formed.
  //
  // C++ core issue 1048 additionally removes top-level cv-qualifiers
  // from the types of returned expressions to match the C++14 auto
  // deduction rules.
  //
  // In addition, in blocks in non-C++ modes, if all of the return
  // statements are enumerator-like expressions of some type T, where
  // T has a name for linkage, then we infer the return type of the
  // block to be that type.

  // First case: no return statements, implicit void return type.
  ASTContext &Ctx = getASTContext();
  if (CSI.Returns.empty()) {
    // It's possible there were simply no /valid/ return statements.
    // In this case, the first one we found may have at least given us a type.
    if (CSI.ReturnType.isNull())
      CSI.ReturnType = Ctx.VoidTy;
    return;
  }

  // Second case: at least one return statement has dependent type.
  // Delay type checking until instantiation.
  assert(!CSI.ReturnType.isNull() && "We should have a tentative return type.");
  if (CSI.ReturnType->isDependentType())
    return;

  // Try to apply the enum-fuzz rule.
  if (!getLangOpts().CPlusPlus) {
    assert(isa<BlockScopeInfo>(CSI));
    const EnumDecl *ED = findCommonEnumForBlockReturns(CSI.Returns);
    if (ED) {
      CSI.ReturnType = Context.getTypeDeclType(ED);
      adjustBlockReturnsToEnum(*this, CSI.Returns, CSI.ReturnType);
      return;
    }
  }

  // Third case: only one return statement. Don't bother doing extra work!
  if (CSI.Returns.size() == 1)
    return;

  // General case: many return statements.
  // Check that they all have compatible return types.

  // We require the return types to strictly match here.
  // Note that we've already done the required promotions as part of
  // processing the return statement.
  for (const ReturnStmt *RS : CSI.Returns) {
    const Expr *RetE = RS->getRetValue();

    QualType ReturnType =
        (RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
    if (Context.getCanonicalFunctionResultType(ReturnType) ==
          Context.getCanonicalFunctionResultType(CSI.ReturnType)) {
      // Use the return type with the strictest possible nullability annotation.
      auto RetTyNullability = ReturnType->getNullability();
      auto BlockNullability = CSI.ReturnType->getNullability();
      if (BlockNullability &&
          (!RetTyNullability ||
           hasWeakerNullability(*RetTyNullability, *BlockNullability)))
        CSI.ReturnType = ReturnType;
      continue;
    }

    // FIXME: This is a poor diagnostic for ReturnStmts without expressions.
    // TODO: It's possible that the *first* return is the divergent one.
    Diag(RS->getBeginLoc(),
         diag::err_typecheck_missing_return_type_incompatible)
        << ReturnType << CSI.ReturnType << isa<LambdaScopeInfo>(CSI);
    // Continue iterating so that we keep emitting diagnostics.
  }
}

QualType Sema::buildLambdaInitCaptureInitialization(
    SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc,
    UnsignedOrNone NumExpansions, IdentifierInfo *Id, bool IsDirectInit,
    Expr *&Init) {
  // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to
  // deduce against.
  QualType DeductType = Context.getAutoDeductType();
  TypeLocBuilder TLB;
  AutoTypeLoc TL = TLB.push<AutoTypeLoc>(DeductType);
  TL.setNameLoc(Loc);
  if (ByRef) {
    DeductType = BuildReferenceType(DeductType, true, Loc, Id);
    assert(!DeductType.isNull() && "can't build reference to auto");
    TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc);
  }
  if (EllipsisLoc.isValid()) {
    if (Init->containsUnexpandedParameterPack()) {
      Diag(EllipsisLoc, getLangOpts().CPlusPlus20
                            ? diag::warn_cxx17_compat_init_capture_pack
                            : diag::ext_init_capture_pack);
      DeductType = Context.getPackExpansionType(DeductType, NumExpansions,
                                                /*ExpectPackInType=*/false);
      TLB.push<PackExpansionTypeLoc>(DeductType).setEllipsisLoc(EllipsisLoc);
    } else {
      // Just ignore the ellipsis for now and form a non-pack variable. We'll
      // diagnose this later when we try to capture it.
    }
  }
  TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);

  // Deduce the type of the init capture.
  QualType DeducedType = deduceVarTypeFromInitializer(
      /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI,
      SourceRange(Loc, Loc), IsDirectInit, Init);
  if (DeducedType.isNull())
    return QualType();

  // Are we a non-list direct initialization?
  ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);

  // Perform initialization analysis and ensure any implicit conversions
  // (such as lvalue-to-rvalue) are enforced.
  InitializedEntity Entity =
      InitializedEntity::InitializeLambdaCapture(Id, DeducedType, Loc);
  InitializationKind Kind =
      IsDirectInit
          ? (CXXDirectInit ? InitializationKind::CreateDirect(
                                 Loc, Init->getBeginLoc(), Init->getEndLoc())
                           : InitializationKind::CreateDirectList(Loc))
          : InitializationKind::CreateCopy(Loc, Init->getBeginLoc());

  MultiExprArg Args = Init;
  if (CXXDirectInit)
    Args =
        MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs());
  QualType DclT;
  InitializationSequence InitSeq(*this, Entity, Kind, Args);
  ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);

  if (Result.isInvalid())
    return QualType();

  Init = Result.getAs<Expr>();
  return DeducedType;
}

VarDecl *Sema::createLambdaInitCaptureVarDecl(
    SourceLocation Loc, QualType InitCaptureType, SourceLocation EllipsisLoc,
    IdentifierInfo *Id, unsigned InitStyle, Expr *Init, DeclContext *DeclCtx) {
  // FIXME: Retain the TypeSourceInfo from buildLambdaInitCaptureInitialization
  // rather than reconstructing it here.
  TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, Loc);
  if (auto PETL = TSI->getTypeLoc().getAs<PackExpansionTypeLoc>())
    PETL.setEllipsisLoc(EllipsisLoc);

  // Create a dummy variable representing the init-capture. This is not actually
  // used as a variable, and only exists as a way to name and refer to the
  // init-capture.
  // FIXME: Pass in separate source locations for '&' and identifier.
  VarDecl *NewVD = VarDecl::Create(Context, DeclCtx, Loc, Loc, Id,
                                   InitCaptureType, TSI, SC_Auto);
  NewVD->setInitCapture(true);
  NewVD->setReferenced(true);
  // FIXME: Pass in a VarDecl::InitializationStyle.
  NewVD->setInitStyle(static_cast<VarDecl::InitializationStyle>(InitStyle));
  NewVD->markUsed(Context);
  NewVD->setInit(Init);
  if (NewVD->isParameterPack())
    getCurLambda()->LocalPacks.push_back(NewVD);
  return NewVD;
}

void Sema::addInitCapture(LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef) {
  assert(Var->isInitCapture() && "init capture flag should be set");
  LSI->addCapture(Var, /*isBlock=*/false, ByRef,
                  /*isNested=*/false, Var->getLocation(), SourceLocation(),
                  Var->getType(), /*Invalid=*/false);
}

// Unlike getCurLambda, getCurrentLambdaScopeUnsafe doesn't
// check that the current lambda is in a consistent or fully constructed state.
static LambdaScopeInfo *getCurrentLambdaScopeUnsafe(Sema &S) {
  assert(!S.FunctionScopes.empty());
  return cast<LambdaScopeInfo>(S.FunctionScopes[S.FunctionScopes.size() - 1]);
}

static TypeSourceInfo *
getDummyLambdaType(Sema &S, SourceLocation Loc = SourceLocation()) {
  // C++11 [expr.prim.lambda]p4:
  //   If a lambda-expression does not include a lambda-declarator, it is as
  //   if the lambda-declarator were ().
  FunctionProtoType::ExtProtoInfo EPI(S.Context.getDefaultCallingConvention(
      /*IsVariadic=*/false, /*IsCXXMethod=*/true));
  EPI.HasTrailingReturn = true;
  EPI.TypeQuals.addConst();
  LangAS AS = S.getDefaultCXXMethodAddrSpace();
  if (AS != LangAS::Default)
    EPI.TypeQuals.addAddressSpace(AS);

  // C++1y [expr.prim.lambda]:
  //   The lambda return type is 'auto', which is replaced by the
  //   trailing-return type if provided and/or deduced from 'return'
  //   statements
  // We don't do this before C++1y, because we don't support deduced return
  // types there.
  QualType DefaultTypeForNoTrailingReturn = S.getLangOpts().CPlusPlus14
                                                ? S.Context.getAutoDeductType()
                                                : S.Context.DependentTy;
  QualType MethodTy =
      S.Context.getFunctionType(DefaultTypeForNoTrailingReturn, {}, EPI);
  return S.Context.getTrivialTypeSourceInfo(MethodTy, Loc);
}

static TypeSourceInfo *getLambdaType(Sema &S, LambdaIntroducer &Intro,
                                     Declarator &ParamInfo, Scope *CurScope,
                                     SourceLocation Loc,
                                     bool &ExplicitResultType) {

  ExplicitResultType = false;

  assert(
      (ParamInfo.getDeclSpec().getStorageClassSpec() ==
           DeclSpec::SCS_unspecified ||
       ParamInfo.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) &&
      "Unexpected storage specifier");
  bool IsLambdaStatic =
      ParamInfo.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static;

  TypeSourceInfo *MethodTyInfo;

  if (ParamInfo.getNumTypeObjects() == 0) {
    MethodTyInfo = getDummyLambdaType(S, Loc);
  } else {
    // Check explicit parameters
    S.CheckExplicitObjectLambda(ParamInfo);

    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();

    bool HasExplicitObjectParameter =
        ParamInfo.isExplicitObjectMemberFunction();

    ExplicitResultType = FTI.hasTrailingReturnType();
    if (!FTI.hasMutableQualifier() && !IsLambdaStatic &&
        !HasExplicitObjectParameter)
      FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const, Loc);

    if (ExplicitResultType && S.getLangOpts().HLSL) {
      QualType RetTy = FTI.getTrailingReturnType().get();
      if (!RetTy.isNull()) {
        // HLSL does not support specifying an address space on a lambda return
        // type.
        LangAS AddressSpace = RetTy.getAddressSpace();
        if (AddressSpace != LangAS::Default)
          S.Diag(FTI.getTrailingReturnTypeLoc(),
                 diag::err_return_value_with_address_space);
      }
    }

    MethodTyInfo = S.GetTypeForDeclarator(ParamInfo);
    assert(MethodTyInfo && "no type from lambda-declarator");

    // Check for unexpanded parameter packs in the method type.
    if (MethodTyInfo->getType()->containsUnexpandedParameterPack())
      S.DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo,
                                        S.UPPC_DeclarationType);
  }
  return MethodTyInfo;
}

CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange,
                                              CXXRecordDecl *Class) {

  // C++20 [expr.prim.lambda.closure]p3:
  // The closure type for a lambda-expression has a public inline function
  // call operator (for a non-generic lambda) or function call operator
  // template (for a generic lambda) whose parameters and return type are
  // described by the lambda-expression's parameter-declaration-clause
  // and trailing-return-type respectively.
  DeclarationName MethodName =
      Context.DeclarationNames.getCXXOperatorName(OO_Call);
  DeclarationNameLoc MethodNameLoc =
      DeclarationNameLoc::makeCXXOperatorNameLoc(IntroducerRange.getBegin());
  CXXMethodDecl *Method = CXXMethodDecl::Create(
      Context, Class, SourceLocation(),
      DeclarationNameInfo(MethodName, IntroducerRange.getBegin(),
                          MethodNameLoc),
      QualType(), /*Tinfo=*/nullptr, SC_None,
      getCurFPFeatures().isFPConstrained(),
      /*isInline=*/true, ConstexprSpecKind::Unspecified, SourceLocation(),
      /*TrailingRequiresClause=*/{});
  Method->setAccess(AS_public);
  return Method;
}

void Sema::AddTemplateParametersToLambdaCallOperator(
    CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
    TemplateParameterList *TemplateParams) {
  assert(TemplateParams && "no template parameters");
  FunctionTemplateDecl *TemplateMethod = FunctionTemplateDecl::Create(
      Context, Class, CallOperator->getLocation(), CallOperator->getDeclName(),
      TemplateParams, CallOperator);
  TemplateMethod->setAccess(AS_public);
  CallOperator->setDescribedFunctionTemplate(TemplateMethod);
}

void Sema::CompleteLambdaCallOperator(
    CXXMethodDecl *Method, SourceLocation LambdaLoc,
    SourceLocation CallOperatorLoc,
    const AssociatedConstraint &TrailingRequiresClause,
    TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
    StorageClass SC, ArrayRef<ParmVarDecl *> Params,
    bool HasExplicitResultType) {

  LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);

  if (TrailingRequiresClause)
    Method->setTrailingRequiresClause(TrailingRequiresClause);

  TemplateParameterList *TemplateParams =
      getGenericLambdaTemplateParameterList(LSI, *this);

  DeclContext *DC = Method->getLexicalDeclContext();
  // DeclContext::addDecl() assumes that the DeclContext we're adding to is the
  // lexical context of the Method. Do so.
  Method->setLexicalDeclContext(LSI->Lambda);
  if (TemplateParams) {
    FunctionTemplateDecl *TemplateMethod =
        Method->getDescribedFunctionTemplate();
    assert(TemplateMethod &&
           "AddTemplateParametersToLambdaCallOperator should have been called");

    LSI->Lambda->addDecl(TemplateMethod);
    TemplateMethod->setLexicalDeclContext(DC);
  } else {
    LSI->Lambda->addDecl(Method);
  }
  LSI->Lambda->setLambdaIsGeneric(TemplateParams);
  LSI->Lambda->setLambdaTypeInfo(MethodTyInfo);

  Method->setLexicalDeclContext(DC);
  Method->setLocation(LambdaLoc);
  Method->setInnerLocStart(CallOperatorLoc);
  Method->setTypeSourceInfo(MethodTyInfo);
  Method->setType(buildTypeForLambdaCallOperator(*this, LSI->Lambda,
                                                 TemplateParams, MethodTyInfo));
  Method->setConstexprKind(ConstexprKind);
  Method->setStorageClass(SC);
  if (!Params.empty()) {
    CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false);
    Method->setParams(Params);
    for (auto P : Method->parameters()) {
      assert(P && "null in a parameter list");
      P->setOwningFunction(Method);
    }
  }

  buildLambdaScopeReturnType(*this, LSI, Method, HasExplicitResultType);
}

void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
                                                Scope *CurrentScope) {

  LambdaScopeInfo *LSI = getCurLambda();
  assert(LSI && "LambdaScopeInfo should be on stack!");

  if (Intro.Default == LCD_ByCopy)
    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
  else if (Intro.Default == LCD_ByRef)
    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
  LSI->CaptureDefaultLoc = Intro.DefaultLoc;
  LSI->IntroducerRange = Intro.Range;
  LSI->AfterParameterList = false;

  assert(LSI->NumExplicitTemplateParams == 0);

  // Determine if we're within a context where we know that the lambda will
  // be dependent, because there are template parameters in scope.
  CXXRecordDecl::LambdaDependencyKind LambdaDependencyKind =
      CXXRecordDecl::LDK_Unknown;
  if (CurScope->getTemplateParamParent() != nullptr) {
    LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
  } else if (Scope *P = CurScope->getParent()) {
    // Given a lambda defined inside a requires expression,
    //
    // struct S {
    //   S(auto var) requires requires { [&] -> decltype(var) { }; }
    //   {}
    // };
    //
    // The parameter var is not injected into the function Decl at the point of
    // parsing lambda. In such scenarios, perceiving it as dependent could
    // result in the constraint being evaluated, which matches what GCC does.
    while (P->getEntity() && P->getEntity()->isRequiresExprBody())
      P = P->getParent();
    if (P->isFunctionDeclarationScope() &&
        llvm::any_of(P->decls(), [](Decl *D) {
          return isa<ParmVarDecl>(D) &&
                 cast<ParmVarDecl>(D)->getType()->isTemplateTypeParmType();
        }))
      LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
  }

  CXXRecordDecl *Class = createLambdaClosureType(
      Intro.Range, /*Info=*/nullptr, LambdaDependencyKind, Intro.Default);
  LSI->Lambda = Class;

  CXXMethodDecl *Method = CreateLambdaCallOperator(Intro.Range, Class);
  LSI->CallOperator = Method;
  // Temporarily set the lexical declaration context to the current
  // context, so that the Scope stack matches the lexical nesting.
  Method->setLexicalDeclContext(CurContext);

  PushDeclContext(CurScope, Method);

  bool ContainsUnexpandedParameterPack = false;

  // Distinct capture names, for diagnostics.
  llvm::DenseMap<IdentifierInfo *, ValueDecl *> CaptureNames;

  // Handle explicit captures.
  SourceLocation PrevCaptureLoc =
      Intro.Default == LCD_None ? Intro.Range.getBegin() : Intro.DefaultLoc;
  for (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E;
       PrevCaptureLoc = C->Loc, ++C) {
    if (C->Kind == LCK_This || C->Kind == LCK_StarThis) {
      if (C->Kind == LCK_StarThis)
        Diag(C->Loc, !getLangOpts().CPlusPlus17
                         ? diag::ext_star_this_lambda_capture_cxx17
                         : diag::warn_cxx14_compat_star_this_lambda_capture);

      // C++11 [expr.prim.lambda]p8:
      //   An identifier or this shall not appear more than once in a
      //   lambda-capture.
      if (LSI->isCXXThisCaptured()) {
        Diag(C->Loc, diag::err_capture_more_than_once)
            << "'this'" << SourceRange(LSI->getCXXThisCapture().getLocation())
            << FixItHint::CreateRemoval(
                   SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
        continue;
      }

      // C++20 [expr.prim.lambda]p8:
      //  If a lambda-capture includes a capture-default that is =,
      //  each simple-capture of that lambda-capture shall be of the form
      //  "&identifier", "this", or "* this". [ Note: The form [&,this] is
      //  redundant but accepted for compatibility with ISO C++14. --end note ]
      if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis)
        Diag(C->Loc, !getLangOpts().CPlusPlus20
                         ? diag::ext_equals_this_lambda_capture_cxx20
                         : diag::warn_cxx17_compat_equals_this_lambda_capture);

      // C++11 [expr.prim.lambda]p12:
      //   If this is captured by a local lambda expression, its nearest
      //   enclosing function shall be a non-static member function.
      QualType ThisCaptureType = getCurrentThisType();
      if (ThisCaptureType.isNull()) {
        Diag(C->Loc, diag::err_this_capture) << true;
        continue;
      }

      CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true,
                          /*FunctionScopeIndexToStopAtPtr*/ nullptr,
                          C->Kind == LCK_StarThis);
      if (!LSI->Captures.empty())
        LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
      continue;
    }

    assert(C->Id && "missing identifier for capture");

    if (C->Init.isInvalid())
      continue;

    ValueDecl *Var = nullptr;
    if (C->Init.isUsable()) {
      Diag(C->Loc, getLangOpts().CPlusPlus14
                       ? diag::warn_cxx11_compat_init_capture
                       : diag::ext_init_capture);

      // If the initializer expression is usable, but the InitCaptureType
      // is not, then an error has occurred - so ignore the capture for now.
      // for e.g., [n{0}] { }; <-- if no <initializer_list> is included.
      // FIXME: we should create the init capture variable and mark it invalid
      // in this case.
      if (C->InitCaptureType.get().isNull())
        continue;

      if (C->Init.get()->containsUnexpandedParameterPack() &&
          !C->InitCaptureType.get()->getAs<PackExpansionType>())
        DiagnoseUnexpandedParameterPack(C->Init.get(), UPPC_Initializer);

      unsigned InitStyle;
      switch (C->InitKind) {
      case LambdaCaptureInitKind::NoInit:
        llvm_unreachable("not an init-capture?");
      case LambdaCaptureInitKind::CopyInit:
        InitStyle = VarDecl::CInit;
        break;
      case LambdaCaptureInitKind::DirectInit:
        InitStyle = VarDecl::CallInit;
        break;
      case LambdaCaptureInitKind::ListInit:
        InitStyle = VarDecl::ListInit;
        break;
      }
      Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
                                           C->EllipsisLoc, C->Id, InitStyle,
                                           C->Init.get(), Method);
      assert(Var && "createLambdaInitCaptureVarDecl returned a null VarDecl?");
      if (auto *V = dyn_cast<VarDecl>(Var))
        CheckShadow(CurrentScope, V);
      PushOnScopeChains(Var, CurrentScope, false);
    } else {
      assert(C->InitKind == LambdaCaptureInitKind::NoInit &&
             "init capture has valid but null init?");

      // C++11 [expr.prim.lambda]p8:
      //   If a lambda-capture includes a capture-default that is &, the
      //   identifiers in the lambda-capture shall not be preceded by &.
      //   If a lambda-capture includes a capture-default that is =, [...]
      //   each identifier it contains shall be preceded by &.
      if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
        Diag(C->Loc, diag::err_reference_capture_with_reference_default)
            << FixItHint::CreateRemoval(
                SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
        continue;
      } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
        Diag(C->Loc, diag::err_copy_capture_with_copy_default)
            << FixItHint::CreateRemoval(
                SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
        continue;
      }

      // C++11 [expr.prim.lambda]p10:
      //   The identifiers in a capture-list are looked up using the usual
      //   rules for unqualified name lookup (3.4.1)
      DeclarationNameInfo Name(C->Id, C->Loc);
      LookupResult R(*this, Name, LookupOrdinaryName);
      LookupName(R, CurScope);
      if (R.isAmbiguous())
        continue;
      if (R.empty()) {
        // FIXME: Disable corrections that would add qualification?
        CXXScopeSpec ScopeSpec;
        DeclFilterCCC<VarDecl> Validator{};
        if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
          continue;
      }

      if (auto *BD = R.getAsSingle<BindingDecl>())
        Var = BD;
      else if (R.getAsSingle<FieldDecl>()) {
        Diag(C->Loc, diag::err_capture_class_member_does_not_name_variable)
            << C->Id;
        continue;
      } else
        Var = R.getAsSingle<VarDecl>();
      if (Var && DiagnoseUseOfDecl(Var, C->Loc))
        continue;
    }

    // C++11 [expr.prim.lambda]p10:
    //   [...] each such lookup shall find a variable with automatic storage
    //   duration declared in the reaching scope of the local lambda expression.
    // Note that the 'reaching scope' check happens in tryCaptureVariable().
    if (!Var) {
      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
      continue;
    }

    // C++11 [expr.prim.lambda]p8:
    //   An identifier or this shall not appear more than once in a
    //   lambda-capture.
    if (auto [It, Inserted] = CaptureNames.insert(std::pair{C->Id, Var});
        !Inserted) {
      if (C->InitKind == LambdaCaptureInitKind::NoInit &&
          !Var->isInitCapture()) {
        Diag(C->Loc, diag::err_capture_more_than_once)
            << C->Id << It->second->getBeginLoc()
            << FixItHint::CreateRemoval(
                   SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
        Var->setInvalidDecl();
      } else if (Var && Var->isPlaceholderVar(getLangOpts())) {
        DiagPlaceholderVariableDefinition(C->Loc);
      } else {
        // Previous capture captured something different (one or both was
        // an init-capture): no fixit.
        Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
        continue;
      }
    }

    // Ignore invalid decls; they'll just confuse the code later.
    if (Var->isInvalidDecl())
      continue;

    VarDecl *Underlying = Var->getPotentiallyDecomposedVarDecl();

    if (!Underlying->hasLocalStorage()) {
      Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
      Diag(Var->getLocation(), diag::note_previous_decl) << C->Id;
      continue;
    }

    // C++11 [expr.prim.lambda]p23:
    //   A capture followed by an ellipsis is a pack expansion (14.5.3).
    SourceLocation EllipsisLoc;
    if (C->EllipsisLoc.isValid()) {
      if (Var->isParameterPack()) {
        EllipsisLoc = C->EllipsisLoc;
      } else {
        Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
            << (C->Init.isUsable() ? C->Init.get()->getSourceRange()
                                   : SourceRange(C->Loc));

        // Just ignore the ellipsis.
      }
    } else if (Var->isParameterPack()) {
      ContainsUnexpandedParameterPack = true;
    }

    if (C->Init.isUsable()) {
      addInitCapture(LSI, cast<VarDecl>(Var), C->Kind == LCK_ByRef);
    } else {
      TryCaptureKind Kind = C->Kind == LCK_ByRef
                                ? TryCaptureKind::ExplicitByRef
                                : TryCaptureKind::ExplicitByVal;
      tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
    }
    if (!LSI->Captures.empty())
      LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
  }
  finishLambdaExplicitCaptures(LSI);
  LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
  PopDeclContext();
}

void Sema::ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
                                        SourceLocation MutableLoc) {

  LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
  LSI->Mutable = MutableLoc.isValid();
  ContextRAII Context(*this, LSI->CallOperator, /*NewThisContext*/ false);

  // C++11 [expr.prim.lambda]p9:
  //   A lambda-expression whose smallest enclosing scope is a block scope is a
  //   local lambda expression; any other lambda expression shall not have a
  //   capture-default or simple-capture in its lambda-introducer.
  //
  // For simple-captures, this is covered by the check below that any named
  // entity is a variable that can be captured.
  //
  // For DR1632, we also allow a capture-default in any context where we can
  // odr-use 'this' (in particular, in a default initializer for a non-static
  // data member).
  if (Intro.Default != LCD_None &&
      !LSI->Lambda->getParent()->isFunctionOrMethod() &&
      (getCurrentThisType().isNull() ||
       CheckCXXThisCapture(SourceLocation(), /*Explicit=*/true,
                           /*BuildAndDiagnose=*/false)))
    Diag(Intro.DefaultLoc, diag::err_capture_default_non_local);
}

void Sema::ActOnLambdaClosureParameters(
    Scope *LambdaScope, MutableArrayRef<DeclaratorChunk::ParamInfo> Params) {
  LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
  PushDeclContext(LambdaScope, LSI->CallOperator);

  for (const DeclaratorChunk::ParamInfo &P : Params) {
    auto *Param = cast<ParmVarDecl>(P.Param);
    Param->setOwningFunction(LSI->CallOperator);
    if (Param->getIdentifier())
      PushOnScopeChains(Param, LambdaScope, false);
  }

  // After the parameter list, we may parse a noexcept/requires/trailing return
  // type which need to know whether the call operator constiture a dependent
  // context, so we need to setup the FunctionTemplateDecl of generic lambdas
  // now.
  TemplateParameterList *TemplateParams =
      getGenericLambdaTemplateParameterList(LSI, *this);
  if (TemplateParams) {
    AddTemplateParametersToLambdaCallOperator(LSI->CallOperator, LSI->Lambda,
                                              TemplateParams);
    LSI->Lambda->setLambdaIsGeneric(true);
    LSI->ContainsUnexpandedParameterPack |=
        TemplateParams->containsUnexpandedParameterPack();
  }
  LSI->AfterParameterList = true;
}

void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                                        Declarator &ParamInfo,
                                        const DeclSpec &DS) {

  LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
  LSI->CallOperator->setConstexprKind(DS.getConstexprSpecifier());

  SmallVector<ParmVarDecl *, 8> Params;
  bool ExplicitResultType;

  SourceLocation TypeLoc, CallOperatorLoc;
  if (ParamInfo.getNumTypeObjects() == 0) {
    CallOperatorLoc = TypeLoc = Intro.Range.getEnd();
  } else {
    unsigned Index;
    ParamInfo.isFunctionDeclarator(Index);
    const auto &Object = ParamInfo.getTypeObject(Index);
    TypeLoc =
        Object.Loc.isValid() ? Object.Loc : ParamInfo.getSourceRange().getEnd();
    CallOperatorLoc = ParamInfo.getSourceRange().getEnd();
  }

  CXXRecordDecl *Class = LSI->Lambda;
  CXXMethodDecl *Method = LSI->CallOperator;

  TypeSourceInfo *MethodTyInfo = getLambdaType(
      *this, Intro, ParamInfo, getCurScope(), TypeLoc, ExplicitResultType);

  LSI->ExplicitParams = ParamInfo.getNumTypeObjects() != 0;

  if (ParamInfo.isFunctionDeclarator() != 0 &&
      !FTIHasSingleVoidParameter(ParamInfo.getFunctionTypeInfo())) {
    const auto &FTI = ParamInfo.getFunctionTypeInfo();
    Params.reserve(Params.size());
    for (unsigned I = 0; I < FTI.NumParams; ++I) {
      auto *Param = cast<ParmVarDecl>(FTI.Params[I].Param);
      Param->setScopeInfo(0, Params.size());
      Params.push_back(Param);
    }
  }

  bool IsLambdaStatic =
      ParamInfo.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static;

  CompleteLambdaCallOperator(
      Method, Intro.Range.getBegin(), CallOperatorLoc,
      AssociatedConstraint(ParamInfo.getTrailingRequiresClause()), MethodTyInfo,
      ParamInfo.getDeclSpec().getConstexprSpecifier(),
      IsLambdaStatic ? SC_Static : SC_None, Params, ExplicitResultType);

  CheckCXXDefaultArguments(Method);

  // This represents the function body for the lambda function, check if we
  // have to apply optnone due to a pragma.
  AddRangeBasedOptnone(Method);

  // code_seg attribute on lambda apply to the method.
  if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(
          Method, /*IsDefinition=*/true))
    Method->addAttr(A);

  // Attributes on the lambda apply to the method.
  ProcessDeclAttributes(CurScope, Method, ParamInfo);

  if (Context.getTargetInfo().getTriple().isAArch64())
    ARM().CheckSMEFunctionDefAttributes(Method);

  // CUDA lambdas get implicit host and device attributes.
  if (getLangOpts().CUDA)
    CUDA().SetLambdaAttrs(Method);

  // OpenMP lambdas might get assumumption attributes.
  if (LangOpts.OpenMP)
    OpenMP().ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Method);

  handleLambdaNumbering(Class, Method);

  for (auto &&C : LSI->Captures) {
    if (!C.isVariableCapture())
      continue;
    ValueDecl *Var = C.getVariable();
    if (Var && Var->isInitCapture()) {
      PushOnScopeChains(Var, CurScope, false);
    }
  }

  auto CheckRedefinition = [&](ParmVarDecl *Param) {
    for (const auto &Capture : Intro.Captures) {
      if (Capture.Id == Param->getIdentifier()) {
        Diag(Param->getLocation(), diag::err_parameter_shadow_capture);
        Diag(Capture.Loc, diag::note_var_explicitly_captured_here)
            << Capture.Id << true;
        return false;
      }
    }
    return true;
  };

  for (ParmVarDecl *P : Params) {
    if (!P->getIdentifier())
      continue;
    if (CheckRedefinition(P))
      CheckShadow(CurScope, P);
    PushOnScopeChains(P, CurScope);
  }

  // C++23 [expr.prim.lambda.capture]p5:
  // If an identifier in a capture appears as the declarator-id of a parameter
  // of the lambda-declarator's parameter-declaration-clause or as the name of a
  // template parameter of the lambda-expression's template-parameter-list, the
  // program is ill-formed.
  TemplateParameterList *TemplateParams =
      getGenericLambdaTemplateParameterList(LSI, *this);
  if (TemplateParams) {
    for (const auto *TP : TemplateParams->asArray()) {
      if (!TP->getIdentifier())
        continue;
      for (const auto &Capture : Intro.Captures) {
        if (Capture.Id == TP->getIdentifier()) {
          Diag(Capture.Loc, diag::err_template_param_shadow) << Capture.Id;
          NoteTemplateParameterLocation(*TP);
        }
      }
    }
  }

  // C++20: dcl.decl.general p4:
  // The optional requires-clause ([temp.pre]) in an init-declarator or
  // member-declarator shall be present only if the declarator declares a
  // templated function ([dcl.fct]).
  if (const AssociatedConstraint &TRC = Method->getTrailingRequiresClause()) {
    // [temp.pre]/8:
    // An entity is templated if it is
    // - a template,
    // - an entity defined ([basic.def]) or created ([class.temporary]) in a
    // templated entity,
    // - a member of a templated entity,
    // - an enumerator for an enumeration that is a templated entity, or
    // - the closure type of a lambda-expression ([expr.prim.lambda.closure])
    // appearing in the declaration of a templated entity. [Note 6: A local
    // class, a local or block variable, or a friend function defined in a
    // templated entity is a templated entity.  — end note]
    //
    // A templated function is a function template or a function that is
    // templated. A templated class is a class template or a class that is
    // templated. A templated variable is a variable template or a variable
    // that is templated.

    // Note: we only have to check if this is defined in a template entity, OR
    // if we are a template, since the rest don't apply. The requires clause
    // applies to the call operator, which we already know is a member function,
    // AND defined.
    if (!Method->getDescribedFunctionTemplate() && !Method->isTemplated()) {
      Diag(TRC.ConstraintExpr->getBeginLoc(),
           diag::err_constrained_non_templated_function);
    }
  }

  // Enter a new evaluation context to insulate the lambda from any
  // cleanups from the enclosing full-expression.
  PushExpressionEvaluationContextForFunction(
      ExpressionEvaluationContext::PotentiallyEvaluated, LSI->CallOperator);
}

void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
                            bool IsInstantiation) {
  LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(FunctionScopes.back());

  // Leave the expression-evaluation context.
  DiscardCleanupsInEvaluationContext();
  PopExpressionEvaluationContext();

  // Leave the context of the lambda.
  if (!IsInstantiation)
    PopDeclContext();

  // Finalize the lambda.
  CXXRecordDecl *Class = LSI->Lambda;
  Class->setInvalidDecl();
  SmallVector<Decl*, 4> Fields(Class->fields());
  ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
              SourceLocation(), ParsedAttributesView());
  CheckCompletedCXXClass(nullptr, Class);

  PopFunctionScopeInfo();
}

template <typename Func>
static void repeatForLambdaConversionFunctionCallingConvs(
    Sema &S, const FunctionProtoType &CallOpProto, Func F) {
  CallingConv DefaultFree = S.Context.getDefaultCallingConvention(
      CallOpProto.isVariadic(), /*IsCXXMethod=*/false);
  CallingConv DefaultMember = S.Context.getDefaultCallingConvention(
      CallOpProto.isVariadic(), /*IsCXXMethod=*/true);
  CallingConv CallOpCC = CallOpProto.getCallConv();

  /// Implement emitting a version of the operator for many of the calling
  /// conventions for MSVC, as described here:
  /// https://devblogs.microsoft.com/oldnewthing/20150220-00/?p=44623.
  /// Experimentally, we determined that cdecl, stdcall, fastcall, and
  /// vectorcall are generated by MSVC when it is supported by the target.
  /// Additionally, we are ensuring that the default-free/default-member and
  /// call-operator calling convention are generated as well.
  /// NOTE: We intentionally generate a 'thiscall' on Win32 implicitly from the
  /// 'member default', despite MSVC not doing so. We do this in order to ensure
  /// that someone who intentionally places 'thiscall' on the lambda call
  /// operator will still get that overload, since we don't have the a way of
  /// detecting the attribute by the time we get here.
  if (S.getLangOpts().MSVCCompat) {
    CallingConv Convs[] = {
        CC_C,        CC_X86StdCall, CC_X86FastCall, CC_X86VectorCall,
        DefaultFree, DefaultMember, CallOpCC};
    llvm::sort(Convs);
    llvm::iterator_range<CallingConv *> Range(std::begin(Convs),
                                              llvm::unique(Convs));
    const TargetInfo &TI = S.getASTContext().getTargetInfo();

    for (CallingConv C : Range) {
      if (TI.checkCallingConvention(C) == TargetInfo::CCCR_OK)
        F(C);
    }
    return;
  }

  if (CallOpCC == DefaultMember && DefaultMember != DefaultFree) {
    F(DefaultFree);
    F(DefaultMember);
  } else {
    F(CallOpCC);
  }
}

// Returns the 'standard' calling convention to be used for the lambda
// conversion function, that is, the 'free' function calling convention unless
// it is overridden by a non-default calling convention attribute.
static CallingConv
getLambdaConversionFunctionCallConv(Sema &S,
                                    const FunctionProtoType *CallOpProto) {
  CallingConv DefaultFree = S.Context.getDefaultCallingConvention(
      CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
  CallingConv DefaultMember = S.Context.getDefaultCallingConvention(
      CallOpProto->isVariadic(), /*IsCXXMethod=*/true);
  CallingConv CallOpCC = CallOpProto->getCallConv();

  // If the call-operator hasn't been changed, return both the 'free' and
  // 'member' function calling convention.
  if (CallOpCC == DefaultMember && DefaultMember != DefaultFree)
    return DefaultFree;
  return CallOpCC;
}

QualType Sema::getLambdaConversionFunctionResultType(
    const FunctionProtoType *CallOpProto, CallingConv CC) {
  const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
      CallOpProto->getExtProtoInfo();
  FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
  InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
  InvokerExtInfo.TypeQuals = Qualifiers();
  assert(InvokerExtInfo.RefQualifier == RQ_None &&
         "Lambda's call operator should not have a reference qualifier");
  return Context.getFunctionType(CallOpProto->getReturnType(),
                                 CallOpProto->getParamTypes(), InvokerExtInfo);
}

/// Add a lambda's conversion to function pointer, as described in
/// C++11 [expr.prim.lambda]p6.
static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange,
                                         CXXRecordDecl *Class,
                                         CXXMethodDecl *CallOperator,
                                         QualType InvokerFunctionTy) {
  // This conversion is explicitly disabled if the lambda's function has
  // pass_object_size attributes on any of its parameters.
  auto HasPassObjectSizeAttr = [](const ParmVarDecl *P) {
    return P->hasAttr<PassObjectSizeAttr>();
  };
  if (llvm::any_of(CallOperator->parameters(), HasPassObjectSizeAttr))
    return;

  // Add the conversion to function pointer.
  QualType PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);

  // Create the type of the conversion function.
  FunctionProtoType::ExtProtoInfo ConvExtInfo(
      S.Context.getDefaultCallingConvention(
      /*IsVariadic=*/false, /*IsCXXMethod=*/true));
  // The conversion function is always const and noexcept.
  ConvExtInfo.TypeQuals = Qualifiers();
  ConvExtInfo.TypeQuals.addConst();
  ConvExtInfo.ExceptionSpec.Type = EST_BasicNoexcept;
  QualType ConvTy = S.Context.getFunctionType(PtrToFunctionTy, {}, ConvExtInfo);

  SourceLocation Loc = IntroducerRange.getBegin();
  DeclarationName ConversionName
    = S.Context.DeclarationNames.getCXXConversionFunctionName(
        S.Context.getCanonicalType(PtrToFunctionTy));
  // Construct a TypeSourceInfo for the conversion function, and wire
  // all the parameters appropriately for the FunctionProtoTypeLoc
  // so that everything works during transformation/instantiation of
  // generic lambdas.
  // The main reason for wiring up the parameters of the conversion
  // function with that of the call operator is so that constructs
  // like the following work:
  // auto L = [](auto b) {                <-- 1
  //   return [](auto a) -> decltype(a) { <-- 2
  //      return a;
  //   };
  // };
  // int (*fp)(int) = L(5);
  // Because the trailing return type can contain DeclRefExprs that refer
  // to the original call operator's variables, we hijack the call
  // operators ParmVarDecls below.
  TypeSourceInfo *ConvNamePtrToFunctionTSI =
      S.Context.getTrivialTypeSourceInfo(PtrToFunctionTy, Loc);
  DeclarationNameLoc ConvNameLoc =
      DeclarationNameLoc::makeNamedTypeLoc(ConvNamePtrToFunctionTSI);

  // The conversion function is a conversion to a pointer-to-function.
  TypeSourceInfo *ConvTSI = S.Context.getTrivialTypeSourceInfo(ConvTy, Loc);
  FunctionProtoTypeLoc ConvTL =
      ConvTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
  // Get the result of the conversion function which is a pointer-to-function.
  PointerTypeLoc PtrToFunctionTL =
      ConvTL.getReturnLoc().getAs<PointerTypeLoc>();
  // Do the same for the TypeSourceInfo that is used to name the conversion
  // operator.
  PointerTypeLoc ConvNamePtrToFunctionTL =
      ConvNamePtrToFunctionTSI->getTypeLoc().getAs<PointerTypeLoc>();

  // Get the underlying function types that the conversion function will
  // be converting to (should match the type of the call operator).
  FunctionProtoTypeLoc CallOpConvTL =
      PtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>();
  FunctionProtoTypeLoc CallOpConvNameTL =
    ConvNamePtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>();

  // Wire up the FunctionProtoTypeLocs with the call operator's parameters.
  // These parameter's are essentially used to transform the name and
  // the type of the conversion operator.  By using the same parameters
  // as the call operator's we don't have to fix any back references that
  // the trailing return type of the call operator's uses (such as
  // decltype(some_type<decltype(a)>::type{} + decltype(a){}) etc.)
  // - we can simply use the return type of the call operator, and
  // everything should work.
  SmallVector<ParmVarDecl *, 4> InvokerParams;
  for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
    ParmVarDecl *From = CallOperator->getParamDecl(I);

    InvokerParams.push_back(ParmVarDecl::Create(
        S.Context,
        // Temporarily add to the TU. This is set to the invoker below.
        S.Context.getTranslationUnitDecl(), From->getBeginLoc(),
        From->getLocation(), From->getIdentifier(), From->getType(),
        From->getTypeSourceInfo(), From->getStorageClass(),
        /*DefArg=*/nullptr));
    CallOpConvTL.setParam(I, From);
    CallOpConvNameTL.setParam(I, From);
  }

  CXXConversionDecl *Conversion = CXXConversionDecl::Create(
      S.Context, Class, Loc,
      DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI,
      S.getCurFPFeatures().isFPConstrained(),
      /*isInline=*/true, ExplicitSpecifier(),
      S.getLangOpts().CPlusPlus17 ? ConstexprSpecKind::Constexpr
                                  : ConstexprSpecKind::Unspecified,
      CallOperator->getBody()->getEndLoc());
  Conversion->setAccess(AS_public);
  Conversion->setImplicit(true);

  // A non-generic lambda may still be a templated entity. We need to preserve
  // constraints when converting the lambda to a function pointer. See GH63181.
  if (const AssociatedConstraint &Requires =
          CallOperator->getTrailingRequiresClause())
    Conversion->setTrailingRequiresClause(Requires);

  if (Class->isGenericLambda()) {
    // Create a template version of the conversion operator, using the template
    // parameter list of the function call operator.
    FunctionTemplateDecl *TemplateCallOperator =
            CallOperator->getDescribedFunctionTemplate();
    FunctionTemplateDecl *ConversionTemplate =
                  FunctionTemplateDecl::Create(S.Context, Class,
                                      Loc, ConversionName,
                                      TemplateCallOperator->getTemplateParameters(),
                                      Conversion);
    ConversionTemplate->setAccess(AS_public);
    ConversionTemplate->setImplicit(true);
    Conversion->setDescribedFunctionTemplate(ConversionTemplate);
    Class->addDecl(ConversionTemplate);
  } else
    Class->addDecl(Conversion);

  // If the lambda is not static, we need to add a static member
  // function that will be the result of the conversion with a
  // certain unique ID.
  // When it is static we just return the static call operator instead.
  if (CallOperator->isImplicitObjectMemberFunction()) {
    DeclarationName InvokerName =
        &S.Context.Idents.get(getLambdaStaticInvokerName());
    // FIXME: Instead of passing in the CallOperator->getTypeSourceInfo()
    // we should get a prebuilt TrivialTypeSourceInfo from Context
    // using FunctionTy & Loc and get its TypeLoc as a FunctionProtoTypeLoc
    // then rewire the parameters accordingly, by hoisting up the InvokeParams
    // loop below and then use its Params to set Invoke->setParams(...) below.
    // This would avoid the 'const' qualifier of the calloperator from
    // contaminating the type of the invoker, which is currently adjusted
    // in SemaTemplateDeduction.cpp:DeduceTemplateArguments.  Fixing the
    // trailing return type of the invoker would require a visitor to rebuild
    // the trailing return type and adjusting all back DeclRefExpr's to refer
    // to the new static invoker parameters - not the call operator's.
    CXXMethodDecl *Invoke = CXXMethodDecl::Create(
        S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc),
        InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static,
        S.getCurFPFeatures().isFPConstrained(),
        /*isInline=*/true, CallOperator->getConstexprKind(),
        CallOperator->getBody()->getEndLoc());
    for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I)
      InvokerParams[I]->setOwningFunction(Invoke);
    Invoke->setParams(InvokerParams);
    Invoke->setAccess(AS_private);
    Invoke->setImplicit(true);
    if (Class->isGenericLambda()) {
      FunctionTemplateDecl *TemplateCallOperator =
          CallOperator->getDescribedFunctionTemplate();
      FunctionTemplateDecl *StaticInvokerTemplate =
          FunctionTemplateDecl::Create(
              S.Context, Class, Loc, InvokerName,
              TemplateCallOperator->getTemplateParameters(), Invoke);
      StaticInvokerTemplate->setAccess(AS_private);
      StaticInvokerTemplate->setImplicit(true);
      Invoke->setDescribedFunctionTemplate(StaticInvokerTemplate);
      Class->addDecl(StaticInvokerTemplate);
    } else
      Class->addDecl(Invoke);
  }
}

/// Add a lambda's conversion to function pointers, as described in
/// C++11 [expr.prim.lambda]p6. Note that in most cases, this should emit only a
/// single pointer conversion. In the event that the default calling convention
/// for free and member functions is different, it will emit both conventions.
static void addFunctionPointerConversions(Sema &S, SourceRange IntroducerRange,
                                          CXXRecordDecl *Class,
                                          CXXMethodDecl *CallOperator) {
  const FunctionProtoType *CallOpProto =
      CallOperator->getType()->castAs<FunctionProtoType>();

  repeatForLambdaConversionFunctionCallingConvs(
      S, *CallOpProto, [&](CallingConv CC) {
        QualType InvokerFunctionTy =
            S.getLambdaConversionFunctionResultType(CallOpProto, CC);
        addFunctionPointerConversion(S, IntroducerRange, Class, CallOperator,
                                     InvokerFunctionTy);
      });
}

/// Add a lambda's conversion to block pointer.
static void addBlockPointerConversion(Sema &S,
                                      SourceRange IntroducerRange,
                                      CXXRecordDecl *Class,
                                      CXXMethodDecl *CallOperator) {
  const FunctionProtoType *CallOpProto =
      CallOperator->getType()->castAs<FunctionProtoType>();
  QualType FunctionTy = S.getLambdaConversionFunctionResultType(
      CallOpProto, getLambdaConversionFunctionCallConv(S, CallOpProto));
  QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);

  FunctionProtoType::ExtProtoInfo ConversionEPI(
      S.Context.getDefaultCallingConvention(
          /*IsVariadic=*/false, /*IsCXXMethod=*/true));
  ConversionEPI.TypeQuals = Qualifiers();
  ConversionEPI.TypeQuals.addConst();
  QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, {}, ConversionEPI);

  SourceLocation Loc = IntroducerRange.getBegin();
  DeclarationName Name
    = S.Context.DeclarationNames.getCXXConversionFunctionName(
        S.Context.getCanonicalType(BlockPtrTy));
  DeclarationNameLoc NameLoc = DeclarationNameLoc::makeNamedTypeLoc(
      S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc));
  CXXConversionDecl *Conversion = CXXConversionDecl::Create(
      S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy,
      S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
      S.getCurFPFeatures().isFPConstrained(),
      /*isInline=*/true, ExplicitSpecifier(), ConstexprSpecKind::Unspecified,
      CallOperator->getBody()->getEndLoc());
  Conversion->setAccess(AS_public);
  Conversion->setImplicit(true);
  Class->addDecl(Conversion);
}

ExprResult Sema::BuildCaptureInit(const Capture &Cap,
                                  SourceLocation ImplicitCaptureLoc,
                                  bool IsOpenMPMapping) {
  // VLA captures don't have a stored initialization expression.
  if (Cap.isVLATypeCapture())
    return ExprResult();

  // An init-capture is initialized directly from its stored initializer.
  if (Cap.isInitCapture())
    return cast<VarDecl>(Cap.getVariable())->getInit();

  // For anything else, build an initialization expression. For an implicit
  // capture, the capture notionally happens at the capture-default, so use
  // that location here.
  SourceLocation Loc =
      ImplicitCaptureLoc.isValid() ? ImplicitCaptureLoc : Cap.getLocation();

  // C++11 [expr.prim.lambda]p21:
  //   When the lambda-expression is evaluated, the entities that
  //   are captured by copy are used to direct-initialize each
  //   corresponding non-static data member of the resulting closure
  //   object. (For array members, the array elements are
  //   direct-initialized in increasing subscript order.) These
  //   initializations are performed in the (unspecified) order in
  //   which the non-static data members are declared.

  // C++ [expr.prim.lambda]p12:
  //   An entity captured by a lambda-expression is odr-used (3.2) in
  //   the scope containing the lambda-expression.
  ExprResult Init;
  IdentifierInfo *Name = nullptr;
  if (Cap.isThisCapture()) {
    QualType ThisTy = getCurrentThisType();
    Expr *This = BuildCXXThisExpr(Loc, ThisTy, ImplicitCaptureLoc.isValid());
    if (Cap.isCopyCapture())
      Init = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
    else
      Init = This;
  } else {
    assert(Cap.isVariableCapture() && "unknown kind of capture");
    ValueDecl *Var = Cap.getVariable();
    Name = Var->getIdentifier();
    Init = BuildDeclarationNameExpr(
      CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var);
  }

  // In OpenMP, the capture kind doesn't actually describe how to capture:
  // variables are "mapped" onto the device in a process that does not formally
  // make a copy, even for a "copy capture".
  if (IsOpenMPMapping)
    return Init;

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

  Expr *InitExpr = Init.get();
  InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture(
      Name, Cap.getCaptureType(), Loc);
  InitializationKind InitKind =
      InitializationKind::CreateDirect(Loc, Loc, Loc);
  InitializationSequence InitSeq(*this, Entity, InitKind, InitExpr);
  return InitSeq.Perform(*this, Entity, InitKind, InitExpr);
}

ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body) {
  LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());

  if (LSI.CallOperator->hasAttr<SYCLKernelEntryPointAttr>())
    SYCL().CheckSYCLEntryPointFunctionDecl(LSI.CallOperator);

  ActOnFinishFunctionBody(LSI.CallOperator, Body);

  return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI);
}

static LambdaCaptureDefault
mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) {
  switch (ICS) {
  case CapturingScopeInfo::ImpCap_None:
    return LCD_None;
  case CapturingScopeInfo::ImpCap_LambdaByval:
    return LCD_ByCopy;
  case CapturingScopeInfo::ImpCap_CapturedRegion:
  case CapturingScopeInfo::ImpCap_LambdaByref:
    return LCD_ByRef;
  case CapturingScopeInfo::ImpCap_Block:
    llvm_unreachable("block capture in lambda");
  }
  llvm_unreachable("Unknown implicit capture style");
}

bool Sema::CaptureHasSideEffects(const Capture &From) {
  if (From.isInitCapture()) {
    Expr *Init = cast<VarDecl>(From.getVariable())->getInit();
    if (Init && Init->HasSideEffects(Context))
      return true;
  }

  if (!From.isCopyCapture())
    return false;

  const QualType T = From.isThisCapture()
                         ? getCurrentThisType()->getPointeeType()
                         : From.getCaptureType();

  if (T.isVolatileQualified())
    return true;

  const Type *BaseT = T->getBaseElementTypeUnsafe();
  if (const CXXRecordDecl *RD = BaseT->getAsCXXRecordDecl())
    return !RD->isCompleteDefinition() || !RD->hasTrivialCopyConstructor() ||
           !RD->hasTrivialDestructor();

  return false;
}

bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
                                       const Capture &From) {
  if (CaptureHasSideEffects(From))
    return false;

  if (From.isVLATypeCapture())
    return false;

  // FIXME: maybe we should warn on these if we can find a sensible diagnostic
  // message
  if (From.isInitCapture() &&
      From.getVariable()->isPlaceholderVar(getLangOpts()))
    return false;

  auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture);
  if (From.isThisCapture())
    diag << "'this'";
  else
    diag << From.getVariable();
  diag << From.isNonODRUsed();
  diag << FixItHint::CreateRemoval(CaptureRange);
  return true;
}

/// Create a field within the lambda class or captured statement record for the
/// given capture.
FieldDecl *Sema::BuildCaptureField(RecordDecl *RD,
                                   const sema::Capture &Capture) {
  SourceLocation Loc = Capture.getLocation();
  QualType FieldType = Capture.getCaptureType();

  TypeSourceInfo *TSI = nullptr;
  if (Capture.isVariableCapture()) {
    const auto *Var = dyn_cast_or_null<VarDecl>(Capture.getVariable());
    if (Var && Var->isInitCapture())
      TSI = Var->getTypeSourceInfo();
  }

  // FIXME: Should we really be doing this? A null TypeSourceInfo seems more
  // appropriate, at least for an implicit capture.
  if (!TSI)
    TSI = Context.getTrivialTypeSourceInfo(FieldType, Loc);

  // Build the non-static data member.
  FieldDecl *Field =
      FieldDecl::Create(Context, RD, /*StartLoc=*/Loc, /*IdLoc=*/Loc,
                        /*Id=*/nullptr, FieldType, TSI, /*BW=*/nullptr,
                        /*Mutable=*/false, ICIS_NoInit);
  // If the variable being captured has an invalid type, mark the class as
  // invalid as well.
  if (!FieldType->isDependentType()) {
    if (RequireCompleteSizedType(Loc, FieldType,
                                 diag::err_field_incomplete_or_sizeless)) {
      RD->setInvalidDecl();
      Field->setInvalidDecl();
    } else {
      NamedDecl *Def;
      FieldType->isIncompleteType(&Def);
      if (Def && Def->isInvalidDecl()) {
        RD->setInvalidDecl();
        Field->setInvalidDecl();
      }
    }
  }
  Field->setImplicit(true);
  Field->setAccess(AS_private);
  RD->addDecl(Field);

  if (Capture.isVLATypeCapture())
    Field->setCapturedVLAType(Capture.getCapturedVLAType());

  return Field;
}

ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
                                 LambdaScopeInfo *LSI) {
  // Collect information from the lambda scope.
  SmallVector<LambdaCapture, 4> Captures;
  SmallVector<Expr *, 4> CaptureInits;
  SourceLocation CaptureDefaultLoc = LSI->CaptureDefaultLoc;
  LambdaCaptureDefault CaptureDefault =
      mapImplicitCaptureStyle(LSI->ImpCaptureStyle);
  CXXRecordDecl *Class;
  CXXMethodDecl *CallOperator;
  SourceRange IntroducerRange;
  bool ExplicitParams;
  bool ExplicitResultType;
  CleanupInfo LambdaCleanup;
  bool ContainsUnexpandedParameterPack;
  bool IsGenericLambda;
  {
    CallOperator = LSI->CallOperator;
    Class = LSI->Lambda;
    IntroducerRange = LSI->IntroducerRange;
    ExplicitParams = LSI->ExplicitParams;
    ExplicitResultType = !LSI->HasImplicitReturnType;
    LambdaCleanup = LSI->Cleanup;
    ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
    IsGenericLambda = Class->isGenericLambda();

    CallOperator->setLexicalDeclContext(Class);
    Decl *TemplateOrNonTemplateCallOperatorDecl =
        CallOperator->getDescribedFunctionTemplate()
        ? CallOperator->getDescribedFunctionTemplate()
        : cast<Decl>(CallOperator);

    // FIXME: Is this really the best choice? Keeping the lexical decl context
    // set as CurContext seems more faithful to the source.
    TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);

    PopExpressionEvaluationContext();

    // True if the current capture has a used capture or default before it.
    bool CurHasPreviousCapture = CaptureDefault != LCD_None;
    SourceLocation PrevCaptureLoc = CurHasPreviousCapture ?
        CaptureDefaultLoc : IntroducerRange.getBegin();

    for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
      const Capture &From = LSI->Captures[I];

      if (From.isInvalid())
        return ExprError();

      assert(!From.isBlockCapture() && "Cannot capture __block variables");
      bool IsImplicit = I >= LSI->NumExplicitCaptures;
      SourceLocation ImplicitCaptureLoc =
          IsImplicit ? CaptureDefaultLoc : SourceLocation();

      // Use source ranges of explicit captures for fixits where available.
      SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I];

      // Warn about unused explicit captures.
      bool IsCaptureUsed = true;
      if (!CurContext->isDependentContext() && !IsImplicit &&
          !From.isODRUsed()) {
        // Initialized captures that are non-ODR used may not be eliminated.
        // FIXME: Where did the IsGenericLambda here come from?
        bool NonODRUsedInitCapture =
            IsGenericLambda && From.isNonODRUsed() && From.isInitCapture();
        if (!NonODRUsedInitCapture) {
          bool IsLast = (I + 1) == LSI->NumExplicitCaptures;
          SourceRange FixItRange;
          if (CaptureRange.isValid()) {
            if (!CurHasPreviousCapture && !IsLast) {
              // If there are no captures preceding this capture, remove the
              // following comma.
              FixItRange = SourceRange(CaptureRange.getBegin(),
                                       getLocForEndOfToken(CaptureRange.getEnd()));
            } else {
              // Otherwise, remove the comma since the last used capture.
              FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc),
                                       CaptureRange.getEnd());
            }
          }

          IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From);
        }
      }

      if (CaptureRange.isValid()) {
        CurHasPreviousCapture |= IsCaptureUsed;
        PrevCaptureLoc = CaptureRange.getEnd();
      }

      // Map the capture to our AST representation.
      LambdaCapture Capture = [&] {
        if (From.isThisCapture()) {
          // Capturing 'this' implicitly with a default of '[=]' is deprecated,
          // because it results in a reference capture. Don't warn prior to
          // C++2a; there's nothing that can be done about it before then.
          if (getLangOpts().CPlusPlus20 && IsImplicit &&
              CaptureDefault == LCD_ByCopy) {
            Diag(From.getLocation(), diag::warn_deprecated_this_capture);
            Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture)
                << FixItHint::CreateInsertion(
                       getLocForEndOfToken(CaptureDefaultLoc), ", this");
          }
          return LambdaCapture(From.getLocation(), IsImplicit,
                               From.isCopyCapture() ? LCK_StarThis : LCK_This);
        } else if (From.isVLATypeCapture()) {
          return LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType);
        } else {
          assert(From.isVariableCapture() && "unknown kind of capture");
          ValueDecl *Var = From.getVariable();
          LambdaCaptureKind Kind =
              From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef;
          return LambdaCapture(From.getLocation(), IsImplicit, Kind, Var,
                               From.getEllipsisLoc());
        }
      }();

      // Form the initializer for the capture field.
      ExprResult Init = BuildCaptureInit(From, ImplicitCaptureLoc);

      // FIXME: Skip this capture if the capture is not used, the initializer
      // has no side-effects, the type of the capture is trivial, and the
      // lambda is not externally visible.

      // Add a FieldDecl for the capture and form its initializer.
      BuildCaptureField(Class, From);
      Captures.push_back(Capture);
      CaptureInits.push_back(Init.get());

      if (LangOpts.CUDA)
        CUDA().CheckLambdaCapture(CallOperator, From);
    }

    Class->setCaptures(Context, Captures);

    // C++11 [expr.prim.lambda]p6:
    //   The closure type for a lambda-expression with no lambda-capture
    //   has a public non-virtual non-explicit const conversion function
    //   to pointer to function having the same parameter and return
    //   types as the closure type's function call operator.
    if (Captures.empty() && CaptureDefault == LCD_None)
      addFunctionPointerConversions(*this, IntroducerRange, Class,
                                    CallOperator);

    // Objective-C++:
    //   The closure type for a lambda-expression has a public non-virtual
    //   non-explicit const conversion function to a block pointer having the
    //   same parameter and return types as the closure type's function call
    //   operator.
    // FIXME: Fix generic lambda to block conversions.
    if (getLangOpts().Blocks && getLangOpts().ObjC && !IsGenericLambda)
      addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);

    // Finalize the lambda class.
    SmallVector<Decl*, 4> Fields(Class->fields());
    ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
                SourceLocation(), ParsedAttributesView());
    CheckCompletedCXXClass(nullptr, Class);
  }

  Cleanup.mergeFrom(LambdaCleanup);

  LambdaExpr *Lambda =
      LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault,
                         CaptureDefaultLoc, ExplicitParams, ExplicitResultType,
                         CaptureInits, EndLoc, ContainsUnexpandedParameterPack);

  // If the lambda expression's call operator is not explicitly marked constexpr
  // and is not dependent, analyze the call operator to infer
  // its constexpr-ness, suppressing diagnostics while doing so.
  if (getLangOpts().CPlusPlus17 && !CallOperator->isInvalidDecl() &&
      !CallOperator->isConstexpr() &&
      !isa<CoroutineBodyStmt>(CallOperator->getBody()) &&
      !Class->isDependentContext()) {
    CallOperator->setConstexprKind(
        CheckConstexprFunctionDefinition(CallOperator,
                                         CheckConstexprKind::CheckValid)
            ? ConstexprSpecKind::Constexpr
            : ConstexprSpecKind::Unspecified);
  }

  // Emit delayed shadowing warnings now that the full capture list is known.
  DiagnoseShadowingLambdaDecls(LSI);

  if (!CurContext->isDependentContext()) {
    switch (ExprEvalContexts.back().Context) {
    // C++11 [expr.prim.lambda]p2:
    //   A lambda-expression shall not appear in an unevaluated operand
    //   (Clause 5).
    case ExpressionEvaluationContext::Unevaluated:
    case ExpressionEvaluationContext::UnevaluatedList:
    case ExpressionEvaluationContext::UnevaluatedAbstract:
    // C++1y [expr.const]p2:
    //   A conditional-expression e is a core constant expression unless the
    //   evaluation of e, following the rules of the abstract machine, would
    //   evaluate [...] a lambda-expression.
    //
    // This is technically incorrect, there are some constant evaluated contexts
    // where this should be allowed.  We should probably fix this when DR1607 is
    // ratified, it lays out the exact set of conditions where we shouldn't
    // allow a lambda-expression.
    case ExpressionEvaluationContext::ConstantEvaluated:
    case ExpressionEvaluationContext::ImmediateFunctionContext:
      // We don't actually diagnose this case immediately, because we
      // could be within a context where we might find out later that
      // the expression is potentially evaluated (e.g., for typeid).
      ExprEvalContexts.back().Lambdas.push_back(Lambda);
      break;

    case ExpressionEvaluationContext::DiscardedStatement:
    case ExpressionEvaluationContext::PotentiallyEvaluated:
    case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
      break;
    }
    maybeAddDeclWithEffects(LSI->CallOperator);
  }

  return MaybeBindToTemporary(Lambda);
}

ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
                                               SourceLocation ConvLocation,
                                               CXXConversionDecl *Conv,
                                               Expr *Src) {
  // Make sure that the lambda call operator is marked used.
  CXXRecordDecl *Lambda = Conv->getParent();
  CXXMethodDecl *CallOperator
    = cast<CXXMethodDecl>(
        Lambda->lookup(
          Context.DeclarationNames.getCXXOperatorName(OO_Call)).front());
  CallOperator->setReferenced();
  CallOperator->markUsed(Context);

  ExprResult Init = PerformCopyInitialization(
      InitializedEntity::InitializeLambdaToBlock(ConvLocation, Src->getType()),
      CurrentLocation, Src);
  if (!Init.isInvalid())
    Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);

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

  // Create the new block to be returned.
  BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation);

  // Set the type information.
  Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo());
  Block->setIsVariadic(CallOperator->isVariadic());
  Block->setBlockMissingReturnType(false);

  // Add parameters.
  SmallVector<ParmVarDecl *, 4> BlockParams;
  for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
    ParmVarDecl *From = CallOperator->getParamDecl(I);
    BlockParams.push_back(ParmVarDecl::Create(
        Context, Block, From->getBeginLoc(), From->getLocation(),
        From->getIdentifier(), From->getType(), From->getTypeSourceInfo(),
        From->getStorageClass(),
        /*DefArg=*/nullptr));
  }
  Block->setParams(BlockParams);

  Block->setIsConversionFromLambda(true);

  // Add capture. The capture uses a fake variable, which doesn't correspond
  // to any actual memory location. However, the initializer copy-initializes
  // the lambda object.
  TypeSourceInfo *CapVarTSI =
      Context.getTrivialTypeSourceInfo(Src->getType());
  VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation,
                                    ConvLocation, nullptr,
                                    Src->getType(), CapVarTSI,
                                    SC_None);
  BlockDecl::Capture Capture(/*variable=*/CapVar, /*byRef=*/false,
                             /*nested=*/false, /*copy=*/Init.get());
  Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false);

  // Add a fake function body to the block. IR generation is responsible
  // for filling in the actual body, which cannot be expressed as an AST.
  Block->setBody(new (Context) CompoundStmt(ConvLocation));

  // Create the block literal expression.
  // TODO: Do we ever get here if we have unexpanded packs in the lambda???
  Expr *BuildBlock =
      new (Context) BlockExpr(Block, Conv->getConversionType(),
                              /*ContainsUnexpandedParameterPack=*/false);
  ExprCleanupObjects.push_back(Block);
  Cleanup.setExprNeedsCleanups(true);

  return BuildBlock;
}

static FunctionDecl *getPatternFunctionDecl(FunctionDecl *FD) {
  if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) {
    while (FD->getInstantiatedFromMemberFunction())
      FD = FD->getInstantiatedFromMemberFunction();
    return FD;
  }

  if (FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate)
    return FD->getInstantiatedFromDecl();

  FunctionTemplateDecl *FTD = FD->getPrimaryTemplate();
  if (!FTD)
    return nullptr;

  while (FTD->getInstantiatedFromMemberTemplate())
    FTD = FTD->getInstantiatedFromMemberTemplate();

  return FTD->getTemplatedDecl();
}

bool Sema::addInstantiatedCapturesToScope(
    FunctionDecl *Function, const FunctionDecl *PatternDecl,
    LocalInstantiationScope &Scope,
    const MultiLevelTemplateArgumentList &TemplateArgs) {
  const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
  const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();

  unsigned Instantiated = 0;

  // FIXME: This is a workaround for not having deferred lambda body
  // instantiation.
  // When transforming a lambda's body, if we encounter another call to a
  // nested lambda that contains a constraint expression, we add all of the
  // outer lambda's instantiated captures to the current instantiation scope to
  // facilitate constraint evaluation. However, these captures don't appear in
  // the CXXRecordDecl until after the lambda expression is rebuilt, so we
  // pull them out from the corresponding LSI.
  LambdaScopeInfo *InstantiatingScope = nullptr;
  if (LambdaPattern->capture_size() && !LambdaClass->capture_size()) {
    for (FunctionScopeInfo *Scope : llvm::reverse(FunctionScopes)) {
      auto *LSI = dyn_cast<LambdaScopeInfo>(Scope);
      if (!LSI || getPatternFunctionDecl(LSI->CallOperator) != PatternDecl)
        continue;
      InstantiatingScope = LSI;
      break;
    }
    assert(InstantiatingScope);
  }

  auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
                              unsigned Index) {
    ValueDecl *CapturedVar =
        InstantiatingScope ? InstantiatingScope->Captures[Index].getVariable()
                           : LambdaClass->getCapture(Index)->getCapturedVar();
    assert(CapturedVar->isInitCapture());
    Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
  };

  for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
    if (!CapturePattern.capturesVariable()) {
      Instantiated++;
      continue;
    }
    ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();

    if (!CapturedPattern->isInitCapture()) {
      Instantiated++;
      continue;
    }

    if (!CapturedPattern->isParameterPack()) {
      AddSingleCapture(CapturedPattern, Instantiated++);
    } else {
      Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
      SemaRef.collectUnexpandedParameterPacks(
          dyn_cast<VarDecl>(CapturedPattern)->getInit(), Unexpanded);
      auto NumArgumentsInExpansion =
          getNumArgumentsInExpansionFromUnexpanded(Unexpanded, TemplateArgs);
      if (!NumArgumentsInExpansion)
        continue;
      for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
        AddSingleCapture(CapturedPattern, Instantiated++);
    }
  }
  return false;
}

Sema::LambdaScopeForCallOperatorInstantiationRAII::
    LambdaScopeForCallOperatorInstantiationRAII(
        Sema &SemaRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
        LocalInstantiationScope &Scope, bool ShouldAddDeclsFromParentScope)
    : FunctionScopeRAII(SemaRef) {
  if (!isLambdaCallOperator(FD)) {
    FunctionScopeRAII::disable();
    return;
  }

  SemaRef.RebuildLambdaScopeInfo(cast<CXXMethodDecl>(FD));

  FunctionDecl *FDPattern = getPatternFunctionDecl(FD);
  if (!FDPattern)
    return;

  if (!ShouldAddDeclsFromParentScope)
    return;

  llvm::SmallVector<std::pair<FunctionDecl *, FunctionDecl *>, 4>
      InstantiationAndPatterns;
  while (FDPattern && FD) {
    InstantiationAndPatterns.emplace_back(FDPattern, FD);

    FDPattern =
        dyn_cast<FunctionDecl>(getLambdaAwareParentOfDeclContext(FDPattern));
    FD = dyn_cast<FunctionDecl>(getLambdaAwareParentOfDeclContext(FD));
  }

  // Add instantiated parameters and local vars to scopes, starting from the
  // outermost lambda to the innermost lambda. This ordering ensures that
  // the outer instantiations can be found when referenced from within inner
  // lambdas.
  //
  //   auto L = [](auto... x) {
  //     return [](decltype(x)... y) { }; // Instantiating y needs x
  //   };
  //

  for (auto [FDPattern, FD] : llvm::reverse(InstantiationAndPatterns)) {
    SemaRef.addInstantiatedParametersToScope(FD, FDPattern, Scope, MLTAL);
    SemaRef.addInstantiatedLocalVarsToScope(FD, FDPattern, Scope);

    if (isLambdaCallOperator(FD))
      SemaRef.addInstantiatedCapturesToScope(FD, FDPattern, Scope, MLTAL);
  }
}
