bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GCC optimizes integer overflow: bug or feature?


From: Paul Eggert
Subject: Re: GCC optimizes integer overflow: bug or feature?
Date: Fri, 29 Dec 2006 00:55:18 -0800
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)

Paolo Bonzini <address@hidden> writes:

>> Or you can do, since elsewhere in the code you compute time_t_max:
>>   for (j = 1; j <= time_t_max / 2 + 1; j *= 2)
>
> No, this does not work.  It would work to have:
>
>   for (j = 1;;)
>     {
>       if (j > time_t_max / 2)
>         break;
>       j *= 2;
>     }
>
> Oops.

"Oops" is my thought as well.  Even the second version of your code is
incorrect in general, since it assumes that 'int' and 'time_t' are the
same width.

It's surprisingly tricky to get right.  This underscores why -O2's
changes in this area are so worrisome.

What I eventually ended up doing -- and this was before reading the
above-quoted email -- was this:

      for (j = 1; ; j <<= 1)
        if (! bigtime_test (j))
          return 1;
        else if (INT_MAX / 2 < j)
          break;

This is portable and should work on all real platforms.

But that was the easy code!  Here's the harder stuff, the
code that computes time_t_max:

  static time_t time_t_max;
  static time_t time_t_min;
  for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2)
    continue;
  time_t_max--;
  if ((time_t) -1 < 0)
    for (time_t_min = -1; (time_t) (time_t_min * 2) < 0; time_t_min *= 2)
      continue;

Obviously this code is buggy, at least in theory, due to the signed
integer overflows.  But rewriting it is not so easy, since we have no
INT_MAX to rescue us as we did in the bigtime_test loop.  Here's what
I eventually came up with:

  for (;;)
    {
      time_t t = (time_t_max << 1) + 1;
      if (t <= time_t_max)
        break;
      time_t_max = t;
    }
  time_t_min = - ((time_t) ~ (time_t) 0 == (time_t) -1) - time_t_max;

This isn't guaranteed to be portable by C99 either, of course; among
other things, left-shift has undefined behavior on signed integer
overflow.  I am relying on your heuristic advice to use left shift
rather than multiplication by 2, so that GCC won't mess up here.  But
it's a weak heuristic and I'm afraid it doesn't inspire a whole lot of
confidence.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]