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?

Reply via email to