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

Rebase. This is still a bit rough, I have a few tests to fix
and some dead code to remove.
---

@erichkeanne I wouldn't mind picking your brain on this.
Consider:

  template <typename T>
  void dependent_init_capture(T x = 0) {
    [y = x] () requires (decltype(y){1}) {
      return y;
    }();
  }
  
  void test_dependent() {
    dependent_init_capture(0);
  }

This used to ""work"" in the previous iteration of the patch,
but with the late concept checking it seems more involved.

My understanding so far is that in `CheckFunctionConstraints` 
we can't find an instanciated declaration of `y` (so it asserts in 
`LocalInstantiationScope::findInstantiationOf`).

I'm not 100% sure of what's the correct approach here would be. 
My guess is that we might need to retransform the captures  in the 
instanciation scope used 
for constraint checking? 
I'm not actually sure whether an instanciation of the lambda does exist at that 
point in some other scope, 
though. Ideally we would not instannciate lambdas more times than needed.

Another issue is that there is no way to walk back from a call expression to a 
lambda expression,
so we might need to add that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D124351

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  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/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/CXX/expr/expr.prim/expr.prim.lambda/p4.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
@@ -1358,7 +1358,7 @@
     <tr>
       <td rowspan=2>Change scope of lambda trailing-return-type</td>
       <td><a href="https://wg21.link/P2036R3";>P2036R3</a></td>
-      <td rowspan=2 class="none" align="center">No</td>
+      <td rowspan=2 class="unreleased" align="center">Clang 16</td>
     </tr>
     <tr>
       <td><a href="https://wg21.link/P2579R0";>P2579R0</a></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,248 @@
+// 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}}
+
+  (void)[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}}
+
+  (void)[x = 1]<typename T = decltype((x))>{}; // expected-note {{variable 'x' is explicitly captured here}} \
+                                                                 // expected-error {{captured variable 'x' cannot appear here}}
+
+  (void)[=]<typename T = decltype((y))>{}; // expected-note {{variable 'y' is captured here}} \
+                                             // expected-error {{captured variable 'y' cannot appear here}}
+
+  (void)[z]<typename T = decltype((z))>{}; // expected-note {{variable 'z' is explicitly captured here}} \
+                                             // expected-error {{captured variable 'z' cannot appear here}}
+}
+
+void gnu_attributes() {
+  int y;
+  (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), const int &>, "wrong type", "warning"))){}();
+  (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), int &>, "wrong type", "warning"))){}();
+  // expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
+
+  (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), int &>, "wrong type", "warning"))) mutable {}();
+  (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), const int &>, "wrong type", "warning"))) mutable {}();
+  // expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
+
+  (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), const int &>, "wrong type", "warning"))){}();
+  (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), int &>, "wrong type", "warning"))){}();
+  // expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
+
+  (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), int &>, "wrong type", "warning"))) mutable {}();
+  (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), const int &>, "wrong type", "warning"))) mutable {}();
+  // expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
+}
+
+void nested() {
+  int x, y, z;
+  (void)[&](
+      decltype([&](
+                   decltype([=](
+                                decltype([&](
+                                             decltype([&](decltype(x)) {})) {})) {})) {})){};
+
+  (void)[&](
+      decltype([&](
+                   decltype([&](
+                                decltype([&](
+                                             decltype([&](decltype(y)) {})) {})) {})) {})){};
+
+  (void)[=](
+      decltype([=](
+                   decltype([=](
+                                decltype([=](
+                                             decltype([&]<decltype(z)> {})) {})) {})) {})){};
+}
+
+template <typename T, typename U>
+void dependent(U&& u) {
+  [&]() requires is_same<decltype(u), T> {}();
+}
+
+template <typename T>
+void dependent_init_capture(T x = 0) {
+  [ y = x + 1, x ]() mutable -> decltype(y + x) requires(is_same<decltype((y)), int &> && is_same<decltype((x)), int &>) {
+    return y;
+  }
+  ();
+  [ y = x + 1, x ]() -> decltype(y + x) requires(is_same<decltype((y)), const int &> && is_same<decltype((x)), const int &>) {
+    return y;
+  }
+  ();
+}
+
+template <typename T, typename...>
+struct extract_type {
+  using type = T;
+};
+
+template <typename... T>
+void dependent_variadic_capture(T... x) {
+  [... y = x, x... ](auto...) mutable -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), int &> && ...) && (is_same<decltype((x)), int &> && ...)) {
+    return 0;
+  }
+  (x...);
+  [... y = x, x... ](auto...) -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), const int &> && ...) && (is_same<decltype((x)), const int &> && ...)) {
+    return 0;
+  }
+  (x...);
+}
+
+void test_dependent() {
+  int v   = 0;
+  int & r = v;
+  const int & cr = v;
+  dependent<int&>(v);
+  dependent<int&>(r);
+  dependent<const int&>(cr);
+  dependent_init_capture(0);
+  dependent_variadic_capture(1, 2, 3, 4);
+}
+
+void check_params() {
+  int i = 0;
+  int &j = i;
+  (void)[=](decltype((j)) jp, decltype((i)) ip) {
+    static_assert(is_same<const int&, decltype((j))>);
+    static_assert(is_same<const int &, decltype((i))>);
+    static_assert(is_same<const int &, decltype((jp))>);
+    static_assert(is_same<const int &, decltype((ip))>);
+  };
+
+  (void)[=](decltype((j)) jp, decltype((i)) ip) mutable {
+    static_assert(is_same<int &, decltype((j))>);
+    static_assert(is_same<int &, decltype((i))>);
+    static_assert(is_same<int &, decltype((jp))>);
+    static_assert(is_same<int &, decltype((ip))>);
+    static_assert(is_same<int &, decltype(jp)>);
+    static_assert(is_same<int &, decltype(ip)>);
+  };
+
+  (void)[a = 0](decltype((a)) ap) mutable {
+    static_assert(is_same<int &, decltype((a))>);
+    static_assert(is_same<int, decltype(a)>);
+    static_assert(is_same<int &, decltype(ap)>);
+  };
+  (void)[a = 0](decltype((a)) ap) {
+    static_assert(is_same<const int &, decltype((a))>);
+    static_assert(is_same<int, decltype(a)>);
+    static_assert(is_same<const int&, decltype((ap))>);
+  };
+}
+
+template <typename T>
+void check_params_tpl() {
+  T i = 0;
+  T &j = i;
+  (void)[=](decltype((j)) jp, decltype((i)) ip) {
+    static_assert(is_same<const int&, decltype((j))>);
+    static_assert(is_same<const int &, decltype((i))>);
+    static_assert(is_same<const int &, decltype((jp))>);
+    static_assert(is_same<const int &, decltype((ip))>);
+  };
+
+  (void)[=](decltype((j)) jp, decltype((i)) ip) mutable {
+    static_assert(is_same<int &, decltype((j))>);
+    static_assert(is_same<int &, decltype((i))>);
+    static_assert(is_same<int &, decltype((jp))>);
+    static_assert(is_same<int &, decltype((ip))>);
+    static_assert(is_same<int &, decltype(jp)>);
+    static_assert(is_same<int &, decltype(ip)>);
+  };
+
+  (void)[a = 0](decltype((a)) ap) mutable {
+    static_assert(is_same<int &, decltype((a))>);
+    static_assert(is_same<int, decltype(a)>);
+    static_assert(is_same<int &, decltype(ap)>);
+  };
+  (void)[a = 0](decltype((a)) ap) {
+    static_assert(is_same<const int &, decltype((a))>);
+    static_assert(is_same<int, decltype(a)>);
+    static_assert(is_same<const int&, decltype((ap))>);
+  };
+}
Index: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
===================================================================
--- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
+++ clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
@@ -43,10 +43,21 @@
   }(5);
 }
 
-struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}}
+struct Incomplete; // expected-note 2{{forward declaration of 'Incomplete'}}
 void test_result_type(int N) {
   auto l1 = [] () -> Incomplete { }; // expected-error{{incomplete result type 'Incomplete' in lambda expression}}
 
   typedef int vla[N];
   auto l2 = [] () -> vla { }; // expected-error{{function cannot return array type 'vla' (aka 'int[N]')}}
 }
+
+template <typename T>
+void test_result_type_tpl(int N) {
+  auto l1 = []() -> T {}; // expected-error{{incomplete result type 'Incomplete' in lambda expression}}
+  typedef int vla[N];
+  auto l2 = []() -> vla {}; // expected-error{{function cannot return array type 'vla' (aka 'int[N]')}}
+}
+
+void test_result_type_call() {
+  test_result_type_tpl<Incomplete>(10); // expected-note {{requested here}}
+}
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
@@ -13195,37 +13195,6 @@
   LambdaScopeInfo *LSI = getSema().PushLambdaScope();
   Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
 
-  // Transform the template parameters, and add them to the current
-  // instantiation scope. The null case is handled correctly.
-  auto TPL = getDerived().TransformTemplateParameterList(
-      E->getTemplateParameterList());
-  LSI->GLTemplateParameterList = TPL;
-
-  // Transform the type of the original lambda's call operator.
-  // The transformation MUST be done in the CurrentInstantiationScope since
-  // it introduces a mapping of the original to the newly created
-  // transformed parameters.
-  TypeSourceInfo *NewCallOpTSI = nullptr;
-  {
-    TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
-    FunctionProtoTypeLoc OldCallOpFPTL =
-        OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
-
-    TypeLocBuilder NewCallOpTLBuilder;
-    SmallVector<QualType, 4> ExceptionStorage;
-    TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
-    QualType NewCallOpType = TransformFunctionProtoType(
-        NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(),
-        [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
-          return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
-                                              ExceptionStorage, Changed);
-        });
-    if (NewCallOpType.isNull())
-      return ExprError();
-    NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
-                                                        NewCallOpType);
-  }
-
   // Create the local class that will describe the lambda.
 
   // FIXME: DependencyKind below is wrong when substituting inside a templated
@@ -13241,10 +13210,8 @@
     DependencyKind = CXXRecordDecl::LDK_NeverDependent;
 
   CXXRecordDecl *OldClass = E->getLambdaClass();
-  CXXRecordDecl *Class =
-      getSema().createLambdaClosureType(E->getIntroducerRange(), NewCallOpTSI,
-                                        DependencyKind, E->getCaptureDefault());
-
+  CXXRecordDecl *Class = getSema().createLambdaClosureType(
+      E->getIntroducerRange(), nullptr, DependencyKind, E->getCaptureDefault());
   getDerived().transformedLocalDecl(OldClass, {Class});
 
   Optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling;
@@ -13254,36 +13221,19 @@
                                OldClass->getDeviceLambdaManglingNumber(),
                                OldClass->getLambdaContextDecl());
 
-  // Build the call operator.
-  CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
-      Class, E->getIntroducerRange(), NewCallOpTSI,
-      E->getCallOperator()->getEndLoc(),
-      NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
-      E->getCallOperator()->getConstexprKind(),
-      E->getCallOperator()->getStorageClass(),
-      E->getCallOperator()->getTrailingRequiresClause());
-
-  LSI->CallOperator = NewCallOperator;
-
-  getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
-  getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
+  CXXMethodDecl *NewCallOperator =
+      getSema().CreateLambdaCallOperator(E->getIntroducerRange(), Class);
+  NewCallOperator->setLexicalDeclContext(getSema().CurContext);
 
-  // Number the lambda for linkage purposes if necessary.
-  getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling);
+  // Enter the scope of the lambda.
+  getSema().buildLambdaScope(LSI, NewCallOperator, E->getIntroducerRange(),
+                             E->getCaptureDefault(), E->getCaptureDefaultLoc(),
+                             E->hasExplicitParameters(), E->isMutable());
 
   // Introduce the context of the call operator.
   Sema::ContextRAII SavedContext(getSema(), NewCallOperator,
                                  /*NewThisContext*/false);
 
-  // Enter the scope of the lambda.
-  getSema().buildLambdaScope(LSI, NewCallOperator,
-                             E->getIntroducerRange(),
-                             E->getCaptureDefault(),
-                             E->getCaptureDefaultLoc(),
-                             E->hasExplicitParameters(),
-                             E->hasExplicitResultType(),
-                             E->isMutable());
-
   bool Invalid = false;
 
   // Transform captures.
@@ -13323,7 +13273,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;
@@ -13404,6 +13355,55 @@
   }
   getSema().finishLambdaExplicitCaptures(LSI);
 
