http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56474
--- Comment #4 from Eric Botcazou <ebotcazou at gcc dot gnu.org> 2013-03-01
14:25:56 UTC ---
This happens because 0 - 1 overflows in sizetype:
#6 0x0000000000ac3e3d in size_binop_loc (loc=0, code=MINUS_EXPR,
arg0=0x7ffff6d65d60, arg1=0x7ffff6d65f00)
at /home/eric/svn/gcc/gcc/fold-const.c:1417
1417 return int_const_binop_1 (code, arg0, arg1, -1);
(gdb) p debug_tree(arg0)
<integer_cst 0x7ffff6d65d60 type <integer_type 0x7ffff6d710a8 sizetype>
constant visited 0>
$28 = void
(gdb) p debug_tree(arg1)
<integer_cst 0x7ffff6d65f00 type <integer_type 0x7ffff6d710a8 sizetype>
constant visited 1>
$29 = void
(gdb) frame 4
#4 0x0000000000f28804 in force_fit_type_double (type=0x7ffff6d710a8, cst=...,
overflowable=-1, overflowed=false) at /home/eric/svn/gcc/gcc/tree.c:1109
1109 tree t = make_node (INTEGER_CST);
(gdb) p cst
$30 = {low = 18446744073709551615, high = -1}
Now it didn't overflow on the 4.7 branch:
Breakpoint 2, int_const_binop (code=MINUS_EXPR, arg1=0x7ffff6d66f00,
arg2=0x7ffff6d790a0) at /home/eric/svn/gcc-4_7-branch/gcc/fold-const.c:1085
1085 return t;
(gdb) p debug_tree(arg1)
<integer_cst 0x7ffff6d66f00 type <integer_type 0x7ffff6d77000 sizetype>
constant visited 0>
$4 = void
(gdb) p debug_tree(arg2)
<integer_cst 0x7ffff6d790a0 type <integer_type 0x7ffff6d77000 sizetype>
constant visited 1>
$5 = void
(gdb) p debug_tree(t)
<integer_cst 0x7ffff6d66f20 type <integer_type 0x7ffff6d77000 sizetype>
constant visited -1>
This low_bound - 1 idiom is pervasive in Ada and it will probably overflow only
for 0 so we could add a kludge to size_binop_loc, similarly to the kludge that
exists in layout_type:
Index: fold-const.c
===================================================================
--- fold-const.c (revision 196253)
+++ fold-const.c (working copy)
@@ -1389,9 +1389,13 @@ size_binop_loc (location_t loc, enum tre
gcc_assert (int_binop_types_match_p (code, TREE_TYPE (arg0),
TREE_TYPE (arg1)));
- /* Handle the special case of two integer constants faster. */
+ /* Handle general case of two integer constants. For sizetype constant
+ calculations, we always want to know about overflow, even in the
+ unsigned case. */
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
{
+ int overflowable = -1;
+
/* And some specific cases even faster than that. */
if (code == PLUS_EXPR)
{
@@ -1404,6 +1408,11 @@ size_binop_loc (location_t loc, enum tre
{
if (integer_zerop (arg1) && !TREE_OVERFLOW (arg1))
return arg0;
+
+ /* ??? We make an exception for 0 - 1 because it's an idiom
+ used in length calculations for zero-based arrays. */
+ if (integer_zerop (arg0) && integer_onep (arg1))
+ overflowable = 1;
}
else if (code == MULT_EXPR)
{
@@ -1411,10 +1420,7 @@ size_binop_loc (location_t loc, enum tre
return arg1;
}
- /* Handle general case of two integer constants. For sizetype
- constant calculations we always want to know about overflow,
- even in the unsigned case. */
- return int_const_binop_1 (code, arg0, arg1, -1);
+ return int_const_binop_1 (code, arg0, arg1, overflowable);
}
return fold_build2_loc (loc, code, type, arg0, arg1);
What do you think Richard?