On Mon, Jan 31, 2022 at 11:07 AM Patrick Palka <ppa...@redhat.com> wrote: > > Here during deduction guide generation for the nested class template > B<char(int)>::C, the computation of outer_targs yields the template > arguments relative to the primary template for B (i.e. {char(int)}) > but what we really what is those relative to the enclosing scope, the > partial specialization of B (i.e. {char, int}). > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk? > > PR c++/104294 > > gcc/cp/ChangeLog: > > * pt.cc (ctor_deduction_guides_for): Correct computation of > outer_targs. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp1z/class-deduction106.C: New test. > --- > gcc/cp/pt.cc | 4 +++- > .../g++.dg/cpp1z/class-deduction106.C | 19 +++++++++++++++++++ > 2 files changed, 22 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction106.C > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index f46a7ad6655..0fe0ad4e44e 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -29568,7 +29568,9 @@ ctor_deduction_guides_for (tree tmpl, tsubst_flags_t > complain) > if (DECL_CLASS_SCOPE_P (tmpl) > && CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (tmpl))) > { > - outer_args = CLASSTYPE_TI_ARGS (DECL_CONTEXT (tmpl)); > + outer_args = copy_node (CLASSTYPE_TI_ARGS (type)); > + gcc_assert (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (outer_args));
Whoops, this assert should be slightly stronger: TMPL_ARGS_DEPTH (outer_args) > 1. Consider that fixed (pending another bootstrap/regtest cycle). > + --TREE_VEC_LENGTH (outer_args); > type = TREE_TYPE (most_general_template (tmpl)); > } > > diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction106.C > b/gcc/testsuite/g++.dg/cpp1z/class-deduction106.C > new file mode 100644 > index 00000000000..382f6b70ef5 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction106.C > @@ -0,0 +1,19 @@ > +// PR c++/104294 > +// { dg-do compile { target c++17 } } > + > +template<class> > +struct B; > + > +template <class R, class... Args> > +struct B<R(Args...)> { > + template<class T> > + struct C { C(T); }; > + > + C(decltype(nullptr)) -> C<void*>; > +}; > + > +using ty1 = decltype(B<char(int)>::C{0}); > +using ty1 = B<char(int)>::C<int>; > + > +using ty2 = decltype(B<char(int)>::C{nullptr}); > +using ty2 = B<char(int)>::C<void*>; > -- > 2.35.0 >