https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116793
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |iains at gcc dot gnu.org --- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Looks like coro lowering bug to me. The ICE is on Aw0 VAR_DECL which is indeed used before its declaration: { struct tuple & D.12700 [value-expr: frame_ptr->_D1_2_0]; int & i [value-expr: frame_ptr->i_1_2]; struct tuple D.14203 [value-expr: frame_ptr->_D1_2_1]; struct tuple D.14203 [value-expr: frame_ptr->_D1_2_1]; struct tuple & D.12700 [value-expr: frame_ptr->_D1_2_0]; TARGET_EXPR <D.14220, 0>; if (<<cleanup_point !C::await_ready (&Aw0)>>) { <<cleanup_point <<< Unknown tree: expr_stmt (void) (_Coro_resume_index = 4) >>>>>; if (<<cleanup_point !C::await_suspend<T::promise_type> (&Aw0, TARGET_EXPR <D.12788, _Coro_self_handle>)>>) { <<cleanup_point <<< Unknown tree: expr_stmt .CO_SUSPN (&coro.restart.dispatch) >>>>>; } switch (<<cleanup_point .CO_YIELD (4, 0, &resume.4, &destroy.4, frame_ptr)>>) { case 0:; <<cleanup_point <<< Unknown tree: expr_stmt .CO_SUSPN (&actor.suspend.ret) >>>>>; case 1:; goto resume.4; default:; goto destroy.4; } destroy.4:; goto coro.delete.promise; } resume.4:; <<cleanup_point { struct C Aw0 [value-expr: frame_ptr->Aw0_2_3]; int T002 [value-expr: frame_ptr->T002_2_3]; int T002 [value-expr: frame_ptr->T002_2_3]; All my patch changed is that instead of having one CLEANUP_POINT_EXPR around the initialization of the unnamed structured binding base variable and another one around the i there is one around the latter and one around all that together, i.e. roughly <<cleanup_point <<< Unknown tree: expr_stmt (void) (D.12700 = D.14203 = <<< Unknown tree: co_await TARGET_EXPR <D.12704, func ((int &) &TARGET_EXPR <D.12703, 3>)> Aw0 Aw0 = TARGET_EXPR <D.12704, func ((int &) &TARGET_EXPR <D.12703, 3>)> {C::await_ready (&Aw0), C::await_suspend<T::promise_type> (&Aw0, TARGET_EXPR <D.12788, _Coro_self_handle>), <<< Unknown tree: aggr_init_expr 4 await_resume D.14196 &Aw0 >>>} 0 >>>, (struct tuple &) &D.14203) >>>; D.14220 = 1;>>; int & i; <<cleanup_point <<< Unknown tree: expr_stmt (void) (i = std::get<0, int&> (NON_LVALUE_EXPR <D.12700>)) >>>>>; to: <<cleanup_point <<< Unknown tree: expr_stmt (void) (D.12700 = D.14203 = <<< Unknown tree: co_await TARGET_EXPR <D.12704, func ((int &) &TARGET_EXPR <D.12703, 3>)> Aw0 Aw0 = TARGET_EXPR <D.12704, func ((int &) &TARGET_EXPR <D.12703, 3>)> {C::await_ready (&Aw0), C::await_suspend<T::promise_type> (&Aw0, TARGET_EXPR <D.12788, _Coro_self_handle>), <<< Unknown tree: aggr_init_expr 4 await_resume D.14196 &Aw0 >>>} 0 >>>, (struct tuple &) &D.14203) >>>; D.14220 = 1; int & i; <<cleanup_point <<< Unknown tree: expr_stmt (void) (i = std::get<0, int&> (NON_LVALUE_EXPR <D.12700>)) >>>>>;>>; and (some of the) cleanups on the outer one need to wait until a helper var (I think D.14220 in this case) is set. I know really nothing about coroutines.cc to find out what needs to be changed.