* 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.
From-SVN: r150325
+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.
2009-07-31 Jason Merrill <jason@redhat.com>
* typeck.c (build_address): Do fold away ADDR_EXPR of INDIRECT_REF.
tree tfrom;
bool related_p;
bool compatible_p;
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))
{
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
{
if (TREE_CODE (from) == REFERENCE_TYPE)
{
/* Anything with reference type is an lvalue. */
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);
}
from = TREE_TYPE (from);
}
- if (lvalue_p == clk_none && expr)
- lvalue_p = real_lvalue_p (expr);
+ if (is_lvalue == clk_none && expr)
+ is_lvalue = real_lvalue_p (expr);
- 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
tfrom = unlowered_expr_type (expr);
/* Figure out whether or not the types are reference-related and
/* 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
/* 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. */
- && (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))))))
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
else
conv->rvaluedness_matches_p
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
/* 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
extern tree ocp_convert (tree, tree, int, int);
extern tree cp_convert (tree, tree);
extern tree cp_convert_and_check (tree, 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);
extern tree convert_to_void (tree, const char */*implicit context*/,
tsubst_flags_t);
extern tree convert_force (tree, tree, int);
+/* 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
/* C++ conversions, preference to static cast conversions. */
tree
/* 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;
/* 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;
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;
}
return op1_lvalue_kind;
}
if (TREE_CODE (type) == REFERENCE_TYPE
&& CLASS_TYPE_P (TREE_TYPE (type))
&& CLASS_TYPE_P (intype)
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
&& DERIVED_FROM_P (intype, TREE_TYPE (type))
&& can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
build_pointer_type (TYPE_MAIN_VARIANT
base, /*nonnull=*/false);
/* Convert the pointer to a reference -- but then remember that
there are no expressions with reference type in C++. */
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));