+  // Transform the template parameters, and add them to the current
+  // instantiation scope. The null case is handled correctly.
+  auto TPL = getDerived().TransformTemplateParameterList(
+      E->getTemplateParameterList());
+  LSI->GLTemplateParameterList = TPL;
+
+  // Transform the type of the original lambda's call operator.
+  // The transformation MUST be done in the CurrentInstantiationScope since
+  // it introduces a mapping of the original to the newly created
+  // transformed parameters.
+  TypeSourceInfo *NewCallOpTSI = nullptr;
+  {
+    TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
+    FunctionProtoTypeLoc OldCallOpFPTL =
+        OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+
+    TypeLocBuilder NewCallOpTLBuilder;
+    SmallVector<QualType, 4> ExceptionStorage;
+    TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
+    QualType NewCallOpType = TransformFunctionProtoType(
+        NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(),
+        [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
+          return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
+                                              ExceptionStorage, Changed);
+        });
+    if (NewCallOpType.isNull())
+      return ExprError();
+    NewCallOpTSI =
+        NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
+  }
+
+  getSema().CompleteLambdaCallOperator(
+      NewCallOperator, E->getCallOperator()->getLocation(),
+      E->getCallOperator()->getInnerLocStart(),
+      E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI,
+      E->getCallOperator()->getConstexprKind(),
+      E->getCallOperator()->getStorageClass(),
+      NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
+      E->hasExplicitResultType());
+
+  getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
+  getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
+
+  {
+    // Number the lambda for linkage purposes if necessary.
+    Sema::ContextRAII ManglingContext(getSema(), Class->getDeclContext());
+    getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling);
+  }
+
   // FIXME: Sema's lambda-building mechanism expects us to push an expression
   // evaluation context even if we're not transforming the function body.
   getSema().PushExpressionEvaluationContext(
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,
@@ -362,14 +363,13 @@
   llvm_unreachable("unexpected context");
 }
 
-CXXMethodDecl *Sema::startLambdaDefinition(
-    CXXRecordDecl *Class, SourceRange IntroducerRange,
-    TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc,
-    ArrayRef<ParmVarDecl *> Params, ConstexprSpecKind ConstexprKind,
-    StorageClass SC, 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.
@@ -377,58 +377,12 @@
     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());
     }
   }
-
-  // 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, getCurFPFeatures().isFPConstrained(),
-      /*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;
+  return MethodType;
 }
 
 void Sema::handleLambdaNumbering(
@@ -486,14 +440,26 @@
   }
 }
 
-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;
+  }
+}
+
+void Sema::buildLambdaScope(LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
+                            SourceRange IntroducerRange,
+                            LambdaCaptureDefault CaptureDefault,
+                            SourceLocation CaptureDefaultLoc,
+                            bool ExplicitParams, bool Mutable) {
   LSI->CallOperator = CallOperator;
   CXXRecordDecl *LambdaClass = CallOperator->getParent();
   LSI->Lambda = LambdaClass;
@@ -505,30 +471,16 @@
   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) {
+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 &&
@@ -544,35 +496,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.
 ///
@@ -859,11 +782,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);
@@ -874,8 +795,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.
@@ -894,35 +815,46 @@
                   Var->getType(), /*Invalid*/false);
 }
 
-void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
-                                        Declarator &ParamInfo,
-                                        Scope *CurScope) {
-  LambdaScopeInfo *const LSI = getCurLambda();
-  assert(LSI && "LambdaScopeInfo should be on stack!");
+// 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]);
+}
 
-  // Determine if we're within a context where we know that the lambda will
-  // be dependent, because there are template parameters in scope.
-  CXXRecordDecl::LambdaDependencyKind LambdaDependencyKind =
-      CXXRecordDecl::LDK_Unknown;
-  if (LSI->NumExplicitTemplateParams > 0) {
-    auto *TemplateParamScope = CurScope->getTemplateParamParent();
-    assert(TemplateParamScope &&
-           "Lambda with explicit template param list should establish a "
-           "template param scope");
-    assert(TemplateParamScope->getParent());
-    if (TemplateParamScope->getParent()->getTemplateParamParent() != nullptr)
-      LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
-  } else if (CurScope->getTemplateParamParent() != nullptr) {
-    LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
-  }
+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);
+}
 
-  // Determine the signature of the call operator.
-  TypeSourceInfo *MethodTyInfo;
-  bool ExplicitParams = true;
-  bool ExplicitResultType = true;
-  bool ContainsUnexpandedParameterPack = false;
-  SourceLocation EndLoc;
-  SmallVector<ParmVarDecl *, 8> Params;
+static TypeSourceInfo *getLambdaType(Sema &S, LambdaIntroducer &Intro,
+                                     Declarator &ParamInfo, Scope *CurScope,
+                                     SourceLocation Loc,
+                                     bool &ExplicitResultType) {
+
+  ExplicitResultType = false;
 
   assert(
       (ParamInfo.getDeclSpec().getStorageClassSpec() ==
@@ -932,146 +864,176 @@
   bool IsLambdaStatic =
       ParamInfo.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static;
 
+  TypeSourceInfo *MethodTyInfo;
+
   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();
+    MethodTyInfo = getDummyLambdaType(S, Loc);
   } 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. [...]
+    ExplicitResultType = FTI.hasTrailingReturnType();
     if (!FTI.hasMutableQualifier() && !IsLambdaStatic) {
-      FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const,
-                                                    SourceLocation());
+      FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const, Loc);
     }
 
-    MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
-    assert(MethodTyInfo && "no type from lambda-declarator");
-    EndLoc = ParamInfo.getSourceRange().getEnd();
-
-    ExplicitResultType = FTI.hasTrailingReturnType();
-
-    if (ExplicitResultType && getLangOpts().HLSL) {
+    if (ExplicitResultType && S.getLangOpts().HLSL) {
       QualType RetTy = FTI.getTrailingReturnType().get();
       if (!RetTy.isNull()) {
         // HLSL does not support specifying an address space on a lambda return
         // type.
         LangAS AddressSpace = RetTy.getAddressSpace();
         if (AddressSpace != LangAS::Default)
-          Diag(FTI.getTrailingReturnTypeLoc(),
-               diag::err_return_value_with_address_space);
+          S.Diag(FTI.getTrailingReturnTypeLoc(),
+                 diag::err_return_value_with_address_space);
       }
     }
 
-    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));
-    }
+    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())
-      DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo,
-                                      UPPC_DeclarationType);
+      S.DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo,
+                                        S.UPPC_DeclarationType);
   }
