diff options
Diffstat (limited to 'gcc/cp/cvt.c')
-rw-r--r-- | gcc/cp/cvt.c | 161 |
1 files changed, 79 insertions, 82 deletions
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index bc9b309fa25..32d0d794cef 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -180,55 +180,57 @@ cp_convert_to_pointer (tree type, tree expr, bool force) } } - if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + if (TYPE_PTRMEMFUNC_P (type)) { - tree b1; - tree b2; - tree binfo; - enum tree_code code = PLUS_EXPR; - base_kind bk; + error ("cannot convert `%E' from type `%T' to type `%T'", + expr, intype, type); + return error_mark_node; + } - b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); - b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)); - binfo = lookup_base (b1, b2, ba_check, &bk); - if (!binfo) - { - binfo = lookup_base (b2, b1, ba_check, &bk); - code = MINUS_EXPR; - } - if (binfo == error_mark_node) - return error_mark_node; + return build_nop (type, expr); + } + else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + { + tree b1; + tree b2; + tree binfo; + enum tree_code code = PLUS_EXPR; + base_kind bk; + + b1 = TYPE_PTRMEM_CLASS_TYPE (type); + b2 = TYPE_PTRMEM_CLASS_TYPE (intype); + binfo = lookup_base (b1, b2, ba_check, &bk); + if (!binfo) + { + binfo = lookup_base (b2, b1, ba_check, &bk); + code = MINUS_EXPR; + } + if (binfo == error_mark_node) + return error_mark_node; - if (bk == bk_via_virtual) + if (bk == bk_via_virtual) + { + if (force) + warning ("pointer to member cast from `%T' to `%T' is via virtual base", + intype, type); + else { - if (force) - warning ("pointer to member cast from `%T' to `%T' is via virtual base", - TREE_TYPE (intype), TREE_TYPE (type)); - else - { - error ("pointer to member cast from `%T' to `%T' is via virtual base", - TREE_TYPE (intype), TREE_TYPE (type)); - return error_mark_node; - } - /* This is a reinterpret cast, whose result is unspecified. - We choose to do nothing. */ - return build1 (NOP_EXPR, type, expr); + error ("pointer to member cast from `%T' to `%T' is via virtual base", + intype, type); + return error_mark_node; } - - if (TREE_CODE (expr) == PTRMEM_CST) - expr = cplus_expand_constant (expr); - - if (binfo) - expr = size_binop (code, convert (sizetype, expr), - BINFO_OFFSET (binfo)); - } - else if (TYPE_PTRMEMFUNC_P (type)) - { - error ("cannot convert `%E' from type `%T' to type `%T'", - expr, intype, type); - return error_mark_node; + /* This is a reinterpret cast, whose result is unspecified. + We choose to do nothing. */ + return build1 (NOP_EXPR, type, expr); } + if (TREE_CODE (expr) == PTRMEM_CST) + expr = cplus_expand_constant (expr); + + if (binfo && !integer_zerop (BINFO_OFFSET (binfo))) + expr = size_binop (code, + build_nop (sizetype, expr), + BINFO_OFFSET (binfo)); return build_nop (type, expr); } else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)) @@ -253,8 +255,6 @@ cp_convert_to_pointer (tree type, tree expr, bool force) return error_mark_node; } - my_friendly_assert (form != OFFSET_TYPE, 186); - if (integer_zerop (expr)) { if (TYPE_PTRMEMFUNC_P (type)) @@ -271,8 +271,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force) force_fit_type (expr, 0); return expr; } - else if ((TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type)) - && INTEGRAL_CODE_P (form)) + else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form)) { error ("invalid conversion from '%T' to '%T'", intype, type); return error_mark_node; @@ -454,7 +453,7 @@ convert_to_reference (tree reftype, tree expr, int convtype, register tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; - int i; + bool can_convert_intype_to_type; if (TREE_CODE (type) == FUNCTION_TYPE && TREE_TYPE (expr) == unknown_type_node) @@ -473,9 +472,9 @@ convert_to_reference (tree reftype, tree expr, int convtype, intype = TYPE_MAIN_VARIANT (intype); - i = comp_target_types (type, intype, 0); - - if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype) + can_convert_intype_to_type = can_convert (type, intype); + if (!can_convert_intype_to_type + && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype) && ! (flags & LOOKUP_NO_CONVERSION)) { /* Look for a user-defined conversion to lvalue that we can use. */ @@ -489,12 +488,12 @@ convert_to_reference (tree reftype, tree expr, int convtype, expr = rval_as_conversion; rval_as_conversion = NULL_TREE; intype = type; - i = 1; + can_convert_intype_to_type = 1; } } - if (((convtype & CONV_STATIC) && i == -1) - || ((convtype & CONV_IMPLICIT) && i == 1)) + if (((convtype & CONV_STATIC) && can_convert (intype, type)) + || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type)) { if (flags & LOOKUP_COMPLAIN) { @@ -550,8 +549,6 @@ convert_to_reference (tree reftype, tree expr, int convtype, return rval; } - my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189); - if (flags & LOOKUP_COMPLAIN) error ("cannot convert type `%T' to type `%T'", intype, reftype); @@ -618,8 +615,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) register tree e = expr; register enum tree_code code = TREE_CODE (type); - if (e == error_mark_node - || TREE_TYPE (e) == error_mark_node) + if (error_operand_p (e) || type == error_mark_node) return error_mark_node; complete_type (type); @@ -671,13 +667,6 @@ ocp_convert (tree type, tree expr, int convtype, int flags) return e; } - /* Just convert to the type of the member. */ - if (code == OFFSET_TYPE) - { - type = TREE_TYPE (type); - code = TREE_CODE (type); - } - if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); @@ -721,8 +710,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) } return fold (convert_to_integer (type, e)); } - if (code == POINTER_TYPE || code == REFERENCE_TYPE - || TYPE_PTRMEMFUNC_P (type)) + if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type)) return fold (cp_convert_to_pointer (type, e, false)); if (code == VECTOR_TYPE) return fold (convert_to_vector (type, e)); @@ -824,8 +812,12 @@ convert_to_void (tree expr, const char *implicit) /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr,1); tree op2 = TREE_OPERAND (expr,2); - tree new_op1 = convert_to_void (op1, implicit); - tree new_op2 = convert_to_void (op2, implicit); + tree new_op1 = convert_to_void + (op1, (implicit && !TREE_SIDE_EFFECTS (op2) + ? "second operand of conditional" : NULL)); + tree new_op2 = convert_to_void + (op2, (implicit && !TREE_SIDE_EFFECTS (op1) + ? "third operand of conditional" : NULL)); expr = build (COND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1, new_op2); @@ -836,14 +828,13 @@ convert_to_void (tree expr, const char *implicit) { /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr,1); - tree new_op1 = convert_to_void (op1, implicit); + tree new_op1 = convert_to_void + (op1, implicit ? "right-hand operand of comma" : NULL); if (new_op1 != op1) { tree t = build (COMPOUND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1); - TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr); - TREE_NO_UNUSED_WARNING (t) = TREE_NO_UNUSED_WARNING (expr); expr = t; } @@ -913,13 +904,9 @@ convert_to_void (tree expr, const char *implicit) if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) { - /* FIXME: This is where we should check for expressions with no - effects. At the moment we do that in both build_x_component_expr - and expand_expr_stmt -- inconsistently too. For the moment - leave implicit void conversions unadorned so that expand_expr_stmt - has a chance of detecting some of the cases. */ - if (!implicit) - expr = build1 (CONVERT_EXPR, void_type_node, expr); + if (implicit && !TREE_SIDE_EFFECTS (expr) && warn_unused_value) + warning ("%s has no effect", implicit); + expr = build1 (CONVERT_EXPR, void_type_node, expr); } return expr; } @@ -1178,10 +1165,20 @@ type_promotes_to (tree type) tree perform_qualification_conversions (tree type, tree expr) { - if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE - && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (expr)))) - return build1 (NOP_EXPR, type, expr); + tree expr_type; + + expr_type = TREE_TYPE (expr); + + if (TYPE_PTR_P (type) && TYPE_PTR_P (expr_type) + && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (expr_type))) + return build_nop (type, expr); + else if (TYPE_PTR_TO_MEMBER_P (type) + && TYPE_PTR_TO_MEMBER_P (expr_type) + && same_type_p (TYPE_PTRMEM_CLASS_TYPE (type), + TYPE_PTRMEM_CLASS_TYPE (expr_type)) + && comp_ptr_ttypes (TYPE_PTRMEM_POINTED_TO_TYPE (type), + TYPE_PTRMEM_POINTED_TO_TYPE (expr_type))) + return build_nop (type, expr); else return error_mark_node; } |