//===--- 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/DeclSpec.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLambda.h"
#include "llvm/ADT/STLExtras.h"
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 Optional<unsigned> 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 Optional<unsigned>
getStackIndexOfNearestEnclosingCaptureReadyLambda(
    ArrayRef<const clang::sema::FunctionScopeInfo *> FunctionScopes,
    VarDecl *VarToCapture) {
  // Label failure to capture.
  const Optional<unsigned> NoLambdaIsCaptureReady;

  // 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 Optional<unsigned> 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.

Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
    ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes,
    VarDecl *VarToCapture, Sema &S) {

  const Optional<unsigned> NoLambdaIsCaptureCapable;

  const Optional<unsigned> OptionalStackIndex =
      getStackIndexOfNearestEnclosingCaptureReadyLambda(FunctionScopes,
                                                        VarToCapture);
  if (!OptionalStackIndex)
    return NoLambdaIsCaptureCapable;

  const unsigned IndexOfCaptureReadyLambda = OptionalStackIndex.getValue();
  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(),
                              clang::Sema::TryCapture_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,
                                             bool KnownDependent,
                                             LambdaCaptureDefault CaptureDefault) {
  DeclContext *DC = CurContext;
  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
    DC = DC->getParent();
  bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
                                                               *this);
  // Start constructing the lambda class.
  CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info,
                                                     IntroducerRange.getBegin(),
                                                     KnownDependent,
                                                     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,
    StaticDataMember,
    InlineVariable,
    VariableTemplate
  } Kind = Normal;

  // 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.
  if (ManglingContextDecl) {
    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) {
      if (const DeclContext *LexicalDC
          = Param->getDeclContext()->getLexicalParent())
        if (LexicalDC->isRecord())
          Kind = DefaultArgument;
    } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {
      if (Var->getDeclContext()->isRecord())
        Kind = StaticDataMember;
      else if (Var->getMostRecentDecl()->isInline())
        Kind = InlineVariable;
      else if (Var->getDescribedVarTemplate())
        Kind = VariableTemplate;
      else if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
        if (!VTS->isExplicitSpecialization())
          Kind = VariableTemplate;
      }
    } else if (isa<FieldDecl>(ManglingContextDecl)) {
      Kind = DataMember;
    }
  }

  // Itanium ABI [5.1.7]:
  //   In the following contexts [...] the one-definition rule requires closure
  //   types in different translation units to "correspond":
  bool IsInNonspecializedTemplate =
      inTemplateInstantiation() || CurContext->isDependentContext();
  switch (Kind) {
  case Normal: {
    //  -- the bodies of non-exported nonspecialized template functions
    //  -- the bodies of inline 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 StaticDataMember:
    //  -- the initializers of nonspecialized static members of template classes
    if (!IsInNonspecializedTemplate)
      return std::make_tuple(nullptr, ManglingContextDecl);
    // Fall through to get the current context.
    LLVM_FALLTHROUGH;

  case DataMember:
    //  -- the in-class initializers of class members
  case DefaultArgument:
    //  -- default arguments appearing in class definitions
  case InlineVariable:
    //  -- the initializers of inline variables
  case VariableTemplate:
    //  -- the initializers of templated variables
    return std::make_tuple(
        &Context.getManglingNumberContext(ASTContext::NeedExtraManglingDecl,
                                          ManglingContextDecl),
        ManglingContextDecl);
  }

  llvm_unreachable("unexpected context");
}

CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
                                           SourceRange IntroducerRange,
                                           TypeSourceInfo *MethodTypeInfo,
                                           SourceLocation EndLoc,
                                           ArrayRef<ParmVarDecl *> Params,
                                           ConstexprSpecKind ConstexprKind,
                                           Expr *TrailingRequiresClause) {
  QualType MethodType = MethodTypeInfo->getType();
  TemplateParameterList *TemplateParams =
      getGenericLambdaTemplateParameterList(getCurLambda(), *this);
  // 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 = SubstAutoType(Result, Context.DependentTy);
      MethodType = Context.getFunctionType(Result, FPT->getParamTypes(),
                                           FPT->getExtProtoInfo());
    }
  }

  // C++11 [expr.prim.lambda]p5:
  //   The closure type for a lambda-expression has a public inline function
  //   call operator (13.5.4) 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);
  CXXMethodDecl *Method = CXXMethodDecl::Create(
      Context, Class, EndLoc,
      DeclarationNameInfo(MethodName, IntroducerRange.getBegin(),
                          MethodNameLoc),
      MethodType, MethodTypeInfo, SC_None,
      /*isInline=*/true, ConstexprKind, EndLoc, TrailingRequiresClause);
  Method->setAccess(AS_public);
  if (!TemplateParams)
    Class->addDecl(Method);

  // Temporarily set the lexical declaration context to the current
  // context, so that the Scope stack matches the lexical nesting.
  Method->setLexicalDeclContext(CurContext);
  // Create a function template if we have a template parameter list
  FunctionTemplateDecl *const TemplateMethod = TemplateParams ?
            FunctionTemplateDecl::Create(Context, Class,
                                         Method->getLocation(), MethodName,
                                         TemplateParams,
                                         Method) : nullptr;
  if (TemplateMethod) {
    TemplateMethod->setAccess(AS_public);
    Method->setDescribedFunctionTemplate(TemplateMethod);
    Class->addDecl(TemplateMethod);
    TemplateMethod->setLexicalDeclContext(CurContext);
  }

  // Add parameters.
  if (!Params.empty()) {
    Method->setParams(Params);
    CheckParmsForFunctionDef(Params,
                             /*CheckParameterNames=*/false);

    for (auto P : Method->parameters())
      P->setOwningFunction(Method);
  }

  return Method;
}

void Sema::handleLambdaNumbering(
    CXXRecordDecl *Class, CXXMethodDecl *Method,
    Optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling) {
  if (Mangling) {
    bool HasKnownInternalLinkage;
    unsigned ManglingNumber, DeviceManglingNumber;
    Decl *ManglingContextDecl;
    std::tie(HasKnownInternalLinkage, ManglingNumber, DeviceManglingNumber,
             ManglingContextDecl) = Mangling.getValue();
    Class->setLambdaMangling(ManglingNumber, ManglingContextDecl,
                             HasKnownInternalLinkage);
    Class->setDeviceLambdaManglingNumber(DeviceManglingNumber);
    return;
  }

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

  MangleNumberingContext *MCtx;
  Decl *ManglingContextDecl;
  std::tie(MCtx, ManglingContextDecl) =
      getCurrentMangleNumberContext(Class->getDeclContext());
  bool HasKnownInternalLinkage = false;
  if (!MCtx && getLangOpts().CUDA) {
    // 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.
    MCtx = getMangleNumberingContext(Class, ManglingContextDecl);
    assert(MCtx && "Retrieving mangle numbering context failed!");
    HasKnownInternalLinkage = true;
  }
  if (MCtx) {
    unsigned ManglingNumber = MCtx->getManglingNumber(Method);
    Class->setLambdaMangling(ManglingNumber, ManglingContextDecl,
                             HasKnownInternalLinkage);
    Class->setDeviceLambdaManglingNumber(MCtx->getDeviceManglingNumber(Method));
  }
}

void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
                                        CXXMethodDecl *CallOperator,
                                        SourceRange IntroducerRange,
                                        LambdaCaptureDefault CaptureDefault,
                                        SourceLocation CaptureDefaultLoc,
                                        bool ExplicitParams,
                                        bool ExplicitResultType,
                                        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;

  if (ExplicitResultType) {
    LSI->ReturnType = CallOperator->getReturnType();

    if (!LSI->ReturnType->isDependentType() &&
        !LSI->ReturnType->isVoidType()) {
      if (RequireCompleteType(CallOperator->getBeginLoc(), LSI->ReturnType,
                              diag::err_lambda_incomplete_result)) {
        // Do nothing.
      }
    }
  } else {
    LSI->HasImplicitReturnType = true;
  }
}

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

