cor3ntin updated this revision to Diff 422282.
cor3ntin added a comment.

After offline discussion with Aaron, we decided that "can not appear here" was a
sufficient diagnostic, so I have implemented that.
A better solution would be to track which captures fail, and collect the 
diagnostics
to emit them after the parameter list, but this seem to add a lot of complexity
for something few people are likely to encounter.

- Add tests
- A diagnostic for use before capture  could be emited twice when parsing

a template parameter list, this was fixed.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119136/new/

https://reviews.llvm.org/D119136

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Scope.h
  clang/include/clang/Sema/ScopeInfo.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Sema/Scope.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaCXXScopeSpec.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaLambda.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
  clang/test/SemaCXX/lambda-capture-type-deduction.cpp
  clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1356,7 +1356,7 @@
     <tr>
       <td>Change scope of lambda trailing-return-type</td>
       <td><a href="https://wg21.link/P2036R3";>P2036R3</a></td>
-      <td class="none" align="center">No</td>
+      <td class="unreleased" align="center">Clang 15</td>
     </tr>
     <tr>
       <td>Multidimensional subscript operator</td>
Index: clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
===================================================================
--- clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -95,7 +95,7 @@
 #ifdef AVOID
   auto l4 = [var = param] (int param) { ; }; // no warning
 #else
-  auto l4 = [var = param] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+  auto l4 = [var = param](int param) { ; }; // expected-warning 2{{declaration shadows a local variable}}
 #endif
 
   // Make sure that inner lambdas work as well.
Index: clang/test/SemaCXX/lambda-capture-type-deduction.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/lambda-capture-type-deduction.cpp
@@ -0,0 +1,156 @@
+// RUN: %clang_cc1 -std=c++2b -verify -fsyntax-only %s
+
+template <typename T, typename U>
+constexpr bool is_same = false;
+
+template <typename T>
+constexpr bool is_same<T, T> = true;
+
+void f() {
+
+  int y;
+
+  static_assert(is_same<const int &,
+                        decltype([x = 1] -> decltype((x)) { return x; }())>);
+
+  static_assert(is_same<int &,
+                        decltype([x = 1] mutable -> decltype((x)) { return x; }())>);
+
+  static_assert(is_same<const int &,
+                        decltype([=] -> decltype((y)) { return y; }())>);
+
+  static_assert(is_same<int &,
+                        decltype([=] mutable -> decltype((y)) { return y; }())>);
+
+  static_assert(is_same<const int &,
+                        decltype([=] -> decltype((y)) { return y; }())>);
+
+  static_assert(is_same<int &,
+                        decltype([=] mutable -> decltype((y)) { return y; }())>);
+
+  auto ref = [&x = y](
+                 decltype([&](decltype(x)) { return 0; }) y) {
+    return x;
+  };
+}
+
+void test_noexcept() {
+
+  int y;
+
+  static_assert(noexcept([x = 1] noexcept(is_same<const int &, decltype((x))>) {}()));
+  static_assert(noexcept([x = 1] mutable noexcept(is_same<int &, decltype((x))>) {}()));
+  static_assert(noexcept([y] noexcept(is_same<const int &, decltype((y))>) {}()));
+  static_assert(noexcept([y] mutable noexcept(is_same<int &, decltype((y))>) {}()));
+  static_assert(noexcept([=] noexcept(is_same<const int &, decltype((y))>) {}()));
+  static_assert(noexcept([=] mutable noexcept(is_same<int &, decltype((y))>) {}()));
+  static_assert(noexcept([&] noexcept(is_same<int &, decltype((y))>) {}()));
+  static_assert(noexcept([&] mutable noexcept(is_same<int &, decltype((y))>) {}()));
+
+  static_assert(noexcept([&] mutable noexcept(!is_same<int &, decltype((y))>) {}())); //expected-error {{static_assert failed due}}
+}
+
+void test_requires() {
+
+  int x;
+
+  [x = 1]() requires is_same<const int &, decltype((x))> {}
+  ();
+  [x = 1]() mutable requires is_same<int &, decltype((x))> {}
+  ();
+  [x]() requires is_same<const int &, decltype((x))> {}
+  ();
+  [x]() mutable requires is_same<int &, decltype((x))> {}
+  ();
+  [=]() requires is_same<const int &, decltype((x))> {}
+  ();
+  [=]() mutable requires is_same<int &, decltype((x))> {}
+  ();
+  [&]() requires is_same<int &, decltype((x))> {}
+  ();
+  [&]() mutable requires is_same<int &, decltype((x))> {}
+  ();
+  [&x]() requires is_same<int &, decltype((x))> {}
+  ();
+  [&x]() mutable requires is_same<int &, decltype((x))> {}
+  ();
+
+  [x = 1]() requires is_same<int &, decltype((x))> {} (); //expected-error {{no matching function for call to object of type}} \
+                                                           // expected-note {{candidate function not viable}} \
+                                                           // expected-note {{'is_same<int &, decltype((x))>' evaluated to false}}
+  [x = 1]() mutable requires is_same<const int &, decltype((x))> {} (); // expected-error {{no matching function for call to object of type}} \
+                                                                     // expected-note {{candidate function not viable}} \
+                                                                     // expected-note {{'is_same<const int &, decltype((x))>' evaluated to false}}
+}
+
+void err() {
+  int y, z;                // expected-note 2{{declared here}}
+  auto implicit_tpl = [=]( // expected-note {{variable 'y' is captured here}}
+                          decltype(
+                              [&]<decltype(y)> { return 0; }) y) { //expected-error{{captured variable 'y' cannot appear here}}
+    return y;
+  };
+
+  auto init_tpl = [x = 1](                                          // expected-note{{explicitly captured here}}
+                      decltype([&]<decltype(x)> { return 0; }) y) { // expected-error {{captured variable 'x' cannot appear here}}
+    return x;
+  };
+
+  auto implicit = [=]( // expected-note {{variable 'z' is captured here}}
+                      decltype(
+                          [&](decltype(z)) { return 0; }) z) { //expected-error{{captured variable 'z' cannot appear here}}
+    return z;
+  };
+
+  auto init = [x = 1](                                          // expected-note{{explicitly captured here}}
+                  decltype([&](decltype(x)) { return 0; }) y) { // expected-error {{captured variable 'x' cannot appear here}}
+    return x;
+  };
+
+  auto use_before_params = [x = 1]<typename T>  // expected-note {{variable 'x' is explicitly captured here}}
+  requires(is_same<const int &, decltype((x))>) // expected-error {{captured variable 'x' cannot appear here}}
+  {};
+
+  auto use_before_params2 = [x = 1]<typename T =  decltype((x))>  // expected-note {{variable 'x' is explicitly captured here}} \
+                                                                 // expected-error {{captured variable 'x' cannot appear here}}
+  {};
+
+
+}
+
+void nested() {
+  int x, y, z; //expected-note {{'x' declared here}} expected-note {{'z' declared here}}
+  (void)[&](
+      decltype([&](
+                   decltype([=]( // expected-note {{variable 'x' is captured here}}
+                                decltype([&](
+                                             decltype([&](decltype(x)) {}) // expected-error{{captured variable 'x' cannot appear here}}
+                                         ) {})) {})) {})){};
+
+  (void)[&](
+      decltype([&](
+                   decltype([&](
+                                decltype([&](
+                                             decltype([&](decltype(y)) {})) {})) {})) {})){};
+
+  (void)[=](
+      decltype([=](
+                   decltype([=](
+                                decltype([=](                              // expected-note {{variable 'z' is captured here}}
+                                             decltype([&]<decltype(z)> {}) // expected-error{{captured variable 'z' cannot appear here}}
+                                         ) {})) {})) {})){};
+}
+
+template <typename T, typename U>
+void dependent(U&& u) {
+  [&]() requires is_same<decltype(u), T> {}();
+}
+
+void test_dependent() {
+  int v   = 0;
+  int & r = v;
+  const int & cr = v;
+  dependent<int&>(v);
+  dependent<int&>(r);
+  dependent<const int&>(cr);
+}
Index: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
===================================================================
--- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
+++ clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
@@ -12,16 +12,16 @@
   using T = double&;
 };
 
