From: Nathaniel Shead Date: Sun, 5 Oct 2025 10:30:56 +0000 (+1100) Subject: c++: Ensure mark_lvalue_use returns an lvalue [PR122163] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac524299110838ed8eafb615d100a28649af7f18;p=thirdparty%2Fgcc.git 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 Reviewed-by: Jason Merrill --- diff --git a/gcc/cp/expr.cc b/gcc/cp/expr.cc index f2e99397aca..a29cb2461a5 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 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(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(); +}