[v3] Fix auto deduction for template specialization scopes [PR114915]
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Testing passed
|
Commit Message
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.
---
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
Comments
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
>
>
On Wed, 15 May 2024, Patrick Palka wrote:
>
> 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?
... now sent to the correct email, sorry for the spam
>
> > ---
> > 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
> >
> >
>
@@ -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);
}
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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;
+}