[clang] 74ce297 - Revert "[Clang] Implement Change scope of lambda trailing-return-type"

Jordan Rupprecht via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 3 08:49:42 PST 2023


Author: Jordan Rupprecht
Date: 2023-02-03T08:49:34-08:00
New Revision: 74ce297045bac4bc475b8e762d2a1ea19bb16d3c

URL: https://github.com/llvm/llvm-project/commit/74ce297045bac4bc475b8e762d2a1ea19bb16d3c
DIFF: https://github.com/llvm/llvm-project/commit/74ce297045bac4bc475b8e762d2a1ea19bb16d3c.diff

LOG: Revert "[Clang] Implement Change scope of lambda trailing-return-type"

This reverts commit d708a186b6a9b050d09558163dd353d9f738c82d (and typo fix e4bc9898ddbeb70bc49d713bbf863f050f21e03f). It causes a compilation error for this:

```
struct StringLiteral {
  template <int N>
  StringLiteral(const char (&array)[N])
      __attribute__((enable_if(N > 0 && N == __builtin_strlen(array) + 1,
                               "invalid string literal")));
};

struct Message {
  Message(StringLiteral);
};

void Func1() {
  auto x = Message("x");  // Note: this is fine

  // Note: "xx\0" to force a different type, StringLiteral<3>, otherwise this
  // successfully builds.
  auto y = [&](decltype(Message("xx"))) {};

  // ^ fails with: repro.cc:18:13: error: reference to local variable 'array'
  // declared in enclosing function 'StringLiteral::StringLiteral<3>'

  (void)x;
  (void)y;
}
```

More details posted to D124351.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/AST/DeclCXX.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/SemaConcept.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaExprCXX.cpp
    clang/lib/Sema/SemaLambda.cpp
    clang/lib/Sema/SemaTemplateInstantiate.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/warn-shadow-in-lambdas.cpp
    clang/www/cxx_status.html

Removed: 
    clang/test/SemaCXX/lambda-capture-type-deduction.cpp


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d2f1919f24a3..4463f0317454 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -130,11 +130,6 @@ C++20 Feature Support
 C++2b Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
-- Implemented `P2036R3: Change scope of lambda trailing-return-type <https://wg21.link/P2036R3>`_
-  and `P2579R0 Mitigation strategies for P2036 <https://wg21.link/P2579R0>`_.
-  These proposals modify 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
 ----------------------------------
 

diff  --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index ff8f8a1bb12d..11276c77490c 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1092,11 +1092,6 @@ class CXXRecordDecl : public RecordDecl {
 
   unsigned capture_size() const { return getLambdaData().NumCaptures; }
 
-  const LambdaCapture *getCapture(unsigned I) const {
-    assert(isLambda() && I < capture_size() && "invalid index for capture");
-    return captures_begin() + I;
-  }
-
   using conversion_iterator = UnresolvedSetIterator;
 
   conversion_iterator conversion_begin() const {
@@ -1831,20 +1826,6 @@ class CXXRecordDecl : public RecordDecl {
     return getLambdaData().MethodTyInfo;
   }
 
-  void setLambdaTypeInfo(TypeSourceInfo *TS) {
-    assert(DefinitionData && DefinitionData->IsLambda &&
-           "setting lambda property of non-lambda class");
-    auto &DL = static_cast<LambdaDefinitionData &>(*DefinitionData);
-    DL.MethodTyInfo = TS;
-  }
-
-  void setLambdaIsGeneric(bool IsGeneric) {
-    assert(DefinitionData && DefinitionData->IsLambda &&
-           "setting lambda property of non-lambda class");
-    auto &DL = static_cast<LambdaDefinitionData &>(*DefinitionData);
-    DL.IsGenericLambda = IsGeneric;
-  }
-
   // Determine whether this type is an Interface Like type for
   // __interface inheritance purposes.
   bool isInterfaceLike() const;

diff  --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index 9e81706cd2aa..be5cdb62045b 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -145,11 +145,6 @@ class Scope {
     /// This is a scope of some OpenMP directive with
     /// order clause which specifies concurrent
     OpenMPOrderClauseScope = 0x4000000,
-    /// This is the scope for a lambda, after the lambda introducer.
-    /// Lambdas need two FunctionPrototypeScope scopes (because there is a
-    /// template scope in between), the outer scope does not increase the
-    /// depth of recursion.
-    LambdaScope = 0x8000000,
   };
 
 private:

diff  --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
index 5888dee0a883..65fa18fbb290 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -838,11 +838,6 @@ class LambdaScopeInfo final :
   /// The lambda's compiler-generated \c operator().
   CXXMethodDecl *CallOperator = nullptr;
 
-  /// Indicate that we parsed the parameter list
-  /// at which point the mutability of the lambda
-  /// is known.
-  bool AfterParameterList = true;
-
   /// Source range covering the lambda introducer [...].
   SourceRange IntroducerRange;
 
@@ -854,9 +849,8 @@ class LambdaScopeInfo final :
   /// explicit captures.
   unsigned NumExplicitCaptures = 0;
 
-  /// Whether this is a mutable lambda. Until the mutable keyword is parsed,
-  /// we assume the lambda is mutable.
-  bool Mutable = true;
+  /// Whether this is a mutable lambda.
+  bool Mutable = false;
 
   /// Whether the (empty) parameter list is explicit.
   bool ExplicitParams = false;

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 67d55ab3d8c6..b8a0727d6510 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7103,21 +7103,15 @@ class Sema final {
           std::nullopt);
 
   /// 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,
+                        SourceLocation CaptureDefaultLoc,
+                        bool ExplicitParams,
+                        bool ExplicitResultType,
                         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.
@@ -7138,9 +7132,11 @@ class Sema final {
   ///
   ///  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, DeclContext *DeclCtx);
+  VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc,
+                                          QualType InitCaptureType,
+                                          SourceLocation EllipsisLoc,
+                                          IdentifierInfo *Id,
+                                          unsigned InitStyle, Expr *Init);
 
   /// Add an init-capture to a lambda scope.
   void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var,
@@ -7150,38 +7146,28 @@ class Sema final {
   /// given lambda.
   void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
 
-  /// 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 ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
-                                            Scope *CurContext);
-
-  /// This is called after parsing the explicit template parameter list
+  /// \brief This is called after parsing the explicit template parameter list
   /// on a lambda (if it exists) in C++2a.
-  void ActOnLambdaExplicitTemplateParameterList(LambdaIntroducer &Intro,
-                                                SourceLocation LAngleLoc,
+  void ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc,
                                                 ArrayRef<NamedDecl *> TParams,
                                                 SourceLocation RAngleLoc,
                                                 ExprResult RequiresClause);
 
-  void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
-                                    SourceLocation MutableLoc);
+  /// Introduce the lambda parameters into scope.
+  void addLambdaParameters(
+      ArrayRef<LambdaIntroducer::LambdaCapture> Captures,
+      CXXMethodDecl *CallOperator, Scope *CurScope);
 
-  void ActOnLambdaClosureParameters(
-      Scope *LambdaScope,
-      MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo);
+  /// Deduce a block or lambda's return type based on the return
+  /// statements present in the body.
+  void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
 
   /// 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, const DeclSpec &DS);
+                                    Declarator &ParamInfo, Scope *CurScope);
 
   /// ActOnLambdaError - If there is an error parsing a lambda, this callback
   /// is invoked to pop the information about the lambda.
