https://gcc.gnu.org/g:0c80a308bfa5ed87570f047fdbc0d44c7415f15e

commit r16-9217-g0c80a308bfa5ed87570f047fdbc0d44c7415f15e
Author: Jason Merrill <[email protected]>
Date:   Thu Jul 2 17:54:21 2026 -0400

    c++: co_await and ->* [PR121094]
    
    The use of TARGET_EXPR in get_member_function_from_ptrfunc since r13-9563
    didn't match the expectations of flatten_await_stmt; the latter isn't
    prepared to handle reuse of a TARGET_EXPR.  Most places in the front-end
    only reuse the TARGET_EXPR_SLOT, not the whole TARGET_EXPR, but that's
    awkward for get_member_function_from_ptrfunc, so let's make it work.
    
            PR c++/121094
            PR c++/117259
    
    gcc/cp/ChangeLog:
    
            * coroutines.cc (replace_proxy): Handle TARGET_EXPR from.
            (flatten_await_stmt): Pass it.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/coroutines/pmf-121094.C: New test.
    
    (cherry picked from commit 1948a863280464ed60168d170ab13580bb6bb51b)

Diff:
---
 gcc/cp/coroutines.cc                         |  8 +++++---
 gcc/testsuite/g++.dg/coroutines/pmf-121094.C | 23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index de0de7a83e04..2aec69461d76 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -2087,7 +2087,9 @@ replace_proxy (tree *here, int *do_subtree, void *d)
 {
   proxy_replace *data = (proxy_replace *) d;
 
-  if (*here == data->from)
+  if (*here == data->from
+      || (TREE_CODE (data->from) == TARGET_EXPR
+         && *here == TARGET_EXPR_SLOT (data->from)))
     {
       *here = data->to;
       *do_subtree = 0;
@@ -3326,8 +3328,8 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> 
*promoted,
                = new var_nest_node (var, init, n->prev, n);
              /* We have to replace the target expr... */
              *v.entry = var;
-             /* ... and any uses of its var.  */
-             proxy_replace pr = {TARGET_EXPR_SLOT (t), var};
+             /* ... and any other uses of it or its slot.  */
+             proxy_replace pr = {t, var};
              cp_walk_tree (&n->init, replace_proxy, &pr, NULL);
              /* Compiler-generated temporaries can also have uses in
                 following arms of compound expressions, which will be listed
diff --git a/gcc/testsuite/g++.dg/coroutines/pmf-121094.C 
b/gcc/testsuite/g++.dg/coroutines/pmf-121094.C
new file mode 100644
index 000000000000..786b2f1b315c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pmf-121094.C
@@ -0,0 +1,23 @@
+// PR c++/121094
+
+#include <coroutine>
+
+struct Future {
+  struct promise_type {
+    Future get_return_object() { return {}; }
+    std::suspend_never initial_suspend() noexcept { return {}; }
+    std::suspend_never final_suspend() noexcept { return {}; }
+    void return_void() {}
+    void unhandled_exception() {}
+  };
+  bool await_ready() { return true; }
+  void await_suspend(std::coroutine_handle<>) {}
+  void await_resume() {}
+};
+
+struct Foo {
+  Future test(Future (Foo::*fn)()) {
+    co_await (this->*fn)();
+    co_return;
+  }
+};

Reply via email to