https://github.com/a-tarasyuk created 
https://github.com/llvm/llvm-project/pull/176749

Fixes #176534

---

This patch resolves a crash when parsing delayed default arguments that contain 
lambda expressions.

```cpp
struct S {
  void f(int x, int = sizeof([x] { return x; }()));
};
```

When late-parsing default arguments that contain lambdas, `Sema` builds a 
`FunctionScopes` stack containing only the lambda scope 
(`FunctionScopes.size()` equals 1), however, `tryCaptureVariable` expects an 
enclosing function scope outside the lambda scope 

https://github.com/llvm/llvm-project/blob/41e231cae38028473dd327e8de5f65792b521ffe/clang/lib/Sema/SemaExpr.cpp#L19473-L19474

https://github.com/llvm/llvm-project/blob/41e231cae38028473dd327e8de5f65792b521ffe/clang/lib/Sema/SemaExpr.cpp#L19518

Scope capture handling logic decrements `FunctionScopesIndex` to align 
declaration contexts

https://github.com/llvm/llvm-project/blob/41e231cae38028473dd327e8de5f65792b521ffe/clang/lib/Sema/SemaExpr.cpp#L19696

and later relies on it when traversing and accessing outer scopes

https://github.com/llvm/llvm-project/blob/41e231cae38028473dd327e8de5f65792b521ffe/clang/lib/Sema/SemaExpr.cpp#L19522-L19524

preserving the function scope in the late-parsing path prevents invalid 
traversal during lambda capture handling



>From 7d943500de92f2216be51885669a7f83ba8c4c84 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <[email protected]>
Date: Mon, 19 Jan 2026 14:20:46 +0200
Subject: [PATCH] [Clang] prevent crash in delayed default-argument lambda
 captures

---
 clang/docs/ReleaseNotes.rst               |  1 +
 clang/lib/Parse/ParseCXXInlineMethods.cpp |  9 +++++++
 clang/test/SemaCXX/lambda-unevaluated.cpp | 30 +++++++++++++++++++++++
 3 files changed, 40 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b75715e873c50..2cfcb8a580b32 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -125,6 +125,7 @@ Improvements to Coverage Mapping
 
 Bug Fixes in This Version
 -------------------------
+- Fixed a crash caused by lambda capture handling in delayed default 
arguments. (#GH176534)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp 
b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index bc18881e89110..99c7595b2295e 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -416,6 +416,15 @@ void 
Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
           Actions,
           Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, 
Param);
 
+      // Delayed default arguments may contain lambdas, e.g.
+      //   struct S {
+      //     void ICE(int x, int = sizeof([x] { return x; }()));
+      //   }
+      // Lambda capture handling in tryCaptureVariable() expects an enclosing
+      // function scope in Sema's FunctionScopes stack.
+      Sema::FunctionScopeRAII PopFnContext(Actions);
+      Actions.PushFunctionScope();
+
       ExprResult DefArgResult;
       if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
         Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp 
b/clang/test/SemaCXX/lambda-unevaluated.cpp
index 55a4bc7aff1b5..9c723c6bc3b99 100644
--- a/clang/test/SemaCXX/lambda-unevaluated.cpp
+++ b/clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -288,3 +288,33 @@ auto t() {
   return [](auto w = [&] { return x; }) { }; // expected-error {{lambda 
expression in default argument cannot capture any entity}}
 };
 }
+
+namespace GH176534 {
+struct S {
+  // expected-error@+9 {{reference to local variable 'x' declared in enclosing 
function 'GH176534::S::a'}}
+  // expected-error@+8 {{variable 'x' cannot be implicitly captured in a 
lambda with no capture-default specified}}
+  // expected-note@+7 {{'x' declared here}}
+  // expected-note@+6 {{'x' declared here}}
+  // expected-note@+5 {{lambda expression begins here}}
+  // expected-note@+4 {{capture 'x' by value}}
+  // expected-note@+3 {{capture 'x' by reference}}
+  // expected-note@+2 {{default capture by value}}
+  // expected-note@+1 {{default capture by reference}}
+  void a(int x, int = sizeof([x] { return x; }()));
+
+  // expected-error@+8 {{'this' cannot be captured in this context}}
+  // expected-error@+7 {{variable 'x' cannot be implicitly captured in a 
lambda with no capture-default specified}}
+  // expected-note@+6 {{default capture by reference}}
+  // expected-note@+5 {{lambda expression begins here}}
+  // expected-note@+4 {{capture 'x' by value}}
+  // expected-note@+3 {{capture 'x' by reference}}
+  // expected-note@+2 {{'x' declared here}}
+  // expected-note@+1 {{default capture by value}}
+  void b(int x, int = sizeof([this] { return x; }));
+
+  // expected-error@+3 {{non-local lambda expression cannot have a 
capture-default}}
+  // expected-error@+2 {{reference to local variable 'x' declared in enclosing 
function 'GH176534::S::c'}}
+  // expected-note@+1 {{'x' declared here}}
+  void c(int x, int = sizeof([=] { return x; }));
+};
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to