-// Within the lambda-expression's compound-statement,
-// the identifier in the init-capture hides any declaration
-// of the same name in scopes enclosing the lambda-expression.
+// Within the lambda-expression the identifier in the init-capture
+// hides any declaration of the same name in scopes enclosing
+// the lambda-expression.
 void hiding() {
   char c;
   (void) [c("foo")] {
     static_assert(sizeof(c) == sizeof(const char*), "");
   };
-  (void) [c("bar")] () -> decltype(c) { // outer c, not init-capture
-    return "baz"; // expected-error {{cannot initialize}}
+  (void)[c("bar")]()->decltype(c) { // inner c
+    return "baz";
   };
 }
 
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -13076,7 +13076,8 @@
         }
         VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl(
             OldVD->getLocation(), InitQualType, NewC.EllipsisLoc,
-            OldVD->getIdentifier(), OldVD->getInitStyle(), Init.get());
+            OldVD->getIdentifier(), OldVD->getInitStyle(), Init.get(),
+            getSema().CurContext);
         if (!NewVD) {
           Invalid = true;
           break;
Index: clang/lib/Sema/SemaLambda.cpp
===================================================================
--- clang/lib/Sema/SemaLambda.cpp
+++ clang/lib/Sema/SemaLambda.cpp
@@ -245,8 +245,9 @@
   DeclContext *DC = CurContext;
   while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
     DC = DC->getParent();
-  bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
-                                                               *this);
+
+  bool IsGenericLambda =
+      Info && getGenericLambdaTemplateParameterList(getCurLambda(), *this);
   // Start constructing the lambda class.
   CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(
       Context, DC, Info, IntroducerRange.getBegin(), LambdaDependencyKind,
@@ -354,16 +355,13 @@
   llvm_unreachable("unexpected context");
 }
 
-CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
-                                           SourceRange IntroducerRange,
-                                           TypeSourceInfo *MethodTypeInfo,
-                                           SourceLocation EndLoc,
-                                           ArrayRef<ParmVarDecl *> Params,
-                                           ConstexprSpecKind ConstexprKind,
-                                           Expr *TrailingRequiresClause) {
+static QualType
+buildTypeForLambdaCallOperator(Sema &S, clang::CXXRecordDecl *Class,
+                               TemplateParameterList *TemplateParams,
+                               TypeSourceInfo *MethodTypeInfo) {
+  assert(MethodTypeInfo && "expected a non null type");
+
   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.
@@ -371,19 +369,43 @@
     const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
     QualType Result = FPT->getReturnType();
     if (Result->isUndeducedType()) {
-      Result = SubstAutoTypeDependent(Result);
-      MethodType = Context.getFunctionType(Result, FPT->getParamTypes(),
-                                           FPT->getExtProtoInfo());
+      Result = S.SubstAutoTypeDependent(Result);
+      MethodType = S.Context.getFunctionType(Result, FPT->getParamTypes(),
+                                             FPT->getExtProtoInfo());
     }
   }
+  return MethodType;
+}
+
+/// Start the definition of a lambda expression.
+/// In this overload, we do not know the type yet
+CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
+                                           SourceRange IntroducerRange,
+                                           TypeSourceInfo *MethodTypeInfo,
+                                           SourceLocation EndLoc,
+                                           ArrayRef<ParmVarDecl *> Params,
+                                           ConstexprSpecKind ConstexprKind,
+                                           Expr *TrailingRequiresClause) {
+
+  LambdaScopeInfo *LSI = getCurLambda();
+
+  TemplateParameterList *TemplateParams =
+      getGenericLambdaTemplateParameterList(LSI, *this);
+
+  // At this point, we may not know the type of the lambda, if we have not
+  // parsed a trailing return type yet
+  QualType MethodType = MethodTypeInfo
+                            ? buildTypeForLambdaCallOperator(
+                                  *this, Class, TemplateParams, MethodTypeInfo)
+                            : QualType();
 
   // 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
+  //   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);
+  DeclarationName MethodName =
+      Context.DeclarationNames.getCXXOperatorName(OO_Call);
   DeclarationNameLoc MethodNameLoc =
       DeclarationNameLoc::makeCXXOperatorNameLoc(IntroducerRange);
   CXXMethodDecl *Method = CXXMethodDecl::Create(
@@ -400,11 +422,11 @@
   // 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;
+  FunctionTemplateDecl *const TemplateMethod =
+      TemplateParams
+          ? FunctionTemplateDecl::Create(Context, Class, Method->getLocation(),
+                                         MethodName, TemplateParams, Method)
+          : nullptr;
   if (TemplateMethod) {
     TemplateMethod->setAccess(AS_public);
     Method->setDescribedFunctionTemplate(TemplateMethod);
@@ -480,14 +502,27 @@
   }
 }
 
-void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
-                                        CXXMethodDecl *CallOperator,
-                                        SourceRange IntroducerRange,
-                                        LambdaCaptureDefault CaptureDefault,
-                                        SourceLocation CaptureDefaultLoc,
-                                        bool ExplicitParams,
-                                        bool ExplicitResultType,
-                                        bool Mutable) {
+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;
+  }
+}
+
+static void buildLambdaScopeCaptures(LambdaScopeInfo *LSI,
+                                     CXXMethodDecl *CallOperator,
+                                     SourceRange IntroducerRange,
+                                     LambdaCaptureDefault CaptureDefault,
+                                     SourceLocation CaptureDefaultLoc,
+                                     bool ExplicitParams, bool Mutable) {
   LSI->CallOperator = CallOperator;
   CXXRecordDecl *LambdaClass = CallOperator->getParent();
   LSI->Lambda = LambdaClass;
@@ -499,30 +534,27 @@
   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::buildLambdaScope(LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
+                            SourceRange IntroducerRange,
+                            LambdaCaptureDefault CaptureDefault,
+                            SourceLocation CaptureDefaultLoc,
+                            bool ExplicitParams, bool ExplicitResultType,
+                            bool Mutable) {
+  buildLambdaScopeCaptures(LSI, CallOperator, IntroducerRange, CaptureDefault,
+                           CaptureDefaultLoc, ExplicitParams, Mutable);
+  buildLambdaScopeReturnType(*this, LSI, CallOperator, ExplicitResultType);
 }
 
 void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
   LSI->finishedExplicitCaptures();
 }
 