@@ -7276,13 +7262,6 @@ class Sema final {
       LocalInstantiationScope &Scope,
       const MultiLevelTemplateArgumentList &TemplateArgs);
 
-  /// Introduce the instantiated captures of the lambda into the local
-  /// instantiation scope.
-  bool addInstantiatedCapturesToScope(
-      FunctionDecl *Function, const FunctionDecl *PatternDecl,
-      LocalInstantiationScope &Scope,
-      const MultiLevelTemplateArgumentList &TemplateArgs);
-
   /// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
   /// the case of lambdas) set up the LocalInstantiationScope of the current
   /// function.

diff  --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 45460db85b87..7f09120574a7 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1275,19 +1275,18 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
                                 "lambda expression parsing");
 
+
+
+  // FIXME: Call into Actions to add any init-capture declarations to the
+  // scope while parsing the lambda-declarator and compound-statement.
+
   // Parse lambda-declarator[opt].
   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.ActOnLambdaExpressionAfterIntroducer(Intro, getCurScope());
 
-  ParsedAttributes Attributes(AttrFactory);
+  ParsedAttributes Attr(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.
@@ -1298,22 +1297,22 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
       if (Tok.is(tok::kw___noinline__)) {
         IdentifierInfo *AttrName = Tok.getIdentifierInfo();
         SourceLocation AttrNameLoc = ConsumeToken();
-        Attributes.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr,
-                          0, ParsedAttr::AS_Keyword);
+        Attr.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+                    ParsedAttr::AS_Keyword);
       } else if (Tok.is(tok::kw___attribute))
-        ParseGNUAttributes(Attributes, nullptr, &D);
+        ParseGNUAttributes(Attr, nullptr, &D);
       else
         break;
     }
 
-    D.takeAttributes(Attributes);
+    D.takeAttributes(Attr);
   }
 
   // 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 : Attributes)
+      for (const ParsedAttr &A : Attr)
         if (A.getKind() == ParsedAttr::AT_CUDADevice ||
             A.getKind() == ParsedAttr::AT_CUDAHost ||
             A.getKind() == ParsedAttr::AT_CUDAGlobal)
@@ -1350,7 +1349,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
       }
 
       Actions.ActOnLambdaExplicitTemplateParameterList(
-          Intro, LAngleLoc, TemplateParams, RAngleLoc, RequiresClause);
+          LAngleLoc, TemplateParams, RAngleLoc, RequiresClause);
       ++CurTemplateDepthTracker;
     }
   }
@@ -1368,36 +1367,32 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
 
   TypeResult TrailingReturnType;
   SourceLocation TrailingReturnTypeLoc;
-  SourceLocation LParenLoc, RParenLoc;
-  SourceLocation DeclEndLoc;
-  bool HasParentheses = false;
-  bool HasSpecifiers = false;
-  SourceLocation MutableLoc;
-
-  auto ParseConstexprAndMutableSpecifiers = [&] {
-    // GNU-style attributes must be parsed before the mutable specifier to
-    // be compatible with GCC. MSVC-style attributes must be parsed before
-    // the mutable specifier to be compatible with MSVC.
-    MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attributes);
-    // 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 =
-      [&](MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo,
+      [&](SourceLocation LParenLoc, SourceLocation RParenLoc,
+          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;
@@ -1405,7 +1400,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
         SmallVector<SourceRange, 2> DynamicExceptionRanges;
         ExprResult NoexceptExpr;
         CachedTokens *ExceptionSpecTokens;
-
         ESpecType = tryParseExceptionSpecification(
             /*Delayed=*/false, ESpecRange, DynamicExceptions,
             DynamicExceptionRanges, NoexceptExpr, ExceptionSpecTokens);
@@ -1414,8 +1408,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
           DeclEndLoc = ESpecRange.getEnd();
 
         // Parse attribute-specifier[opt].
-        if (MaybeParseCXX11Attributes(Attributes))
-          DeclEndLoc = Attributes.Range.getEnd();
+        if (MaybeParseCXX11Attributes(Attr))
+          DeclEndLoc = Attr.Range.getEnd();
 
         // Parse OpenCL addr space attribute.
         if (Tok.isOneOf(tok::kw___private, tok::kw___global, tok::kw___local,
@@ -1451,32 +1445,27 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
                 /*ExceptionSpecTokens*/ nullptr,
                 /*DeclsInPrototype=*/std::nullopt, LParenLoc, FunLocalRangeEnd,
                 D, TrailingReturnType, TrailingReturnTypeLoc, &DS),
-            std::move(Attributes), DeclEndLoc);
-
-        Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
-
-        if (HasParentheses && Tok.is(tok::kw_requires))
-          ParseTrailingRequiresClause(D);
+            std::move(Attr), DeclEndLoc);
       };
 
-  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)) {
+    ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
+                                        Scope::FunctionDeclarationScope |
+                                        Scope::DeclScope);
+
     BalancedDelimiterTracker T(*this, tok::l_paren);
     T.consumeOpen();
