On 12/14/2011 12:14 AM, Jason Merrill wrote:
The code for casting to rvalue ref was assuming that no base adjustment
would be necessary.  This patch delegates to the normal lvalue binding
code, and then changes the result to be an rvalue reference.

The test for DECL_P isn't sufficient to catch all cases where the result of cp_fold_convert is still an lvalue. Now that we're doing delayed folding, let's replace the cp_fold_convert with an unconditional NON_LVALUE_EXPR.

Tested x86_64-pc-linux-gnu, applying to trunk. For GCC 5 I'm changing DECL_P to real_lvalue_p instead.


commit 46ab061b39527bbdd427bdf887eb6954768d4b61
Author: Jason Merrill <ja...@redhat.com>
Date:   Wed Mar 2 01:11:30 2016 -0500

    	PR c++/51406
    
    	* typeck.c (build_static_cast_1): Avoid folding back to lvalue.

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5145879..20f0afc 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6704,11 +6704,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
 	  tree lref = cp_build_reference_type (TREE_TYPE (type), false);
 	  result = (perform_direct_initialization_if_possible
 		    (lref, expr, c_cast_p, complain));
-	  result = cp_fold_convert (type, result);
-	  /* Make sure we don't fold back down to a named rvalue reference,
-	     because that would be an lvalue.  */
-	  if (DECL_P (result))
-	    result = build1 (NON_LVALUE_EXPR, type, result);
+	  result = build1 (NON_LVALUE_EXPR, type, result);
 	  return convert_from_reference (result);
 	}
       else
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast5.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast5.C
new file mode 100644
index 0000000..c2473e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast5.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+
+template <typename T>
+struct hold {
+  T value;
+  constexpr T&& operator()() && { return static_cast<T&&>(value); }
+};
+
+int main()
+{
+  hold<bool&&>{42}();
+}

Reply via email to