-void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc,
-                                                    ArrayRef<NamedDecl *> TParams,
-                                                    SourceLocation RAngleLoc,
-                                                    ExprResult RequiresClause) {
+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 &&
@@ -538,35 +570,6 @@
   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.
 ///
@@ -853,11 +856,9 @@
   return DeducedType;
 }
 
-VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
-                                              QualType InitCaptureType,
-                                              SourceLocation EllipsisLoc,
-                                              IdentifierInfo *Id,
-                                              unsigned InitStyle, Expr *Init) {
+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);
@@ -868,8 +869,8 @@
   // 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);
+  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.
@@ -888,12 +889,107 @@
                   Var->getType(), /*Invalid*/false);
 }
 
-void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
-                                        Declarator &ParamInfo,
-                                        Scope *CurScope) {
+// 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, None, EPI);
+  return S.Context.getTrivialTypeSourceInfo(MethodTy, Loc);
+}
+
+static TypeSourceInfo *getLambdaType(Sema &S, LambdaIntroducer &Intro,
+                                     Declarator &ParamInfo, Scope *CurScope,
+                                     SourceLocation Loc,
+                                     bool &ExplicitResultType) {
+
+  ExplicitResultType = false;
+
+  TypeSourceInfo *MethodTyInfo;
+
+  if (ParamInfo.getNumTypeObjects() == 0) {
+    MethodTyInfo = getDummyLambdaType(S, Loc);
+  } else {
+    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
+    ExplicitResultType = FTI.hasTrailingReturnType();
+    if (!FTI.hasMutableQualifier()) {
+      FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const, Loc);
+    }
+
+    MethodTyInfo = S.GetTypeForDeclarator(ParamInfo, CurScope);
+
+    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;
+}
+
+static CXXMethodDecl *CreateMethod(Sema &S, SourceRange IntroducerRange,
+                                   CXXRecordDecl *Class) {
+  // 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 =
+      S.Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclarationNameLoc MethodNameLoc =
+      DeclarationNameLoc::makeCXXOperatorNameLoc(IntroducerRange.getBegin());
+  CXXMethodDecl *Method = CXXMethodDecl::Create(
+      S.Context, Class, SourceLocation(),
+      DeclarationNameInfo(MethodName, IntroducerRange.getBegin(),
+                          MethodNameLoc),
+      QualType(), nullptr, SC_None, S.getCurFPFeatures().isFPConstrained(),
+      /*isInline=*/true, ConstexprSpecKind::Unspecified, SourceLocation(),
+      nullptr);
+  Method->setAccess(AS_public);
+  return Method;
+}
+
+void Sema::ActOnLambdaIntroducer(LambdaIntroducer &Intro, Scope *CurrentScope) {
+
   LambdaScopeInfo *const 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->BeforeLambdaQualifiersScope = true;
+
+  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 =
@@ -910,181 +1006,37 @@
     LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
   }
 
-  // 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, LambdaDependencyKind, 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);
+      Intro.Range, nullptr, LambdaDependencyKind, Intro.Default);
+  LSI->Lambda = Class;
 
-  // 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);
+  // 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.
 
-  // Number the lambda for linkage purposes if necessary.
-  handleLambdaNumbering(Class, Method);
+  CXXMethodDecl *Method = CreateMethod(*this, Intro.Range, Class);
+  LSI->CallOperator = Method;
+  Method->setLexicalDeclContext(CurContext);
 
-  // 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);
+  bool ContainsUnexpandedParameterPack = false;
 
   // Distinct capture names, for diagnostics.
-  llvm::SmallSet<IdentifierInfo*, 8> CaptureNames;
+  llvm::SmallSet<IdentifierInfo *, 8> CaptureNames;
 
   // Handle explicit captures.
-  SourceLocation PrevCaptureLoc
-    = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
+  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;
 
@@ -1122,13 +1074,10 @@
       }
       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);
