http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56474
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> 2013-03-04
09:53:39 UTC ---
(In reply to comment #4)
> 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?
What will the result be used for in this case? The result, usizetype_max,
is certainly not 0 - 1 == -1 as it is unsigned.
Adding kludges like that might work, but I'd rather try to fix callers
to "ask more intelligent questions". That is,
+ /* ??? 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;
the length of an array is max-index - min-index + 1. What's the call
stack of this testcases case triggering the overflow?