This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Bug in fold-const.c
- From: "Hartmut Penner" <HPENNER at de dot ibm dot com>
- To: gcc at gcc dot gnu dot org
- Cc: "Torsten Hendel" <HENDELT at de dot ibm dot com>
- Date: Fri, 8 Mar 2002 09:31:52 +0100
- Subject: Bug in fold-const.c
unsigned short c = 0x8000;
main()
{
if ((c-0x8000) < 0 || (c-0x8000) >0x7fff)
abort();
}
When compiling this little testcase with any gcc version (2.95, 3.1...)
without optimization anything works fine. By turning on optimization
it will abort. I debugged it a bit and found out, that the bug is probably
in the function make_range in fold-const.c
Take a look in the following code from make_range line 3027:
/* If we're converting from an unsigned to a signed type,
we will be doing the comparison as unsigned. The tests above
have already verified that LOW and HIGH are both positive.
So we have to make sure that the original unsigned value will
be interpreted as positive. */
-> (c-0x8000) < 0)
-> minus_expr exp is done integer signed mode, TREE_UNSIGNED (type) is true (type of c)
->n_low is 0x8000
if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
{
tree equiv_type = type_for_mode (TYPE_MODE (type), 1);
tree high_positive;
/* A range without an upper bound is, naturally, unbounded.
Since convert would have cropped a very large value, use
the max value for the destination type. */
high_positive
= TYPE_MAX_VALUE (equiv_type) ? TYPE_MAX_VALUE (equiv_type)
: TYPE_MAX_VALUE (type);
-> high positive is 0xffff
high_positive = fold (build (RSHIFT_EXPR, type,
convert (type, high_positive),
convert (type, integer_one_node)));
->high_posotive is converted to 0x7fff
/* If the low bound is specified, "and" the range with the
range for which the original unsigned value will be
positive. */
if (low != 0)
{
if (! merge_ranges (&n_in_p, &n_low, &n_high,
1, n_low, n_high,
1, convert (type, integer_zero_node),
high_positive))
break;
in_p = (n_in_p == in_p);
}
else
{
/* Otherwise, "or" the range with the range of the input
that will be interpreted as negative. */
if (! merge_ranges (&n_in_p, &n_low, &n_high,
0, n_low, n_high,
1, convert (type, integer_zero_node),
high_positive))
break;
in_p = (in_p != n_in_p);
}
->n_low is 0, n_high is 0,
->>> n_low should be 0x8000, n_high should be 0xffff
}
My first guess to fix this would be to something like this
if (TREE_PRECISION (type) >= TREE_PRECISION (TREE_TYPE (exp)))
high_positive = fold (build (RSHIFT_EXPR, type,
convert (type, high_positive),
convert (type, integer_one_node)));
Mit freundlichem Gruß / Best regards,
Hartmut Penner
GCC for S/390 Development
Internet Mail Address : hpenner@de.ibm.com
Tel: (49)-7031-16-4364