void Sema::ActOnLambdaExplicitTemplateParameterList(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;
}

void Sema::addLambdaParameters(
    ArrayRef<LambdaIntroducer::LambdaCapture> Captures,
    CXXMethodDecl *CallOperator, Scope *CurScope) {
  // Introduce our parameters into the function scope
  for (unsigned p = 0, NumParams = CallOperator->getNumParams();
       p < NumParams; ++p) {
    ParmVarDecl *Param = CallOperator->getParamDecl(p);

    // If this has an identifier, add it to the scope stack.
    if (CurScope && Param->getIdentifier()) {
      bool Error = false;
      // Resolution of CWG 2211 in C++17 renders shadowing ill-formed, but we
      // retroactively apply it.
      for (const auto &Capture : Captures) {
        if (Capture.Id == Param->getIdentifier()) {
          Error = true;
          Diag(Param->getLocation(), diag::err_parameter_shadow_capture);
          Diag(Capture.Loc, diag::note_var_explicitly_captured_here)
              << Capture.Id << true;
        }
      }
      if (!Error)
        CheckShadow(CurScope, Param);

      PushOnScopeChains(Param, CurScope);
    }
  }
}

/// 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_RValue,
                                 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(Ctx);
      auto BlockNullability = CSI.ReturnType->getNullability(Ctx);
      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,
    Optional<unsigned> 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) {
  // 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, CurContext, 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) {
  assert(Var->isInitCapture() && "init capture flag should be set");
  LSI->addCapture(Var, /*isBlock*/false, Var->getType()->isReferenceType(),
                  /*isNested*/false, Var->getLocation(), SourceLocation(),
                  Var->getType(), /*Invalid*/false);
}

