re PR c++/49105 ([C++0x][SFINAE] ICE during list-initialization of rvalue-references...
authorJason Merrill <jason@redhat.com>
Mon, 23 May 2011 22:55:56 +0000 (18:55 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 23 May 2011 22:55:56 +0000 (18:55 -0400)
PR c++/49105
* typeck.c (build_const_cast_1): Handle rvalue references.

From-SVN: r174092

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/rv-cast2.C [new file with mode: 0644]

index ea617dfe947bfc36aa385ca27054f8867f116b7f..2a4ffe09cd88e1df6fa7e50715096627db27c768 100644 (file)
@@ -1,5 +1,8 @@
 2011-05-23  Jason Merrill  <jason@redhat.com>
 
+       PR c++/49105
+       * typeck.c (build_const_cast_1): Handle rvalue references.
+
        PR c++/47263
        * decl.c (use_eh_spec_block): Do use an EH spec block for a
        lambda op().
index 81ee63d7efdd4d1790b933dae1294430efef79bd..13b919ca37ffe25c99c0ca7c00360d4665a51e7b 100644 (file)
@@ -6241,14 +6241,29 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
 
   /* [expr.const.cast]
 
-     An lvalue of type T1 can be explicitly converted to an lvalue of
-     type T2 using the cast const_cast<T2&> (where T1 and T2 are object
-     types) if a pointer to T1 can be explicitly converted to the type
-     pointer to T2 using a const_cast.  */
+     For two object types T1 and T2, if a pointer to T1 can be explicitly
+     converted to the type "pointer to T2" using a const_cast, then the
+     following conversions can also be made:
+
+     -- an lvalue of type T1 can be explicitly converted to an lvalue of
+     type T2 using the cast const_cast<T2&>;
+
+     -- a glvalue of type T1 can be explicitly converted to an xvalue of
+     type T2 using the cast const_cast<T2&&>; and
+
+     -- if T1 is a class type, a prvalue of type T1 can be explicitly
+     converted to an xvalue of type T2 using the cast const_cast<T2&&>.  */
+
   if (TREE_CODE (dst_type) == REFERENCE_TYPE)
     {
       reference_type = dst_type;
-      if (! real_lvalue_p (expr))
+      if (!TYPE_REF_IS_RVALUE (dst_type)
+         ? real_lvalue_p (expr)
+         : (CLASS_TYPE_P (TREE_TYPE (dst_type))
+            ? lvalue_p (expr)
+            : lvalue_or_rvalue_with_address_p (expr)))
+       /* OK.  */;
+      else
        {
          if (complain & tf_error)
            error ("invalid const_cast of an rvalue of type %qT to type %qT",
index 8c1fc39c65ce89df85a6f51aa1e6d3232773e95e..ea4466c54edb7c74900d9fbbc3fbe26b9f637ead 100644 (file)
@@ -1,5 +1,7 @@
 2011-05-23  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/rv-cast2.C: New.
+
        * g++.dg/cpp0x/enum14.C: New.
 
 2011-05-23  Jakub Jelinek  <jakub@redhat.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C
new file mode 100644 (file)
index 0000000..94ee4ca
--- /dev/null
@@ -0,0 +1,21 @@
+// Test for const_cast to reference (5.2.11/4).
+// { dg-options -std=c++0x }
+
+template <class T> T&& xval();
+template <class T> T& lval();
+template <class T> T prval();
+
+struct A { };
+
+int main()
+{
+  const_cast<int&>(lval<int>());
+  const_cast<int&>(xval<int>());   // { dg-error "" }
+  const_cast<int&>(prval<int>());  // { dg-error "" }
+  const_cast<int&&>(lval<int>());
+  const_cast<int&&>(xval<int>());
+  const_cast<int&&>(prval<int>()); // { dg-error "" }
+  const_cast<A&&>(lval<A>());
+  const_cast<A&&>(xval<A>());
+  const_cast<A&&>(prval<A>());
+}