diff options
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/call.c | 29 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 9 | ||||
-rw-r--r-- | gcc/cp/tree.c | 8 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 4 |
6 files changed, 45 insertions, 17 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1f57251..9a9de74 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,16 @@ 2009-07-31 Jason Merrill <jason@redhat.com> + * call.c (reference_binding): Rename lvalue_p to is_lvalue. + Do direct binding of "rvalues" in memory to rvalue references. + * tree.c (lvalue_p_1): Can't be both non-addressable lvalue and + "rvalue" in memory. + * typeck.c (build_static_cast_1): Do direct binding of memory + "rvalues" to rvalue references. + * cvt.c (cp_fold_convert): New. + * cp-tree.h: Declare it. + +2009-07-31 Jason Merrill <jason@redhat.com> + * typeck.c (build_address): Do fold away ADDR_EXPR of INDIRECT_REF. * tree.c (rvalue): Use cp_build_qualified_type, not TYPE_MAIN_VARIANT. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 0254ecb..144d07e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1205,7 +1205,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) tree tfrom; bool related_p; bool compatible_p; - cp_lvalue_kind lvalue_p = clk_none; + cp_lvalue_kind is_lvalue = clk_none; if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr)) { @@ -1218,7 +1218,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) if (TREE_CODE (from) == REFERENCE_TYPE) { /* Anything with reference type is an lvalue. */ - lvalue_p = clk_ordinary; + is_lvalue = clk_ordinary; from = TREE_TYPE (from); } @@ -1235,11 +1235,11 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) } } - if (lvalue_p == clk_none && expr) - lvalue_p = real_lvalue_p (expr); + if (is_lvalue == clk_none && expr) + is_lvalue = real_lvalue_p (expr); tfrom = from; - if ((lvalue_p & clk_bitfield) != 0) + if ((is_lvalue & clk_bitfield) != 0) tfrom = unlowered_expr_type (expr); /* Figure out whether or not the types are reference-related and @@ -1256,12 +1256,15 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) /* Directly bind reference when target expression's type is compatible with the reference and expression is an lvalue. In DR391, the wording in [8.5.3/5 dcl.init.ref] is changed to also require direct bindings for - const and rvalue references to rvalues of compatible class type. */ + const and rvalue references to rvalues of compatible class type. + We should also do direct bindings for non-class "rvalues" derived from + rvalue references. */ if (compatible_p - && (lvalue_p - || (!(flags & LOOKUP_NO_TEMP_BIND) - && (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto)) - && CLASS_TYPE_P (from)))) + && (is_lvalue + || (((CP_TYPE_CONST_NON_VOLATILE_P (to) + && !(flags & LOOKUP_NO_TEMP_BIND)) + || TYPE_REF_IS_RVALUE (rto)) + && (CLASS_TYPE_P (from) || (expr && lvalue_p (expr)))))) { /* [dcl.init.ref] @@ -1288,10 +1291,10 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto); else conv->rvaluedness_matches_p - = (TYPE_REF_IS_RVALUE (rto) == !lvalue_p); + = (TYPE_REF_IS_RVALUE (rto) == !is_lvalue); - if ((lvalue_p & clk_bitfield) != 0 - || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to))) + if ((is_lvalue & clk_bitfield) != 0 + || ((is_lvalue & clk_packed) != 0 && !TYPE_PACKED (to))) /* For the purposes of overload resolution, we ignore the fact this expression is a bitfield or packed field. (In particular, [over.ics.ref] says specifically that a function with a diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index dcad934..07e89d3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4339,6 +4339,7 @@ extern tree force_rvalue (tree); extern tree ocp_convert (tree, tree, int, int); extern tree cp_convert (tree, tree); extern tree cp_convert_and_check (tree, tree); +extern tree cp_fold_convert (tree, tree); extern tree convert_to_void (tree, const char */*implicit context*/, tsubst_flags_t); extern tree convert_force (tree, tree, int); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index c42d21c..cdc6a10 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -539,7 +539,16 @@ force_rvalue (tree expr) return expr; } + +/* Fold away simple conversions, but make sure the result is an rvalue. */ + +tree +cp_fold_convert (tree type, tree expr) +{ + return rvalue (fold_convert (type, expr)); +} + /* C++ conversions, preference to static cast conversions. */ tree diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index cbadf04..9e194fc 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -214,10 +214,14 @@ lvalue_p_1 (const_tree ref) /* Otherwise, it's an lvalue, and it has all the odd properties contributed by either operand. */ op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind; - /* It's not an ordinary lvalue if it involves either a bit-field or - a class rvalue. */ + /* It's not an ordinary lvalue if it involves any other kind. */ if ((op1_lvalue_kind & ~clk_ordinary) != clk_none) op1_lvalue_kind &= ~clk_ordinary; + /* It can't be both a pseudo-lvalue and a non-addressable lvalue. + A COND_EXPR of those should be wrapped in a TARGET_EXPR. */ + if ((op1_lvalue_kind & (clk_rvalueref|clk_class)) + && (op1_lvalue_kind & (clk_bitfield|clk_packed))) + op1_lvalue_kind = clk_none; return op1_lvalue_kind; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 35c82d6..a956fdc 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5284,7 +5284,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, if (TREE_CODE (type) == REFERENCE_TYPE && CLASS_TYPE_P (TREE_TYPE (type)) && CLASS_TYPE_P (intype) - && real_lvalue_p (expr) + && (TYPE_REF_IS_RVALUE (type) || real_lvalue_p (expr)) && DERIVED_FROM_P (intype, TREE_TYPE (type)) && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)), build_pointer_type (TYPE_MAIN_VARIANT @@ -5310,7 +5310,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, base, /*nonnull=*/false); /* Convert the pointer to a reference -- but then remember that there are no expressions with reference type in C++. */ - return convert_from_reference (build_nop (type, expr)); + return convert_from_reference (cp_fold_convert (type, expr)); } orig = expr; |