On Tue, Jan 29, 2019 at 6:53 PM Marek Polacek <pola...@redhat.com> wrote: > > My recent patch for 88815 and 78244 caused 89083, a P1 9 regression, which > happens to be the same problem as 80864 and its many dupes, something I'd > been meaning to fix for a long time. > > Basically, the problem is repeated reshaping of a constructor, once when > parsing, and then again when substituting. With the recent fix, we call > reshape_init + digest_init in finish_compound_literal even in a template > if the expression is not instantiation-dependent, and then again when > tsubst_*. > > For instance, in initlist107.C, when parsing a functional cast, we call > finish_compound_literal which calls reshape_init, which turns > > { NON_LVALUE_EXPR<1>, NON_LVALUE_EXPR<2> } > > into > > { { NON_LVALUE_EXPR<1>, NON_LVALUE_EXPR<2> } } > > and then digest_init turns that into > > { .x = { 1, 2 } } > > which is a compound literal (TREE_HAS_CONSTRUCTOR set), but the subexpression > "{ 1, 2 }" isn't. "{ 1, 2 }" will now have the type int[3], so it's not > BRACE_ENCLOSED_INITIALIZER_P. > > And then tsubst_* processes "{ .x = { 1, 2 } }". The case CONSTRUCTOR > in tsubst_copy_and_build will call finish_compound_literal on a copy of > "{ 1, 2 }" wrapped in a new { }, because the whole expr has > TREE_HAS_CONSTRUCTOR. > That crashes in reshape_init_r in the > 6155 if (TREE_CODE (stripped_init) == CONSTRUCTOR) > block; we have a constructor, it's not COMPOUND_LITERAL_P, and because > digest_init had given it the type int[3], we hit > 6172 gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (stripped_init)); > > As expand_default_init explains in a comment, a CONSTRUCTOR of the target's > type > is a previously digested initializer, so we should probably do a similar trick > here. This fixes all the variants of the problem I've come up with. > > 80864 is a similar case, we reshape when parsing and then second time in > fold_non_dependent_expr called from store_init_value, because of the > 'constexpr'. > > Also update a stale comment. > > Bootstrapped/regtest running on x86_64-linux, ok for trunk and 8 after a > while? > > 2019-01-29 Marek Polacek <pola...@redhat.com> > > PR c++/89083, c++/80864 - ICE with list initialization in template. > * decl.c (reshape_init_r): Don't reshape a digested initializer. > > * g++.dg/cpp0x/initlist107.C: New test. > * g++.dg/cpp0x/initlist108.C: New test. > * g++.dg/cpp0x/initlist109.C: New test. > > diff --git gcc/cp/decl.c gcc/cp/decl.c > index 79eeac177b6..da08ecc21aa 100644 > --- gcc/cp/decl.c > +++ gcc/cp/decl.c > @@ -6161,11 +6161,17 @@ reshape_init_r (tree type, reshape_iter *d, bool > first_initializer_p, > ; > else if (COMPOUND_LITERAL_P (stripped_init)) > /* For a nested compound literal, there is no need to reshape since > - brace elision is not allowed. Even if we decided to allow it, > - we should add a call to reshape_init in finish_compound_literal, > - before calling digest_init, so changing this code would still > - not be necessary. */ > + we called reshape_init in finish_compound_literal, before calling > + digest_init. */ > gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init)); > + /* Similarly, a CONSTRUCTOR of the target's type is a previously > + digested initializer. */ > + else if (same_type_ignoring_top_level_qualifiers_p (type, > + TREE_TYPE > (init)))
Hmm, aren't both of these tests true for a dependent compound literal, which won't have been reshaped already? Jason