[Bug c/34389] -Wconversion produces wrong warning
manu at gcc dot gnu dot org
gcc-bugzilla@gcc.gnu.org
Fri Feb 15 18:05:00 GMT 2008
------- Comment #8 from manu at gcc dot gnu dot org 2008-02-15 18:04 -------
This patch fixes this bug but it is an ugly hack. Perhaps such an ugly hack is
the only thing we can do at the moment.
Once bootstrapping + testing finishes, I will submit.
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c (revision 132310)
+++ gcc/c-common.c (working copy)
@@ -1270,65 +1270,98 @@ conversion_warning (tree type, tree expr
"conversion to %qT alters %qT constant value",
type, TREE_TYPE (expr));
}
else /* 'expr' is not a constant. */
{
+ tree expr_type = TREE_TYPE (expr);
+
/* Warn for real types converted to integer types. */
- if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ if (TREE_CODE (expr_type) == REAL_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
give_warning = true;
- else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ else if (TREE_CODE (expr_type) == INTEGER_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
{
/* Don't warn about unsigned char y = 0xff, x = (int) y; */
expr = get_unwidened (expr, 0);
+ expr_type = TREE_TYPE (expr);
+ /* Don't warn for short y; short x = ((int)y & 0xff); */
+ if (TREE_CODE (expr) == BIT_AND_EXPR
+ && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST)
+ {
+ int unsigned0, unsigned1;
+ tree arg0, arg1;
+ tree tmp_type;
+ tree op0, op1;
+
+ op0 = convert (expr_type, TREE_OPERAND (expr, 0));
+ op1 = convert (expr_type, TREE_OPERAND (expr, 1));
+
+ arg0 = get_narrower (op0, &unsigned0);
+ arg1 = get_narrower (op1, &unsigned1);
+
+ /* Handle the case that OP0 (or OP1) does not *contain* a
conversion
+ but it *requires* conversion to TYPE. */
+ if ((TYPE_PRECISION (TREE_TYPE (op0))
+ == TYPE_PRECISION (TREE_TYPE (arg0)))
+ && TREE_TYPE (op0) != expr_type)
+ unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+
+ if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION
(expr_type)
+ && (tmp_type
+ = c_common_signed_or_unsigned_type (unsigned0,
+ TREE_TYPE (arg0)))
+ && !POINTER_TYPE_P (tmp_type)
+ && int_fits_type_p (arg1, tmp_type))
+ expr_type = tmp_type;
+ }
/* Warn for integer types converted to smaller integer types. */
- if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+ if (formal_prec < TYPE_PRECISION (expr_type))
give_warning = true;
/* When they are the same width but different signedness,
then the value may change. */
- else if ((formal_prec == TYPE_PRECISION (TREE_TYPE (expr))
- && TYPE_UNSIGNED (TREE_TYPE (expr)) != TYPE_UNSIGNED
(type))
+ else if ((formal_prec == TYPE_PRECISION (expr_type)
+ && TYPE_UNSIGNED (expr_type) != TYPE_UNSIGNED (type))
/* Even when converted to a bigger type, if the type is
unsigned but expr is signed, then negative values
will be changed. */
- || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE
(expr))))
+ || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)))
warning (OPT_Wsign_conversion,
"conversion to %qT from %qT may change the sign of the
result",
- type, TREE_TYPE (expr));
+ type, expr_type);
}
/* Warn for integer types converted to real types if and only if
all the range of values of the integer type cannot be
represented by the real type. */
- else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ else if (TREE_CODE (expr_type) == INTEGER_TYPE
&& TREE_CODE (type) == REAL_TYPE)
{
- tree type_low_bound = TYPE_MIN_VALUE (TREE_TYPE (expr));
- tree type_high_bound = TYPE_MAX_VALUE (TREE_TYPE (expr));
+ tree type_low_bound = TYPE_MIN_VALUE (expr_type);
+ tree type_high_bound = TYPE_MAX_VALUE (expr_type);
REAL_VALUE_TYPE real_low_bound = real_value_from_int_cst (0,
type_low_bound);
REAL_VALUE_TYPE real_high_bound = real_value_from_int_cst (0,
type_high_bound);
if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
|| !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
give_warning = true;
}
/* Warn for real types converted to smaller real types. */
- else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ else if (TREE_CODE (expr_type) == REAL_TYPE
&& TREE_CODE (type) == REAL_TYPE
- && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+ && formal_prec < TYPE_PRECISION (expr_type))
give_warning = true;
if (give_warning)
warning (OPT_Wconversion,
"conversion to %qT from %qT may alter its value",
- type, TREE_TYPE (expr));
+ type, expr_type);
}
}
/* Produce warnings after a conversion. RESULT is the result of
converting EXPR to TYPE. This is a helper function for
--
manu at gcc dot gnu dot org changed:
What |Removed |Added
----------------------------------------------------------------------------
Last reconfirmed|2007-12-13 21:38:26 |2008-02-15 18:04:44
date| |
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34389
More information about the Gcc-bugs
mailing list