]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Check template parameters in member class template specialization [PR115716]
authorSimon Martin <simon@nasilyan.com>
Sun, 25 Aug 2024 19:59:31 +0000 (21:59 +0200)
committerSimon Martin <simon@nasilyan.com>
Mon, 26 Aug 2024 16:18:31 +0000 (18:18 +0200)
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.

gcc/cp/pt.cc
gcc/testsuite/g++.dg/template/spec42.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/spec43.C [new file with mode: 0644]

index bc3ad5edcc59e0f1eb0b4d8f5d5a940ec896b2de..24a6241d3a5124caf7aba7dc31a726968862c2d3 100644 (file)
@@ -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 (file)
index 0000000..cac1264
--- /dev/null
@@ -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 (file)
index 0000000..d33659d
--- /dev/null
@@ -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;
+}