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