c++: c++20 constexpr default ctor and array init

The implicit constexpr patch revealed that marking the constructor in the
PR70690 testcase as constexpr made the bug reappear, because build_vec_init
assumed that a constexpr default constructor initialized the whole object,
so it was equivalent to value-initialization.  But this is no longer true in
C++20.

	PR c++/70690

gcc/cp/ChangeLog:

	* init.c (build_vec_init): Check default_init_uninitialized_part in
	C++20.

gcc/testsuite/ChangeLog:

	* g++.dg/init/array41a.C: New test.
This commit is contained in:
Jason Merrill 2021-11-11 22:03:53 -05:00
parent 4df7f8c798
commit bd95d75f34
2 changed files with 32 additions and 2 deletions

View File

@ -4470,11 +4470,14 @@ build_vec_init (tree base, tree maxindex, tree init,
We do need to keep going if we're copying an array. */
if (try_const && !init)
if (try_const && !init
&& (cxx_dialect < cxx20
|| !default_init_uninitialized_part (inner_elt_type)))
/* With a constexpr default constructor, which we checked for when
setting try_const above, default-initialization is equivalent to
value-initialization, and build_value_init gives us something more
friendly to maybe_constant_init. */
friendly to maybe_constant_init. Except in C++20 and up a constexpr
constructor need not initialize all the members. */
explicit_value_init_p = true;
if (from_array
|| ((type_build_ctor_call (type) || init || explicit_value_init_p)

View File

@ -0,0 +1,27 @@
// PR c++/70690
// { dg-do run { target c++11 } }
struct A {
constexpr A() {}
};
struct APadded : public A {
char pad[63];
};
int f();
int i = f();
APadded cache[50];
APadded *p = cache;
int f()
{
cache[0].pad[0] = 42;
return 1;
}
int main()
{
if (cache[0].pad[0] != 42)
__builtin_abort();
}