+  return MethodTyInfo;
+}
 
-  CXXRecordDecl *Class = createLambdaClosureType(
-      Intro.Range, MethodTyInfo, LambdaDependencyKind, Intro.Default);
-  CXXMethodDecl *Method =
-      startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params,
-                            ParamInfo.getDeclSpec().getConstexprSpecifier(),
-                            IsLambdaStatic ? SC_Static : SC_None,
-                            ParamInfo.getTrailingRequiresClause());
-  if (ExplicitParams)
-    CheckCXXDefaultArguments(Method);
+CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange,
+                                              CXXRecordDecl *Class) {
 
-  // This represents the function body for the lambda function, check if we
-  // have to apply optnone due to a pragma.
-  AddRangeBasedOptnone(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.
+  DeclarationName MethodName =
+      Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclarationNameLoc MethodNameLoc =
+      DeclarationNameLoc::makeCXXOperatorNameLoc(IntroducerRange.getBegin());
+  CXXMethodDecl *Method = CXXMethodDecl::Create(
+      Context, Class, SourceLocation(),
+      DeclarationNameInfo(MethodName, IntroducerRange.getBegin(),
+                          MethodNameLoc),
+      QualType(), nullptr, SC_None, getCurFPFeatures().isFPConstrained(),
+      /*isInline=*/true, ConstexprSpecKind::Unspecified, SourceLocation(),
+      nullptr);
+  Method->setAccess(AS_public);
+  return Method;
+}
 
-  // code_seg attribute on lambda apply to the method.
-  if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
-    Method->addAttr(A);
+void Sema::CompleteLambdaCallOperator(
+    CXXMethodDecl *Method, SourceLocation LambdaLoc,
+    SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
+    TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
+    StorageClass SC, ArrayRef<ParmVarDecl *> Params,
+    bool HasExplicitResultType) {
 
-  // Attributes on the lambda apply to the method.
-  ProcessDeclAttributes(CurScope, Method, ParamInfo);
+  LambdaScopeInfo *const LSI = getCurrentLambdaScopeUnsafe(*this);
 
-  // CUDA lambdas get implicit host and device attributes.
-  if (getLangOpts().CUDA)
-    CUDASetLambdaAttrs(Method);
+  if (TrailingRequiresClause)
+    Method->setTrailingRequiresClause(TrailingRequiresClause);
 
-  // OpenMP lambdas might get assumumption attributes.
-  if (LangOpts.OpenMP)
-    ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Method);
+  TemplateParameterList *TemplateParams =
+      getGenericLambdaTemplateParameterList(LSI, *this);
+
+  auto DC = Method->getLexicalDeclContext();
+  Method->setLexicalDeclContext(LSI->Lambda);
+  if (TemplateParams) {
+    FunctionTemplateDecl *const TemplateMethod = FunctionTemplateDecl::Create(
+        Context, LSI->Lambda, Method->getLocation(), Method->getDeclName(),
+        TemplateParams, Method);
+    TemplateMethod->setAccess(AS_public);
+    Method->setDescribedFunctionTemplate(TemplateMethod);
+    LSI->Lambda->addDecl(TemplateMethod);
+    TemplateMethod->setLexicalDeclContext(DC);
+  } else {
+    LSI->Lambda->addDecl(Method);
+  }
+  LSI->Lambda->setLambdaIsGeneric(TemplateParams);
+  LSI->Lambda->setLambdaTypeInfo(MethodTyInfo);
+
+  Method->setLexicalDeclContext(DC);
+  Method->setLocation(LambdaLoc);
+  Method->setInnerLocStart(CallOperatorLoc);
+  Method->setTypeSourceInfo(MethodTyInfo);
+  Method->setType(buildTypeForLambdaCallOperator(*this, LSI->Lambda,
+                                                 TemplateParams, MethodTyInfo));
+  Method->setConstexprKind(ConstexprKind);
+  Method->setStorageClass(SC);
+  if (!Params.empty()) {
+    CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false);
+    Method->setParams(Params);
+    for (auto P : Method->parameters())
+      P->setOwningFunction(Method);
+  }
 
-  // Number the lambda for linkage purposes if necessary.
-  handleLambdaNumbering(Class, Method);
+  buildLambdaScopeReturnType(*this, LSI, Method, HasExplicitResultType);
+}
 
-  // Introduce the function call operator as the current declaration context.
-  PushDeclContext(CurScope, Method);
+void Sema::ActOnLambdaIntroducer(LambdaIntroducer &Intro, Scope *CurrentScope) {
 
-  // Build the lambda scope.
-  buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc,
-                   ExplicitParams, ExplicitResultType, !Method->isConst());
+  LambdaScopeInfo *const LSI = getCurLambda();
+  assert(LSI && "LambdaScopeInfo should be on stack!");
 
-  // 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);
+  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->HasKnownMutability = false;
+  LSI->AfterParameterList = false;
+
+  assert(LSI->NumExplicitTemplateParams == 0);
+
+  // Determine if we're within a context where we know that the lambda will
+  // be dependent, because there are template parameters in scope.
+  CXXRecordDecl::LambdaDependencyKind LambdaDependencyKind =
+      CXXRecordDecl::LDK_Unknown;
+  if (LSI->NumExplicitTemplateParams > 0) {
+    auto *TemplateParamScope = CurScope->getTemplateParamParent();
+    assert(TemplateParamScope &&
+           "Lambda with explicit template param list should establish a "
+           "template param scope");
+    assert(TemplateParamScope->getParent());
+    if (TemplateParamScope->getParent()->getTemplateParamParent() != nullptr)
+      LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
+  } else if (CurScope->getTemplateParamParent() != nullptr) {
+    LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
+  }
+
+  CXXRecordDecl *Class = createLambdaClosureType(
+      Intro.Range, nullptr, LambdaDependencyKind, Intro.Default);
+  LSI->Lambda = 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.
+
+  CXXMethodDecl *Method = CreateLambdaCallOperator(Intro.Range, Class);
+  LSI->CallOperator = Method;
+  Method->setLexicalDeclContext(CurContext);
+
+  PushDeclContext(CurScope, Method);
+
+  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);
+                         ? 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
@@ -1084,7 +1046,7 @@
         continue;
       }
 
-      // C++2a [expr.prim.lambda]p8:
+      // 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
@@ -1102,17 +1064,11 @@
         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;
