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);
+ }
+ 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<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();
+}
--
2.51.0