+                                           C->Init.get(), Method);
+      assert(Var && "createLambdaInitCaptureVarDecl returned a null VarDecl?");
+      CheckShadow(CurrentScope, Var);
+      PushOnScopeChains(Var, CurrentScope, false);
     } else {
       assert(C->InitKind == LambdaCaptureInitKind::NoInit &&
              "init capture has valid but null init?");
@@ -1175,9 +1124,14 @@
     //   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)) {
+      auto it = LSI->DelayedCaptures.end();
+      if (Var)
+        it = llvm::find_if(LSI->DelayedCaptures, [&Var](auto &&Pair) {
+          return Pair.second.Var == Var;
+        });
+      if (it != LSI->DelayedCaptures.end()) {
         Diag(C->Loc, diag::err_capture_more_than_once)
-            << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
+            << C->Id << SourceRange(it->second.Loc)
             << FixItHint::CreateRemoval(
                    SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
       } else
@@ -1223,22 +1177,247 @@
       ContainsUnexpandedParameterPack = true;
     }
 
-    if (C->Init.isUsable()) {
-      addInitCapture(LSI, Var);
+    if (Var)
+      LSI->DelayedCaptures[std::distance(Intro.Captures.begin(), C)] =
+          LambdaScopeInfo::DelayedCapture{Var, C->ExplicitRange.getBegin(),
+                                          C->Kind};
+  }
+
+  LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
+  PopDeclContext();
+}
+
+static void AddExplicitCapturesToContext(Sema &S, LambdaScopeInfo *LSI,
+                                         LambdaIntroducer &Intro) {
+  SourceLocation PrevCaptureLoc;
+  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)
+        S.Diag(C->Loc, !S.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()) {
+        S.Diag(C->Loc, diag::err_capture_more_than_once)
+            << "'this'" << SourceRange(LSI->getCXXThisCapture().getLocation())
+            << FixItHint::CreateRemoval(
+                   SourceRange(S.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)
+        S.Diag(C->Loc,
+               !S.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 = S.getCurrentThisType();
+      if (ThisCaptureType.isNull()) {
+        S.Diag(C->Loc, diag::err_this_capture) << true;
+        continue;
+      }
+      S.CheckCXXThisCapture(C->Loc, true, true, nullptr,
+                            C->Kind == LCK_StarThis);
     } else {
-      TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
-                                                   TryCapture_ExplicitByVal;
-      tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
+      VarDecl *Var =
+          LSI->DelayedCaptures[std::distance(Intro.Captures.begin(), C)].Var;
+      if (!Var)
+        continue;
+      if (Var->isInitCapture() && C->Init.isUsable()) {
+        S.addInitCapture(LSI, Var);
+        S.PushOnScopeChains(Var, S.getCurScope(), false);
+      } else {
+        Sema::TryCaptureKind Kind = C->Kind == LCK_ByRef
+                                        ? Sema::TryCapture_ExplicitByRef
+                                        : Sema::TryCapture_ExplicitByVal;
+        S.tryCaptureVariable(Var, C->Loc, Kind, C->EllipsisLoc);
+      }
     }
     if (!LSI->Captures.empty())
       LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
   }
-  finishLambdaExplicitCaptures(LSI);
+  S.finishLambdaExplicitCaptures(LSI);
+}
 
-  LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
+void Sema::ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
+                                        SourceLocation MutableLoc,
+                                        SourceLocation EndLoc,
+                                        const DeclSpec &DS) {
+
+  LambdaScopeInfo *const LSI = getCurrentLambdaScopeUnsafe(*this);
+  LSI->Mutable = MutableLoc.isValid();
+  LSI->BeforeLambdaQualifiersScope = false;
+  LSI->CallOperator->setConstexprKind(DS.getConstexprSpecifier());
+
+  // 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);
+
+  PushDeclContext(CurScope, LSI->CallOperator);
+  AddExplicitCapturesToContext(*this, LSI, Intro);
+}
+
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        Scope *CurScope) {
+
+  LambdaScopeInfo *const LSI = getCurrentLambdaScopeUnsafe(*this);
+
+  SmallVector<ParmVarDecl *, 8> Params;
+  bool ExplicitResultType;
+
+  SourceLocation TypeLoc, LambdaLoc;
+  if (ParamInfo.getNumTypeObjects() == 0) {
+    LambdaLoc = 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();
+    LambdaLoc = ParamInfo.getSourceRange().getEnd();
+  }
+
+  CXXRecordDecl *Class = LSI->Lambda;
+  CXXMethodDecl *Method = LSI->CallOperator;
+
+  if (auto *C = ParamInfo.getTrailingRequiresClause())
+    Method->setTrailingRequiresClause(C);
+
+  TemplateParameterList *TemplateParams =
+      getGenericLambdaTemplateParameterList(LSI, *this);
+
+  auto DC = Method->getLexicalDeclContext();
+  Method->setLexicalDeclContext(Class);
+  if (TemplateParams) {
+    FunctionTemplateDecl *const TemplateMethod = FunctionTemplateDecl::Create(
+        Context, Class, Method->getLocation(), Method->getDeclName(),
+        TemplateParams, Method);
+    TemplateMethod->setAccess(AS_public);
+    Method->setDescribedFunctionTemplate(TemplateMethod);
+    Class->addDecl(TemplateMethod);
+    TemplateMethod->setLexicalDeclContext(DC);
+  } else {
+    Class->addDecl(Method);
+  }
+  Method->setLexicalDeclContext(DC);
+  Class->setLambdaIsGeneric(TemplateParams);
+
+  TypeSourceInfo *MethodTyInfo = getLambdaType(
+      *this, Intro, ParamInfo, getCurScope(), TypeLoc, ExplicitResultType);
+
+  Class->setLambdaTypeInfo(MethodTyInfo);
+  Method->setInnerLocStart(LambdaLoc);
+  Method->setLocation(Intro.Range.getBegin());
+  Method->setTypeSourceInfo(MethodTyInfo);
+  Method->setType(buildTypeForLambdaCallOperator(*this, Class, TemplateParams,
+                                                 MethodTyInfo));
+  Method->setConstexprKind(ParamInfo.getDeclSpec().getConstexprSpecifier());
+  buildLambdaScopeReturnType(*this, LSI, Method, 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());
+      Param->setOwningFunction(Method);
+      Params.push_back(Param);
+    }
+  }
+
+  ContextRAII ManglingContext(*this, Class->getDeclContext());
+
+  CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false);
 
