Fix cast to rvalue reference from prvalue.
authorJason Merrill <jason@redhat.com>
Wed, 23 May 2018 17:21:39 +0000 (13:21 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 23 May 2018 17:21:39 +0000 (13:21 -0400)
* cvt.c (diagnose_ref_binding): Handle rvalue reference.
* rtti.c (build_dynamic_cast_1): Don't try to build a reference to
non-class type.  Handle xvalue argument.
* typeck.c (build_reinterpret_cast_1): Allow cast from prvalue to
rvalue reference.
* semantics.c (finish_compound_literal): Do direct-initialization,
not cast, to initialize a reference.

From-SVN: r260622

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

index 3adb570a0cbeb4c4181ad00702d5023b88b99ddf..f38d385e3be3e43548f9f6451334185d405996ef 100644 (file)
@@ -1,5 +1,14 @@
 2018-05-23  Jason Merrill  <jason@redhat.com>
 
+       Fix cast to rvalue reference from prvalue.
+       * cvt.c (diagnose_ref_binding): Handle rvalue reference.
+       * rtti.c (build_dynamic_cast_1): Don't try to build a reference to
+       non-class type.  Handle xvalue argument.
+       * typeck.c (build_reinterpret_cast_1): Allow cast from prvalue to
+       rvalue reference.
+       * semantics.c (finish_compound_literal): Do direct-initialization,
+       not cast, to initialize a reference.
+
        CWG 616, 1213 - value category of subobject references.
        * tree.c (lvalue_kind): A reference to a subobject of a prvalue is
        an xvalue.
index 30b44b7d7eafdc55a6415cbf7cc5cb0253b2a2fc..3f87317a47d2d6f9ee1bc99e8fa96c98e70efd8f 100644 (file)
@@ -381,7 +381,8 @@ diagnose_ref_binding (location_t loc, tree reftype, tree intype, tree decl)
 {
   tree ttl = TREE_TYPE (reftype);
 
-  if (!CP_TYPE_CONST_NON_VOLATILE_P (ttl))
+  if (!TYPE_REF_IS_RVALUE (reftype)
+      && !CP_TYPE_CONST_NON_VOLATILE_P (ttl))
     {
       const char *msg;
 
index 426a23276e02f7234caece93a728a2a48afa3718..6692fb7ff861722c636a3b5b1d0506a074070ad2 100644 (file)
@@ -616,22 +616,22 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
   else
     {
       expr = mark_lvalue_use (expr);
-
-      exprtype = build_reference_type (TREE_TYPE (expr));
+      exprtype = TREE_TYPE (expr);
 
       /* T is a reference type, v shall be an lvalue of a complete class
         type, and the result is an lvalue of the type referred to by T.  */
-
-      if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (exprtype)))
+      if (! MAYBE_CLASS_TYPE_P (exprtype))
        {
          errstr = _("source is not of class type");
          goto fail;
        }
-      if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (exprtype))))
+      if (!COMPLETE_TYPE_P (complete_type (exprtype)))
        {
          errstr = _("source is of incomplete class type");
          goto fail;
        }
+
+      exprtype = cp_build_reference_type (exprtype, !lvalue_p (expr));
     }
 
   /* The dynamic_cast operator shall not cast away constness.  */
index 94e8f54254d527e3f80cc62f1ecb0bc616b5961c..46251deaa6c363bb7c1503b458cae802e5158ef5 100644 (file)
@@ -2734,7 +2734,10 @@ finish_compound_literal (tree type, tree compound_literal,
       compound_literal
        = finish_compound_literal (TREE_TYPE (type), compound_literal,
                                   complain, fcl_context);
-      return cp_build_c_cast (type, compound_literal, complain);
+      /* The prvalue is then used to direct-initialize the reference.  */
+      tree r = (perform_implicit_conversion_flags
+               (type, compound_literal, complain, LOOKUP_NORMAL));
+      return convert_from_reference (r);
     }
 
   if (!TYPE_OBJ_P (type))
index 82089c451056d6097fd5ee749c33d7f11ae1f634..a694499190fc6c6c25b79c5215964fdffead0d8f 100644 (file)
@@ -7315,13 +7315,19 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
     type = cv_unqualified (type);
 
   /* [expr.reinterpret.cast]
-     Alvalue expression of type T1 can be cast to the type
+     A glvalue expression of type T1 can be cast to the type
      "reference to T2" if an expression of type "pointer to T1" can be
      explicitly converted to the type "pointer to T2" using a
      reinterpret_cast.  */
   if (TYPE_REF_P (type))
     {
-      if (! lvalue_p (expr))
+      if (TYPE_REF_IS_RVALUE (type))
+       {
+         if (!obvalue_p (expr))
+           /* Perform the temporary materialization conversion.  */
+           expr = get_target_expr_sfinae (expr, complain);
+       }
+      else if (!lvalue_p (expr))
        {
           if (complain & tf_error)
             error ("invalid cast of an rvalue expression of type "
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast6.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast6.C
new file mode 100644 (file)
index 0000000..3ae5691
--- /dev/null
@@ -0,0 +1,11 @@
+// Test that a prvalue can be used where a glvalue is expected.
+// { dg-do compile { target c++11 } }
+
+struct A { virtual void f(); };
+struct B : A {};
+
+auto && a = static_cast<A&&>(B());
+auto && b = reinterpret_cast<A&&>(B());
+auto && c = dynamic_cast<A&&>(B());
+auto && d = dynamic_cast<B&&>(static_cast<A&&>(B()));
+auto && e = const_cast<B&&>(B());