+      CheckCXXThisCapture(C->Loc, true, true, nullptr, C->Kind == LCK_StarThis);
       continue;
     }
 
     assert(C->Id && "missing identifier for capture");
-
     if (C->Init.isInvalid())
       continue;
 
@@ -1150,13 +1106,11 @@
       }
       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?");
+      if (auto *V = dyn_cast<VarDecl>(Var))
+        CheckShadow(CurrentScope, V);
+      PushOnScopeChains(Var, CurrentScope, false);
     } else {
       assert(C->InitKind == LambdaCaptureInitKind::NoInit &&
              "init capture has valid but null init?");
@@ -1202,13 +1156,25 @@
         continue;
     }
 
+    // C++11 [expr.prim.lambda]p10:
+    //   [...] each such lookup shall find a variable with automatic storage
+    //   duration declared in the reaching scope of the local lambda expression.
+    // Note that the 'reaching scope' check happens in tryCaptureVariable().
+    if (!Var) {
+      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
+      continue;
+    }
+
     // C++11 [expr.prim.lambda]p8:
     //   An identifier or this shall not appear more than once in a
     //   lambda-capture.
     if (!CaptureNames.insert(C->Id).second) {
-      if (Var && LSI->isCaptured(Var)) {
+      auto 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
@@ -1218,15 +1184,6 @@
       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;
@@ -1261,21 +1218,170 @@
     }
 
     if (C->Init.isUsable()) {
-      addInitCapture(LSI, cast<VarDecl>(Var));
+      addInitCapture(LSI, Underlying);
+      PushOnScopeChains(Var, CurScope, false);
     } else {
-      TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
-                                                   TryCapture_ExplicitByVal;
+      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;
+  PopDeclContext();
+}
+
+void Sema::ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
+                                        SourceLocation MutableLoc) {
+
+  LambdaScopeInfo *const LSI = getCurrentLambdaScopeUnsafe(*this);
+  LSI->Mutable = MutableLoc.isValid();
+  LSI->HasKnownMutability = true;
+  ContextRAII Context(*this, LSI->CallOperator, /*NewThisContext*/ false);
 
-  // Add lambda parameters into scope.
-  addLambdaParameters(Intro.Captures, Method, CurScope);
+  // C++11 [expr.prim.lambda]p9:
+  //   A lambda-expression whose smallest enclosing scope is a block scope is a
+  //   local lambda expression; any other lambda expression shall not have a
+  //   capture-default or simple-capture in its lambda-introducer.
+  //
+  // For simple-captures, this is covered by the check below that any named
+  // entity is a variable that can be captured.
+  //
+  // For DR1632, we also allow a capture-default in any context where we can
+  // odr-use 'this' (in particular, in a default initializer for a non-static
+  // data member).
+  if (Intro.Default != LCD_None &&
+      !LSI->Lambda->getParent()->isFunctionOrMethod() &&
+      (getCurrentThisType().isNull() ||
+       CheckCXXThisCapture(SourceLocation(), /*Explicit*/ true,
+                           /*BuildAndDiagnose*/ false)))
+    Diag(Intro.DefaultLoc, diag::err_capture_default_non_local);
+}
+
+void Sema::ActOnLambdaClosureParameters(
+    Scope *LambdaScope, MutableArrayRef<DeclaratorChunk::ParamInfo> Params) {
+  LambdaScopeInfo *const LSI = getCurrentLambdaScopeUnsafe(*this);
+  PushDeclContext(LambdaScope, LSI->CallOperator);
+
+  for (const DeclaratorChunk::ParamInfo &P : Params) {
+    auto *Param = cast<ParmVarDecl>(P.Param);
+    Param->setOwningFunction(LSI->CallOperator);
+    if (Param->getIdentifier())
+      PushOnScopeChains(Param, LambdaScope, false);
+  }
+
+  LSI->AfterParameterList = true;
+}
+
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        const DeclSpec &DS) {
+
+  LambdaScopeInfo *const LSI = getCurrentLambdaScopeUnsafe(*this);
+  LSI->CallOperator->setConstexprKind(DS.getConstexprSpecifier());
+
+  SmallVector<ParmVarDecl *, 8> Params;
+  bool ExplicitResultType;
+
+  SourceLocation TypeLoc, CallOperatorLoc;
+  if (ParamInfo.getNumTypeObjects() == 0) {
+    CallOperatorLoc = TypeLoc = Intro.Range.getEnd();
+  } else {
+    unsigned index;
+    ParamInfo.isFunctionDeclarator(index);
+    const auto &Object = ParamInfo.getTypeObject(index);
+    TypeLoc =
+        Object.Loc.isValid() ? Object.Loc : ParamInfo.getSourceRange().getEnd();
+    CallOperatorLoc = ParamInfo.getSourceRange().getEnd();
+  }
+
+  CXXRecordDecl *Class = LSI->Lambda;
+  CXXMethodDecl *Method = LSI->CallOperator;
+
+  TypeSourceInfo *MethodTyInfo = getLambdaType(
+      *this, Intro, ParamInfo, getCurScope(), TypeLoc, ExplicitResultType);
+
+  LSI->ExplicitParams = ParamInfo.getNumTypeObjects() != 0;
+
+  if (ParamInfo.isFunctionDeclarator() != 0 &&
+      !FTIHasSingleVoidParameter(ParamInfo.getFunctionTypeInfo())) {
+    const auto &FTI = ParamInfo.getFunctionTypeInfo();
+    Params.reserve(Params.size());
+    for (unsigned I = 0; I < FTI.NumParams; ++I) {
+      auto *Param = cast<ParmVarDecl>(FTI.Params[I].Param);
+      Param->setScopeInfo(0, Params.size());
+      Params.push_back(Param);
+    }
+  }
+
+  bool IsLambdaStatic =
+      ParamInfo.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static;
+
+  CompleteLambdaCallOperator(
+      Method, Intro.Range.getBegin(), CallOperatorLoc,
+      ParamInfo.getTrailingRequiresClause(), MethodTyInfo,
+      ParamInfo.getDeclSpec().getConstexprSpecifier(),
+      IsLambdaStatic ? SC_Static : SC_None, Params, ExplicitResultType);
+
+  ContextRAII ManglingContext(*this, Class->getDeclContext());
+
+  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->Captures) {
+    if (!C.isVariableCapture())
+      continue;
+    ValueDecl *Var = C.getVariable();
+    if (Var && Var->isInitCapture()) {
+      PushOnScopeChains(Var, CurScope, false);
+    }
+  }
+  LSI->DelayedCaptures.clear();
+
+  auto CheckRedefinition = [&](ParmVarDecl *Param) {
+    for (const auto &Capture : Intro.Captures) {
+      if (Capture.Id == Param->getIdentifier()) {
+        Diag(Param->getLocation(), diag::err_parameter_shadow_capture);
+        Diag(Capture.Loc, diag::note_var_explicitly_captured_here)
+            << Capture.Id << true;
+        return false;
+      }
+    }
+    return true;
+  };
+
+  for (ParmVarDecl *P : Params) {
+    if (!P->getIdentifier())
+      continue;
+    if (CheckRedefinition(P))
+      CheckShadow(CurScope, P);
+    PushOnScopeChains(P, CurScope);
+  }
 
   // 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
