>>gcc/cp/ChangeLog:
>>      * pt.cc (lookup_template_class): Honour provided namespace contexts
>>      when looking up class templates.

>This is good, but I'd also expect namespace context to take priority over 
>innermost_non_namespace_value just above?

So the attached version is more aggressive - it now asserts that the
combination of an identifier + a provided context implies that we want a
namespace lookup only.  Since the function header content mentioned
FUNCTION_CONTEXT - but there is no such parameter I was a little concerned
that a non-namespace decl could be passed for CONTEXT; so I have added a
checking assert that CONTEXT is a namespace decl - that did not fire on
a bootstrap + testsuite (but without Ada or D).
does this look ready?
thanks
Iain

--- 8< ---

In the reported issues, using lookup_template_class () directly on (for example)
the coroutine_handle identifier fails because a class-local TYPE_DECL is found.
This is because, in the existing code, lookup is called with default parameters
which means that class contexts are examined first.

Fix this, when a context is provided by the caller, by doing lookup in namespace
provided.

        PR c++/120495
        PR c++/115605

gcc/cp/ChangeLog:

        * pt.cc (lookup_template_class): Honour provided namespace contexts
        when looking up class templates.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>
---
 gcc/cp/pt.cc                               | 22 ++++++---
 gcc/testsuite/g++.dg/coroutines/pr120495.C | 55 ++++++++++++++++++++++
 gcc/testsuite/g++.dg/pr115605.C            | 10 ++++
 3 files changed, 80 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr120495.C
 create mode 100644 gcc/testsuite/g++.dg/pr115605.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c5a3abe6d8b..4fbbee7d18f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10052,6 +10052,10 @@ tsubst_entering_scope (tree t, tree args, 
tsubst_flags_t complain, tree in_decl)
 
    D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
 
+   If D1 is an identifier and CONTEXT is non-NULL, then the lookup is
+   carried out in the CONTEXT namespace, otherwise CONTEXT is ignored and
+   lookup is carried out with default priority.
+
    IN_DECL, if non-NULL, is the template declaration we are trying to
    instantiate.
 
@@ -10079,20 +10083,24 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
   spec_entry **slot;
   spec_entry *entry;
 
-  if (identifier_p (d1))
+  if (identifier_p (d1) && context)
+    {
+      gcc_checking_assert (TREE_CODE (context) == NAMESPACE_DECL);
+      push_decl_namespace (context);
+      templ = lookup_name (d1, LOOK_where::NAMESPACE, LOOK_want::NORMAL);
+      templ = maybe_get_template_decl_from_type_decl (templ);
+      pop_decl_namespace ();
+    }
+  else if (identifier_p (d1))
     {
       tree value = innermost_non_namespace_value (d1);
       if (value && DECL_TEMPLATE_TEMPLATE_PARM_P (value))
        templ = value;
       else
-       {
-         if (context)
-           push_decl_namespace (context);
+        {
          templ = lookup_name (d1);
          templ = maybe_get_template_decl_from_type_decl (templ);
-         if (context)
-           pop_decl_namespace ();
-       }
+        }
     }
   else if (TREE_CODE (d1) == TYPE_DECL && MAYBE_CLASS_TYPE_P (TREE_TYPE (d1)))
     {
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();
+}
diff --git a/gcc/testsuite/g++.dg/pr115605.C b/gcc/testsuite/g++.dg/pr115605.C
new file mode 100644
index 00000000000..9e342555c89
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr115605.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++20 } }
+
+#include <array>
+
+int foo() {
+    int const tuple_size = 5;
+    std::array<int, 3> array {1, 2, 3};
+    auto [a, b, c] = array;
+    return c;
+}
-- 
2.39.2 (Apple Git-143)

Reply via email to