https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94883
Bug ID: 94883 Summary: coroutines: ICE building folly in verify_gimple_stmt, at tree-cfg.c:4959 Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: iains at gcc dot gnu.org Target Milestone: --- Created attachment 48423 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48423&action=edit fix under test The following should compile but produces: folly-2.C:59:1: internal compiler error: in verify_gimple_stmt, at tree-cfg.c:4959 The problem here is that target cleanup expressions have been added to the initialisers for the awaitable (and returns of non-trivial values from await_suspend() calls. This is because the expansion of the co_await into its control flow is not apparent to the machinery adding the target cleanup expressions. The solution being tested is simply to recreate target expressions as the co_awaits are lowered. Teaching the machinery to handle walking co_await expressions in different ways at different points (outside the coroutine transformation) seems overly complex. === namespace std { template <typename a, typename...> struct coroutine_traits : a {}; template <typename = void> struct coroutine_handle; template <> struct coroutine_handle<> {}; template <typename> struct coroutine_handle : coroutine_handle<> {}; struct b { bool await_ready(); void await_suspend(coroutine_handle<>); void await_resume(); }; } // namespace std template <typename d> auto ab(int ac, d ad) -> decltype(ad.e(ac)); int f; class h { class j { public: bool await_ready(); void await_suspend(std::coroutine_handle<>); void await_resume(); }; public: void get_return_object(); std::b initial_suspend(); j final_suspend(); void unhandled_exception(); template <typename g> auto await_transform (g c) { return ab(f, c); } }; template <typename, typename = int> class k { public: using promise_type = h; using i = std::coroutine_handle<>; class l { public: ~l(); operator bool(); }; class m { public: bool await_ready(); i await_suspend(std::coroutine_handle<>); l await_resume(); }; class n { public: m e(int); }; n ah(); }; template <typename ai, typename aj, typename ak> k<aj> my_coro (k<aj, ak> am, ai) { if (auto an = co_await am.ah()) ; } void foo () { k<int> a; my_coro (a, [] {}); }