https://gcc.gnu.org/g:ac524299110838ed8eafb615d100a28649af7f18
commit r16-4384-gac524299110838ed8eafb615d100a28649af7f18 Author: Nathaniel Shead <[email protected]> Date: Sun Oct 5 21:30:56 2025 +1100 c++: Ensure mark_lvalue_use returns an lvalue [PR122163] 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. PR c++/122163 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]> Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/expr.cc | 11 ++++++++++- gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref3.C | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/gcc/cp/expr.cc b/gcc/cp/expr.cc index f2e99397acac..a29cb2461a5b 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); + } + 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.C new file mode 100644 index 000000000000..1e085b237968 --- /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(); +}
