On 9/25/24 6:24 PM, Arsen Arsenović wrote:
Tested on x86_64-pc-linux-gnu.  OK for trunk?

OK.

TIA
---------- >8 ----------
If we reach a CLEANUP_POINT_EXPR while trying to walk statements, we
actually care about the statement or statement list contained within it.

Indeed, such a construction started happening with
r15-3513-g964577c31df206, after temporary promotion.  In the test case
presented in PR116793, the compiler generated:

   <<cleanup_point {
     struct _cleanup_task Aw0 [value-expr: frame_ptr->Aw0_2_3];
     int T002 [value-expr: frame_ptr->T002_2_3];

       int T002 [value-expr: frame_ptr->T002_2_3];
     <<cleanup_point <<< Unknown tree: expr_stmt
       (void) (T002 = TARGET_EXPR <D.20994, 3>) >>>>>;
       struct _cleanup_task Aw0 [value-expr: frame_ptr->Aw0_2_3];
     <<cleanup_point <<< Unknown tree: expr_stmt
       (void) (Aw0 = TARGET_EXPR <D.20995, func ((int &) &T002)>) >>>>>;
     <<cleanup_point <<< Unknown tree: expr_stmt
       (void) (D.22450 = <<< Unknown tree: co_await
         TARGET_EXPR <D.20995, func ((int &) &T002)>
         Aw0

         {_cleanup_task::await_ready (&Aw0), _cleanup_task::await_suspend<_task1::promise_type> 
(&Aw0, TARGET_EXPR <D.21078, _Coro_self_handle>), <<< Unknown tree: aggr_init_expr
           4
           await_resume
           D.22443
           &Aw0 >>>}
         0 >>>) >>>>>;
     <<cleanup_point <<< Unknown tree: expr_stmt
       (void) (D.20991 = (struct tuple &) &D.22450) >>>>>;
   }
   D.22467 = 1;
   int & i [value-expr: frame_ptr->i_1_2];
   <<cleanup_point <<< Unknown tree: expr_stmt
     (void) (i = std::get<0, int&> (NON_LVALUE_EXPR <D.20991>)) >>>>>;>>;

... i.e. a statement list within a cleanup point.  In such a case, we
don't actually care about the cleanup point, but we do care about the
statement inside, so, we can just walk down into the CLEANUP_POINT_EXPR.

        PR c++/116793

gcc/cp/ChangeLog:

        * coroutines.cc (await_statement_expander): Just process
        subtrees if encountering a CLEANUP_POINT_EXPR.

gcc/testsuite/ChangeLog:

        * g++.dg/coroutines/pr116793-1.C: New test.
---
  gcc/cp/coroutines.cc                         |  4 ++-
  gcc/testsuite/g++.dg/coroutines/pr116793-1.C | 26 ++++++++++++++++++++
  2 files changed, 29 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/coroutines/pr116793-1.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index f1543e8ecd39..31113e3b763e 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -2194,7 +2194,9 @@ await_statement_expander (tree *stmt, int *do_subtree, 
void *d)
    tree res = NULL_TREE;
/* Process a statement at a time. */
-  if (STATEMENT_CLASS_P (*stmt) || TREE_CODE (*stmt) == BIND_EXPR)
+  if (STATEMENT_CLASS_P (*stmt)
+      || TREE_CODE (*stmt) == BIND_EXPR
+      || TREE_CODE (*stmt) == CLEANUP_POINT_EXPR)
      return NULL_TREE; /* Just process the sub-trees.  */
    else if (TREE_CODE (*stmt) == STATEMENT_LIST)
      {
diff --git a/gcc/testsuite/g++.dg/coroutines/pr116793-1.C 
b/gcc/testsuite/g++.dg/coroutines/pr116793-1.C
new file mode 100644
index 000000000000..ed2bdd26996a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr116793-1.C
@@ -0,0 +1,26 @@
+// https://gcc.gnu.org/PR116793
+#include <tuple>
+#include <coroutine>
+struct _cleanup_task {
+  bool await_ready() const noexcept;
+  template <typename Promise>
+  bool await_suspend(std::coroutine_handle<Promise> parent) noexcept;
+  std::tuple<int &> await_resume() noexcept;
+};
+struct _task1 {
+  struct promise_type final {
+    std::suspend_always initial_suspend() noexcept;
+    _task1 get_return_object() noexcept;
+    void unhandled_exception() noexcept;
+    struct awaiter final {
+      bool await_ready() noexcept;
+      void await_resume() noexcept;
+      void await_suspend(std::coroutine_handle<promise_type> h) noexcept;
+    };
+    awaiter final_suspend() noexcept;
+  };
+};
+_cleanup_task func(int &&);
+_task1 g() {
+  auto &&[i] = co_await func(3);
+}

Reply via email to