-    LParenLoc = T.getOpenLocation();
+    SourceLocation LParenLoc = T.getOpenLocation();
+
+    // Parse parameter-declaration-clause.
+    SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+    SourceLocation EllipsisLoc;
 
     if (Tok.isNot(tok::r_paren)) {
       Actions.RecordParsingTemplateParameterDepth(
           CurTemplateDepthTracker.getOriginalDepth());
 
-      ParseParameterDeclarationClause(D, Attributes, ParamInfo, EllipsisLoc);
+      ParseParameterDeclarationClause(D, Attr, 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
@@ -1487,47 +1476,44 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
     }
 
     T.consumeClose();
-    DeclEndLoc = RParenLoc = T.getCloseLocation();
-    HasParentheses = true;
-  }
 
-  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)
+    // 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)
       // 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);
-
-  if (!HasParentheses)
-    Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
-
-  if (HasSpecifiers || HasParentheses)
-    ParseLambdaSpecifiers(ParamInfo, EllipsisLoc);
+    SourceLocation NoLoc;
+    // Parse lambda-specifiers.
+    std::vector<DeclaratorChunk::ParamInfo> EmptyParamInfo;
+    ParseLambdaSpecifiers(/*LParenLoc=*/NoLoc, /*RParenLoc=*/NoLoc,
+                          EmptyParamInfo, /*EllipsisLoc=*/NoLoc);
+  }
 
   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, DS);
+  Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
 
   // Parse compound-statement.
   if (!Tok.is(tok::l_brace)) {
@@ -1539,7 +1525,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
   StmtResult Stmt(ParseCompoundStatementBody());
   BodyScope.Exit();
   TemplateParamScope.Exit();
-  LambdaScope.Exit();
 
   if (!Stmt.isInvalid() && !TrailingReturnType.isInvalid())
     return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope());

diff  --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp
index 4570d8c615fe..c995c7e65f4b 100644
--- a/clang/lib/Sema/Scope.cpp
+++ b/clang/lib/Sema/Scope.cpp
@@ -70,10 +70,8 @@ void Scope::setFlags(Scope *parent, unsigned flags) {
   if (flags & BlockScope)         BlockParent = this;
   if (flags & TemplateParamScope) TemplateParamParent = this;
 
-  // 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 this is a prototype scope, record that.
+  if (flags & FunctionPrototypeScope) PrototypeDepth++;
 
   if (flags & DeclScope) {
     if (flags & FunctionPrototypeScope)

diff  --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 770b8db7e350..e5566b177aff 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2333,8 +2333,7 @@ FunctionScopeInfo *Sema::getEnclosingFunction() const {
 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) &&
-          LSI->AfterParameterList) {
+      if (LSI->Lambda && !LSI->Lambda->Encloses(CurContext)) {
         // 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.
@@ -2360,8 +2359,8 @@ LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
       return nullptr;
   }
   auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I);
-  if (CurLSI && CurLSI->Lambda && CurLSI->CallOperator &&
-      !CurLSI->Lambda->Encloses(CurContext) && CurLSI->AfterParameterList) {
+  if (CurLSI && CurLSI->Lambda &&
+      !CurLSI->Lambda->Encloses(CurContext)) {
     // We have switched contexts due to template instantiation.
     assert(!CodeSynthesisContexts.empty());
     return nullptr;

diff  --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 1ef83ea52e73..daa61ba45e8e 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -292,11 +292,6 @@ bool Sema::ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc,
 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()) {
@@ -313,6 +308,9 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
   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;

diff  --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 765110d6b230..a92bbde113fc 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -519,55 +519,6 @@ bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
       .isInvalid();
 }
 
-bool Sema::addInstantiatedCapturesToScope(
-    FunctionDecl *Function, const FunctionDecl *PatternDecl,
-    LocalInstantiationScope &Scope,
-    const MultiLevelTemplateArgumentList &TemplateArgs) {
-  const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
-  const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
-
-  unsigned Instantiated = 0;
-  for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
-    if (!CapturePattern.capturesVariable()) {
-      Instantiated++;
-      continue;
-    }
-    const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
-    if (!CapturedPattern->isParameterPack()) {
-      ValueDecl *CapturedVar =
-          LambdaClass->getCapture(Instantiated)->getCapturedVar();
-      if (cast<CXXMethodDecl>(Function)->isConst()) {
-        QualType T = CapturedVar->getType();
-        T.addConst();
-        CapturedVar->setType(T);
-      }
-      if (CapturedVar->isInitCapture())
-        Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
-      Instantiated++;
-    } else {
-      Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
-      std::optional<unsigned> NumArgumentsInExpansion =
-          getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
-      if (!NumArgumentsInExpansion)
-        continue;
-      for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
-        ValueDecl *CapturedVar =
-            LambdaClass->getCapture(Instantiated)->getCapturedVar();
-        if (cast<CXXMethodDecl>(Function)->isConst()) {
-          QualType T = CapturedVar->getType();
-          T.addConst();
-          CapturedVar->setType(T);
-        }
-        if (CapturedVar->isInitCapture())
-          Scope.InstantiatedLocalPackArg(CapturedPattern,
-                                         cast<VarDecl>(CapturedVar));
-        Instantiated++;
-      }
-    }
-  }
-  return false;
-}
-
 bool Sema::SetupConstraintScope(
     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
     MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
@@ -601,11 +552,6 @@ bool Sema::SetupConstraintScope(
       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
                                            Scope, MLTAL))
         return true;
-      // Make sure the captures are also added to the instantiation scope.
-      if (isLambdaCallOperator(FD) &&
-          addInstantiatedCapturesToScope(FD, FromMemTempl->getTemplatedDecl(),
-                                         Scope, MLTAL))
-        return true;
     }
 
     return false;
@@ -630,11 +576,6 @@ bool Sema::SetupConstraintScope(
     // child-function.
     if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
       return true;
-
-    // Make sure the captures are also added to the instantiation scope.
-    if (isLambdaCallOperator(FD) &&
-        addInstantiatedCapturesToScope(FD, InstantiatedFrom, Scope, MLTAL))
-      return true;
   }
 
   return false;

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 829765c7c461..6758797a1107 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19082,6 +19082,11 @@ bool Sema::tryCaptureVariable(
     }
   }
 
