c++: loop over array elts w/o explicit init [PR92385]
authorJason Merrill <jason@redhat.com>
Sat, 1 Jan 2022 21:00:09 +0000 (16:00 -0500)
committerJason Merrill <jason@redhat.com>
Fri, 7 Jan 2022 00:23:16 +0000 (19:23 -0500)
commite948436eab818c527dd60b0ef939c4f42fbe8ba4
tree71b7313390be11341e0c975d27076d8387b9c39c
parentad64a821970ef5547d77ece22d302b0e599ae0d2
c++: loop over array elts w/o explicit init [PR92385]

The PR complains that initializing a large array with {} takes a long time
to compile; this was because digest_init would turn {} into a long
CONSTRUCTOR with an initializer for each element, instead of more sensibly
generating a loop.  The standard doesn't specify this implementation, but it
does allow for it by specifying that a temporary created "when a default
constructor is called to initialize an element of an array with no
corresponding initializer" is destroyed "before the construction of the next
array element, if any." rather than living until the end of the complete
object initialization as usual.

This change is also needed before the PR94041 fix extends the lifetime of
temporaries from elements with explicit initializers.

To implement this, I change digest_init so that in cases where
initialization of trailing array elements isn't constant, we return a
VEC_INIT_EXPR instead of a bare CONSTRUCTOR; when it is encountered later,
we call build_vec_init to generate the actual initialization code.

PR c++/92385

gcc/cp/ChangeLog:

* typeck2.c (PICFLAG_VEC_INIT): New.
(process_init_constructor_array): Set it.
(process_init_constructor): Handle it.
(split_nonconstant_init_1): Handle VEC_INIT_EXPR.
* init.c (build_vec_init): Likewise.
* cp-gimplify.c (cp_gimplify_expr): Factor out...
* tree.c (expand_vec_init_expr): ...this function.
(build_vec_init_elt): Handle BRACE_ENCLOSED_INITIALIZER_P.
(build_vec_init_expr): Likewise.
* constexpr.c (cxx_eval_vec_init): Likewise.
(reduced_constant_expression_p): Check arrays before C++20.
* cp-tree.h (expand_vec_init_expr): Declare.

gcc/testsuite/ChangeLog:

* g++.dg/init/array61.C: New test.
gcc/cp/constexpr.c
gcc/cp/cp-gimplify.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/tree.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/init/array61.C [new file with mode: 0644]