@@ -1135,7 +1135,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
@@ -18803,10 +18803,42 @@
   }
 }
 
+/*static bool CheckCaptureUseBeforeLambdaQualifiers(Sema &S, ValueDecl *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) {
+    ValueDecl *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->HasKnownMutability) {
+    // 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(
     ValueDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
     SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
     QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt) {
+
   // An init-capture is notionally from the context surrounding its
   // declaration, but its parent DC is the lambda class.
   DeclContext *VarDC = Var->getDeclContext();
@@ -18833,11 +18865,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 = !VD->hasLocalStorage();
@@ -18862,13 +18889,39 @@
   bool Nested = false;
   bool Explicit = (Kind != TryCapture_Implicit);
   unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
+  bool IsInScopeDeclarationContext;
+  bool CanCapture;
   do {
+    IsInScopeDeclarationContext = true;
+    CanCapture = true;
+
+    LambdaScopeInfo *LSI = nullptr;
+    if (!FunctionScopes.empty())
+      LSI = dyn_cast_or_null<LambdaScopeInfo>(
+          FunctionScopes[FunctionScopesIndex]);
+
+    IsInScopeDeclarationContext =
+        !LSI || LSI->AfterParameterList || CurContext == LSI->CallOperator;
+
+    if (LSI && !LSI->AfterParameterList) {
+      // This allows capturing parameters from a default value which does not
+      // seems correct
+      if (isa<ParmVarDecl>(Var) && !Var->getDeclContext()->isFunctionOrMethod())
+        return true;
+    }
+    // If the variable is declared in the current context, there is no need to
+    // capture it.
+    if (IsInScopeDeclarationContext &&
+        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 =
+        !IsInScopeDeclarationContext
+            ? 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.
@@ -18883,10 +18936,9 @@
     FunctionScopeInfo  *FSI = FunctionScopes[FunctionScopesIndex];
     CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI);
 
-
     // Check whether we've already captured it.
-    if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
-                                             DeclRefType)) {
+    if (CanCapture && isVariableAlreadyCapturedInScopeInfo(
+                          CSI, Var, Nested, CaptureType, DeclRefType)) {
       CSI->getCapture(Var).markUsed(BuildAndDiagnose);
       break;
     }
@@ -18894,7 +18946,7 @@
     // 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 (CanCapture && isGenericLambdaCallOperatorSpecialization(DC)) {
       if (BuildAndDiagnose) {
         LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
         if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
@@ -18909,7 +18961,7 @@
     }
 
     // Try to capture variable-length arrays types.
-    if (Var->getType()->isVariablyModifiedType()) {
+    if (CanCapture && Var->getType()->isVariablyModifiedType()) {
       // We're going to walk down into the type and look for VLA
       // expressions.
       QualType QTy = Var->getType();
@@ -18918,7 +18970,7 @@
       captureVariablyModifiedType(Context, QTy, CSI);
     }
 
-    if (getLangOpts().OpenMP) {
+    if (CanCapture && 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
@@ -18999,10 +19051,10 @@
       }
       return true;
     }
-
-    FunctionScopesIndex--;
-    DC = ParentDC;
     Explicit = false;
+    FunctionScopesIndex--;
+    if (IsInScopeDeclarationContext)
+      DC = ParentDC;
   } while (!VarDC->Equals(DC));
 
   // Walk back down the scope stack, (e.g. from outer lambda to inner lambda)
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
@@ -2308,7 +2308,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->AfterParameterList) {
         // 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.
@@ -2334,8 +2335,8 @@
       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->AfterParameterList) {
     // 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
@@ -1265,6 +1265,62 @@
   }
 }
 
+void Parser::ParseLambdaLexedGNUAttributeArgs(LateParsedAttribute &LA,
+                                              ParsedAttributes &Attrs,
+                                              Declarator &D) {
+  // Create a fake EOF so that attribute parsing won't go off the end of the
+  // attribute.
+  Token AttrEnd;
+  AttrEnd.startToken();
+  AttrEnd.setKind(tok::eof);
+  AttrEnd.setLocation(Tok.getLocation());
+  AttrEnd.setEofData(LA.Toks.data());
+  LA.Toks.push_back(AttrEnd);
+  // Append the current token at the end of the new token stream so that it
+  // doesn't get lost.
+  LA.Toks.push_back(Tok);
+  PP.EnterTokenStream(LA.Toks, true, /*IsReinject=*/true);
+  // Consume the previously pushed token.
+  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+
+  ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, nullptr, nullptr,
+                        SourceLocation(), ParsedAttr::AS_GNU, &D);
+  // After parsing attribute arguments, we've either reached the EOF token
+  // (signaling that parsing was successful) or we have tokens we need to
+  // consume until we reach the EOF.
+  while (Tok.isNot(tok::eof))
+    ConsumeAnyToken();
+
+  assert(Tok.is(tok::eof));
+  ConsumeAnyToken();
+}
+
+/// LambdaMayHaveMutableSpecifier Look ahead to see if the lambda will be
+/// mutable
+/// \returns true on success and false if the token was not balanced
+SourceLocation Parser::LambdaLookAheadMutableSpecifier() {
+  assert(Tok.is(tok::l_paren) && "expected the start of a lambda parameter");
+  RevertingTentativeParsingAction RAII(*this);
+  // skip the parameter list
+  ConsumeParen();
+  if (!SkipUntil(tok::r_paren))
+    return SourceLocation{};
+  // skip GNU/MSVC attributes
+  while (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec)) {
+    ConsumeToken();
+    if (!Tok.is(tok::l_paren))
+      return SourceLocation{};
+    ConsumeParen();
+    if (!SkipUntil(tok::r_paren))
+      return SourceLocation{};
+  }
+  while (Tok.isOneOf(tok::kw_constexpr, tok::kw_consteval))
+    ConsumeToken();
+  if (Tok.is(tok::kw_mutable))
+    return Tok.getLocation();
+  return SourceLocation{};
+}
+
 /// ParseLambdaExpressionAfterIntroducer - Parse the rest of a lambda
 /// expression.
 ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
