On Wed, Jan 30, 2019 at 04:11:11PM -0500, Marek Polacek wrote:
> On Tue, Jan 29, 2019 at 09:40:18PM -0500, Jason Merrill wrote:
> > 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?
> 
> I'm hoping that can't happen, but it's a good question.  When we have a
> dependent compound literal, finish_compound_literal just sets
> TREE_HAS_CONSTRUCTOR and returns it, so then in tsubst_*, after substituting
> each element of the constructor, we call finish_compound_literal.  The
> constructor is no longer dependent and since we operate on a copy on which
> we didn't set TREE_HAS_CONSTRUCTOR, the first condition shouldn't be true.
> 
> And the second condition should also never be true for a compound literal
> that hasn't been reshaped, because digest_init is only ever called after
> reshape_init (and the comment for digest_init_r says it assumes that
> reshape_init has already run).  The type of a CONSTRUCTOR can also by changed
> in tsubst_copy_and_build:
> 19269         TREE_TYPE (r) = type;
> but I haven't been able to trigger any problem yet.  Worst comes to worst this
> patch changes the ICE to another ICE, but I'm not finding a testcase.

And if that ever happens, I guess we'll have to add a new flag that says if
a CONSTRUCTOR has been reshaped already.

Marek

Reply via email to