-  // Add lambda parameters into scope.
-  addLambdaParameters(Intro.Captures, Method, CurScope);
+  if (LSI->ExplicitParams) {
+    Method->setParams(Params);
+    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);
+
+  handleLambdaNumbering(Class, Method);
+
+  ManglingContext.pop();
+
+  for (auto &&C : LSI->DelayedCaptures) {
+    VarDecl *Var = C.second.Var;
+    if (Var && Var->isInitCapture()) {
+      PushOnScopeChains(Var, CurScope, false);
+    }
+  }
+
+  LSI->DelayedCaptures.clear();
+
+  auto CheckRedefinition = [&](ParmVarDecl *Param) {
+    if (!Param->getIdentifier())
+      return true;
+    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 (auto &&P : Params) {
+    if (!P->getIdentifier())
+      continue;
+    if (CheckRedefinition(P))
+      CheckShadow(CurScope, P);
+    PushOnScopeChains(P, CurScope);
+  }
 
   // Enter a new evaluation context to insulate the lambda from any
   // cleanups from the enclosing full-expression.
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -1130,7 +1130,7 @@
 
     if (C.isCopyCapture()) {
       ClassType.removeLocalCVRQualifiers(Qualifiers::CVRMask);
-      if (CurLSI->CallOperator->isConst())
+      if (!CurLSI->Mutable)
         ClassType.addConst();
       return ASTCtx.getPointerType(ClassType);
     }
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -3383,7 +3383,7 @@
     // FIXME: Support lambda-capture of BindingDecls, once CWG actually
     // decides how that's supposed to work.
     auto *BD = cast<BindingDecl>(VD);
-    if (BD->getDeclContext() != CurContext) {
+    if (BD->getDeclContext() != CurContext && !isUnevaluatedContext()) {
       auto *DD = dyn_cast_or_null<VarDecl>(BD->getDecomposedDecl());
       if (DD && DD->hasLocalStorage())
         diagnoseUncapturableValueReference(*this, Loc, BD);
@@ -18396,6 +18396,37 @@
   }
 }
 
+static bool CheckCaptureUseBeforeLambdaQualifiers(Sema &S, VarDecl *Var,
+                                                  SourceLocation ExprLoc,
+                                                  LambdaScopeInfo *LSI) {
+  if (Var->isInvalidDecl())
+    return false;
+
+  bool ByCopy = LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByval;
+  SourceLocation Loc = LSI->IntroducerRange.getBegin();
+  bool Explicitly = false;
+  for (auto &&C : LSI->DelayedCaptures) {
+    VarDecl *CV = C.second.Var;
+    if (Var != CV)
+      continue;
+    ByCopy = C.second.Kind == LambdaCaptureKind::LCK_ByCopy;
+    Loc = C.second.Loc;
+    Explicitly = true;
+    break;
+  }
+  if (ByCopy && LSI->BeforeLambdaQualifiersScope) {
+    // This can only occur in a non-ODR context, so we need to diagnose eagerly,
+    // even when BuildAndDiagnose is false
+    S.Diag(ExprLoc, diag::err_lambda_used_before_capture) << Var;
+    S.Diag(Loc, diag::note_var_explicitly_captured_here) << Var << Explicitly;
+    if (!Var->isInitCapture())
+      S.Diag(Var->getBeginLoc(), diag::note_entity_declared_at) << Var;
+    Var->setInvalidDecl();
+    return false;
+  }
+  return true;
+}
+
 bool Sema::tryCaptureVariable(
     VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
     SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
@@ -18419,11 +18450,6 @@
     }
   }
 
-
-  // If the variable is declared in the current context, there is no need to
-  // capture it.
-  if (VarDC == DC) return true;
-
   // Capture global variables if it is required to use private copy of this
   // variable.
   bool IsGlobal = !Var->hasLocalStorage();
@@ -18446,13 +18472,36 @@
   bool Nested = false;
   bool Explicit = (Kind != TryCapture_Implicit);
   unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
+  bool IsInLambdaBeforeQualifiers;
   do {
+    IsInLambdaBeforeQualifiers = false;
+
+    LambdaScopeInfo *LSI = nullptr;
+    if (!FunctionScopes.empty())
+      LSI = dyn_cast_or_null<LambdaScopeInfo>(
+          FunctionScopes[FunctionScopesIndex]);
+    if (LSI && LSI->BeforeLambdaQualifiersScope) {
+      if (isa<ParmVarDecl>(Var))
+        return true;
+      IsInLambdaBeforeQualifiers = true;
+      if (!CheckCaptureUseBeforeLambdaQualifiers(*this, Var, ExprLoc, LSI)) {
+        break;
+      }
+    }
+
+    // If the variable is declared in the current context, there is no need to
+    // capture it.
+    if (!IsInLambdaBeforeQualifiers &&
+        FunctionScopesIndex == MaxFunctionScopesIndex && VarDC == DC)
+      return true;
+
     // Only block literals, captured statements, and lambda expressions can
     // capture; other scopes don't work.
-    DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var,
-                                                              ExprLoc,
-                                                              BuildAndDiagnose,
-                                                              *this);
+    DeclContext *ParentDC =
+        IsInLambdaBeforeQualifiers
+            ? DC->getParent()
+            : getParentOfCapturingContextOrNull(DC, Var, ExprLoc,
+                                                BuildAndDiagnose, *this);
     // We need to check for the parent *first* because, if we *have*
     // private-captured a global variable, we need to recursively capture it in
     // intermediate blocks, lambdas, etc.
@@ -18467,9 +18516,9 @@
     FunctionScopeInfo  *FSI = FunctionScopes[FunctionScopesIndex];
     CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI);
 
-
     // Check whether we've already captured it.
