Tested on x86_64-darwin, OK for trunk?
thanks
Iain

--- 8< ---

Using lookup_template_class () directly on the coroutine_handle identifier
fails in the reported test because the using TYPE_DECL is found.  Fix this
by looking up the std::coroutine_handle template specifically and then
instantiating that.

        PR c++/120495

gcc/cp/ChangeLog:

        * coroutines.cc
        (instantiate_coro_handle_for_promise_type): Lookup the coroutine
        handle template specifically and then instantiate that.

gcc/testsuite/ChangeLog:

        * g++.dg/coroutines/pr120495.C: New test.

Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>
---
 gcc/cp/coroutines.cc                       | 17 ++++---
 gcc/testsuite/g++.dg/coroutines/pr120495.C | 55 ++++++++++++++++++++++
 2 files changed, 66 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr120495.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 42f719ddde1..7ea1ad7c3aa 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -609,16 +609,21 @@ get_handle_type_from_address (location_t kw, tree 
handle_type)
 static tree
 instantiate_coro_handle_for_promise_type (location_t kw, tree promise_type)
 {
+  /* Look up the template.  */
+  tree handle_type = find_coro_handle_template_decl (kw);
+  if (!handle_type)
+    return NULL_TREE;
+
   /* So now build up a type list for the template, one entry, the promise.  */
   tree targ = make_tree_vec (1);
   TREE_VEC_ELT (targ, 0) = promise_type;
-  tree handle_type
-    = lookup_template_class (coro_handle_identifier, targ,
-                            /* in_decl=*/NULL_TREE,
-                            /* context=*/std_node,
-                            tf_warning_or_error);
 
-  if (handle_type == error_mark_node)
+  /* Instantiate for the promise type.  */
+  handle_type 
+    = lookup_template_class (handle_type, targ, /*in_decl*/NULL_TREE,
+                            /*context*/std_node, tf_warning_or_error);
+
+  if (!handle_type || handle_type == error_mark_node)
     {
       error_at (kw, "cannot instantiate a %<coroutine handle%> for"
                " promise type %qT", promise_type);
diff --git a/gcc/testsuite/g++.dg/coroutines/pr120495.C 
b/gcc/testsuite/g++.dg/coroutines/pr120495.C
new file mode 100644
index 00000000000..f59c34a8676
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr120495.C
@@ -0,0 +1,55 @@
+// { dg-additional-options "-fsyntax-only" }
+
+#include <coroutine>
+#include <exception>
+
+struct fire_and_forget {
+};
+
+template <typename... Args>
+struct std::coroutine_traits<fire_and_forget, Args...>
+{
+    struct promise_type
+    {
+        fire_and_forget get_return_object() const noexcept
+        {
+            return{};
+        }
+
+        void return_void() const noexcept
+        {
+        }
+
+        suspend_never initial_suspend() const noexcept
+        {
+            return{};
+        }
+
+        suspend_never final_suspend() const noexcept
+        {
+            return{};
+        }
+
+        void unhandled_exception() const noexcept
+        {
+            std::terminate();
+        }
+    };
+};
+
+struct foo
+{
+    fire_and_forget bar()
+    {
+        co_await std::suspend_always{ };
+    }
+
+private:
+    // The line below triggered the error.
+    using coroutine_handle = std::coroutine_handle<>;
+};
+
+int main()
+{
+    foo{}.bar();
+}
-- 
2.39.2 (Apple Git-143)

Reply via email to