summaryrefslogtreecommitdiff
path: root/gcc/c-common.c
diff options
context:
space:
mode:
authormanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>2006-11-24 01:50:33 +0000
committermanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>2006-11-24 01:50:33 +0000
commitd31d55f0c3199621e0317574d9a156c933c26db3 (patch)
tree5f5522ac3829784d28af2cccffb6ea3878cf5875 /gcc/c-common.c
parent44a2bb4a172e461a7bd99e12eef4d0d0d2f829cf (diff)
downloadgcc-d31d55f0c3199621e0317574d9a156c933c26db3.tar.gz
2006-11-24 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/2707 PR c++/26167 * c-common.c (conversion_warning): New. (convert_and_check): Call conversion_warning unless there is an overflow warning. * doc/invoke.texi (-Wconversion): Update description. testsuite/ * gcc.dg/Wconversion-integer.c: New. Supersedes Wconversion-negative-constants.c * gcc.dg/Wconversion-real.c: New. * gcc.dg/Wconversion-real-integer.c: New. * gcc.dg/Wconversion-negative-constants.c: Deleted. * g++.dg/warn/Wconversion1.C: Modified. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119143 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r--gcc/c-common.c165
1 files changed, 139 insertions, 26 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 0603da65bc1..8e4cbff3b9e 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -1127,6 +1127,113 @@ vector_types_convertible_p (tree t1, tree t2)
== INTEGRAL_TYPE_P (TREE_TYPE (t2)));
}
+/* Warns if the conversion of EXPR to TYPE may alter a value.
+ This function is called from convert_and_check. */
+
+static void
+conversion_warning (tree type, tree expr)
+{
+ bool give_warning = false;
+
+ unsigned int formal_prec = TYPE_PRECISION (type);
+
+ if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
+ {
+ /* Warn for real constant that is not an exact integer converted
+ to integer type. */
+ if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE)
+ {
+ if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (TREE_TYPE (expr))))
+ give_warning = true;
+ }
+ /* Warn for an integer constant that does not fit into integer
+ type. However, warnings for negative constants converted to
+ unsigned types are detected by unsigned_conversion_warning. */
+ else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE
+ && !int_fits_type_p (expr, type)
+ && !(TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr))))
+ give_warning = true;
+
+ else if (TREE_CODE (type) == REAL_TYPE)
+ {
+ /* Warn for an integer constant that does not fit into real type. */
+ if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE)
+ {
+ REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
+ if (!exact_real_truncate (TYPE_MODE (type), &a))
+ give_warning = true;
+ }
+ /* Warn for a real constant that does not fit into a smaller
+ real type. */
+ else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+ {
+ REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
+ if (!exact_real_truncate (TYPE_MODE (type), &a))
+ give_warning = true;
+ }
+ }
+
+ if (give_warning)
+ warning (OPT_Wconversion,
+ "conversion to %qT alters %qT constant value",
+ type, TREE_TYPE (expr));
+ }
+ else /* 'expr' is not a constant. */
+ {
+ /* Warn for real types converted to integer types. */
+ if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE)
+ give_warning = true;
+
+ else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE)
+ {
+ /* Warn for integer types converted to smaller integer types. */
+ if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr))
+ /* When they are the same width but different signedness,
+ then the value may change. */
+ || (formal_prec == TYPE_PRECISION (TREE_TYPE (expr))
+ && TYPE_UNSIGNED (TREE_TYPE (expr)) != 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))))
+ give_warning = true;
+ }
+
+ /* 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
+ && 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));
+ 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
+ && TREE_CODE (type) == REAL_TYPE
+ && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+ give_warning = true;
+
+
+ if (give_warning)
+ warning (OPT_Wconversion,
+ "conversion to %qT from %qT may alter its value",
+ type, TREE_TYPE (expr));
+ }
+}
+
/* Convert EXPR to TYPE, warning about conversion problems with constants.
Invoke this function on every expression that is converted implicitly,
i.e. because of language rules and not because of an explicit cast. */
@@ -1135,33 +1242,39 @@ tree
convert_and_check (tree type, tree expr)
{
tree t = convert (type, expr);
- if (TREE_CODE (t) == INTEGER_CST)
+ if (TREE_CODE (t) == INTEGER_CST && TREE_OVERFLOW (t))
+ {
+ TREE_OVERFLOW (t) = 0;
+
+ /* Do not diagnose overflow in a constant expression merely
+ because a conversion overflowed. */
+ TREE_CONSTANT_OVERFLOW (t) = CONSTANT_CLASS_P (expr)
+ && TREE_CONSTANT_OVERFLOW (expr);
+
+ /* No warning for converting 0x80000000 to int. */
+ if (!(TYPE_UNSIGNED (type) < TYPE_UNSIGNED (TREE_TYPE (expr))
+ && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr))))
+ {
+ /* If EXPR fits in the unsigned version of TYPE,
+ don't warn unless pedantic. */
+ if ((pedantic
+ || TYPE_UNSIGNED (type)
+ || !constant_fits_type_p (expr,
+ c_common_unsigned_type (type)))
+ && skip_evaluation == 0)
+ warning (OPT_Woverflow,
+ "overflow in implicit constant conversion");
+ }
+ else if (warn_conversion && !skip_evaluation)
+ conversion_warning (type, expr);
+ }
+ else
{
- if (TREE_OVERFLOW (t))
- {
- TREE_OVERFLOW (t) = 0;
-
- /* Do not diagnose overflow in a constant expression merely
- because a conversion overflowed. */
- TREE_CONSTANT_OVERFLOW (t) = CONSTANT_CLASS_P (expr)
- && TREE_CONSTANT_OVERFLOW (expr);
-
- /* No warning for converting 0x80000000 to int. */
- if (!(TYPE_UNSIGNED (type) < TYPE_UNSIGNED (TREE_TYPE (expr))
- && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
- && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr))))
- /* If EXPR fits in the unsigned version of TYPE,
- don't warn unless pedantic. */
- if ((pedantic
- || TYPE_UNSIGNED (type)
- || !constant_fits_type_p (expr,
- c_common_unsigned_type (type)))
- && skip_evaluation == 0)
- warning (OPT_Woverflow,
- "overflow in implicit constant conversion");
- }
- else
- unsigned_conversion_warning (t, expr);
+ if (warn_conversion && !skip_evaluation)
+ conversion_warning (type, expr);
+
+ unsigned_conversion_warning (t, expr);
}
return t;
}