https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66974

Manuel López-Ibáñez <manu at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
                 CC|                            |manu at gcc dot gnu.org

--- Comment #3 from Manuel López-Ibáñez <manu at gcc dot gnu.org> ---
The reason seems to be that GCC unrolls the inner loop completely to something
like:

if (i / 2 != 0) {
  // i > 1
      c[0] += c[i] * c[i-1];
      c[i-1] += c[i] * c[0];
      if (i / 2 > 1) {
        // i > 3
        c[1] += c[i] * c[i-2];
        c[i-2] += c[i] * c[1];
        if (i / 2 > 2) {
        // i > 5
          c[2] += c[i] * c[i-3];
          c[i-3] += c[i] * c[2];
        }
      }
 }

by reasoning that j < 3. However, it is not able to remove the two inner
conditions by reasoning that i < 3  Since i's upper-bound depends on order and
order is a parameter, it should be able to assume it (or at least say "may be
above").

Interestingly, if one changes the function to:

int foo(unsigned order) {
  int c[3] = {1, 2, 3};
  if (order >= 5) return 0;
  unsigned i, j;
  for (i = 1; i < order; i++) {
    for (j = 0; j < i / 2; j++) {
      c[j] += c[i] * c[i-j-1];
      c[i-j-1] += c[i] * c[j];
    }
  }
  return c[0];
}

There is an out-of-bounds access that is not detected by -Warray-bounds, but it
is detected by -Wuninitialized:

test.c:7:16: warning: ‘c[3u]’ may be used uninitialized in this function
[-Wmaybe-uninitialized]
       c[j] += c[i] * c[i-j-1];
                ^

Reply via email to