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

Giannis Gonidelis <gonidelis at hotmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |gonidelis at hotmail dot com

--- Comment #6 from Giannis Gonidelis <gonidelis at hotmail dot com> ---
I am not opening a new bug report because I feel this is tightly related and
stems from the same reason. I wrote a simpler reproducer than the godbolt above
which emits same false positive:

```
// compile with: g++ -O3 -Wall -Werror=stringop-overflow to repro

struct counter {   // mimic counting iterator
    char val;
    char operator*() const { return val; }
    counter& operator++() { ++val; return *this; }
    bool operator!=(counter o) const { return val != o.val; }
};

struct out_iter {  // mimic output iterator with a non-assignable reference
type
    char* p;
    char& operator*() const { return *p; }
    out_iter& operator++() { ++p; return *this; }
};

template <typename I, typename O>
__attribute__((always_inline))
inline O my_copy(I first, I last, O result) { // emulate std::copy
  for (; first != last; ++first, ++result)
      *result = *first;
  return result;
}

void use(  char*); // compile without linking

__attribute__((noinline))
    void test(char start) {
    char* buf = new char[4];
    char end = 4;

    counter first{start};
    counter last{end};
    out_iter dst{buf}; // wrap to output_iterator to create indirection
    my_copy(first, last, dst);

    use(buf); // we need buf not to be optimized awyay
    delete[] buf;
}

int main() {
    test(0);
}
```

Compile with:

    `g++ -O3 -Wall -c repro.cpp`

Expected: No warnings. The loop writes at most 4 bytes into a 4-byte buffer.

Actual (GCC 14, 5 warnings):

```
    writing 16 bytes into a region of size 4
    writing 8 bytes into a region of size 4
    writing 1 byte into a region of size 0  (x3)
```

Actual (GCC 16, 19 warnings):

```
    writing 16 bytes into a region of size 4
    writing 16 bytes into a region of size 0  (x14)
    writing 8 bytes into a region of size 4
    writing 1 byte into a region of size 0  (x3)
```

Analysis via `-fdump-tree-optimized` shows the vectorizer generates:

```
    _6 = operator new (4);
    ...
    MEM <vector(16) signed char> [(signed char &)_6] = _28;
```

These stores are guarded by trip-count checks (`bnd = niters >> 4`) and are
unreachable when the buffer is 4 bytes, but the warning pass does not
analyze the guards.

The vectorizer generates guarded vector(16) stores for a loop that copies chars
through iterator indirection into a small heap allocation. The
-Wstringop-overflow warning pass sees the 16-byte stores targeting a 4-byte
allocation and warns, without accounting for the control-flow guards that
prevent them from executing at runtime.

Reply via email to