https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103328
--- Comment #11 from Richard Biener <rguenth at gcc dot gnu.org> --- The first stmt we complain on remains in the same function. The functions scope tree at the point of complaint is { Scope block #0 { Scope block #0 (unused) struct coroutine_handle _Coro_actor_continue; { Scope block #0 (unused) void (*<Te0e>) (struct _ZZZNSt11server_impl12send_messageISt7variantIJN12_GLOBAL__N_114append_requestEEEEEvNS2_8internal9tagged_idINS2_13server_id_tagEEET_ENKUlS9_E_clIS3_EEDaS9_ENKUlvE_clEv.Frame *) _Coro_resume_fn [value-expr: frame_ptr->_Coro_resume_fn]; void (*<Te0e>) (struct _ZZZNSt11server_impl12send_messageISt7variantIJN12_GLOBAL__N_114append_requestEEEEEvNS2_8internal9tagged_idINS2_13server_id_tagEEET_ENKUlS9_E_clIS3_EEDaS9_ENKUlvE_clEv.Frame *) _Coro_destroy_fn [value-expr: frame_ptr->_Coro_destroy_fn]; struct promise_type _Coro_promise [value-expr: frame_ptr->_Coro_promise]; struct coroutine_handle _Coro_self_handle [value-expr: frame_ptr->_Coro_self_handle]; const struct ._anon_5 * const __closure [value-expr: frame_ptr->__closure]; short unsigned int _Coro_resume_index [value-expr: frame_ptr->_Coro_resume_index]; bool _Coro_frame_needs_free [value-expr: frame_ptr->_Coro_frame_needs_free]; bool _Coro_initial_await_resume_called [value-expr: frame_ptr->_Coro_initial_await_resume_called]; { Scope block #0 (unused) struct suspend_never Is [value-expr: frame_ptr->Is_1_1]; } { Scope block #0 void resume.6 = <<< error >>>; void destroy.6 = <<< error >>>; void resume.4 = <<< error >>>; void destroy.4 = <<< error >>>; void resume.2 = <<< error >>>; void destroy.2 = <<< error >>>; void coro.delete.frame = <<< error >>>; void coro.delete.promise = <<< error >>>; void actor.continue.ret = <<< error >>>; void actor.suspend.ret = <<< error >>>; void actor.begin = <<< error >>>; void final.suspend = <<< error >>>; const struct tagged_id cid [value-expr: __closure->__cid]; const struct append_request cm [value-expr: __closure->__cm]; struct server_impl * const this [value-expr: __closure->__this]; { Scope block #0 (unused) struct _ZZZNSt11server_impl12send_messageISt7variantIJN12_GLOBAL__N_114append_requestEEEEEvNS2_8internal9tagged_idINS2_13server_id_tagEEET_ENKUlS9_E_clIS3_EEDaS9_ENKUlvE_clEv.Frame * _Coro_frameptr; bool _Coro_promise_live; bool _Coro_gro_live; { Scope block #0 (unused) } } } } } } while at the point we lower control flow and set gimple_block it is { Scope block #0 { Scope block #0 (unused) struct coroutine_handle _Coro_actor_continue; { Scope block #0 (unused) void (*<Te0e>) (struct _ZZZNSt11server_impl12send_messageISt7variantIJN12_GLOBAL__N_114append_requestEEEEEvNS2_8internal9tagged_idINS2_13server_id_tagEEET_ENKUlS9_E_clIS3_EEDaS9_ENKUlvE_clEv.Frame *) _Coro_resume_fn [value-expr: frame_ptr->_Coro_resume_fn]; void (*<Te0e>) (struct _ZZZNSt11server_impl12send_messageISt7variantIJN12_GLOBAL__N_114append_requestEEEEEvNS2_8internal9tagged_idINS2_13server_id_tagEEET_ENKUlS9_E_clIS3_EEDaS9_ENKUlvE_clEv.Frame *) _Coro_destroy_fn [value-expr: frame_ptr->_Coro_destroy_fn]; struct promise_type _Coro_promise [value-expr: frame_ptr->_Coro_promise]; struct coroutine_handle _Coro_self_handle [value-expr: frame_ptr->_Coro_self_handle]; const struct ._anon_5 * const __closure [value-expr: frame_ptr->__closure]; short unsigned int _Coro_resume_index [value-expr: frame_ptr->_Coro_resume_index]; bool _Coro_frame_needs_free [value-expr: frame_ptr->_Coro_frame_needs_free]; bool _Coro_initial_await_resume_called [value-expr: frame_ptr->_Coro_initial_await_resume_called]; { Scope block #0 void resume.6 = <<< error >>>; void destroy.6 = <<< error >>>; void resume.4 = <<< error >>>; void destroy.4 = <<< error >>>; void resume.2 = <<< error >>>; void destroy.2 = <<< error >>>; void coro.delete.frame = <<< error >>>; void coro.delete.promise = <<< error >>>; void actor.continue.ret = <<< error >>>; void actor.suspend.ret = <<< error >>>; void actor.begin = <<< error >>>; void final.suspend = <<< error >>>; const struct tagged_id cid [value-expr: __closure->__cid]; const struct append_request cm [value-expr: __closure->__cm]; struct server_impl * const this [value-expr: __closure->__this]; { Scope block #0 struct append_request m [value-expr: frame_ptr->m_2_3]; struct tagged_id id [value-expr: frame_ptr->id_2_3]; { Scope block #0 (unused) struct awaiter Aw0 [value-expr: frame_ptr->Aw0_3_4]; } } } { Scope block #0 (unused) struct suspend_never Is [value-expr: frame_ptr->Is_1_1]; } } } } The block we associate with the stmt is { Scope block #0 (unused) struct awaiter Aw0 [value-expr: frame_ptr->Aw0_3_4]; } it looks like there's mangling of the block tree happening somehow. We run into /* Lower a bind_expr TSI. DATA is passed through the recursion. */ static void lower_gimple_bind (gimple_stmt_iterator *gsi, struct lower_data *data) { tree old_block = data->block; gbind *stmt = as_a <gbind *> (gsi_stmt (*gsi)); tree new_block = gimple_bind_block (stmt); if (new_block) { if (new_block == old_block) { /* The outermost block of the original function may not be the outermost statement chain of the gimplified function. So we may see the outermost block just inside the function. */ gcc_assert (new_block == DECL_INITIAL (current_function_decl)); new_block = NULL; } else { /* We do not expect to handle duplicate blocks. */ gcc_assert (!TREE_ASM_WRITTEN (new_block)); TREE_ASM_WRITTEN (new_block) = 1; /* Block tree may get clobbered by inlining. Normally this would be fixed in rest_of_decl_compilation using block notes, but since we are not going to emit them, it is up to us. */ BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (old_block); BLOCK_SUBBLOCKS (old_block) = new_block; BLOCK_SUBBLOCKS (new_block) = NULL_TREE; BLOCK_SUPERCONTEXT (new_block) = old_block; with BLOCK_CHAIN (new_block) != NULL and lose those blocks. old_block is the outermost block here. It looks like the BIND_EXPR nesting does not match the BLOCK tree nesting and things go wrong from there. The IL looks like { [t.i:533:13] try { [t.i:533:13] { struct _ZZZNSt11server_impl12send_messageISt7variantIJN12_GLOBAL__N_114append_requestEEEEEvNS2_8internal9tagged_idINS2_13server_id_tagEEET_ENKUlS9_E_clIS3_EEDaS9_ENKUlvE_clEv.Frame * _Coro_frameptr; bool _Coro_promise_live; bool _Coro_gro_live; [t.i:533:13] _Coro_frameptr = 0B; [t.i:533:13] _Coro_promise_live = 0; [t.i:533:13] _Coro_gro_live = 0; [t.i:533:13] _1 = .CO_FRAME (48, _Coro_frameptr); [t.i:533:13] _Coro_frameptr = operator new (_1); [t.i:533:13] try { [t.i:533:13] [t.i:533:13] _Coro_frameptr->_Coro_frame_needs_free = 1; [t.i:533:13] [t.i:533:13] _Coro_frameptr->_Coro_resume_fn = operator(); [t.i:533:13] [t.i:533:13] _Coro_frameptr->_Coro_destroy_fn = operator(); [t.i:533:13] [t.i:533:13] _Coro_frameptr->__closure = __closure; [t.i:533:13] { [t.i:533:13] _2 = [t.i:533:13] &[t.i:533:13] _Coro_frameptr->_Coro_promise; [t.i:533:13] seastar::internal::coroutine_traits_base<>::promise_type::get_return_object (_2); [t.i:533:13] [t.i:533:13] _Coro_frameptr->_Coro_resume_index = 0; [t.i:533:13] std::server_impl::send_message<std::variant<{anonymous}::append_request> >({anonymous}::server_id, std::variant<{anonymous}::append_request>)::<lambda(auto:1)>::<lambda()>::operator() (_Coro_frameptr); [t.i:533:13] return <retval>; } } catch { [t.i:533:13] catch (NULL) { [t.i:533:13] try { [t.i:533:13] _3 = __builtin_eh_pointer (0); [t.i:533:13] __cxa_begin_catch (_3); [t.i:533:13] operator delete (_Coro_frameptr); [t.i:533:13] __cxa_rethrow (); } finally { [t.i:533:13] __cxa_end_catch (); } } } } } catch { <<<eh_must_not_throw (terminate)>>> } } IIRC there's no "verification" of IL BIND_EXPR/gimple_block nesting vs. DECL_INITIAL block tree nesting.