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?