* 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
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.
{
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;
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. */
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))
type = cv_unqualified (type);
/* [expr.reinterpret.cast]
- An lvalue 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 "
--- /dev/null
+// 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());