> On 2 Jun 2025, at 17:10, Andrew Pinski <pins...@gmail.com> wrote:
>
> 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.
Ah good, that was actually my expectation too.
> 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.
OK.. I can take a look (we need a solution somehow) - although I have some
concerns about fallout.
Iain
>
> 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();
>>> +}