From: Simon Martin Date: Sun, 25 Aug 2024 19:59:31 +0000 (+0200) Subject: c++: Check template parameters in member class template specialization [PR115716] X-Git-Tag: basepoints/gcc-16~6358 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=26ee954476bef7328d2cf45928c3c9b84df77178;p=thirdparty%2Fgcc.git 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 struct x { template struct y { typedef T result2; }; }; template<> template struct x::y { typedef double result2; }; int main() { x::y::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 --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 struct x { + template struct y { // { dg-note "used 1 template parameter" } + typedef T result2; + }; +}; + +template<> +template +struct x::y { // { dg-error "redeclared with 2 template parameters" } + typedef double result2; +}; + +int main() { + x::y::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 struct x { + template struct y { // { dg-note "original" } + typedef T result2; + }; +}; + +template<> +template +requires true +struct x::y { // { dg-error "different constraints" } + typedef double result2; +}; + +int main() { + x::y::result2 xxx2; +}