@@ -1284,9 +1340,15 @@
   DeclSpec DS(AttrFactory);
   Declarator D(DS, ParsedAttributesView::none(), 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);
+  ParsedAttributes Attributes(AttrFactory);
   if (getLangOpts().CUDA) {
     // In CUDA code, GNU attributes are allowed to appear immediately after the
     // "[...]", even if there is no "(...)" before the lambda body.
@@ -1297,22 +1359,22 @@
       if (Tok.is(tok::kw___noinline__)) {
         IdentifierInfo *AttrName = Tok.getIdentifierInfo();
         SourceLocation AttrNameLoc = ConsumeToken();
-        Attr.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
-                    ParsedAttr::AS_Keyword);
+        Attributes.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr,
+                          0, ParsedAttr::AS_Keyword);
       } else if (Tok.is(tok::kw___attribute))
-        ParseGNUAttributes(Attr, nullptr, &D);
+        ParseGNUAttributes(Attributes, nullptr, &D);
       else
         break;
     }
 
-    D.takeAttributes(Attr);
+    D.takeAttributes(Attributes);
   }
 
   // Helper to emit a warning if we see a CUDA host/device/global attribute
   // after '(...)'. nvcc doesn't accept this.
   auto WarnIfHasCUDATargetAttr = [&] {
     if (getLangOpts().CUDA)
-      for (const ParsedAttr &A : Attr)
+      for (const ParsedAttr &A : Attributes)
         if (A.getKind() == ParsedAttr::AT_CUDADevice ||
             A.getKind() == ParsedAttr::AT_CUDAHost ||
             A.getKind() == ParsedAttr::AT_CUDAGlobal)
@@ -1349,7 +1411,7 @@
       }
 
       Actions.ActOnLambdaExplicitTemplateParameterList(
-          LAngleLoc, TemplateParams, RAngleLoc, RequiresClause);
+          Intro, LAngleLoc, TemplateParams, RAngleLoc, RequiresClause);
       ++CurTemplateDepthTracker;
     }
   }
@@ -1367,32 +1429,44 @@
 
   TypeResult TrailingReturnType;
   SourceLocation TrailingReturnTypeLoc;
+  SourceLocation LParenLoc, RParenLoc;
+  SourceLocation DeclEndLoc;
+  bool HasParentheses = false;
+  bool HasSpecifiers = false;
+  SourceLocation MutableLoc;
+  LateParsedAttrList LateParsedAttrs(true);
+
+  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.
+    // However, because GNU attributes could refer to captured variables,
+    // which only become visible after the mutable keyword is parsed
+    // we delay the parsing of gnu attributes - by reusing the mechanism used
+    // for C++ late method parsing. Note, __declspec attributes do not make
+    // use of late parsing (expressions cannot appear in __declspec arguments),
+    // so only GNU style attributes are affected here.
+    MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attributes,
+                         &LateParsedAttrs);
+    // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update
+    // the DeclEndLoc.
+    SourceLocation ConstexprLoc;
+    SourceLocation ConstevalLoc;
+    SourceLocation StaticLoc;
+
+    tryConsumeLambdaSpecifierToken(*this, MutableLoc, StaticLoc, ConstexprLoc,
+                                   ConstevalLoc, DeclEndLoc);
+
+    DiagnoseStaticSpecifierRestrictions(*this, StaticLoc, MutableLoc, Intro);
+
+    addStaticToLambdaDeclSpecifier(*this, StaticLoc, DS);
+    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 lambda specifiers and update the DeclEndLoc.
-        SourceLocation MutableLoc;
-        SourceLocation StaticLoc;
-        SourceLocation ConstexprLoc;
-        SourceLocation ConstevalLoc;
-        tryConsumeLambdaSpecifierToken(*this, MutableLoc, StaticLoc,
-                                       ConstexprLoc, ConstevalLoc, DeclEndLoc);
-
-        DiagnoseStaticSpecifierRestrictions(*this, StaticLoc, MutableLoc,
-                                            Intro);
-
-        addStaticToLambdaDeclSpecifier(*this, StaticLoc, DS);
-        addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
-        addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
         // Parse exception-specification[opt].
         ExceptionSpecificationType ESpecType = EST_None;
         SourceRange ESpecRange;
@@ -1400,6 +1474,15 @@
         SmallVector<SourceRange, 2> DynamicExceptionRanges;
         ExprResult NoexceptExpr;
         CachedTokens *ExceptionSpecTokens;
+
+        // At this point we know whether the lambda is mutable so we can
+        // complete the parsing of gnu attributes.
+        for (LateParsedAttribute *Attr : LateParsedAttrs) {
+          ParseLambdaLexedGNUAttributeArgs(*Attr, Attributes, D);
+          delete Attr;
+        }
+        LateParsedAttrs.clear();
+
         ESpecType = tryParseExceptionSpecification(
             /*Delayed=*/false, ESpecRange, DynamicExceptions,
             DynamicExceptionRanges, NoexceptExpr, ExceptionSpecTokens);
@@ -1408,8 +1491,8 @@
           DeclEndLoc = ESpecRange.getEnd();
 
         // Parse attribute-specifier[opt].
-        if (MaybeParseCXX11Attributes(Attr))
-          DeclEndLoc = Attr.Range.getEnd();
+        if (MaybeParseCXX11Attributes(Attributes))
+          DeclEndLoc = Attributes.Range.getEnd();
 
         // Parse OpenCL addr space attribute.
         if (Tok.isOneOf(tok::kw___private, tok::kw___global, tok::kw___local,
@@ -1445,27 +1528,32 @@
                 /*ExceptionSpecTokens*/ nullptr,
                 /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D,
                 TrailingReturnType, TrailingReturnTypeLoc, &DS),
-            std::move(Attr), DeclEndLoc);
+            std::move(Attributes), DeclEndLoc);
+
+        if (HasParentheses && Tok.is(tok::kw_requires))
+          ParseTrailingRequiresClause(D);
+
+        Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
       };
 
