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;
+}

Reply via email to