From: Seyed Sajad Kahani <sska1377@gmail.com>
To: gcc-patches@gcc.gnu.org
Cc: ppalka@redhat.com, jason@redhat.com,
Seyed Sajad Kahani <sska1377@gmail.com>
Subject: [PATCH v2] Fix auto deduction for template specialization scopes [PR114915]
Date: Sat, 4 May 2024 16:15:03 +0100 [thread overview]
Message-ID: <20240504151503.661288-1-sska1377@gmail.com> (raw)
In-Reply-To: <CAPJwJpeEcedRyKMxXP=fDBc2hcfVUX1JFAikMrWLBJm7SFGb4g@mail.gmail.com>
The limitations of the initial patch (checking specializiation template usage), have been discussed.
> I realized that for the case where we have a member function template
> of a class template, and a specialization of the enclosing class only
> (like below),
>
> template <>
> template <typename U>
> void S<int>::f() {
> // some constrained auto
> }
>
> When using S<int>::f<double>, DECL_TEMPLATE_INFO(fn) is non-zero, and
> DECL_TEMPLATE_SPECIALIZATION(fn) is zero, while
> DECL_TEMPLATE_SPECIALIZATION(DECL_TI_TEMPLATE(fn)) is non-zero.
> So it means that the patch will extract DECL_TI_ARGS(fn) as
> outer_targs, and it would be <int> <double> while the type of the
> constrained auto will be as template <typename U> ... and will not be
> dependent on the parameters of the enclosing class.
> This means that again (outer_targs + targs) will have more depth than
> auto_node levels.
> This means that for the case where the function is not an explicit
> specialization, but it is defined in an explicitly specialized scope,
> the patch will not work.
As described in more detail below, this patch attempts to resolve this issue by trimming full_targs.
> > Another more context-unaware approach to fix this might be to only
> > use the innermost level from 'full_targs' for satisfaction if
> > TEMPLATE_TYPE_ORIG_LEVEL is 1 (which means this constrained auto
> > appeared in a context that doesn't have template parameters such as an
> > explicit specialization or ordinary non-template function, and so
> > only the level corresponding to the deduced type is needed for
> > satisfaction.)
> >
> > Generalizing on that, another approach might be to handle missing_levels < 0
> > by removing -missing_levels from full_targs via get_innermost_template_args.
> > But AFAICT it should suffice to handle the TEMPLATE_TYPE_ORIG_LEVEL == 1
> > case specifically.
>
> I was unable to understand why you think that it might not handle
> TEMPLATE_TYPE_ORIG_LEVEL > 1 cases, so I tried to formulate my
> reasoning as follows.
>
> Assuming contexts adc_variable_type, adc_return_type, adc_decomp_type:
> For any case where missing_level < 0, it means that the type depends
> on fewer levels than the template arguments used to materialize it.
> This can only happen when the type is defined in an explicit
> specialization scope. This explicit specialization might not occur in
> its immediate scope.
> Note that partial specialization (while changing the set of
> parameters) cannot reduce the number of levels for the type.
> Because of the fact that the enclosing scope of any explicit
> specialization is explicitly specialized
> (https://eel.is/c++draft/temp.expl.spec#16), the type will not depend
> on template parameters outside of its innermost explicit specialized
> scope.
> Assuming that there are no real missing levels, by removing those
> levels, missing_level should be = 0. As a result, by roughly doing
>
> if (missing_levels < 0) {
> tree trimmed_full_args = get_innermost_template_args(full_targs,
> TEMPLATE_TYPE_ORIG_LEVEL(auto_node));
> full_targs = trimmed_full_args;
> }
> in pt.cc:31262, where we calculate and check missing_levels, we would
> be able to fix the errors.
> Note that, for the case where there are real missing levels, we are
> putting irrelevant template arguments for the missing levels instead
> of make_tree_vec(0). By this change:
> - If the type is independent of those missing levels: it works fine either way.
> - If the type is dependent on those missing levels: Instead of raising
> an ICE, the compiler exhibits undefined behavior.
---
gcc/cp/pt.cc | 14 ++++++--
.../g++.dg/cpp2a/concepts-placeholder14.C | 19 +++++++++++
.../g++.dg/cpp2a/concepts-placeholder15.C | 15 +++++++++
.../g++.dg/cpp2a/concepts-placeholder16.C | 33 +++++++++++++++++++
4 files changed, 78 insertions(+), 3 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..bdf03a1a7 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -31044,7 +31044,8 @@ unparenthesized_id_or_class_member_access_p (tree init)
OUTER_TARGS is used during template argument deduction (context == adc_unify)
to properly substitute the result. It's also used in the adc_unify and
adc_requirement contexts to communicate the necessary template arguments
- to satisfaction. OUTER_TARGS is ignored in other contexts.
+ to satisfaction. OUTER_TARGS will be used for other contexts if it is a
+ function scope deduction. Otherwise it is ignored.
Additionally for adc_unify contexts TMPL is the template for which TYPE
is a template parameter type.
@@ -31260,8 +31261,15 @@ 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)))
+ int missing_levels = (TEMPLATE_TYPE_ORIG_LEVEL (auto_node)
+ - TMPL_ARGS_DEPTH (full_targs));
+ if (missing_levels < 0)
+ {
+ tree trimmed_full_args = get_innermost_template_args(full_targs,
+ TEMPLATE_TYPE_ORIG_LEVEL (auto_node));
+ full_targs = trimmed_full_args;
+ }
+ if (missing_levels > 0)
{
tree dummy_levels = make_tree_vec (missing_levels);
for (int i = 0; i < missing_levels; ++i)
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
next prev parent reply other threads:[~2024-05-04 15:15 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-01 22:52 [PATCH] Fix auto deduction for template specialization scopes [114915] Seyed Sajad Kahani
2024-05-03 16:24 ` Patrick Palka
2024-05-04 14:11 ` Seyed Sajad Kahani
2024-05-04 15:15 ` Seyed Sajad Kahani [this message]
2024-05-06 18:46 ` [PATCH v2] Fix auto deduction for template specialization scopes [PR114915] Patrick Palka
2024-05-10 12:43 ` Seyed Sajad Kahani
2024-05-10 12:47 ` [PATCH v3] " Seyed Sajad Kahani
2024-05-15 15:07 ` [PATCH v3] c++: " Patrick Palka
2024-05-15 15:09 ` Patrick Palka
2024-05-15 17:27 ` [PATCH v4] c++: fix constained auto deduction in templ spec " Seyed Sajad Kahani
2024-05-22 20:30 ` Jason Merrill
2024-06-14 14:15 ` sska1377
2024-06-14 14:18 ` [PATCH v5] " Seyed Sajad Kahani
2024-05-22 15:41 ` [PATCH] Fix auto deduction for template specialization scopes [114915] Jason Merrill
2024-05-22 16:48 ` Patrick Palka
2024-05-22 17:32 ` Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240504151503.661288-1-sska1377@gmail.com \
--to=sska1377@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
--cc=ppalka@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).