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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |missed-optimization
             Status|WAITING                     |NEW
          Component|testsuite                   |tree-optimization

--- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> ---
That does look like the same problem.  I was also able to tweak the test case
so that it reproduces the spurious warning even with an x86_64-linux native
compiler:

$ cat pr92955.c && gcc -O3 -S -Wall pr92955.c 
typedef struct S { unsigned char n, a[4]; } S;

void f (S *s, const unsigned char *p, const unsigned char *q)
{
  long n;

  for (n = 0; n < (s->n & 7); ++n);

  if (p + (4 - n) > q)
    while (p < q)
      s->a[n++] = *p++;
}
pr92955.c: In function ‘f’:
pr92955.c:11:17: warning: writing 1 byte into a region of size 0
[-Wstringop-overflow=]
   11 |       s->a[n++] = *p++;
      |       ~~~~~~~~~~^~~~~~
pr92955.c:1:37: note: at offset [4, 11] to object ‘a’ with size 4 declared here
    1 | typedef struct S { unsigned char n, a[4]; } S;
      |                                     ^

The loop is only unrolled at -O3.  The dump below shows that the last unrolled
iteration accesses the member array at index 4, so it should be avoided
Compiling with -fno-unroll-loops doesn't show the warning.

This is very close to the problem in bug 60505 where the warning was
-Warray-bounds.  The two warnings detect many of the same problems but
-Wstringop-overflow only detects out-of-bounds char stores and runs just a
little before -Warray-bounds so it gets first dibs on diagnosing those.  With
the former suppressed via -Wno-stringop-overflow I would expect -Warray-bounds
to trigger for this test case but it doesn't, even though the IL is the same. 
The false negative seems like a separate bug.

;;   basic block 10, loop depth 0, count 27487790 (estimated locally), maybe
hot
;;    prev block 9, next block 11, flags: (NEW, REACHABLE, VISITED)
;;    pred:       9 [80.0% (guessed)]  count:27487790 (estimated locally)
(TRUE_
VALUE,EXECUTABLE)
  # PT = nonlocal 
  p_46 = p_39 + 1;
  # RANGE [4, 11] NONZERO 15
  n_47 = n_40 + 1;          <<< n_47 is out of bounds here
  # VUSE <.MEM_42>
  _48 = *p_39;
  # .MEM_49 = VDEF <.MEM_42>
  s_15(D)->aD.2902[n_40] = _48;
  if (q_17(D) > p_46)
    goto <bb 11>; [80.00%]
  else
    goto <bb 5>; [20.00%]
;;    succ:       11 [80.0% (guessed)]  count:21990232 (estimated locally)
(TRUE
_VALUE,EXECUTABLE)
;;                5 [20.0% (guessed)]  count:5497558 (estimated locally)
(FALSE_
VALUE,EXECUTABLE)

;;   basic block 11, loop depth 0, count 21990232 (estimated locally), maybe
hot
;;    prev block 10, next block 12, flags: (NEW, REACHABLE, VISITED)
;;    pred:       10 [80.0% (guessed)]  count:21990232 (estimated locally)
(TRUE
_VALUE,EXECUTABLE)
  # PT = nonlocal 
  p_53 = p_46 + 1;
  # RANGE [5, 12] NONZERO 15
  n_54 = n_47 + 1;
  # VUSE <.MEM_49>
  _55 = *p_46;
  # .MEM_56 = VDEF <.MEM_49>
  s_15(D)->aD.2902[n_47] = _55;   <<< n_47 is used here

Reply via email to