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

--- Comment #13 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning for the test case in comment #12 isn't directly related to ranges:
it's issued simply because the invalid statement is in the IL and not
eliminated by DCE (the secret functions don't let it).  Similar warnings have
been issued in equivalent situations for constants propagated through inlining.
 Here's one for -Wnonnull (issued since GCC 7):

char *sink;

__attribute__ ((noinline, noipa)) int
null_safe_strlen (const char *p) { return p ?__builtin_strlen (p) : 0; }

static inline void copy (const char *p)
{
  int N = null_safe_strlen (p);
  if (N) /* disabling this branch prevents the warning */
    __builtin_memcpy (sink, p, N);
  else
    *sink = 0;
}

void f()
{
  copy (0); // bogus warning
}

In function ‘copy’,
    inlined from ‘f’ at z.c:17:3:
z.c:10:5: warning: argument 2 null where non-null expected [-Wnonnull]
   10 |     __builtin_memcpy (sink, p, N);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
z.c:10:5: note: in a call to built-in function ‘__builtin_memcpy’

All GCC warnings trigger on invalid statements in the IL, regardless of whether
the statements are in reality reachable.  This includes all warnings that
consider data flow like -Wnonnull, -Warray-bounds, and -Wformat-overflow among
many others.  Ranges just let them find more invalid statements than constants
alone would.  This is also the most basic reason why the -Wstringop- warnings
are issued for the test case in comment #0 or in or PR 103332.

Two changes are behind the spate of recent bug reports about these warnings for
std::string: 1) in GCC 11 we enabled a subset of warnings for code inlined from
system headers, and 2) in GCC 12 thanks to Ranger the range info has become
more accurate and tighter (larger lower bounds and smaller upper bounds).

Before Jonathan suppressed the warnings in r12-5874 in libstdc++, Andrew
MacLeod suggested temporarily (for GCC 12) disabling the context-sensitive
Ranger info and going back to global ranges, until we have a better way of
dealing with the increased accuracy.  That would reduce the number of false
positives but it would also correspondingly increase false negatives, and so
defeat one of the main reasons for Ranger: better quality warnings.  It might
still be a compromise to consider if the problem turns out to be sufficiently
severe and if we can think of a way of to handle the ranges better in the
future.  But with the libstdc++ suppression I'm not convinced the problem is
severe enough anymore.  And I also can't think of a solution that would let us
re-enable Ranger for warnings in the future.  Nothing I've tried so far has
showed much promise, and neither seems anything anyone has suggested.

Independently, I have been thinking about adding -Wmaybe- forms of some of
these warnings analogous to -Wmaybe-uninitialized (or corresponding levels), to
diagnose conditional problems as in:

  char a[4], b[8];

  void f (int i)
  {
    __builtin_memset (i ? a : b, 0, 7);   // okay for b, overflow for a: thus
"may overflow a"
  }

but I have not been considering disabling the existing warnings (or removing it
from -Wall) and issuing them only under the new option or some new level.  That
would in my mind be a drastic step back.

Reply via email to