Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

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.
---
 gcc/cp/coroutines.cc                         |  8 ++++---
 gcc/testsuite/g++.dg/coroutines/pmf-121094.C | 23 ++++++++++++++++++++
 2 files changed, 28 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pmf-121094.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 46ec8c0a953..f4df662bbcb 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 00000000000..786b2f1b315
--- /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;
+  }
+};
-- 
2.54.0

Reply via email to