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();
> > +}
>

Reply via email to