]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/51406 ([c++0x] Incorrect result of static_cast to rvalue reference to base...
authorJason Merrill <jason@redhat.com>
Wed, 14 Dec 2011 16:03:07 +0000 (11:03 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 14 Dec 2011 16:03:07 +0000 (11:03 -0500)
PR c++/51406
PR c++/51161
* typeck.c (build_static_cast_1): Fix cast of lvalue to
base rvalue reference.

From-SVN: r182339

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 ecacea34c8926f293372086ffb70d18cb9c0bd8c..eaac7029592f409e9420e63389ab133bcf3a115e 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-11-22  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/51265
index 73d57e9fc1fb2d777f7370cc7b2e7c9bc4a5ecee..1c099a2c80ca78088a06312840077ef9c2ee9cda 100644 (file)
@@ -5770,8 +5770,18 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       && 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
index 2af4c9539ac40f2af38fba9dc2dacf216431fa6d..6350a25a352a4f8f63e3d984a05c93b74f437d0c 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-12  Jakub Jelinek  <jakub@redhat.com>
 
        PR testsuite/51511
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" }
+}