OSDN Git Service

PR c++/51406
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Dec 2011 05:18:39 +0000 (05:18 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Dec 2011 05:18:39 +0000 (05:18 +0000)
PR c++/51161
* typeck.c (build_static_cast_1): Fix cast of lvalue to
base rvalue reference.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182322 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 23748d8..d326133 100644 (file)
@@ -1,3 +1,10 @@
+2011-12-13  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51406
+       PR c++/51161
+       * typeck.c (build_static_cast_1): Fix cast of lvalue to
+       base rvalue reference.
+
 2011-12-13  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/51464
 2011-12-13  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/51464
index 4973d7d..b168963 100644 (file)
@@ -5856,12 +5856,22 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
      cv2 T2 if cv2 T2 is reference-compatible with cv1 T1 (8.5.3)."  */
   if (TREE_CODE (type) == REFERENCE_TYPE
       && TYPE_REF_IS_RVALUE (type)
      cv2 T2 if cv2 T2 is reference-compatible with cv1 T1 (8.5.3)."  */
   if (TREE_CODE (type) == REFERENCE_TYPE
       && TYPE_REF_IS_RVALUE (type)
-      && lvalue_or_rvalue_with_address_p (expr)
+      && real_lvalue_p (expr)
       && reference_related_p (TREE_TYPE (type), intype)
       && (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype)))
     {
       && reference_related_p (TREE_TYPE (type), intype)
       && (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype)))
     {
-      expr = build_typed_address (expr, type);
-      return convert_from_reference (expr);
+      /* Handle the lvalue case here by casting to lvalue reference and
+        then changing it to an rvalue reference.  Casting an xvalue to
+        rvalue reference will be handled by the main code path.  */
+      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);
+      return convert_from_reference (result);
     }
 
   /* Resolve overloaded address here rather than once in
     }
 
   /* Resolve overloaded address here rather than once in
index 5011d2c..e22d114 100644 (file)
@@ -1,3 +1,10 @@
+2011-12-13  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51406
+       PR c++/51161
+       * g++.dg/cpp0x/rv-cast3.C: New.
+       * g++.dg/cpp0x/rv-cast4.C: New.
+
 2011-12-13  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/51464
 2011-12-13  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/51464
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast3.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast3.C
new file mode 100644 (file)
index 0000000..6c70324
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/51406
+// { dg-do run { target c++11 } }
+
+extern "C" int printf(const char *,...);
+extern "C" void abort();
+
+struct A { int a; A() : a(1) {} };
+struct B { int b; B() : b(2) {} };
+struct X : A, B {};
+
+int main() {
+    X x;
+    int a=static_cast<A&&>(x).a;
+    int b=static_cast<B&&>(x).b;
+    // printf ("%d %d\n", a, b);
+    if (a!=1 || b!=2) abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast4.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast4.C
new file mode 100644 (file)
index 0000000..13f369d
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/51161
+// { dg-do compile { target c++11 } }
+
+struct A{};
+struct B : A{};
+struct C : A{};
+struct D : B, C{};
+
+int main()
+{
+  D d;
+  static_cast<A &&>(d);                // { dg-error "ambiguous" }
+}