Hi Jason, On 22 Aug 2024, at 19:28, Jason Merrill wrote:
> On 8/22/24 12:51 PM, Simon Martin wrote: >> We currently ICE upon the following invalid code, because we don't >> check the >> number of template parameters in member class template >> specializations. This >> patch fixes the PR by adding such a check. >> >> === cut here === >> template <typename T> struct x { >> template <typename U> struct y { >> typedef T result2; >> }; >> }; >> template<> template<typename U, typename> struct x<int>::y { >> typedef double result2; >> }; >> int main() { >> x<int>::y<int>::result2 xxx2; >> } >> === cut here === >> >> Successfully tested on x86_64-pc-linux-gnu. >> >> PR c++/115716 >> >> gcc/cp/ChangeLog: >> >> * pt.cc (maybe_process_partial_specialization): Check number of >> template parameters in specialization. >> >> gcc/testsuite/ChangeLog: >> >> * g++.dg/template/spec42.C: New test. >> >> --- >> gcc/cp/pt.cc | 14 ++++++++++++++ >> gcc/testsuite/g++.dg/template/spec42.C | 17 +++++++++++++++++ >> 2 files changed, 31 insertions(+) >> create mode 100644 gcc/testsuite/g++.dg/template/spec42.C >> >> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc >> index bc3ad5edcc5..db8c2a3b4de 100644 >> --- a/gcc/cp/pt.cc >> +++ b/gcc/cp/pt.cc >> @@ -1173,6 +1173,20 @@ maybe_process_partial_specialization (tree >> type) >> type, inst); >> } >> + /* Check that the number of template parameters matches the >> template >> + being specialized. */ >> + gcc_assert (current_template_parms); >> + if (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS >> + (CLASSTYPE_TI_ARGS (type))) >> + != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS >> + (current_template_parms))) >> + { >> + error ("wrong number of template parameters for %qT", type); >> + inform (DECL_SOURCE_LOCATION (tmpl), "from definition of >> %q#D", >> + tmpl); > > How about printing the numbers for each place? > > What if the mismatch is other than in the number of parameters? Can > you use template_parameter_lists_equivalent_p? Or if that's > complicated, compare current_template_args() to CLASSTYPE_TI_ARGS > (type)? > Thanks for the review. After checking further, I believe we just miss a call to redeclare_class_template, that will catch various template parameter mismatch and properly report them. This is what the updated attached patch does, successfully tested on x86_64-pc-linux-gnu. OK for trunk? Thanks, Simon > Jason
From 7e817c158e7d2e83e0283c3fa892370dbf9a238a Mon Sep 17 00:00:00 2001 From: Simon Martin <si...@nasilyan.com> Date: Sun, 25 Aug 2024 21:59:31 +0200 Subject: [PATCH] c++: Check template parameters in member class template specialization [PR115716] We currently ICE upon the following invalid code, because we don't check that the template parameters in a member class template specialization are correct. === cut here === template <typename T> struct x { template <typename U> struct y { typedef T result2; }; }; template<> template<typename U, typename> struct x<int>::y { typedef double result2; }; int main() { x<int>::y<int>::result2 xxx2; } === cut here === This patch fixes the PR by calling redeclare_class_template. Successfully tested on x86_64-pc-linux-gnu. PR c++/115716 gcc/cp/ChangeLog: * pt.cc (maybe_process_partial_specialization): Call redeclare_class_template. gcc/testsuite/ChangeLog: * g++.dg/template/spec42.C: New test. * g++.dg/template/spec43.C: New test. --- gcc/cp/pt.cc | 5 +++++ gcc/testsuite/g++.dg/template/spec42.C | 17 +++++++++++++++++ gcc/testsuite/g++.dg/template/spec43.C | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 gcc/testsuite/g++.dg/template/spec42.C create mode 100644 gcc/testsuite/g++.dg/template/spec43.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index bc3ad5edcc5..24a6241d3a5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -1173,6 +1173,11 @@ maybe_process_partial_specialization (tree type) type, inst); } + /* Make sure that the specialization is valid. */ + if (!redeclare_class_template (type, current_template_parms, + current_template_constraints ())) + return error_mark_node; + /* Mark TYPE as a specialization. And as a result, we only have one level of template argument for the innermost class template. */ diff --git a/gcc/testsuite/g++.dg/template/spec42.C b/gcc/testsuite/g++.dg/template/spec42.C new file mode 100644 index 00000000000..cac1264fc9f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec42.C @@ -0,0 +1,17 @@ +// PR c++/115716 +// { dg-do compile } +template <typename T> struct x { + template <typename U> struct y { // { dg-note "used 1 template parameter" } + typedef T result2; + }; +}; + +template<> +template<typename U, typename> +struct x<int>::y { // { dg-error "redeclared with 2 template parameters" } + typedef double result2; +}; + +int main() { + x<int>::y<int>::result2 xxx2; +} diff --git a/gcc/testsuite/g++.dg/template/spec43.C b/gcc/testsuite/g++.dg/template/spec43.C new file mode 100644 index 00000000000..d33659dd506 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec43.C @@ -0,0 +1,18 @@ +// PR c++/115716 +// { dg-do compile { target c++20 } } +template <typename T> struct x { + template <typename U> struct y { // { dg-note "original" } + typedef T result2; + }; +}; + +template<> +template<typename U> +requires true +struct x<int>::y { // { dg-error "different constraints" } + typedef double result2; +}; + +int main() { + x<int>::y<int>::result2 xxx2; +} -- 2.44.0