https://github.com/Praneeth740 updated 
https://github.com/llvm/llvm-project/pull/235529

>From 1d95da5f3a00e04f9d87ec79d9827e9212424b15 Mon Sep 17 00:00:00 2001
From: Praneeth <[email protected]>
Date: Mon, 26 Oct 2026 02:50:30 +0530
Subject: [PATCH] [clang] Don't skip capture of parameters in default arguments

The early return in tryCaptureVariable was meant for unevaluated
operands but never checked for them, so lambdas in default arguments
skipped capture analysis. Restrict it to unevaluated contexts.

Fixes #233811
---
 clang/lib/Sema/SemaExpr.cpp                    | 12 ++++++++++--
 .../SemaCXX/lambda-as-default-parameter.cpp    |  7 ++++++-
 .../lambda-default-arg-param-capture.cpp       | 18 ++++++++++++++++++
 3 files changed, 34 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/SemaCXX/lambda-default-arg-param-capture.cpp

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 43b0c86132172b..e0f87936d451cd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -20238,8 +20238,16 @@ bool Sema::tryCaptureVariable(
   // Exception: Function parameters are not tied to the function's DeclContext
   // until we enter the function definition. Capturing them anyway would result
   // in an out-of-bounds error while traversing DC and its parents.
-  if (isa<ParmVarDecl>(Var) && !VarDC->isFunctionOrMethod())
-    return true;
+
+  bool InDefaultArg = llvm::any_of(
+    ExprEvalContexts, [](const ExpressionEvaluationContextRecord &C) {
+      return isa_and_nonnull<ParmVarDecl>(C.ManglingContextDecl);
+    });
+  if (isa<ParmVarDecl>(Var) && !VarDC->isFunctionOrMethod() && !InDefaultArg &&
+    llvm::any_of(ExprEvalContexts,
+                 [](const ExpressionEvaluationContextRecord &C) {
+                   return C.isUnevaluated();
+                 })) return true;
 
   const auto *VD = dyn_cast<VarDecl>(Var);
   if (VD) {
diff --git a/clang/test/SemaCXX/lambda-as-default-parameter.cpp 
b/clang/test/SemaCXX/lambda-as-default-parameter.cpp
index 1f07a7f5644b7c..1c8ceaa806c60f 100644
--- a/clang/test/SemaCXX/lambda-as-default-parameter.cpp
+++ b/clang/test/SemaCXX/lambda-as-default-parameter.cpp
@@ -3,4 +3,9 @@
 struct a; // expected-note {{forward declaration of 'a'}} \
              expected-note {{forward declaration of 'a'}}
 void b(a c = [] { return c; }); // expected-error {{initialization of 
incomplete type 'a'}} \
-                                   expected-error {{variable has incomplete 
type 'a'}}
+                                   expected-error {{variable has incomplete 
type 'a'}} \
+                                   expected-error {{variable 'c' cannot be 
implicitly captured in a lambda with no capture-default specified}} \
+                                   expected-note {{'c' declared here}} \
+                                   expected-note {{lambda expression begins 
here}} \
+                                   expected-note {{capture 'c' by reference}} \
+                                   expected-note {{default capture by 
reference}}
diff --git a/clang/test/SemaCXX/lambda-default-arg-param-capture.cpp 
b/clang/test/SemaCXX/lambda-default-arg-param-capture.cpp
new file mode 100644
index 00000000000000..914c0f3754b5e6
--- /dev/null
+++ b/clang/test/SemaCXX/lambda-default-arg-param-capture.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+int a(int g, int h = []{ return g; }()); // expected-error {{variable 'g' 
cannot be implicitly captured in a lambda with no capture-default specified}} 
expected-note {{'g' declared here}} expected-note {{lambda expression begins 
here}} expected-note {{capture 'g' by value}} expected-note {{capture 'g' by 
reference}} expected-note {{default capture by value}} expected-note {{default 
capture by reference}}
+
+int e(int g, int h = [] { int g = 1; return g; }());
+
+// Unevaluated operand in a trailing return type: still accepted.
+auto u(int g) -> decltype([] { return g; }());
+
+// A default argument is potentially evaluated even when the lambda sits in an
+// unevaluated operand; GCC rejects these too.
+int s1(int x, int h = sizeof([] { return x; }())); // expected-error 
{{variable 'x' cannot be implicitly captured in a lambda with no 
capture-default specified}} \
+                                                      expected-note {{'x' 
declared here}} \
+                                                      expected-note {{lambda 
expression begins here}} \
+                                                      expected-note {{capture 
'x' by value}} \
+                                                      expected-note {{capture 
'x' by reference}} \
+                                                      expected-note {{default 
capture by value}} \
+                                                      expected-note {{default 
capture by reference}}

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

Reply via email to