This is one of the major installments in the on-going TREE_OVERFLOW
clean-ups. Currently, when asked to truncate an INTEGER_CST to a
narrower type, the middle-end may set the TREE_OVERFLOW flag on the
result. Even though the semantics of signed and unsigned truncation
are well-defined in the middle-end, the setting TREE_OVERFLOW has
historically been a source of problems in tree-ssa optimizers, as
it disables many transformations and triggers less well tested code
paths.
The propsed goal is to change fold_convert_const_int_from_int so
that it no longer sets TREE_OVERFLOW or TREE_CONSTANT_OVERFLOW.
The major remaining user of this functionality is the convert_and_check
function in the C family front-ends, that uses the TREE_OVERFLOW from
these truncations to issue front-end diagnostics. It turns out that
its relatively simple to use the middle-end function int_fits_type
which is intended for exactly this use. This reduces the overflow
bit pollution of trees in the tree-ssa optimizers.
The following patch has been tested (in conjunction with my recently
posted C++ clean-up) on x86_64-unknown-linux-gnu, with a full "make
bootstrap", all default languages, and regression tested with a
top-level "make -k check" with no new failures. Critically, no
changes in the C/C++ diagnostics issued anywhere in the testsuite.
I believe that the rationalization of this logic in a single
front-end function, makes it easier to see what's going on, and
for front-end maintainers to tune as they wish.
Ok for mainline? I'd appreciate it if anyone with access to Plum-Hall
or similar validation suite could give it a spin. Hopefully, folks
agree this untangling of front-ends from the middle-end is a direction
that we want to go.
2006-11-12 Roger Sayle <roger@eyesopen.com>
* c-common.c (constant_fits_type_p): Delete.
(unsigned_conversion_warning): Delete. Integrate into...
(convert_and_check): Reorganize and simplify to avoid dependence
upon the middle-end setting TREE_OVERFLOW on integral conversions,
by using int_fits_type directly.
Index: c-common.c
===================================================================
*** c-common.c (revision 118625)
--- c-common.c (working copy)
*************** const struct fname_var_t fname_vars[] =
*** 499,505 ****
{NULL, 0, 0},
};
- static int constant_fits_type_p (tree, tree);
static tree check_case_value (tree);
static bool check_case_bounds (tree, tree, tree *, tree *);
--- 499,504 ----
*************** overflow_warning (tree value)
*** 957,988 ****
}
}
- /* Print a warning if a large constant is truncated to unsigned,
- or if -Wconversion is used and a constant < 0 is converted to unsigned.
- Invoke this function on every expression that might be implicitly
- converted to an unsigned type. */
-
- static void
- unsigned_conversion_warning (tree result, tree operand)
- {
- tree type = TREE_TYPE (result);
-
- if (TREE_CODE (operand) == INTEGER_CST
- && TREE_CODE (type) == INTEGER_TYPE
- && TYPE_UNSIGNED (type)
- && skip_evaluation == 0
- && !int_fits_type_p (operand, type))
- {
- if (!int_fits_type_p (operand, c_common_signed_type (type)))
- /* This detects cases like converting -129 or 256 to unsigned char. */
- warning (OPT_Woverflow,
- "large integer implicitly truncated to unsigned type");
- else
- warning (OPT_Wconversion,
- "negative integer implicitly converted to unsigned type");
- }
- }
-
/* Print a warning about casts that might indicate violation
of strict aliasing rules if -Wstrict-aliasing is used and
strict aliasing mode is in effect. OTYPE is the original
--- 956,961 ----
*************** check_main_parameter_types (tree decl)
*** 1100,1118 ****
}
- /* Nonzero if constant C has a value that is permissible
- for type TYPE (an INTEGER_TYPE). */
-
- static int
- constant_fits_type_p (tree c, tree type)
- {
- if (TREE_CODE (c) == INTEGER_CST)
- return int_fits_type_p (c, type);
-
- c = convert (type, c);
- return !TREE_OVERFLOW (c);
- }
-
/* Nonzero if vector types T1 and T2 can be converted to each other
without an explicit cast. */
int
--- 1073,1078 ----
*************** vector_types_convertible_p (tree t1, tre
*** 1134,1169 ****
tree
convert_and_check (tree type, tree expr)
{
! tree t = convert (type, expr);
! if (TREE_CODE (t) == INTEGER_CST)
! {
! 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);
}
! return t;
}
/* A node in a list that describes references to variables (EXPR), which are
--- 1094,1150 ----
tree
convert_and_check (tree type, tree expr)
{
! tree result;
! if (TREE_TYPE (expr) == type)
! return expr;
! result = convert (type, expr);
! if (TREE_CODE (result) != INTEGER_CST
! || skip_evaluation)
! return result;
!
! if (TREE_CODE (expr) == INTEGER_CST
! && (TREE_CODE (type) == INTEGER_TYPE
! || TREE_CODE (type) == ENUMERAL_TYPE)
! && !int_fits_type_p (expr, type))
! {
! /* Do not diagnose overflow in a constant expression merely
! because a conversion overflowed. */
! if (TREE_OVERFLOW (result))
! {
! TREE_CONSTANT_OVERFLOW (result) = TREE_CONSTANT_OVERFLOW (expr);
! TREE_OVERFLOW (result) = TREE_OVERFLOW (expr);
! }
!
! if (TYPE_UNSIGNED (type))
! {
! /* This detects cases like converting -129 or 256 to
! unsigned char. */
! if (!int_fits_type_p (expr, c_common_signed_type (type)))
! warning (OPT_Woverflow,
! "large integer implicitly truncated to unsigned type");
! else
! warning (OPT_Wconversion,
! "negative integer implicitly converted to unsigned type");
}
else
! {
! if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
! warning (OPT_Woverflow,
! "overflow in implicit constant conversion");
! /* No warning for converting 0x80000000 to int. */
! else if (pedantic
! && (TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE
! || TYPE_PRECISION (TREE_TYPE (expr))
! != TYPE_PRECISION (type)))
! warning (OPT_Woverflow,
! "overflow in implicit constant conversion");
! }
}
! else if (TREE_OVERFLOW (result))
! warning (OPT_Woverflow, "overflow in implicit constant conversion");
! return result;
}
/* A node in a list that describes references to variables (EXPR), which are
Roger
--