[gcc(refs/vendors/ARM/heads/arm-struct-reorg-wip)] coroutines: Fix handling of target cleanup exprs [PR94883]
Tamar Christina
tnfchris@gcc.gnu.org
Fri Jul 17 14:54:54 GMT 2020
https://gcc.gnu.org/g:aa94a22f5cb337e173d7119ffd5a92f1e607f544
commit aa94a22f5cb337e173d7119ffd5a92f1e607f544
Author: Iain Sandoe <iain@sandoe.co.uk>
Date: Wed Apr 29 19:46:35 2020 +0100
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 <iain@sandoe.co.uk>
PR c++/94883
* coroutines.cc (register_awaits): Update target
expressions for awaitable and suspend handle
initializers.
gcc/testsuite/ChangeLog:
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
PR c++/94883
* g++.dg/coroutines/pr94883-folly-2.C: New test.
Diff:
---
gcc/cp/ChangeLog | 7 +++
gcc/cp/coroutines.cc | 11 ++++
gcc/testsuite/ChangeLog | 5 ++
gcc/testsuite/g++.dg/coroutines/pr94883-folly-2.C | 64 +++++++++++++++++++++++
4 files changed, 87 insertions(+)
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 <iain@sandoe.co.uk>
+
+ PR c++/94883
+ * coroutines.cc (register_awaits): Update target
+ expressions for awaitable and suspend handle
+ initializers.
+
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
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 <iain@sandoe.co.uk>
+
+ PR c++/94883
+ * g++.dg/coroutines/pr94883-folly-2.C: New test.
+
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
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 <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, [] {});
+}
More information about the Gcc-cvs
mailing list