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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2017-11-18
          Component|regression                  |tree-optimization
            Summary|[8 regression] warning at   |warning at random points in
                   |random points in the input  |the input (array subscript
                   |(array subscript -1 is      |-1 is below array bounds)
                   |below array bounds)         |
     Ever confirmed|0                           |1
      Known to fail|                            |8.0

--- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> ---
I can reproduce the bad location after stripping line directives from the .i
files and compiling the result as a .c file.  There are many other warnings so
I suppressed them to reduce the clutter, but they do suggest the reason for the
warning.

$ gcc -O2 -S -Wno-pointer-to-int-cast -Wno-builtin-declaration-mismatch
-Wno-int-to-pointer-cast -Wno-attributes -Warray-bounds  -Warray-bounds
pr83038.c
pr83038.c:56415:29: warning: array subscript -1 is below array bounds of
‘DIDEVICEOBJECTINSTANCEW[256] {aka struct DIDEVICEOBJECTINSTANCEW[256]}’
[-Warray-bounds]
     DIDEVICEOBJECTINSTANCEW ddo = device->ddo[obj];
                             ^~~

A dump shows that VRP thinks obj is (or might be) negative:

  _234: [-INF, -1]  EQUIVALENCES: { _148 } (1 elements)
  Array bound warning for device_137->ddo[_234]
  ...
  _147 = SendDlgItemMessageW (dialog_25(D), 28, 4108, 18446744073709551615, 2);
  _148 = (int) _147;
  if (_148 < 0)
    goto <bb 39>; [1.19%]
  else
    goto <bb 26>; [98.81%]

  <bb 39> [local count: 21340]:
  _234 = ASSERT_EXPR <_148, _148 < 0>;

  <bb 25> [local count: 21340]:
  # _184 = PHI <-1(39)>
  item ={v} {CLOBBER};
  _47 = &device_137->ddo[_234];

Negative index values into the last member array (like device->ddo) were not
diagnosed prior to r254830 (due to bug 68325).  With the bug resolved, these
kinds of problems are now detected and diagnosed.  If struct DeviceData is
changed so that the ddo array is not last, the same warning is emitted even
with GCC 7, with the same poor location.  So both the location problem and the
warning are latent issues (i.e., not a regression).

The bad location aside, as some of the other warnings indicate, the source code
in the translation unit takes liberties with conversions between integers (and
pointers) of different sizes.  The value of obj (which is an int) is the result
of calling lv_get_cur_item(dialog) which returns a long converted to int. 
These conversions tend to cause "trouble," as in trigger warnings due to jump
threading or other optimizations introducing paths that don't apparently exist
in the original source code.  If I'm reading the dumps right, this is also what
happens in this case.   Sometimes, although not always, these problems can be
prevented by avoiding these kinds of conversions.  In this case, changing the
type of both obj and lv_get_cur_item() to long (to match the result of the
SendDlgItemMessageW() function whose result lv_get_cur_item() returns) prevents
jump threading from inserting a path along which the index is negative and
makes the warning go away.

With that, I can confirm both the poor location and the spurious warning.

Reply via email to