https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88572
--- Comment #12 from Will Wray <wjwray at gmail dot com> --- On further investigation the logic of using first_initializer_p looks correct. The comment on reshape_init suggests that it wasn't intended for scalar init: /* Undo the brace-elision allowed by [dcl.init.aggr] in a brace-enclosed aggregate initializer. INIT is the CONSTRUCTOR containing the list of initializers describing a brace-enclosed initializer for an entity of the indicated aggregate TYPE. In fact, reshape_init is used more broadly to error-check braced-init-list - - the first substantive case is direct enum init, a scalar init special-case. Perhaps the general scalar case should be dealt with here at the top level. Instead the recursive call to reshape_init_r is done next setting first_initializer_p to true - the only place it is set true (the true value will be forwarded to reshape_init_class for class type). So, for a scalar init, the tree type passed to reshape_init is SCALAR_TYPE_P. This is passed down to reshape_init_r with first_initializer_p set true. Entering reshape_init_r we have if (first_initializer_p && !CP_AGGREGATE_TYPE_P (type) && has_designator_problem (d, complain)) return error_mark_node; Here, first_initializer_p && !CP_AGGREGATE_TYPE_P (type) covers scalar init (and other non-aggregate init). Arriving at our block, we also enter a context requiring a single-initializer /* A non-aggregate type is always initialized with a single initializer. */ if (!CP_AGGREGATE_TYPE_P (type)) and then further filter down to CONSTRUCTOR with BRACE_ENCLOSED_INITIALIZER_P and, specifically of SCALAR_TYPE_P if (TREE_CODE (stripped_init) == CONSTRUCTOR /* Don't complain about a capture-init. */ && !CONSTRUCTOR_IS_DIRECT_INIT (stripped_init) && BRACE_ENCLOSED_INITIALIZER_P (stripped_init)) /* p7626.C */ { if (SCALAR_TYPE_P (type)) > I understood it to mean something like {{1}, 2} is the first, > ^^^ Me too, but taking "outermost CONSTRUCTOR node" to mean the actual outer type here (first_initializer_p==true) and with only a single scalar initializer: like scalar_type{{1}} not { {1} } ^^^ scalar_type^^^ So, I've convinced myself that my patch follows the existing logic. It'd be good to get review from someone not suffering from confirmation bias.