On Mon, Jun 2, 2025 at 8:17 AM Jason Merrill <ja...@redhat.com> wrote: > > On 6/2/25 5:13 AM, Iain Sandoe wrote: > > 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. > > Hmm, this seems like a longstanding (since the implementation of > namespaces in r19631) bug in lookup_template_class; if context is a > namespace, I'd expect that to bypass any local declaration.
Yes and this was mentioned while I was fixing PR 115605 (https://inbox.sourceware.org/gcc-patches/5d1efe6a-d2f2-4b37-aa92-ce3a73739...@redhat.com/). I didn't get some time to look into changing that yet. Iain, if you look into fixing lookup_template_class, check the testcases for PR 115605 at the same time too. Thanks, Andrew > > > 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(); > > +} >