-    if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
+    if (!IsInLambdaBeforeQualifiers &&
+        isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
                                              DeclRefType)) {
       CSI->getCapture(Var).markUsed(BuildAndDiagnose);
       break;
@@ -18478,7 +18527,8 @@
     // we do not want to capture new variables.  What was captured
     // during either a lambdas transformation or initial parsing
     // should be used.
-    if (isGenericLambdaCallOperatorSpecialization(DC)) {
+    if (!IsInLambdaBeforeQualifiers &&
+        isGenericLambdaCallOperatorSpecialization(DC)) {
       if (BuildAndDiagnose) {
         LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
         if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
@@ -18493,7 +18543,8 @@
     }
 
     // Try to capture variable-length arrays types.
-    if (Var->getType()->isVariablyModifiedType()) {
+    if (!IsInLambdaBeforeQualifiers &&
+        Var->getType()->isVariablyModifiedType()) {
       // We're going to walk down into the type and look for VLA
       // expressions.
       QualType QTy = Var->getType();
@@ -18502,7 +18553,7 @@
       captureVariablyModifiedType(Context, QTy, CSI);
     }
 
-    if (getLangOpts().OpenMP) {
+    if (!IsInLambdaBeforeQualifiers && getLangOpts().OpenMP) {
       if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
         // OpenMP private variables should not be captured in outer scope, so
         // just break here. Similarly, global variables that are captured in a
@@ -18583,11 +18634,11 @@
       }
       return true;
     }
-
-    FunctionScopesIndex--;
-    DC = ParentDC;
     Explicit = false;
-  } while (!VarDC->Equals(DC));
+    FunctionScopesIndex--;
+    if (!IsInLambdaBeforeQualifiers)
+      DC = ParentDC;
+  } while (IsInLambdaBeforeQualifiers || !VarDC->Equals(DC));
 
   // Walk back down the scope stack, (e.g. from outer lambda to inner lambda)
   // computing the type of the capture at each step, checking type-specific
@@ -18622,6 +18673,9 @@
       Nested = true;
     } else {
       LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
+      if (!CheckCaptureUseBeforeLambdaQualifiers(*this, Var, ExprLoc, LSI)) {
+        return true;
+      }
       Invalid =
           !captureInLambda(LSI, Var, ExprLoc, BuildAndDiagnose, CaptureType,
                            DeclRefType, Nested, Kind, EllipsisLoc,
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14349,7 +14349,6 @@
   else if (LCD == LCD_ByRef)
     LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
   DeclarationNameInfo DNI = CallOperator->getNameInfo();
-
   LSI->IntroducerRange = DNI.getCXXOperatorNameRange();
   LSI->Mutable = !CallOperator->isConst();
 
Index: clang/lib/Sema/SemaCXXScopeSpec.cpp
===================================================================
--- clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -292,6 +292,11 @@
 bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
                                     SourceLocation ColonColonLoc,
                                     CXXScopeSpec &SS) {
+  if (getCurLambda()) {
+    Diag(SuperLoc, diag::err_super_in_lambda_unsupported);
+    return true;
+  }
+
   CXXRecordDecl *RD = nullptr;
   for (Scope *S = getCurScope(); S; S = S->getParent()) {
     if (S->isFunctionScope()) {
@@ -308,9 +313,6 @@
   if (!RD) {
     Diag(SuperLoc, diag::err_invalid_super_scope);
     return true;
-  } else if (RD->isLambda()) {
-    Diag(SuperLoc, diag::err_super_in_lambda_unsupported);
-    return true;
   } else if (RD->getNumBases() == 0) {
     Diag(SuperLoc, diag::err_no_base_classes) << RD->getName();
     return true;
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2297,7 +2297,8 @@
 LambdaScopeInfo *Sema::getEnclosingLambda() const {
   for (auto *Scope : llvm::reverse(FunctionScopes)) {
     if (auto *LSI = dyn_cast<sema::LambdaScopeInfo>(Scope)) {
-      if (LSI->Lambda && !LSI->Lambda->Encloses(CurContext)) {
+      if (LSI->Lambda && !LSI->Lambda->Encloses(CurContext) &&
+          !LSI->BeforeLambdaQualifiersScope) {
         // We have switched contexts due to template instantiation.
         // FIXME: We should swap out the FunctionScopes during code synthesis
         // so that we don't need to check for this.
@@ -2323,8 +2324,9 @@
       return nullptr;
   }
   auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I);
-  if (CurLSI && CurLSI->Lambda &&
-      !CurLSI->Lambda->Encloses(CurContext)) {
+  if (CurLSI && CurLSI->Lambda && CurLSI->CallOperator &&
+      !CurLSI->Lambda->Encloses(CurContext) &&
+      !CurLSI->BeforeLambdaQualifiersScope) {
     // We have switched contexts due to template instantiation.
     assert(!CodeSynthesisContexts.empty());
     return nullptr;
Index: clang/lib/Sema/Scope.cpp
===================================================================
--- clang/lib/Sema/Scope.cpp
+++ clang/lib/Sema/Scope.cpp
@@ -67,8 +67,10 @@
   if (flags & BlockScope)         BlockParent = this;
   if (flags & TemplateParamScope) TemplateParamParent = this;
 
-  // If this is a prototype scope, record that.
-  if (flags & FunctionPrototypeScope) PrototypeDepth++;
+  // If this is a prototype scope, record that. Lambdas have an extra prototype
+  // scope that doesn't add any depth.
+  if (flags & FunctionPrototypeScope && !(flags & LambdaScope))
+    PrototypeDepth++;
 
   if (flags & DeclScope) {
     if (flags & FunctionPrototypeScope)
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -1250,7 +1250,13 @@
   DeclSpec DS(AttrFactory);
   Declarator D(DS, DeclaratorContext::LambdaExpr);
   TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+
+  ParseScope LambdaScope(this, Scope::LambdaScope | Scope::DeclScope |
+                                   Scope::FunctionDeclarationScope |
+                                   Scope::FunctionPrototypeScope);
+
   Actions.PushLambdaScope();
+  Actions.ActOnLambdaIntroducer(Intro, getCurScope());
 
   ParsedAttributes Attr(AttrFactory);
   if (getLangOpts().CUDA) {
@@ -1300,7 +1306,7 @@
       }
 
       Actions.ActOnLambdaExplicitTemplateParameterList(
-          LAngleLoc, TemplateParams, RAngleLoc, RequiresClause);
+          Intro, LAngleLoc, TemplateParams, RAngleLoc, RequiresClause);
       ++CurTemplateDepthTracker;
     }
   }
@@ -1318,28 +1324,31 @@
 
   TypeResult TrailingReturnType;
   SourceLocation TrailingReturnTypeLoc;
+  SourceLocation LParenLoc, RParenLoc;
+  SourceLocation DeclEndLoc;
+  bool HasParentheses = false;
+  bool HasSpecifiers = false;
+  SourceLocation MutableLoc;
+
+  auto ParseConstexprAndMutableSpecifiers = [&] {
+    // GNU-style attributes must be parsed before the mutable specifier to
+    // be compatible with GCC. MSVC-style attributes must be parsed before
+    // the mutable specifier to be compatible with MSVC.
+    MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attr);
+    // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update
+    // the DeclEndLoc.
+    SourceLocation ConstexprLoc;
+    SourceLocation ConstevalLoc;
+    tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc,
+                                   ConstevalLoc, DeclEndLoc);
+
+    addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
+    addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
+  };
 
   auto ParseLambdaSpecifiers =
-      [&](SourceLocation LParenLoc, SourceLocation RParenLoc,
-          MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo,
+      [&](MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo,
           SourceLocation EllipsisLoc) {
-        SourceLocation DeclEndLoc = RParenLoc;
-
-        // GNU-style attributes must be parsed before the mutable specifier to
-        // be compatible with GCC. MSVC-style attributes must be parsed before
-        // the mutable specifier to be compatible with MSVC.
-        MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attr);
-
-        // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update
-        // the DeclEndLoc.
-        SourceLocation MutableLoc;
-        SourceLocation ConstexprLoc;
-        SourceLocation ConstevalLoc;
-        tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc,
-                                       ConstevalLoc, DeclEndLoc);
-
-        addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
-        addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
         // Parse exception-specification[opt].
         ExceptionSpecificationType ESpecType = EST_None;
         SourceRange ESpecRange;
@@ -1393,20 +1402,22 @@
                 /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D,
                 TrailingReturnType, TrailingReturnTypeLoc, &DS),
             std::move(Attr), DeclEndLoc);
+
+        if (HasParentheses && Tok.is(tok::kw_requires))
+          ParseTrailingRequiresClause(D);
       };
 
-  if (Tok.is(tok::l_paren)) {
-    ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
-                                        Scope::FunctionDeclarationScope |
-                                        Scope::DeclScope);
+  ParseScope Prototype(this, Scope::FunctionPrototypeScope |
+                                 Scope::FunctionDeclarationScope |
+                                 Scope::DeclScope);
 
+  // Parse parameter-declaration-clause.
+  SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+  SourceLocation EllipsisLoc;
+  if (Tok.is(tok::l_paren)) {
     BalancedDelimiterTracker T(*this, tok::l_paren);
     T.consumeOpen();
-    SourceLocation LParenLoc = T.getOpenLocation();
-
-    // Parse parameter-declaration-clause.
-    SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
-    SourceLocation EllipsisLoc;
+    LParenLoc = T.getOpenLocation();
 
     if (Tok.isNot(tok::r_paren)) {
       Actions.RecordParsingTemplateParameterDepth(
@@ -1424,36 +1435,38 @@
     }
 
     T.consumeClose();
+    DeclEndLoc = RParenLoc = T.getCloseLocation();
+    HasParentheses = true;
+  }
 
-    // Parse lambda-specifiers.
-    ParseLambdaSpecifiers(LParenLoc, /*DeclEndLoc=*/T.getCloseLocation(),
-                          ParamInfo, EllipsisLoc);
-
-    // Parse requires-clause[opt].
-    if (Tok.is(tok::kw_requires))
-      ParseTrailingRequiresClause(D);
-  } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute,
-                         tok::kw_constexpr, tok::kw_consteval,
-                         tok::kw___private, tok::kw___global, tok::kw___local,
-                         tok::kw___constant, tok::kw___generic,
-                         tok::kw_requires, tok::kw_noexcept) ||
-             (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
-    if (!getLangOpts().CPlusPlus2b)
+  if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute,
+                  tok::kw_constexpr, tok::kw_consteval, tok::kw___private,
+                  tok::kw___global, tok::kw___local, tok::kw___constant,
+                  tok::kw___generic, tok::kw_requires, tok::kw_noexcept) ||
+      (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
+    HasSpecifiers = true;
+    if (!HasParentheses && !getLangOpts().CPlusPlus2b) {
       // It's common to forget that one needs '()' before 'mutable', an
       // attribute specifier, the result type, or the requires clause. Deal with
       // this.
       Diag(Tok, diag::ext_lambda_missing_parens)
           << FixItHint::CreateInsertion(Tok.getLocation(), "() ");
+    }
+  }
 
-    SourceLocation NoLoc;
-    // Parse lambda-specifiers.
-    std::vector<DeclaratorChunk::ParamInfo> EmptyParamInfo;
-    ParseLambdaSpecifiers(/*LParenLoc=*/NoLoc, /*RParenLoc=*/NoLoc,
-                          EmptyParamInfo, /*EllipsisLoc=*/NoLoc);
+  if (HasParentheses || HasSpecifiers) {
+    ParseConstexprAndMutableSpecifiers();
   }
 
+  Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc, DeclEndLoc, DS);
+
+  if (HasSpecifiers || HasParentheses)
+    ParseLambdaSpecifiers(ParamInfo, EllipsisLoc);
+
   WarnIfHasCUDATargetAttr();
 
+  Prototype.Exit();
+
   // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
   // it.
   unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope |
@@ -1472,6 +1485,7 @@
   StmtResult Stmt(ParseCompoundStatementBody());
   BodyScope.Exit();
   TemplateParamScope.Exit();
+  LambdaScope.Exit();
 
   if (!Stmt.isInvalid() && !TrailingReturnType.isInvalid())
     return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope());
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -6837,11 +6837,9 @@
   ///
   ///  CodeGen handles emission of lambda captures, ignoring these dummy
   ///  variables appropriately.
-  VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc,
-                                          QualType InitCaptureType,
-                                          SourceLocation EllipsisLoc,
-                                          IdentifierInfo *Id,
-                                          unsigned InitStyle, Expr *Init);
+  VarDecl *createLambdaInitCaptureVarDecl(
+      SourceLocation Loc, QualType InitCaptureType, SourceLocation EllipsisLoc,
+      IdentifierInfo *Id, unsigned InitStyle, Expr *Init, DeclContext *DeclCtx);
 
   /// Add an init-capture to a lambda scope.
   void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var);
