* EXPR is not a constant of integer type which cannot be
exactly converted to real type.
- Function allows conversions between types of different signedness and
- can return SAFE_CONVERSION (zero) in that case. Function can produce
- signedness warnings if PRODUCE_WARNS is true.
+ Function allows conversions between types of different signedness if
+ CHECK_SIGN is false and can return SAFE_CONVERSION (zero) in that
+ case. Function can return UNSAFE_SIGN if CHECK_SIGN is true.
RESULT, when non-null is the result of the conversion. When constant
it is included in the text of diagnostics.
enum conversion_safety
unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
- bool produce_warns)
+ bool check_sign)
{
enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */
tree expr_type = TREE_TYPE (expr);
- bool cstresult = (result
- && TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant);
-
loc = expansion_point_location_if_in_system_header (loc);
expr = fold_for_warn (expr);
if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
&& tree_int_cst_sgn (expr) < 0)
{
- if (produce_warns)
- {
- if (cstresult)
- warning_at (loc, OPT_Wsign_conversion,
- "unsigned conversion from %qT to %qT "
- "changes value from %qE to %qE",
- expr_type, type, expr, result);
- else
- warning_at (loc, OPT_Wsign_conversion,
- "unsigned conversion from %qT to %qT "
- "changes the value of %qE",
- expr_type, type, expr);
- }
+ if (check_sign)
+ give_warning = UNSAFE_SIGN;
}
else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type))
{
- if (cstresult)
- warning_at (loc, OPT_Wsign_conversion,
- "signed conversion from %qT to %qT changes "
- "value from %qE to %qE",
- expr_type, type, expr, result);
- else
- warning_at (loc, OPT_Wsign_conversion,
- "signed conversion from %qT to %qT changes "
- "the value of %qE",
- expr_type, type, expr);
+ if (check_sign)
+ give_warning = UNSAFE_SIGN;
}
else
give_warning = UNSAFE_OTHER;
is a constant, it's type is not used in text of generated warnings
(otherwise they could sound misleading). */
return unsafe_conversion_p (loc, type, TREE_REALPART (expr), result,
- produce_warns);
+ check_sign);
/* Conversion from complex constant with non-zero imaginary part. */
else
{
Perform checks for both real and imaginary parts. */
if (TREE_CODE (type) == COMPLEX_TYPE)
{
- /* Unfortunately, produce_warns must be false in two subsequent
- calls of unsafe_conversion_p, because otherwise we could
- produce strange "double" warnings, if both real and imaginary
- parts have conversion problems related to signedness.
-
- For example:
- int32_t _Complex a = 0x80000000 + 0x80000000i;
-
- Possible solution: add a separate function for checking
- constants and combine result of two calls appropriately. */
enum conversion_safety re_safety =
- unsafe_conversion_p (loc, type, TREE_REALPART (expr),
- result, false);
+ unsafe_conversion_p (loc, type, TREE_REALPART (expr),
+ result, check_sign);
enum conversion_safety im_safety =
- unsafe_conversion_p (loc, type, imag_part, result, false);
+ unsafe_conversion_p (loc, type, imag_part, result, check_sign);
/* Merge the results into appropriate single warning. */
/* When they are the same width but different signedness,
then the value may change. */
else if (((TYPE_PRECISION (type) == 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 (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 (expr_type)))
- && produce_warns)
- warning_at (loc, OPT_Wsign_conversion, "conversion to %qT from %qT "
- "may change the sign of the result",
- type, expr_type);
+ && check_sign)
+ give_warning = UNSAFE_SIGN;
}
/* Warn for integer types converted to real types if and only if
/* Check for different signedness, see case for real-domain
integers (above) for a more detailed comment. */
else if (((TYPE_PRECISION (to_type) == TYPE_PRECISION (from_type)
- && TYPE_UNSIGNED (to_type) != TYPE_UNSIGNED (from_type))
- || (TYPE_UNSIGNED (to_type) && !TYPE_UNSIGNED (from_type)))
- && produce_warns)
- warning_at (loc, OPT_Wsign_conversion,
- "conversion to %qT from %qT "
- "may change the sign of the result",
- type, expr_type);
+ && TYPE_UNSIGNED (to_type) != TYPE_UNSIGNED (from_type))
+ || (TYPE_UNSIGNED (to_type) && !TYPE_UNSIGNED (from_type)))
+ && check_sign)
+ give_warning = UNSAFE_SIGN;
}
else if (TREE_CODE (from_type) == INTEGER_TYPE
&& TREE_CODE (to_type) == REAL_TYPE
else
break;
- if (TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant)
+ if (conversion_kind == UNSAFE_SIGN)
+ {
+ bool cstresult
+ = (result
+ && TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant);
+ if (TYPE_UNSIGNED (type))
+ {
+ if (cstresult)
+ warning_at (loc, OPT_Wsign_conversion,
+ "unsigned conversion from %qT to %qT "
+ "changes value from %qE to %qE",
+ expr_type, type, expr, result);
+ else
+ warning_at (loc, OPT_Wsign_conversion,
+ "unsigned conversion from %qT to %qT "
+ "changes the value of %qE",
+ expr_type, type, expr);
+ }
+ else
+ {
+ if (cstresult)
+ warning_at (loc, OPT_Wsign_conversion,
+ "signed conversion from %qT to %qT changes "
+ "value from %qE to %qE",
+ expr_type, type, expr, result);
+ else
+ warning_at (loc, OPT_Wsign_conversion,
+ "signed conversion from %qT to %qT changes "
+ "the value of %qE",
+ expr_type, type, expr);
+ }
+ }
+ else if (TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant)
warning_at (loc, warnopt,
"conversion from %qT to %qT changes value from %qE to %qE",
expr_type, type, expr, result);
default: /* 'expr' is not a constant. */
conversion_kind = unsafe_conversion_p (loc, type, expr, result, true);
- if (conversion_kind == UNSAFE_IMAGINARY)
- warning_at (loc, OPT_Wconversion,
- "conversion from %qT to %qT discards imaginary component",
- expr_type, type);
- else
- {
- int warnopt;
- if (conversion_kind == UNSAFE_REAL)
- warnopt = OPT_Wfloat_conversion;
- else if (conversion_kind)
- warnopt = OPT_Wconversion;
- else
- break;
+ {
+ int warnopt;
+ if (conversion_kind == UNSAFE_REAL)
+ warnopt = OPT_Wfloat_conversion;
+ else if (conversion_kind == UNSAFE_SIGN)
+ warnopt = OPT_Wsign_conversion;
+ else if (conversion_kind)
+ warnopt = OPT_Wconversion;
+ else
+ break;
+ if (conversion_kind == UNSAFE_SIGN)
+ warning_at (loc, warnopt, "conversion to %qT from %qT "
+ "may change the sign of the result",
+ type, expr_type);
+ else if (conversion_kind == UNSAFE_IMAGINARY)
+ warning_at (loc, warnopt,
+ "conversion from %qT to %qT discards imaginary component",
+ expr_type, type);
+ else
warning_at (loc, warnopt,
"conversion from %qT to %qT may change value",
expr_type, type);
- }
+ }
}
}