We represent deduction guides with FUNCTION_DECLs, but they are built without DECL_CONTEXT, leading to an ICE in type_dependent_expression_p on the assert that the type of a function template with no dependent (innermost!) template arguments must be non-dependent. Consider the attached class-deduction79.C: we create a deduction guide:
template<class T> G(T)-> E<Z>::G<T> we deduce T and create a partial instantiation: G(T) -> E<Z>::G<T> [with T = int] And then do_class_deduction wants to create a CALL_EXPR from the above using build_new_function_call -> build_over_call which calls mark_used -> maybe_instantiate_noexcept -> type_dependent_expression_p. There, the innermost template arguments are non-dependent (<int>), but the fntype is dependent -- the return type is a TYPENAME_TYPE, and since we have no DECL_CONTEXT, this check holds: /* Otherwise, if the function decl isn't from a dependent scope, it can't be type-dependent. Checking this is important for functions with auto return type, which looks like a dependent type. */ if (TREE_CODE (expression) == FUNCTION_DECL && !(DECL_CLASS_SCOPE_P (expression) && dependent_type_p (DECL_CONTEXT (expression))) whereupon we ICE. Experiments with setting DECL_CONTEXT didn't pan out. So perhaps we just want to skip the assert for deduction guides, because they are a little special. Better ideas solicited. Bootstrapped/regtested on x86_64-pc-linux-gnu. gcc/cp/ChangeLog: PR c++/97034 PR c++/99009 * pt.c (type_dependent_expression_p): Don't assert that the type of a deduction guide must non-dependent. gcc/testsuite/ChangeLog: PR c++/97034 PR c++/99009 * g++.dg/cpp1z/class-deduction79.C: New test. * g++.dg/cpp1z/class-deduction80.C: New test. * g++.dg/cpp2a/class-deduction-aggr8.C: New test. * g++.dg/cpp2a/class-deduction-aggr9.C: New test. --- gcc/cp/pt.c | 5 ++++- .../g++.dg/cpp1z/class-deduction79.C | 20 +++++++++++++++++++ .../g++.dg/cpp1z/class-deduction80.C | 12 +++++++++++ .../g++.dg/cpp2a/class-deduction-aggr8.C | 19 ++++++++++++++++++ .../g++.dg/cpp2a/class-deduction-aggr9.C | 18 +++++++++++++++++ 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction79.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction80.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 60de8e93ff7..3e6f3407d40 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -27282,7 +27282,10 @@ type_dependent_expression_p (tree expression) && DECL_UNIQUE_FRIEND_P (expression) && (!DECL_FRIEND_CONTEXT (expression) || dependent_type_p (DECL_FRIEND_CONTEXT (expression)))) - && !DECL_LOCAL_DECL_P (expression)) + && !DECL_LOCAL_DECL_P (expression) + /* We build deduction guides without any DECL_CONTEXT, but they can + be type-dependent. */ + && !deduction_guide_p (expression)) { gcc_assert (!dependent_type_p (TREE_TYPE (expression)) || undeduced_auto_decl (expression)); diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C new file mode 100644 index 00000000000..86a68248157 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C @@ -0,0 +1,20 @@ +// PR c++/97034 +// { dg-do compile { target c++17 } } + +template <typename Z> +struct E { + template <typename T> + struct G { + T t; + G(T) { } + }; + + void fn() { G{1}; } +}; + +void +g () +{ + E<int> e; + e.fn (); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C new file mode 100644 index 00000000000..238024c508f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C @@ -0,0 +1,12 @@ +// PR c++/99009 +// { dg-do compile { target c++17 } } + +template<typename> struct B { + B(int = A()) {} + template <typename ...> struct A; +}; + +template<typename T> struct X { + template <T...> struct Y; + X() { Y y; }; +}; diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C new file mode 100644 index 00000000000..399061100ae --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C @@ -0,0 +1,19 @@ +// PR c++/97034 +// { dg-do compile { target c++20 } } + +namespace N { +template <typename, typename> struct S { + template <typename T, typename U> S(T, U); +}; +} // namespace N +template <int> struct E { + template <typename T> struct G { T t; }; + void fn() { G{N::S<char, int>{'a', 1}}; } +}; + +void +g () +{ + E<1> e; + e.fn (); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C new file mode 100644 index 00000000000..245a04cd5f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C @@ -0,0 +1,18 @@ +// PR c++/97034 +// { dg-do compile { target c++20 } } + +template<typename> +struct E { + template <typename T> + struct G { + T t; + }; + + void fn() { G{1}; } +}; + +void +g () { + E<int> e; + e.fn (); +} base-commit: eb64b0b285b4fda9e8eeda4c2f370e636b1ab2ae -- 2.29.2