Ping. On Fri, Feb 12, 2021 at 06:12:12PM -0500, Marek Polacek via Gcc-patches wrote: > 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 >
Marek