Hi Jason, >>a bootstrap + testsuite (but without Ada or D).
>Hmm, it looks like make_typename_type wants to call lookup_template_class with >a class as CONTEXT. > But it first does the lookup separately. So I read that to indicate this does not need addressing (at this point) - we could extend it to allow class contexts. > So I guess it makes sense to say that passing an identifier and context is > only supported if context is a namespace. Done. >>+ 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. >This "otherwise" blurs two different cases: D1 is an id and CONTEXT is NULL >(in which case lookup selects the innermost non-namespace binding), or D1 is >not an id (in which case CONTEXT is ignored and no lookup is performed). Fixed >Let's also remove the FUNCTION_CONTEXT paragraph. Done >I guess we should stop passing the CONTEXT argument in non-id+ns cases such as >make_typename_type and tsubst... I have not tried to address caller-side changes. >>+ templ = maybe_get_template_decl_from_type_decl (templ); >This line is unnecessary for namespace lookup, it's just for the >injected-class-name. Thanks, fixed. re-tested on x86_64-darwin, powerpc64le is still running, how does it look now? 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 | 30 +++++++----- gcc/testsuite/g++.dg/coroutines/pr120495.C | 55 ++++++++++++++++++++++ gcc/testsuite/g++.dg/pr115605.C | 10 ++++ 3 files changed, 84 insertions(+), 11 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..3c8fa9a6728 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -10052,15 +10052,20 @@ 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 CONTEXT. Currently, only namespaces are supported for + CONTEXT. + + If D1 is an identifier and CONTEXT is NULL, the lookup is performed + in the innermost non-namespace binding. + + Otherwise CONTEXT is ignored and no lookup is carried out. + IN_DECL, if non-NULL, is the template declaration we are trying to instantiate. Issue error and warning messages under control of COMPLAIN. - If the template class is really a local class in a template - function, then the FUNCTION_CONTEXT is the function in which it is - being instantiated. - ??? Note that this function is currently called *twice* for each template-id: the first time from the parser, while creating the incomplete type (finish_template_type), and the second type during the @@ -10079,20 +10084,23 @@ 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); + 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)