On 2/18/25 5:12 AM, Simon Martin wrote:
We've been rejecting this valid code since r8-4571:
=== cut here ===
void foo (float);
int main () {
constexpr float x = 0;
(void) [&] () {
foo (x);
(void) [] () {
foo (x);
};
};
}
=== cut here ===
The problem is that when processing X in the inner lambda,
process_outer_var_ref errors out even though it does find the capture
from the enclosing lambda.
This patch changes process_outer_var_ref to accept and return the outer
proxy if it finds any.
Successfully tested on x86_64-pc-linux-gnu.
PR c++/110584
gcc/cp/ChangeLog:
* semantics.cc (process_outer_var_ref): Use capture from
enclosing lambda, if any.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/lambda/lambda-nested10.C: New test.
---
gcc/cp/semantics.cc | 4 ++
.../g++.dg/cpp0x/lambda/lambda-nested10.C | 46 +++++++++++++++++++
2 files changed, 50 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested10.C
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 7c7d3e3c432..7bbc82f7dc1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4598,6 +4598,10 @@ process_outer_var_ref (tree decl, tsubst_flags_t
complain, bool odr_use)
if (!odr_use && context == containing_function)
decl = add_default_capture (lambda_stack,
/*id=*/DECL_NAME (decl), initializer);
+ /* When doing lambda capture, if we found a capture in an enclosing lambda,
+ we can use it. */
+ else if (!odr_use && is_capture_proxy (decl))
+ return decl;
What makes this OK is not that it's a capture, but that the captured
variable is constant, so it should have satisfied this branch:
/* Only an odr-use of an outer automatic variable causes an
error, and a constant variable can decay to a prvalue
constant without odr-use. So don't complain yet. */
else if (!odr_use && decl_constant_var_p (decl))
return decl;
is_constant_capture_proxy might be useful here. And/or a new
strip_normal_capture function (that I'm surprised doesn't exist yet).
Jason