https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96934
Bug ID: 96934
Summary: Copy initialization of struct involving aggregate
array initialization miscompiles in GCC 9
Product: gcc
Version: 9.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: wielkiegie at gmail dot com
Target Milestone: ---
GCC 9 (but not <= 8 and not >= 10, including trunk) miscompiles the following
piece of code. I have tested GCC 9.1 (which produces even worse code, as it
assumes the const char* has only a single character) and GCC 9.2, 9.3
(explained below). I was not able to test the current GCC 9 branch.
Test case: https://godbolt.org/z/jPq4h7
The Code struct holds an array of chars that is meant to be always
null-terminated. A simple constructor is provided to simulate how the array
should be initialized (this is a reduced real world scenario). It uses
aggregate initialization in order to store the "12" string.
There are two problems, probably originating from the same underlying issue:
1. Bogus -Wstringop-overflow warning saying the _buffer is unterminated, while
it most certainly is (as you can see in the assembly).
2. std::strcmp call miscompiled as if _buffer == "1" (and not "12").
Switching the TEST define on line 17 into T1, T2, T3, T4 doesn't change the
outcome. However, T5 and T6 fix the issue. What seems to be the difference is
the copy-initialization [1] being involved in T1 and T2 (and T3, T4
"inheriting" the buggy state). T5 doesn't do copy-initialization, and T6 just
copies it.
[1] https://en.cppreference.com/w/cpp/language/copy_initialization