+
+  // 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();
@@ -19107,34 +19112,12 @@ bool Sema::tryCaptureVariable(
   bool Explicit = (Kind != TryCapture_Implicit);
   unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
   do {
-
-    LambdaScopeInfo *LSI = nullptr;
-    if (!FunctionScopes.empty())
-      LSI = dyn_cast_or_null<LambdaScopeInfo>(
-          FunctionScopes[FunctionScopesIndex]);
-
-    bool 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 =
-        !IsInScopeDeclarationContext
-            ? DC->getParent()
-            : getParentOfCapturingContextOrNull(DC, Var, ExprLoc,
-                                                BuildAndDiagnose, *this);
+    DeclContext *ParentDC = 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.
@@ -19149,6 +19132,7 @@ bool Sema::tryCaptureVariable(
     FunctionScopeInfo  *FSI = FunctionScopes[FunctionScopesIndex];
     CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI);
 
+
     // Check whether we've already captured it.
     if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
                                              DeclRefType)) {
@@ -19264,10 +19248,10 @@ bool Sema::tryCaptureVariable(
       }
       return true;
     }
-    Explicit = false;
+
     FunctionScopesIndex--;
-    if (IsInScopeDeclarationContext)
-      DC = ParentDC;
+    DC = ParentDC;
+    Explicit = false;
   } while (!VarDC->Equals(DC));
 
   // Walk back down the scope stack, (e.g. from outer lambda to inner lambda)

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 17408ef9504e..ef012770747c 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1136,7 +1136,7 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda(
 
     if (C.isCopyCapture()) {
       ClassType.removeLocalCVRQualifiers(Qualifiers::CVRMask);
-      if (!CurLSI->Mutable)
+      if (CurLSI->CallOperator->isConst())
         ClassType.addConst();
       return ASTCtx.getPointerType(ClassType);
     }

diff  --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 2b2b2e3afd86..00ab6ba580bf 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -247,9 +247,8 @@ Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info,
   DeclContext *DC = CurContext;
   while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
     DC = DC->getParent();
-
-  bool IsGenericLambda =
-      Info && getGenericLambdaTemplateParameterList(getCurLambda(), *this);
+  bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
+                                                               *this);
   // Start constructing the lambda class.
   CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(
       Context, DC, Info, IntroducerRange.getBegin(), LambdaDependencyKind,
@@ -365,13 +364,14 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) {
   llvm_unreachable("unexpected context");
 }
 
