On Fri, 10 May 2024, Seyed Sajad Kahani wrote:
> This patch resolves PR114915 by replacing the logic that fills in the missing > levels in do_auto_deduction in cp/pt.cc. > The new approach now trims targs if the depth of targs is deeper than desired > (this will only happen in specific contexts), and still fills targs with > empty layers if it has fewer depths than expected. The logic looks good to me, thanks! Note that as per https://gcc.gnu.org/contribute.html patches need a ChangeLog entry in the commit message, for example let's use: PR c++/114915 gcc/cp/ChangeLog: * pt.cc (do_auto_deduction): Handle excess outer template arguments during constrained auto satisfaction. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-placeholder14.C: New test. * g++.dg/cpp2a/concepts-placeholder15.C: New test. * g++.dg/cpp2a/concepts-placeholder16.C: New test. Jason, what do you think? > --- > gcc/cp/pt.cc | 20 ++++++++--- > .../g++.dg/cpp2a/concepts-placeholder14.C | 19 +++++++++++ > .../g++.dg/cpp2a/concepts-placeholder15.C | 15 +++++++++ > .../g++.dg/cpp2a/concepts-placeholder16.C | 33 +++++++++++++++++++ > 4 files changed, 83 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index 3b2106dd3..479b2a5bd 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -31253,6 +31253,19 @@ do_auto_deduction (tree type, tree init, tree > auto_node, > full_targs = add_outermost_template_args (tmpl, full_targs); > full_targs = add_to_template_args (full_targs, targs); > > + int want = TEMPLATE_TYPE_ORIG_LEVEL (auto_node); > + int have = TMPL_ARGS_DEPTH (full_targs); > + > + if (want < have) > + { > + // if a constrained auto is declared in an explicit specialization > + gcc_assert (context == adc_variable_type || context == adc_return_type > + || context == adc_decomp_type); > + tree trimmed_full_args = get_innermost_template_args > + (full_targs, want); > + full_targs = trimmed_full_args; > + } > + > /* HACK: Compensate for callers not always communicating all levels of > outer template arguments by filling in the outermost missing levels > with dummy levels before checking satisfaction. We'll still crash > @@ -31260,11 +31273,10 @@ do_auto_deduction (tree type, tree init, tree > auto_node, > these missing levels, but this hack otherwise allows us to handle a > large subset of possible constraints (including all non-dependent > constraints). */ > - if (int missing_levels = (TEMPLATE_TYPE_ORIG_LEVEL (auto_node) > - - TMPL_ARGS_DEPTH (full_targs))) > + if (want > have) > { > - tree dummy_levels = make_tree_vec (missing_levels); > - for (int i = 0; i < missing_levels; ++i) > + tree dummy_levels = make_tree_vec (want - have); > + for (int i = 0; i < want - have; ++i) > TREE_VEC_ELT (dummy_levels, i) = make_tree_vec (0); > full_targs = add_to_template_args (dummy_levels, full_targs); > } > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C > b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C > new file mode 100644 > index 000000000..fcdbd7608 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C > @@ -0,0 +1,19 @@ > +// PR c++/114915 > +// { dg-do compile { target c++20 } } > + > +template<typename T> > +concept C = __is_same(T, int); > + > +template<typename T> > +void f() { > +} > + > +template<> > +void f<int>() { > + C auto x = 1; > +} > + > +int main() { > + f<int>(); > + return 0; > +} > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C > b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C > new file mode 100644 > index 000000000..b4f73f407 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C > @@ -0,0 +1,15 @@ > +// PR c++/114915 > +// { dg-do compile { target c++20 } } > + > +template<typename T, typename U> > +concept C = __is_same(T, U); > + > +template<typename T> > +int x = 0; > + > +template<> > +C<double> auto x<double> = 1.0; > + > +int main() { > + return 0; > +} > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C > b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C > new file mode 100644 > index 000000000..f808ef1b6 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C > @@ -0,0 +1,33 @@ > +// PR c++/114915 > +// { dg-do compile { target c++20 } } > + > +template<typename T, typename U> > +concept C = __is_same(T, U); > + > +template<typename T> > +struct A > +{ > + template<typename U> > + void f() { > + } > +}; > + > +template<> > +template<> > +void A<int>::f<int>() { > + C<int> auto x = 1; > +} > + > +template<> > +template<typename U> > +void A<bool>::f() { > + C<int> auto x = 1; > +} > + > +int main() { > + A<bool> a; > + a.f<char>(); > + A<int> b; > + b.f<int>(); > + return 0; > +} > -- > 2.45.0 > >