On Fri, Feb 14, 2020 at 09:12:58AM +0100, Jason Merrill wrote:
> On 2/13/20 8:56 PM, Marek Polacek wrote:
> > My P0388R4 patch changed build_array_conv to create an identity
> > conversion at the start of the conversion chain.
> 
> Hmm, an identity conversion of {} suggests that it has a type, which it
> doesn't in the language.  I'm not strongly against it, but what was the
> reason for this change?

There are two reasons:
1) without it we couldn't get to the original expression at the start
of the conversion chain (saved in .u.expr), this is needed in compare_ics:
10660           tree n1 = nelts_initialized_by_list_init (t1);
10661           tree n2 = nelts_initialized_by_list_init (t2);
and nelts_initialized_by_list_init uses conv_get_original_expr for
arrays that have no dimensions.
2) struct conversion says
/* An implicit conversion sequence, in the sense of [over.best.ics].
   The first conversion to be performed is at the end of the chain.
   That conversion is always a cr_identity conversion.  */
and we were breaking that promise.

> > That was a sound change but now we crash in convert_like_real
> > 
> >   7457     case ck_identity:
> >   7458       if (BRACE_ENCLOSED_INITIALIZER_P (expr))
> >   7459         {
> >   7460           int nelts = CONSTRUCTOR_NELTS (expr);
> >   7461           if (nelts == 0)
> >   7462             expr = build_value_init (totype, complain);
> >   7463           else if (nelts == 1)
> >   7464             expr = CONSTRUCTOR_ELT (expr, 0)->value;
> >   7465           else
> >   7466             gcc_unreachable ();  // HERE
> >   7467         }
> 
> Right, this is assuming that any other {} will either be ill-formed or
> handled by ck_aggr or ck_list.  How are we getting here without going
> through one of those?

So here we have a ck_aggr which is bad_p, so in convert_like_real we go to the
 7285   if (convs->bad_p
block at the beginning, which will look at the next conversion:
 7319       for (; t ; t = next_conversion (t))
that conversion is a ck_identity which is not bad_p, so we call
 7343           else if (t->kind == ck_user || !t->bad_p)
 7344             {
 7345               expr = convert_like_real (t, expr, fn, argnum,
 7346                                         
/*issue_conversion_warnings=*/false,
 7347                                         /*c_cast_p=*/false,
 7348                                         complain);
and crash there.

Marek

Reply via email to