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

Reply via email to