-static QualType
-buildTypeForLambdaCallOperator(Sema &S, clang::CXXRecordDecl *Class,
-                               TemplateParameterList *TemplateParams,
-                               TypeSourceInfo *MethodTypeInfo) {
-  assert(MethodTypeInfo && "expected a non null type");
-
+CXXMethodDecl *Sema::startLambdaDefinition(
+    CXXRecordDecl *Class, SourceRange IntroducerRange,
+    TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc,
+    ArrayRef<ParmVarDecl *> Params, ConstexprSpecKind ConstexprKind,
+    StorageClass SC, Expr *TrailingRequiresClause) {
   QualType MethodType = MethodTypeInfo->getType();
+  TemplateParameterList *TemplateParams =
+      getGenericLambdaTemplateParameterList(getCurLambda(), *this);
   // If a lambda appears in a dependent context or is a generic lambda (has
   // template parameters) and has an 'auto' return type, deduce it to a
   // dependent type.
@@ -379,12 +379,58 @@ buildTypeForLambdaCallOperator(Sema &S, clang::CXXRecordDecl *Class,
     const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
     QualType Result = FPT->getReturnType();
     if (Result->isUndeducedType()) {
-      Result = S.SubstAutoTypeDependent(Result);
-      MethodType = S.Context.getFunctionType(Result, FPT->getParamTypes(),
-                                             FPT->getExtProtoInfo());
+      Result = SubstAutoTypeDependent(Result);
+      MethodType = Context.getFunctionType(Result, FPT->getParamTypes(),
+                                           FPT->getExtProtoInfo());
     }
   }
-  return MethodType;
+
+  // 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;
 }
 
 void Sema::handleLambdaNumbering(
@@ -442,25 +488,14 @@ void Sema::handleLambdaNumbering(
   }
 }
 
-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) {
+void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
+                                        CXXMethodDecl *CallOperator,
+                                        SourceRange IntroducerRange,
+                                        LambdaCaptureDefault CaptureDefault,
+                                        SourceLocation CaptureDefaultLoc,
+                                        bool ExplicitParams,
+                                        bool ExplicitResultType,
+                                        bool Mutable) {
   LSI->CallOperator = CallOperator;
   CXXRecordDecl *LambdaClass = CallOperator->getParent();
   LSI->Lambda = LambdaClass;
@@ -472,16 +507,30 @@ void Sema::buildLambdaScope(LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
   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(
-    LambdaIntroducer &Intro, SourceLocation LAngleLoc,
-    ArrayRef<NamedDecl *> TParams, SourceLocation RAngleLoc,
-    ExprResult RequiresClause) {
+void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc,
+                                                    ArrayRef<NamedDecl *> TParams,
+                                                    SourceLocation RAngleLoc,
+                                                    ExprResult RequiresClause) {
   LambdaScopeInfo *LSI = getCurLambda();
   assert(LSI && "Expected a lambda scope");
   assert(LSI->NumExplicitTemplateParams == 0 &&
@@ -497,6 +546,35 @@ void Sema::ActOnLambdaExplicitTemplateParameterList(
   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.
 ///
@@ -783,9 +861,11 @@ QualType Sema::buildLambdaInitCaptureInitialization(
   return DeducedType;
 }
 
-VarDecl *Sema::createLambdaInitCaptureVarDecl(
-    SourceLocation Loc, QualType InitCaptureType, SourceLocation EllipsisLoc,
-    IdentifierInfo *Id, unsigned InitStyle, Expr *Init, DeclContext *DeclCtx) {
+VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
+                                              QualType InitCaptureType,
+                                              SourceLocation EllipsisLoc,
+                                              IdentifierInfo *Id,
+                                              unsigned InitStyle, Expr *Init) {
   // FIXME: Retain the TypeSourceInfo from buildLambdaInitCaptureInitialization
   // rather than reconstructing it here.
   TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, Loc);
@@ -796,8 +876,8 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(
   // used as a variable, and only exists as a way to name and refer to the
   // init-capture.
   // FIXME: Pass in separate source locations for '&' and identifier.
-  VarDecl *NewVD = VarDecl::Create(Context, DeclCtx, Loc, Loc, Id,
-                                   InitCaptureType, TSI, SC_Auto);
+  VarDecl *NewVD = VarDecl::Create(Context, CurContext, Loc,
+                                   Loc, Id, InitCaptureType, TSI, SC_Auto);
   NewVD->setInitCapture(true);
   NewVD->setReferenced(true);
   // FIXME: Pass in a VarDecl::InitializationStyle.
@@ -817,46 +897,35 @@ void Sema::addInitCapture(LambdaScopeInfo *LSI, VarDecl *Var,
                   Var->getType(), /*Invalid*/ false);
 }
 
-// Unlike getCurLambda, getCurrentLambdaScopeUnsafe doesn't
-// check that the current lambda is in a consistent or fully constructed state.
-static LambdaScopeInfo *getCurrentLambdaScopeUnsafe(Sema &S) {
-  assert(!S.FunctionScopes.empty());
-  return cast<LambdaScopeInfo>(S.FunctionScopes[S.FunctionScopes.size() - 1]);
-}
-
-static TypeSourceInfo *
-getDummyLambdaType(Sema &S, SourceLocation Loc = SourceLocation()) {
-  // C++11 [expr.prim.lambda]p4:
-  //   If a lambda-expression does not include a lambda-declarator, it is as
-  //   if the lambda-declarator were ().
-  FunctionProtoType::ExtProtoInfo EPI(S.Context.getDefaultCallingConvention(
-      /*IsVariadic=*/false, /*IsCXXMethod=*/true));
-  EPI.HasTrailingReturn = true;
-  EPI.TypeQuals.addConst();
-  LangAS AS = S.getDefaultCXXMethodAddrSpace();
-  if (AS != LangAS::Default)
-    EPI.TypeQuals.addAddressSpace(AS);
-
-  // C++1y [expr.prim.lambda]:
-  //   The lambda return type is 'auto', which is replaced by the
-  //   trailing-return type if provided and/or deduced from 'return'
-  //   statements
-  // We don't do this before C++1y, because we don't support deduced return
-  // types there.
-  QualType DefaultTypeForNoTrailingReturn = S.getLangOpts().CPlusPlus14
-                                                ? S.Context.getAutoDeductType()
-                                                : S.Context.DependentTy;
-  QualType MethodTy = S.Context.getFunctionType(DefaultTypeForNoTrailingReturn,
-                                                std::nullopt, EPI);
-  return S.Context.getTrivialTypeSourceInfo(MethodTy, Loc);
-}
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        Scope *CurScope) {
+  LambdaScopeInfo *const LSI = getCurLambda();
+  assert(LSI && "LambdaScopeInfo should be on stack!");
 
-static TypeSourceInfo *getLambdaType(Sema &S, LambdaIntroducer &Intro,
-                                     Declarator &ParamInfo, Scope *CurScope,
-                                     SourceLocation Loc,
-                                     bool &ExplicitResultType) {
+  // 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;
+  }
 
-  ExplicitResultType = false;
+  // Determine the signature of the call operator.
+  TypeSourceInfo *MethodTyInfo;
+  bool ExplicitParams = true;
+  bool ExplicitResultType = true;
+  bool ContainsUnexpandedParameterPack = false;
+  SourceLocation EndLoc;
+  SmallVector<ParmVarDecl *, 8> Params;
 
   assert(
       (ParamInfo.getDeclSpec().getStorageClassSpec() ==
@@ -866,174 +935,146 @@ static TypeSourceInfo *getLambdaType(Sema &S, LambdaIntroducer &Intro,
   bool IsLambdaStatic =
       ParamInfo.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static;
 
-  TypeSourceInfo *MethodTyInfo;
-
   if (ParamInfo.getNumTypeObjects() == 0) {
-    MethodTyInfo = getDummyLambdaType(S, Loc);
+    // 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,
+                                                std::nullopt, EPI);
+    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+    ExplicitParams = false;
+    ExplicitResultType = false;
+    EndLoc = Intro.Range.getEnd();
   } else {
+    assert(ParamInfo.isFunctionDeclarator() &&
+           "lambda-declarator is a function");
     DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
+
+    // C++11 [expr.prim.lambda]p5:
+    //   This function call operator is declared const (9.3.1) if and only if
+    //   the lambda-expression's parameter-declaration-clause is not followed
+    //   by mutable. It is neither virtual nor declared volatile. [...]
+    if (!FTI.hasMutableQualifier() && !IsLambdaStatic) {
+      FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const,
+                                                    SourceLocation());
+    }
+
+    MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
+    assert(MethodTyInfo && "no type from lambda-declarator");
+    EndLoc = ParamInfo.getSourceRange().getEnd();
+
     ExplicitResultType = FTI.hasTrailingReturnType();
-    if (!FTI.hasMutableQualifier() && !IsLambdaStatic)
-      FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const, Loc);
 
-    if (ExplicitResultType && S.getLangOpts().HLSL) {
+    if (ExplicitResultType && getLangOpts().HLSL) {
       QualType RetTy = FTI.getTrailingReturnType().get();
       if (!RetTy.isNull()) {
         // HLSL does not support specifying an address space on a lambda return
         // type.
         LangAS AddressSpace = RetTy.getAddressSpace();
         if (AddressSpace != LangAS::Default)
-          S.Diag(FTI.getTrailingReturnTypeLoc(),
-                 diag::err_return_value_with_address_space);
+          Diag(FTI.getTrailingReturnTypeLoc(),
+               diag::err_return_value_with_address_space);
       }
     }
 
-    MethodTyInfo = S.GetTypeForDeclarator(ParamInfo, CurScope);
-    assert(MethodTyInfo && "no type from lambda-declarator");
+    if (FTIHasNonVoidParameters(FTI)) {
+      Params.reserve(FTI.NumParams);
+      for (unsigned i = 0, e = FTI.NumParams; i != e; ++i)
+        Params.push_back(cast<ParmVarDecl>(FTI.Params[i].Param));
+    }
 
     // Check for unexpanded parameter packs in the method type.
     if (MethodTyInfo->getType()->containsUnexpandedParameterPack())
-      S.DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo,
-                                        S.UPPC_DeclarationType);
-  }
-  return MethodTyInfo;
-}
-
-CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange,
-                                              CXXRecordDecl *Class) {
-
-  // C++11 [expr.prim.lambda]p5:
-  //   The closure type for a lambda-expression has a public inline function
-  //   call operator (13.5.4) whose parameters and return type are described
-  //   by the lambda-expression's parameter-declaration-clause and
-  //   trailing-return-type respectively.
-  DeclarationName MethodName =
-      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;
-}
-
-void Sema::CompleteLambdaCallOperator(
-    CXXMethodDecl *Method, SourceLocation LambdaLoc,
-    SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
-    TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
-    StorageClass SC, ArrayRef<ParmVarDecl *> Params,
-    bool HasExplicitResultType) {
-
-  LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
-
-  if (TrailingRequiresClause)
-    Method->setTrailingRequiresClause(TrailingRequiresClause);
-
-  TemplateParameterList *TemplateParams =
-      getGenericLambdaTemplateParameterList(LSI, *this);
-
-  DeclContext *DC = Method->getLexicalDeclContext();
-  Method->setLexicalDeclContext(LSI->Lambda);
-  if (TemplateParams) {
-    FunctionTemplateDecl *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);
+      DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo,
+                                      UPPC_DeclarationType);
   }
-  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);
-  }
-
-  buildLambdaScopeReturnType(*this, LSI, Method, HasExplicitResultType);
-}
 
