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. From-SVN: r260622
This commit is contained in:
parent
955da5e544
commit
a347241b93
6 changed files with 39 additions and 9 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -7315,13 +7315,19 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
|
|||
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 "
|
||||
|
|
11
gcc/testsuite/g++.dg/cpp0x/rv-cast6.C
Normal file
11
gcc/testsuite/g++.dg/cpp0x/rv-cast6.C
Normal file
|
@ -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());
|
Loading…
Add table
Reference in a new issue