C++ PATCH for c++/89083, c++/80864 - ICE with list initialization in template

Jason Merrill jason@redhat.com
Wed Jan 30 02:43:00 GMT 2019


On Tue, Jan 29, 2019 at 6:53 PM Marek Polacek <polacek@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  <polacek@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



More information about the Gcc-patches mailing list