@@ -6850,21 +6848,28 @@
   /// given lambda.
   void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
 
-  /// \brief This is called after parsing the explicit template parameter list
+  /// Deduce a block or lambda's return type based on the return
+  /// statements present in the body.
+  void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+
+  /// Once the Lambdas capture are known, we can
+  /// start to create the closure, call operator method,
+  /// and keep track of the captures.
+  /// We do the capture lookup here, but they are not actually captured
+  /// until after we know what the qualifiers of the call operator are.
+  void ActOnLambdaIntroducer(LambdaIntroducer &Intro, Scope *CurContext);
+
+  /// This is called after parsing the explicit template parameter list
   /// on a lambda (if it exists) in C++2a.
-  void ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc,
+  void ActOnLambdaExplicitTemplateParameterList(LambdaIntroducer &Intro,
+                                                SourceLocation LAngleLoc,
                                                 ArrayRef<NamedDecl *> TParams,
                                                 SourceLocation RAngleLoc,
                                                 ExprResult RequiresClause);
 
-  /// Introduce the lambda parameters into scope.
-  void addLambdaParameters(
-      ArrayRef<LambdaIntroducer::LambdaCapture> Captures,
-      CXXMethodDecl *CallOperator, Scope *CurScope);
-
-  /// Deduce a block or lambda's return type based on the return
-  /// statements present in the body.
-  void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+  void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
+                                    SourceLocation MutableLoc,
+                                    SourceLocation EndLoc, const DeclSpec &DS);
 
   /// ActOnStartOfLambdaDefinition - This is called just before we start
   /// parsing the body of a lambda; it analyzes the explicit captures and
