On 5/9/24 12:04, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
Here we crash on a cp_gimplify_expr/TARGET_EXPR assert:

       /* A TARGET_EXPR that expresses direct-initialization should have been
          elided by cp_gimplify_init_expr.  */
       gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));

the TARGET_EXPR in question is created for the NSDMI in:

   class Vector { int m_size; };
   struct S {
     const Vector &vec{};
   };

where we first need to create a Vector{} temporary, and then bind the
vec reference to it.  The temporary is represented by a TARGET_EXPR
and it cannot be elided.  When we create an object of type S, we get

   D.2848 = {.vec=(const struct Vector &) &TARGET_EXPR <D.2840, {.m_size=0}>}

where the TARGET_EXPR is no longer direct-initializing anything.

Seems like the problem is in convert_like_internal:

            bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
            if (abstract_virtuals_error (NULL_TREE, totype, complain))
              return error_mark_node;
            expr = build_value_init (totype, complain);
            expr = get_target_expr (expr, complain);
            if (expr != error_mark_node)
              {
                TARGET_EXPR_LIST_INIT_P (expr) = true;
=>              TARGET_EXPR_DIRECT_INIT_P (expr) = direct;
              }

My patch for 50930 assumed that if a CONSTRUCTOR represents syntactic direct-initialization, a resulting TARGET_EXPR is itself the direct initializer, but that isn't the case here; the temporary is copy-initialized.

We could calculate direct-initializanity from cand->flags, but perhaps we can just stop trying to set TARGET_EXPR_DIRECT_INIT_P here at all? We don't do that for other list-initialization in ck_user, I don't know why I thought it was needed for {} specifically. It doesn't seem to be needed for the 50930 testcase.

Jason

Reply via email to