https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128653
Bug ID: 128653
Summary: Constant-initialized array of NSDMI class loses
trailing elements after element assignment in
constexpr function
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: barry.revzin at gmail dot com
Target Milestone: ---
My colleague (Tom Carotti) ran into this miscompilation:
using size_t = decltype(sizeof(0));
template <class T, size_t N>
struct array {
T elems[N];
};
struct Storage {
char value = 'x';
};
auto values = [] {
array<Storage, 10> result{};
result.elems[2].value = 0;
return result;
}();
This emits:
"values":
.byte 120
.byte 120
.byte 0
.zero 7
Writing to elems[2] corrupts every trailing element! Note that writing to
elems[0] or elems[1] works fine, only that element is zeroed, it's only
starting at 2 that we see this behavior.
Another example:
struct S { char c = 1; };
struct A { S e[8]; };
constexpr A f(int i) {
A a{};
a.e[i].c = 0;
return a;
}
A v = f(5); // expect 1 1 1 1 1 0 1 1
A w = f(3); // expect 1 1 1 0 1 1 1 1
On gcc, v is [1, 1, 1, 0, 0, 0, 1, 1] instead. However, if you comment out the
declaration of w, then v actually is correctly [1, 1, 1, 1, 1, 0, 1, 1]! We're
retroactively breaking a constant initialization?!
Moreover, this seems to fail on every version of gcc since like 9.1.0. It works
correctly on all of the 8.x's I tried.