-  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(
           CurTemplateDepthTracker.getOriginalDepth());
 
-      ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
+      ParseParameterDeclarationClause(D, Attributes, ParamInfo, EllipsisLoc);
       // For a generic lambda, each 'auto' within the parameter declaration
       // clause creates a template type parameter, so increment the depth.
       // If we've parsed any explicit template parameters, then the depth will
@@ -1476,44 +1564,49 @@
     }
 
     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_static,
-                         tok::kw___private, tok::kw___global, tok::kw___local,
-                         tok::kw___constant, tok::kw___generic,
-                         tok::kw_groupshared, 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_static,
+                  tok::kw___private, tok::kw___global, tok::kw___local,
+                  tok::kw___constant, tok::kw___generic, tok::kw_groupshared,
+                  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(), "() ");
+  }
+
+  if (HasParentheses || HasSpecifiers) {
+    ParseConstexprAndMutableSpecifiers();
+  }
+
+  Actions.ActOnLambdaClosureParameters(getCurScope(), ParamInfo);
 
-    SourceLocation NoLoc;
-    // Parse lambda-specifiers.
-    std::vector<DeclaratorChunk::ParamInfo> EmptyParamInfo;
-    ParseLambdaSpecifiers(/*LParenLoc=*/NoLoc, /*RParenLoc=*/NoLoc,
-                          EmptyParamInfo, /*EllipsisLoc=*/NoLoc);
+  if (!HasParentheses) {
+    Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
   }
 
+  if (HasSpecifiers || HasParentheses || !LateParsedAttrs.empty())
+    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 |
                         Scope::CompoundStmtScope;
   ParseScope BodyScope(this, ScopeFlags);
 
-  Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
+  Actions.ActOnStartOfLambdaDefinition(Intro, D, DS);
 
   // Parse compound-statement.
   if (!Tok.is(tok::l_brace)) {
@@ -1525,6 +1618,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
@@ -7062,15 +7062,21 @@
       Optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling = None);
 
   /// Endow the lambda scope info with the relevant properties.
-  void buildLambdaScope(sema::LambdaScopeInfo *LSI,
-                        CXXMethodDecl *CallOperator,
+  void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
                         SourceRange IntroducerRange,
                         LambdaCaptureDefault CaptureDefault,
-                        SourceLocation CaptureDefaultLoc,
-                        bool ExplicitParams,
-                        bool ExplicitResultType,
+                        SourceLocation CaptureDefaultLoc, bool ExplicitParams,
                         bool Mutable);
 
+  CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
+                                          CXXRecordDecl *Class);
+  void CompleteLambdaCallOperator(
+      CXXMethodDecl *Method, SourceLocation LambdaLoc,
+      SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
+      TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
+      StorageClass SC, ArrayRef<ParmVarDecl *> Params,
+      bool HasExplicitResultType);
+
   /// Perform initialization analysis of the init-capture and perform
   /// any implicit conversions such as an lvalue-to-rvalue conversion if
   /// not being used to initialize a reference.
@@ -7091,11 +7097,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);
@@ -7104,28 +7108,38 @@
   /// 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);
+  void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
+                                    SourceLocation MutableLoc);
 
-  /// Deduce a block or lambda's return type based on the return
-  /// statements present in the body.
-  void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+  void ActOnLambdaClosureParameters(
+      Scope *LambdaScope,
+      MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo);
 
   /// ActOnStartOfLambdaDefinition - This is called just before we start
   /// parsing the body of a lambda; it analyzes the explicit captures and
   /// arguments, and sets up various data-structures for the body of the
   /// lambda.
   void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
-                                    Declarator &ParamInfo, Scope *CurScope);
+                                    Declarator &ParamInfo, const DeclSpec &DS);
 
   /// ActOnLambdaError - If there is an error parsing a lambda, this callback
   /// is invoked to pop the information about the lambda.
Index: clang/include/clang/Sema/ScopeInfo.h
===================================================================
--- clang/include/clang/Sema/ScopeInfo.h
+++ clang/include/clang/Sema/ScopeInfo.h
@@ -835,6 +835,29 @@
   /// The lambda's compiler-generated \c operator().
   CXXMethodDecl *CallOperator = nullptr;
 
+  struct DelayedCapture {
+    ValueDecl *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 HasKnownMutability = true;
+  bool AfterParameterList = true;
+
   /// 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
@@ -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/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -1920,7 +1920,10 @@
   bool
   ParseLambdaIntroducer(LambdaIntroducer &Intro,
                         LambdaIntroducerTentativeParse *Tentative = nullptr);
+  SourceLocation LambdaLookAheadMutableSpecifier();
   ExprResult ParseLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro);
+  void ParseLambdaLexedGNUAttributeArgs(LateParsedAttribute &LA,
+                                        ParsedAttributes &Attrs, Declarator &D);
 
   //===--------------------------------------------------------------------===//
   // C++ 5.2p1: C++ Casts
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7804,6 +7804,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
@@ -1814,6 +1814,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
@@ -656,6 +656,9 @@
 - Implemented `P1169R4: static operator() <https://wg21.link/P1169R4>`_.
 - Implemented "char8_t Compatibility and Portability Fix" (`P2513R3 <https://wg21.link/P2513R3>`_).
   This Change was applied to C++20 as a Defect Report.
+- 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/HIP Language Changes in Clang
 ----------------------------------
@@ -812,8 +815,8 @@
 - Introduced the new function ``clang_CXXMethod_isMoveAssignmentOperator``,
   which identifies whether a method cursor is a move-assignment
   operator.
-- ``clang_Cursor_getNumTemplateArguments``, ``clang_Cursor_getTemplateArgumentKind``, 
-  ``clang_Cursor_getTemplateArgumentType``, ``clang_Cursor_getTemplateArgumentValue`` and 
+- ``clang_Cursor_getNumTemplateArguments``, ``clang_Cursor_getTemplateArgumentKind``,
+  ``clang_Cursor_getTemplateArgumentType``, ``clang_Cursor_getTemplateArgumentValue`` and
   ``clang_Cursor_getTemplateArgumentUnsignedValue`` now work on struct, class,
   and partial template specialization cursors in addition to function cursors.
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to