[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