aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/cvt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/cvt.c')
-rw-r--r--gcc/cp/cvt.c161
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;
}