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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |msebor at gcc dot gnu.org
         Resolution|---                         |INVALID

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning can be reproduced with the following simplified test case and the
IL below (I used -m32 to make the numbers smaller), showing it behaves as
designed:

$ cat pr100477.C && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout -m32 -xc
pr100477.C
struct A
{
    int  *p;
    __SIZE_TYPE__ n;
};

void f (struct A *p, int v)
{
  __SIZE_TYPE__ n = p->n + sizeof (int);

  if (n < p->n)
    __builtin_memset (p->p + n, 0, (p->n - n) * sizeof *p->p);
}

pr100477.C: In function ‘f’:
pr100477.C:12:5: warning: ‘__builtin_memset’ specified bound 4294967280 exceeds
maximum object size 2147483647 [-Wstringop-overflow=]
   12 |     __builtin_memset (p->p + n, 0, (p->n - n) * sizeof *p->p);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

;; Function f (f, funcdef_no=0, decl_uid=1886, cgraph_uid=1, symbol_order=0)

Removing basic block 5
void f (struct A * p, int v)
{
  unsigned int n;
  unsigned int _1;
  int * _2;
  unsigned int _3;
  int * _4;
  __complex__ unsigned int _10;
  unsigned int _11;

  <bb 2> [local count: 1073741824]:
  _1 = p_7(D)->n;
  _10 = .ADD_OVERFLOW (_1, 4);
  n_8 = REALPART_EXPR <_10>;
  _11 = IMAGPART_EXPR <_10>;
  if (_11 != 0)
    goto <bb 3>; [33.00%]
  else
    goto <bb 4>; [67.00%]

  <bb 3> [local count: 354334800]:
  _2 = p_7(D)->p;
  _3 = n_8 * 4;
  _4 = _2 + _3;
  __builtin_memset (_4, 0, 4294967280); [tail call]   <<< -Wstringop-overflow

  <bb 4> [local count: 1073741824]:
  return;

}

Since n is set to _size + 4 in test(), (n < _size) holds only if the addition
wraps around zero, implying _size is excessively large.  The warning can be
avoided by asserting that that isn't so, e.g., by adding the following

          if (_size >= __PTRDIFF_MAX__ / 4)
            __builtin_unreachable ();

just before the memset call.

Reply via email to