-void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
-                                                Scope *CurrentScope) {
-
-  LambdaScopeInfo *LSI = getCurLambda();
-  assert(LSI && "LambdaScopeInfo should be on stack!");
+  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);
 
-  if (Intro.Default == LCD_ByCopy)
-    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
-  else if (Intro.Default == LCD_ByRef)
-    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
-  LSI->CaptureDefaultLoc = Intro.DefaultLoc;
-  LSI->IntroducerRange = Intro.Range;
-  LSI->AfterParameterList = false;
+  // This represents the function body for the lambda function, check if we
+  // have to apply optnone due to a pragma.
+  AddRangeBasedOptnone(Method);
 
-  assert(LSI->NumExplicitTemplateParams == 0);
+  // code_seg attribute on lambda apply to the method.
+  if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
+    Method->addAttr(A);
 
-  // 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) {
-    Scope *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;
-  }
+  // Attributes on the lambda apply to the method.
+  ProcessDeclAttributes(CurScope, Method, ParamInfo);
 
-  CXXRecordDecl *Class = createLambdaClosureType(
-      Intro.Range, nullptr, LambdaDependencyKind, Intro.Default);
-  LSI->Lambda = Class;
+  // CUDA lambdas get implicit host and device attributes.
+  if (getLangOpts().CUDA)
+    CUDASetLambdaAttrs(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.
+  // OpenMP lambdas might get assumumption attributes.
+  if (LangOpts.OpenMP)
+    ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Method);
 
-  CXXMethodDecl *Method = CreateLambdaCallOperator(Intro.Range, Class);
-  LSI->CallOperator = Method;
-  Method->setLexicalDeclContext(CurContext);
+  // Number the lambda for linkage purposes if necessary.
+  handleLambdaNumbering(Class, Method);
 
+  // Introduce the function call operator as the current declaration context.
   PushDeclContext(CurScope, Method);
 
-  bool ContainsUnexpandedParameterPack = false;
+  // Build the lambda scope.
+  buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc,
+                   ExplicitParams, ExplicitResultType, !Method->isConst());
+
+  // C++11 [expr.prim.lambda]p9:
+  //   A lambda-expression whose smallest enclosing scope is a block scope is a
+  //   local lambda expression; any other lambda expression shall not have a
+  //   capture-default or simple-capture in its lambda-introducer.
+  //
+  // For simple-captures, this is covered by the check below that any named
+  // entity is a variable that can be captured.
+  //
+  // For DR1632, we also allow a capture-default in any context where we can
+  // odr-use 'this' (in particular, in a default initializer for a non-static
+  // data member).
+  if (Intro.Default != LCD_None && !Class->getParent()->isFunctionOrMethod() &&
+      (getCurrentThisType().isNull() ||
+       CheckCXXThisCapture(SourceLocation(), /*Explicit*/true,
+                           /*BuildAndDiagnose*/false)))
+    Diag(Intro.DefaultLoc, diag::err_capture_default_non_local);
 
   // Distinct capture names, for diagnostics.
-  llvm::DenseMap<IdentifierInfo *, ValueDecl *> 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
@@ -1046,7 +1087,7 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
         continue;
       }
 
-      // C++20 [expr.prim.lambda]p8:
+      // C++2a [expr.prim.lambda]p8:
       //  If a lambda-capture includes a capture-default that is =,
       //  each simple-capture of that lambda-capture shall be of the form
       //  "&identifier", "this", or "* this". [ Note: The form [&,this] is
@@ -1112,11 +1153,13 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
       }
       Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
                                            C->EllipsisLoc, C->Id, InitStyle,
-                                           C->Init.get(), Method);
-      assert(Var && "createLambdaInitCaptureVarDecl returned a null VarDecl?");
-      if (auto *V = dyn_cast<VarDecl>(Var))
-        CheckShadow(CurrentScope, V);
-      PushOnScopeChains(Var, CurrentScope, false);
+                                           C->Init.get());
+      // C++1y [expr.prim.lambda]p11:
+      //   An init-capture behaves as if it declares and explicitly
+      //   captures a variable [...] whose declarative region is the
+      //   lambda-expression's compound-statement
+      if (Var)
+        PushOnScopeChains(Var, CurScope, false);
     } else {
       assert(C->InitKind == LambdaCaptureInitKind::NoInit &&
              "init capture has valid but null init?");
@@ -1162,33 +1205,31 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
         continue;
     }
 
