Testcase (reduced from tcmalloc): struct Elem { Elem* next_ = this; Elem* prev_ = this; }; constinit Elem qs[3]; GCC generates a zero initializer for qs: qs: .zero 48 If the `constinit` is removed, GCC instead incorrectly generates a dynamic initializer, so presumably GCC knows that this variable *should* have a constant initializer but can't actually form one. The same problem can be observed without constinit: constexpr Elem rs[3]; const void *p = rs; ... again results in a zero-initialized global and no dynamic initializer.
Confirmed.
Another testcase: struct Elem { Elem* next_ = this; }; constexpr Elem rs[1]; const void *p = rs[0].next_; Which shows it is just an array issue; changing rs to be a non-array works that is: struct Elem { Elem* next_ = this; }; constexpr Elem rs; const void *p = rs.next_;
Here is a simple compile time testcase: struct Elem { Elem* next_ = this; }; constexpr Elem rs[1]; static_assert (rs[0].next_ == rs);
This is a dup of bug 64989 really. My reduced testcase in comment #3 shows it is. Sometimes we reject the constexpr as the array used in its own initializer and other times just produce wrong code. *** This bug has been marked as a duplicate of bug 64989 ***