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.