https://gcc.gnu.org/g:26ee954476bef7328d2cf45928c3c9b84df77178
commit r15-3195-g26ee954476bef7328d2cf45928c3c9b84df77178 Author: Simon Martin <si...@nasilyan.com> Date: Sun Aug 25 21:59:31 2024 +0200 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. 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. Diff: --- 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(+) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index bc3ad5edcc59..24a6241d3a51 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 000000000000..cac1264fc9f2 --- /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 000000000000..d33659dd5063 --- /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; +}