Index: clang/include/clang/Sema/ScopeInfo.h
===================================================================
--- clang/include/clang/Sema/ScopeInfo.h
+++ clang/include/clang/Sema/ScopeInfo.h
@@ -831,6 +831,28 @@
   /// The lambda's compiler-generated \c operator().
   CXXMethodDecl *CallOperator = nullptr;
 
+  struct DelayedCapture {
+    VarDecl *Var;
+    SourceLocation Loc;
+    LambdaCaptureKind Kind;
+  };
+
+  /// Holds the captures until we parsed the qualifiers, as the cv qualified
+  /// type of captures can only be computed at that point, and the captures
+  /// should not be visible before.
+  /// The index represents the position in the original capture list.
+  /// We use a map as not all index represents captures (defaults), or are
+  /// captured (some captures are invalid).
+  llvm::DenseMap<unsigned, DelayedCapture> DelayedCaptures;
+
+  /// Whether the current scope when parsing the lambda
+  /// is after the call operator qualifiers,
+  /// which is the point at which the captures are usable
+  /// per [expr.prim.id.unqual]/p3.2 and [expr.prim.lambda.capture]/6.
+  /// This is set to false by default as the lambda can be reconstructed during
+  /// instantiation
+  bool BeforeLambdaQualifiersScope = false;
+
   /// Source range covering the lambda introducer [...].
   SourceRange IntroducerRange;
 
Index: clang/include/clang/Sema/Scope.h
===================================================================
--- clang/include/clang/Sema/Scope.h
+++ clang/include/clang/Sema/Scope.h
@@ -44,11 +44,11 @@
   enum ScopeFlags {
     /// This indicates that the scope corresponds to a function, which
     /// means that labels are set here.
-    FnScope       = 0x01,
+    FnScope = 0x01,
 
     /// This is a while, do, switch, for, etc that can have break
     /// statements embedded into it.
-    BreakScope    = 0x02,
+    BreakScope = 0x02,
 
     /// This is a while, do, for, which can have continue statements
     /// embedded into it.
@@ -140,6 +140,12 @@
     /// parsed. If such a scope is a ContinueScope, it's invalid to jump to the
     /// continue block from here.
     ConditionVarScope = 0x2000000,
+
+    /// This is the scope for a lambda, after the lambda introducer.
+    /// Lambdas need 2 FunctionPrototypeScope scopes (because there is a
+    /// template scope in between), the outer scope does not increase the
+    /// depth of recursion.
+    LambdaScope = 0x4000000,
   };
 
 private:
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7698,6 +7698,8 @@
   def err_lambda_impcap : Error<
     "variable %0 cannot be implicitly captured in a lambda with no "
     "capture-default specified">;
+  def err_lambda_used_before_capture: Error<
+    "captured variable %0 cannot appear here">;
   def note_lambda_variable_capture_fixit : Note<
     "capture %0 by %select{value|reference}1">;
   def note_lambda_default_capture_fixit : Note<
Index: clang/include/clang/AST/DeclCXX.h
===================================================================
--- clang/include/clang/AST/DeclCXX.h
+++ clang/include/clang/AST/DeclCXX.h
@@ -1799,6 +1799,20 @@
     return getLambdaData().MethodTyInfo;
   }
 
+  void setLambdaTypeInfo(TypeSourceInfo *TS) {
+    auto *DD = DefinitionData;
+    assert(DD && DD->IsLambda && "setting lambda property of non-lambda class");
+    auto &DL = static_cast<LambdaDefinitionData &>(*DD);
+    DL.MethodTyInfo = TS;
+  }
+
+  void setLambdaIsGeneric(bool IsGeneric) {
+    auto *DD = DefinitionData;
+    assert(DD && DD->IsLambda && "setting lambda property of non-lambda class");
+    auto &DL = static_cast<LambdaDefinitionData &>(*DD);
+    DL.IsGenericLambda = IsGeneric;
+  }
+
   // Determine whether this type is an Interface Like type for
   // __interface inheritance purposes.
   bool isInterfaceLike() const;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -214,6 +214,9 @@
 - Implemented `P2128R6: Multidimensional subscript operator <https://wg21.link/P2128R6>`_.
 - Implemented `P0849R8: auto(x): decay-copy in the language <https://wg21.link/P0849R8>`_.
 - Implemented `P2242R3: Non-literal variables (and labels and gotos) in constexpr functions	<https://wg21.link/P2242R3>`_.
+- Implemented `P2036R3: Change scope of lambda trailing-return-type <https://wg21.link/P2036R3>`_.
+  This proposal modifies how variables captured in lambdas can appear in trailing return type
+  expressions and how their types are deduced therein, in all C++ language versions.
 
 CUDA Language Changes in Clang
 ------------------------------
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to