On 10/5/25 11:34 AM, Nathaniel Shead wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?-- >8 -- When processing a tentative capture of a rvalue reference, mark_use folds it away to the referred-to entity. But this is an rvalue, and when called from an lvalue context an rvalue reference should still be an lvalue. gcc/cp/ChangeLog: * expr.cc (mark_use): When processing a reference, always return an lvalue reference when !rvalue_p. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/lambda/lambda-ref3.C: New test. Signed-off-by: Nathaniel Shead <[email protected]> --- gcc/cp/expr.cc | 11 ++++++++++- .../g++.dg/cpp0x/lambda/lambda-ref3.C | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref3.C diff --git a/gcc/cp/expr.cc b/gcc/cp/expr.cc index 32dc3eee78f..092cf886a25 100644 --- a/gcc/cp/expr.cc +++ b/gcc/cp/expr.cc @@ -183,7 +183,16 @@ mark_use (tree expr, bool rvalue_p, bool read_p, } tree r = mark_rvalue_use (ref, loc, reject_builtin); if (r != ref) - expr = convert_from_reference (r); + { + if (!rvalue_p) + { + /* Make sure we still return an lvalue. */ + gcc_assert (TREE_CODE (r) == NOP_EXPR); + TREE_TYPE (r) = cp_build_reference_type (TREE_TYPE (r), + false);
Perhaps we could generalize the is_normal_capture_proxy block above to handle !rvalue_p, to return the captured variable directly with no NOP_EXPR/ADDR_EXPR?
But the patch is OK as is if you'd rather not bother.
+ } + expr = convert_from_reference (r); + } } break;diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref3.Cnew file mode 100644 index 00000000000..1e085b23796 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref3.C @@ -0,0 +1,18 @@ +// { dg-do run { target c++11 } } + +int x; +int main() { + constexpr int&& r = static_cast<int&&>(x); + r = 1; + + auto a = [] { r = 2; }; // Not an ODR-use of 'r' so no capture needed. + auto b = [&] { r = 3; }; + + a(); + if (r != 2) + __builtin_abort(); + + b(); + if (r != 3) + __builtin_abort(); +}