-    // C++11 [expr.prim.lambda]p10:
-    //   [...] each such lookup shall find a variable with automatic storage
-    //   duration declared in the reaching scope of the local lambda expression.
-    // Note that the 'reaching scope' check happens in tryCaptureVariable().
-    if (!Var) {
-      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
-      continue;
-    }
-
     // C++11 [expr.prim.lambda]p8:
     //   An identifier or this shall not appear more than once in a
     //   lambda-capture.
-    if (auto [It, Inserted] = CaptureNames.insert(std::pair{C->Id, Var});
-        !Inserted) {
-      if (C->InitKind == LambdaCaptureInitKind::NoInit &&
-          !Var->isInitCapture()) {
+    if (!CaptureNames.insert(C->Id).second) {
+      if (Var && LSI->isCaptured(Var)) {
         Diag(C->Loc, diag::err_capture_more_than_once)
-            << C->Id << It->second->getBeginLoc()
+            << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
             << FixItHint::CreateRemoval(
                    SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
       } else
         // Previous capture captured something 
diff erent (one or both was
-        // an init-capture): no fixit.
+        // an init-cpature): no fixit.
         Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
       continue;
     }
 
+    // C++11 [expr.prim.lambda]p10:
+    //   [...] each such lookup shall find a variable with automatic storage
+    //   duration declared in the reaching scope of the local lambda expression.
+    // Note that the 'reaching scope' check happens in tryCaptureVariable().
+    if (!Var) {
+      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
+      continue;
+    }
+
     // Ignore invalid decls; they'll just confuse the code later.
     if (Var->isInvalidDecl())
       continue;
@@ -1220,167 +1261,20 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
 
     if (C->Init.isUsable()) {
       addInitCapture(LSI, cast<VarDecl>(Var), C->Kind == LCK_ByRef);
-      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 *LSI = getCurrentLambdaScopeUnsafe(*this);
-  LSI->Mutable = MutableLoc.isValid();
-  ContextRAII Context(*this, LSI->CallOperator, /*NewThisContext*/ false);
-
-  // C++11 [expr.prim.lambda]p9:
-  //   A lambda-expression whose smallest enclosing scope is a block scope is a
-  //   local lambda expression; any other lambda expression shall not have a
-  //   capture-default or simple-capture in its lambda-introducer.
-  //
-  // For simple-captures, this is covered by the check below that any named
-  // entity is a variable that can be captured.
-  //
-  // For DR1632, we also allow a capture-default in any context where we can
-  // odr-use 'this' (in particular, in a default initializer for a non-static
-  // data member).
-  if (Intro.Default != LCD_None &&
-      !LSI->Lambda->getParent()->isFunctionOrMethod() &&
-      (getCurrentThisType().isNull() ||
-       CheckCXXThisCapture(SourceLocation(), /*Explicit*/ true,
-                           /*BuildAndDiagnose*/ false)))
-    Diag(Intro.DefaultLoc, diag::err_capture_default_non_local);
-}
-
-void Sema::ActOnLambdaClosureParameters(
-    Scope *LambdaScope, MutableArrayRef<DeclaratorChunk::ParamInfo> Params) {
-  LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
-  PushDeclContext(LambdaScope, LSI->CallOperator);
-
-  for (const DeclaratorChunk::ParamInfo &P : Params) {
-    auto *Param = cast<ParmVarDecl>(P.Param);
-    Param->setOwningFunction(LSI->CallOperator);
-    if (Param->getIdentifier())
-      PushOnScopeChains(Param, LambdaScope, false);
-  }
-
-  LSI->AfterParameterList = true;
-}
-
-void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
-                                        Declarator &ParamInfo,
-                                        const DeclSpec &DS) {
-
-  LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
-  LSI->CallOperator->setConstexprKind(DS.getConstexprSpecifier());
-
-  SmallVector<ParmVarDecl *, 8> Params;
-  bool ExplicitResultType;
-
-  SourceLocation TypeLoc, CallOperatorLoc;
-  if (ParamInfo.getNumTypeObjects() == 0) {
-    CallOperatorLoc = TypeLoc = Intro.Range.getEnd();
-  } else {
-    unsigned Index;
-    ParamInfo.isFunctionDeclarator(Index);
-    const auto &Object = ParamInfo.getTypeObject(Index);
-    TypeLoc =
-        Object.Loc.isValid() ? Object.Loc : ParamInfo.getSourceRange().getEnd();
-    CallOperatorLoc = ParamInfo.getSourceRange().getEnd();
-  }
-
-  CXXRecordDecl *Class = LSI->Lambda;
-  CXXMethodDecl *Method = LSI->CallOperator;
-
-  TypeSourceInfo *MethodTyInfo = getLambdaType(
-      *this, Intro, ParamInfo, getCurScope(), TypeLoc, ExplicitResultType);
-
-  LSI->ExplicitParams = ParamInfo.getNumTypeObjects() != 0;
-
-  if (ParamInfo.isFunctionDeclarator() != 0 &&
-      !FTIHasSingleVoidParameter(ParamInfo.getFunctionTypeInfo())) {
-    const auto &FTI = ParamInfo.getFunctionTypeInfo();
-    Params.reserve(Params.size());
-    for (unsigned I = 0; I < FTI.NumParams; ++I) {
-      auto *Param = cast<ParmVarDecl>(FTI.Params[I].Param);
-      Param->setScopeInfo(0, Params.size());
-      Params.push_back(Param);
-    }
-  }
-
-  bool IsLambdaStatic =
-      ParamInfo.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static;
-
-  CompleteLambdaCallOperator(
-      Method, Intro.Range.getBegin(), CallOperatorLoc,
-      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);
-    }
-  }
-
-  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;
-  };
+  LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
 
-  for (ParmVarDecl *P : Params) {
-    if (!P->getIdentifier())
-      continue;
-    if (CheckRedefinition(P))
-      CheckShadow(CurScope, P);
-    PushOnScopeChains(P, CurScope);
-  }
+  // Add lambda parameters into scope.
+  addLambdaParameters(Intro.Captures, Method, CurScope);
 
   // Enter a new evaluation context to insulate the lambda from any
   // cleanups from the enclosing full-expression.

diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index da66ffea46f4..2790e78aa53a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1231,8 +1231,7 @@ namespace {
 
       // We recreated a local declaration, but not by instantiating it. There
       // may be pending dependent diagnostics to produce.
-      if (auto *DC = dyn_cast<DeclContext>(Old);
-          DC && DC->isDependentContext() && DC->isFunctionOrMethod())
+      if (auto *DC = dyn_cast<DeclContext>(Old); DC && DC->isDependentContext())
         SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
     }
 

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 6b33c8f2fb82..ef56f6219868 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -13238,6 +13238,37 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   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
@@ -13254,8 +13285,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
     DependencyKind = CXXRecordDecl::LDK_NeverDependent;
 
   CXXRecordDecl *OldClass = E->getLambdaClass();
-  CXXRecordDecl *Class = getSema().createLambdaClosureType(
-      E->getIntroducerRange(), nullptr, DependencyKind, E->getCaptureDefault());
+  CXXRecordDecl *Class =
+      getSema().createLambdaClosureType(E->getIntroducerRange(), NewCallOpTSI,
+                                        DependencyKind, E->getCaptureDefault());
+
   getDerived().transformedLocalDecl(OldClass, {Class});
 
   std::optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling;
@@ -13265,19 +13298,36 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
                                OldClass->getDeviceLambdaManglingNumber(),
                                OldClass->getLambdaContextDecl());
 
