https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81505
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Priority|P3 |P2 Status|UNCONFIRMED |ASSIGNED Last reconfirmed| |2017-07-21 Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot gnu.org Target Milestone|--- |5.5 Ever confirmed|0 |1 --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- 90 if (TREE_CODE (step) == INTEGER_CST) 91 { 92 if (TYPE_UNSIGNED (TREE_TYPE (step))) 93 { 94 step1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step); 95 if (tree_int_cst_lt (step1, step)) 96 { (gdb) p debug_generic_expr (step) -4B(OVF) note this is a POINTER_TYPE constant. fold_negate_const produces a non-overflown 4B from that which is what confuses things. Of course pointers should never get TREE_OVERFLOW set IMHO. It gets that from #1 0x0000000000b079aa in fold_convert_const_int_from_int ( type=<pointer_type 0x7ffff69d6690>, arg1=0x7ffff6a0bb70) at /tmp/trunk/gcc/fold-const.c:1869 1869 TREE_OVERFLOW (arg1)); (gdb) l 1864 /* Given an integer constant, make new constant with new type, 1865 appropriately sign-extended or truncated. Use widest_int 1866 so that any extension is done according ARG1's type. */ 1867 return force_fit_type (type, wi::to_widest (arg1), 1868 !POINTER_TYPE_P (TREE_TYPE (arg1)), 1869 TREE_OVERFLOW (arg1)); 1870 } 1871 1872 /* A subroutine of fold_convert_const handling conversions a REAL_CST 1873 to an integer type. */ (gdb) p arg1 $18 = (const_tree) 0x7ffff6a0bb70 (gdb) p debug_generic_expr (arg1) -4(OVF) so somewhat reasonable. So the bug is in fold_negate_const loosing the overflow flag. Fix: Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 250386) +++ gcc/fold-const.c (working copy) @@ -13693,8 +13693,8 @@ fold_negate_const (tree arg0, tree type) bool overflow; wide_int val = wi::neg (arg0, &overflow); t = force_fit_type (type, val, 1, - (overflow | TREE_OVERFLOW (arg0)) - && !TYPE_UNSIGNED (type)); + (overflow && ! TYPE_UNSIGNED (type)) + || TREE_OVERFLOW (arg0)); break; }