From aa94a22f5cb337e173d7119ffd5a92f1e607f544 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Wed, 29 Apr 2020 19:46:35 +0100 Subject: [PATCH] coroutines: Fix handling of target cleanup exprs [PR94883] 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. gcc/cp/ChangeLog: 2020-04-30 Iain Sandoe PR c++/94883 * coroutines.cc (register_awaits): Update target expressions for awaitable and suspend handle initializers. gcc/testsuite/ChangeLog: 2020-04-30 Iain Sandoe PR c++/94883 * g++.dg/coroutines/pr94883-folly-2.C: New test. --- gcc/cp/ChangeLog | 7 ++ gcc/cp/coroutines.cc | 11 ++++ gcc/testsuite/ChangeLog | 5 ++ .../g++.dg/coroutines/pr94883-folly-2.C | 64 +++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 gcc/testsuite/g++.dg/coroutines/pr94883-folly-2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3172f949ee9..62f997eb459 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2020-04-30 Iain Sandoe + + PR c++/94883 + * coroutines.cc (register_awaits): Update target + expressions for awaitable and suspend handle + initializers. + 2020-04-30 Iain Sandoe PR c++/94879 diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index e2dbeabf48b..cb9074e4c17 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -2757,6 +2757,17 @@ register_awaits (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d) free (nam); } + tree o = TREE_OPERAND (aw_expr, 2); /* Initialiser for the frame var. */ + /* If this is a target expression, then we need to remake it to strip off + any extra cleanups added. */ + if (TREE_CODE (o) == TARGET_EXPR) + TREE_OPERAND (aw_expr, 2) = get_target_expr (TREE_OPERAND (o, 1)); + + tree v = TREE_OPERAND (aw_expr, 3); + o = TREE_VEC_ELT (v, 1); + if (TREE_CODE (o) == TARGET_EXPR) + TREE_VEC_ELT (v, 1) = get_target_expr (TREE_OPERAND (o, 1)); + register_await_info (aw_expr, aw_field_type, aw_field_nam); /* Count how many awaits the current expression contains. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7f39eda0277..369ce423fbc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-30 Iain Sandoe + + PR c++/94883 + * g++.dg/coroutines/pr94883-folly-2.C: New test. + 2020-04-30 Iain Sandoe PR c++/94879 diff --git a/gcc/testsuite/g++.dg/coroutines/pr94883-folly-2.C b/gcc/testsuite/g++.dg/coroutines/pr94883-folly-2.C new file mode 100644 index 00000000000..088f1335493 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr94883-folly-2.C @@ -0,0 +1,64 @@ + +namespace std { +template struct coroutine_traits : a {}; +template struct coroutine_handle; +template <> struct coroutine_handle<> {}; +template struct coroutine_handle : coroutine_handle<> {}; +struct b { + bool await_ready(); + void await_suspend(coroutine_handle<>); + void await_resume(); +}; +} // namespace std + +template 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 + auto await_transform (g c) { return ab(f, c); } +}; +template 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 +k +my_coro (k am, ai) { + if (auto an = co_await am.ah()) + ; +} + +void foo () { + k a; + my_coro (a, [] {}); +} -- 2.30.2