-  CXXMethodDecl *NewCallOperator =
-      getSema().CreateLambdaCallOperator(E->getIntroducerRange(), Class);
-  NewCallOperator->setLexicalDeclContext(getSema().CurContext);
+  // 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());
 
-  // Enter the scope of the lambda.
-  getSema().buildLambdaScope(LSI, NewCallOperator, E->getIntroducerRange(),
-                             E->getCaptureDefault(), E->getCaptureDefaultLoc(),
-                             E->hasExplicitParameters(), E->isMutable());
+  LSI->CallOperator = NewCallOperator;
+
+  getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
+  getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
+
+  // Number the lambda for linkage purposes if necessary.
+  getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling);
 
   // 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.
@@ -13317,8 +13367,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
         }
         VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl(
             OldVD->getLocation(), InitQualType, NewC.EllipsisLoc,
-            OldVD->getIdentifier(), OldVD->getInitStyle(), Init.get(),
-            getSema().CurContext);
+            OldVD->getIdentifier(), OldVD->getInitStyle(), Init.get());
         if (!NewVD) {
           Invalid = true;
           break;
@@ -13398,55 +13447,6 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   }
   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();
-    auto 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(

diff  --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
index 67953c6a6f90..4a0cf39bc56b 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
@@ -12,16 +12,16 @@ auto with_float_2 = [&f(f)] { // ok, refers to outer f
   using T = double&;
 };
 
-// Within the lambda-expression the identifier in the init-capture
-// hides any declaration of the same name in scopes enclosing
-// the lambda-expression.
+// 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.
 void hiding() {
   char c;
   (void) [c("foo")] {
     static_assert(sizeof(c) == sizeof(const char*), "");
   };
-  (void)[c("bar")]()->decltype(c) { // inner c
-    return "baz";
+  (void) [c("bar")] () -> decltype(c) { // outer c, not init-capture
+    return "baz"; // expected-error {{cannot initialize}}
   };
 }
 

diff  --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
index 660f6091bb66..5f7f73d622d8 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
@@ -43,21 +43,10 @@ X infer_X_return_type_2(X x) {
   }(5);
 }
 
-struct Incomplete; // expected-note 2{{forward declaration of 'Incomplete'}}
+struct Incomplete; // expected-note{{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}}
-}

diff  --git a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
deleted file mode 100644
index e22e3af02c5c..000000000000
--- a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-// 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))>) {}()));
-}
-
-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<const int &, decltype((x))> {} ();
-  [x = 1]() mutable requires is_same<int &, decltype((x))> {} ();
-}
-
-void err() {
-  int y, z;
-  (void)[x = 1]<typename T>
-  requires(is_same<const int &, decltype((x))>) {};
-
-  (void)[x = 1]<typename T = decltype((x))>{};
-
-  (void)[=]<typename T = decltype((y))>{};
-
-  (void)[z]<typename T = decltype((z))>{};
-}
-
-void gnu_attributes() {
-  int y;
-  (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), const int &>, "wrong type", "warning"))){}();
-  // expected-warning at -1 {{wrong type}} expected-note at -1{{'diagnose_if' attribute on 'operator()'}}
-  (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), int &>, "wrong type", "warning"))){}();
-
-  (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 at -1 {{wrong type}} expected-note at -1{{'diagnose_if' attribute on 'operator()'}}
-
-
-  (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), const int &>, "wrong type", "warning"))){}();
-  // expected-warning at -1 {{wrong type}} expected-note at -1{{'diagnose_if' attribute on 'operator()'}}
-  (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), int &>, "wrong type", "warning"))){}();
-
-  (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 at -1 {{wrong type}} expected-note at -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<int &, decltype((jp))>);
-    static_assert(is_same<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<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<int&, decltype((ap))>);
-  };
-}

diff  --git a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
index 9dddbf8b5f3b..a772af049ab4 100644
--- a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -95,7 +95,7 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}}
 #ifdef AVOID
   auto l4 = [var = param] (int param) { ; }; // no warning
 #else
-  auto l4 = [var = param](int param) { ; }; // expected-warning 2{{declaration shadows a local variable}}
+  auto l4 = [var = param] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
 #endif
 
   // Make sure that inner lambdas work as well.

diff  --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index b64c2cf20da0..c9df1ed37350 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1358,7 +1358,7 @@ <h2 id="cxx23">C++2b implementation status</h2>
     <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="unreleased" align="center">Clang 17</td>
+      <td rowspan=2 class="none" align="center">No</td>
     </tr>
     <tr>
       <td><a href="https://wg21.link/P2579R0">P2579R0</a></td>


        


More information about the cfe-commits mailing list