void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                                        Declarator &ParamInfo,
                                        Scope *CurScope) {
  LambdaScopeInfo *const LSI = getCurLambda();
  assert(LSI && "LambdaScopeInfo should be on stack!");

  // Determine if we're within a context where we know that the lambda will
  // be dependent, because there are template parameters in scope.
  bool KnownDependent;
  if (LSI->NumExplicitTemplateParams > 0) {
    auto *TemplateParamScope = CurScope->getTemplateParamParent();
    assert(TemplateParamScope &&
           "Lambda with explicit template param list should establish a "
           "template param scope");
    assert(TemplateParamScope->getParent());
    KnownDependent = TemplateParamScope->getParent()
                                       ->getTemplateParamParent() != nullptr;
  } else {
    KnownDependent = CurScope->getTemplateParamParent() != nullptr;
  }

  // Determine the signature of the call operator.
  TypeSourceInfo *MethodTyInfo;
  bool ExplicitParams = true;
  bool ExplicitResultType = true;
  bool ContainsUnexpandedParameterPack = false;
  SourceLocation EndLoc;
  SmallVector<ParmVarDecl *, 8> Params;
  if (ParamInfo.getNumTypeObjects() == 0) {
    // 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(Context.getDefaultCallingConvention(
        /*IsVariadic=*/false, /*IsCXXMethod=*/true));
    EPI.HasTrailingReturn = true;
    EPI.TypeQuals.addConst();
    LangAS AS = 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 =
        getLangOpts().CPlusPlus14 ? Context.getAutoDeductType()
                                  : Context.DependentTy;
    QualType MethodTy =
        Context.getFunctionType(DefaultTypeForNoTrailingReturn, None, EPI);
    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
    ExplicitParams = false;
    ExplicitResultType = false;
    EndLoc = Intro.Range.getEnd();
  } else {
    assert(ParamInfo.isFunctionDeclarator() &&
           "lambda-declarator is a function");
    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();

    // C++11 [expr.prim.lambda]p5:
    //   This function call operator is declared const (9.3.1) if and only if
    //   the lambda-expression's parameter-declaration-clause is not followed
    //   by mutable. It is neither virtual nor declared volatile. [...]
    if (!FTI.hasMutableQualifier()) {
      FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const,
                                                    SourceLocation());
    }

    MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
    assert(MethodTyInfo && "no type from lambda-declarator");
    EndLoc = ParamInfo.getSourceRange().getEnd();

    ExplicitResultType = FTI.hasTrailingReturnType();

    if (FTIHasNonVoidParameters(FTI)) {
      Params.reserve(FTI.NumParams);
      for (unsigned i = 0, e = FTI.NumParams; i != e; ++i)
        Params.push_back(cast<ParmVarDecl>(FTI.Params[i].Param));
    }

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

  CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo,
                                                 KnownDependent, Intro.Default);
  CXXMethodDecl *Method =
      startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params,
                            ParamInfo.getDeclSpec().getConstexprSpecifier(),
                            ParamInfo.getTrailingRequiresClause());
  if (ExplicitParams)
    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);

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

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

  // Number the lambda for linkage purposes if necessary.
  handleLambdaNumbering(Class, Method);

  // Introduce the function call operator as the current declaration context.
  PushDeclContext(CurScope, Method);

  // Build the lambda scope.
  buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc,
                   ExplicitParams, ExplicitResultType, !Method->isConst());

  // 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 && !Class->getParent()->isFunctionOrMethod() &&
      (getCurrentThisType().isNull() ||
       CheckCXXThisCapture(SourceLocation(), /*Explicit*/true,
                           /*BuildAndDiagnose*/false)))
    Diag(Intro.DefaultLoc, diag::err_capture_default_non_local);

  // Distinct capture names, for diagnostics.
  llvm::SmallSet<IdentifierInfo*, 8> 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++2a [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;

    VarDecl *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());
      // C++1y [expr.prim.lambda]p11:
      //   An init-capture behaves as if it declares and explicitly
      //   captures a variable [...] whose declarative region is the
      //   lambda-expression's compound-statement
      if (Var)
        PushOnScopeChains(Var, CurScope, 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;
      }

      Var = R.getAsSingle<VarDecl>();
      if (Var && DiagnoseUseOfDecl(Var, C->Loc))
        continue;
    }

    // C++11 [expr.prim.lambda]p8:
    //   An identifier or this shall not appear more than once in a
    //   lambda-capture.
    if (!CaptureNames.insert(C->Id).second) {
      if (Var && LSI->isCaptured(Var)) {
        Diag(C->Loc, diag::err_capture_more_than_once)
            << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
            << FixItHint::CreateRemoval(
                   SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
      } else
        // Previous capture captured something different (one or both was
        // an init-cpature): no fixit.
        Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
      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;
    }

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

    if (!Var->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, Var);
    } else {
      TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
                                                   TryCapture_ExplicitByVal;
      tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
    }
    if (!LSI->Captures.empty())
      LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
  }
  finishLambdaExplicitCaptures(LSI);

  LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;

  // Add lambda parameters into scope.
  addLambdaParameters(Intro.Captures, Method, CurScope);

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

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), std::unique(std::begin(Convs), std::end(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, None, 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,
      /*isInline=*/true, ExplicitSpecifier(),
      S.getLangOpts().CPlusPlus17 ? ConstexprSpecKind::Constexpr
                                  : ConstexprSpecKind::Unspecified,
      CallOperator->getBody()->getEndLoc());
  Conversion->setAccess(AS_public);
  Conversion->setImplicit(true);

  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);
  // Add a non-static member function that will be the result of
  // the conversion with a certain unique ID.
  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,
      /*isInline=*/true, ConstexprSpecKind::Unspecified,
      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, None, 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),
      /*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 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");
    VarDecl *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,
                                 Scope *CurScope) {
  LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
  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 = 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;

  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()) {
    auto *Var = Capture.getVariable();
    if (Var->isInitCapture())
      TSI = Capture.getVariable()->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");
          VarDecl *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)
        CUDACheckLambdaCapture(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 we are not in a dependent context, 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->getDeclContext()->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:
      // 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;
    }
  }

  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(),
                                                 /*NRVO=*/false),
      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.
  Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType());
  ExprCleanupObjects.push_back(Block);
  Cleanup.setExprNeedsCleanups(true);

  return BuildBlock;
}
