https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126335

--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Marek Polacek <[email protected]>:

https://gcc.gnu.org/g:e3da9acc2462e43e0ce3b9a5d414b988c35595c3

commit r17-2835-ge3da9acc2462e43e0ce3b9a5d414b988c35595c3
Author: Marek Polacek <[email protected]>
Date:   Thu Jul 30 15:18:14 2026 -0400

    c++: fix array initialization wrong code [PR126335]

    This is a wrong-code problem starting with the recent check_initializer
    simplification (r17-1661).  I thought the fix would be to bring some of
    those dropped conditions back, but now I think the change just uncovered
    a latent bug.

    Since r17-1661, when initializing 'm' of type 'M[2]' we no longer call
    build_aggr_init_full_exprs in check_initializer; instead, we go on to
    store_init_value -> split_nonconstant_init.  There we arrive with:

    {{.a=TARGET_EXPR <D.3136, <<< Unknown tree: aggr_init_expr
      3
      operator""_s
      D.3136 >>>>, .b=TARGET_EXPR <D.3139, <<< Unknown tree: aggr_init_expr
      3
      operator""_s
      D.3139 >>>>}, {.a={.p=&empty.str}, .b={.p=&empty.str}}}

    which so far seems OK.  The type is an array so split_nonconstant_init_1
    delegates to build_vec_init and returns true which, as the comment says,
    should mean that "the whole of the value was initialized by the generated
    statements".  This is inaccurate: since try_const and do_static_init are
    both true in build_vec_init, we have split out the constant initializer
    (the {.a={.p=&empty.str}, .b={.p=&empty.str}} part) into DECL_INITIAL:

    5374       else if (do_static_init && !vec_safe_is_empty (const_vec))
    5375         DECL_INITIAL (obase) = build_constructor (atype, const_vec);

    so we have both dynamic and static initializers.  But since
    split_nonconstant_init_1 returns bool, it's not ready to signal this case
    to split_nonconstant_init, which then does:

     943       if (split_nonconstant_init_1 (dest, init, true, &flags))
     944         init = NULL_TREE;

    and then overwrites DECL_INITIAL (dest).  So we've lost a half of the
    initializer and got wrong-code as the result.

    This patch fixes it by not throwing away the DECL_INITIAL that
    build_vec_init set for us.  I suppose another approach would be
    to somehow change split_nonconstant_init_1/ARRAY_TYPE to follow
    the element pruning/add_stmt like the rest of the function, but that
    seems more complicated.

            PR c++/126335

    gcc/cp/ChangeLog:

            * typeck2.cc (split_nonconstant_init): Assert that DECL_INITIAL
            is initially null.  Don't clear DECL_INITIAL if build_vec_init
            set it.  Only clear TREE_READONLY if CODE has side-effects.

    gcc/testsuite/ChangeLog:

            * g++.dg/init/array68.C: New test.

    Reviewed-by: Jason Merrill <[email protected]>

Reply via email to