re PR c++/6440 (template specializations cause ICE)
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Sat, 15 Mar 2003 10:08:31 +0000 (10:08 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Sat, 15 Mar 2003 10:08:31 +0000 (10:08 +0000)
PR c++/6440
* pt.c (maybe_process_partial_specialization): Handle
member class template when enclosing class template is
explicit specialized.
(most_general_template): Stop looking when DECL is already
specialized.

* g++.dg/template/spec7.C: New test.
* g++.dg/template/spec8.C: Likewise.

From-SVN: r64395

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/spec7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/spec8.C [new file with mode: 0644]

index 539ad19f9998e101b2c0c700098895011e79fa71..46356856b0e811389b5025188c69554317e228c7 100644 (file)
@@ -1,3 +1,12 @@
+2003-03-15  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       PR c++/6440
+       * pt.c (maybe_process_partial_specialization): Handle
+       member class template when enclosing class template is
+       explicit specialized.
+       (most_general_template): Stop looking when DECL is already
+       specialized.
+
 2003-03-13  Jason Merrill  <jason@redhat.com>
 
        PR c++/9420
index a05897810109c44685ffaef3fc3329ad339c1321..410cd8fe025c3cfe37e64ba54975200f0401855f 100644 (file)
@@ -776,8 +776,22 @@ void
 maybe_process_partial_specialization (type)
      tree type;
 {
+  /* TYPE maybe an ERROR_MARK_NODE.  */
+  tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE;
+
   if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
     {
+      /* This is for ordinary explicit specialization and partial
+        specialization of a template class such as:
+
+          template <> class C<int>;
+
+        or:
+
+          template <class T> class C<T*>;
+
+        Make sure that `C<int>' and `C<T*>' are implicit instantiations.  */
+
       if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
          && !COMPLETE_TYPE_P (type))
        {
@@ -795,6 +809,62 @@ maybe_process_partial_specialization (type)
       else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
        error ("specialization of `%T' after instantiation", type);
     }
+  else if (CLASS_TYPE_P (type)
+          && !CLASSTYPE_USE_TEMPLATE (type)
+          && CLASSTYPE_TEMPLATE_INFO (type)
+          && context && CLASS_TYPE_P (context)
+          && CLASSTYPE_TEMPLATE_INFO (context))
+    {
+      /* This is for an explicit specialization of member class
+        template according to [temp.expl.spec/18]:
+
+          template <> template <class U> class C<int>::D;
+
+        The context `C<int>' must be an implicit instantiation.
+        Otherwise this is just a member class template declared
+        earlier like:
+
+          template <> class C<int> { template <class U> class D; };
+          template <> template <class U> class C<int>::D;
+
+        In the first case, `C<int>::D' is a specialization of `C<T>::D'
+        while in the second case, `C<int>::D' is a primary template
+        and `C<T>::D' may not exist.  */
+
+      if (CLASSTYPE_IMPLICIT_INSTANTIATION (context)
+         && !COMPLETE_TYPE_P (type))
+       {
+         tree t;
+
+         if (current_namespace
+             != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+           {
+             pedwarn ("specializing `%#T' in different namespace", type);
+             cp_pedwarn_at ("  from definition of `%#D'",
+                            CLASSTYPE_TI_TEMPLATE (type));
+           }
+
+         /* Check for invalid specialization after instantiation:
+
+              template <> template <> class C<int>::D<int>;
+              template <> template <class U> class C<int>::D;  */
+
+         for (t = DECL_TEMPLATE_INSTANTIATIONS
+                (most_general_template (CLASSTYPE_TI_TEMPLATE (type)));
+              t; t = TREE_CHAIN (t))
+           if (TREE_VALUE (t) != type
+               && TYPE_CONTEXT (TREE_VALUE (t)) == context)
+             error ("specialization `%T' after instantiation `%T'",
+                    type, TREE_VALUE (t));
+
+         /* Mark TYPE as a specialization.  And as a result, we only
+            have one level of template argument for the innermost
+            class template.  */
+         SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+         CLASSTYPE_TI_ARGS (type)
+           = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
+       }
+    }
   else if (processing_specialization)
     error ("explicit specialization of non-template `%T'", type);
 }
@@ -10124,6 +10194,10 @@ most_general_template (decl)
       if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
        break;
 
+      if (CLASS_TYPE_P (TREE_TYPE (decl))
+         && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+       break;
+
       /* Stop if we run into an explicitly specialized class template.  */
       if (!DECL_NAMESPACE_SCOPE_P (decl)
          && DECL_CONTEXT (decl)
index 75049056c022d972b27db91fe2c07363d3fde572..f3222e6844db6140fa9dbcb3e9efcb4a5c368087 100644 (file)
@@ -1,3 +1,9 @@
+2003-03-15  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       PR c++/6440
+       * g++.dg/template/spec7.C: New test.
+       * g++.dg/template/spec8.C: Likewise.
+
 2003-03-14  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.c-torture/execute/20030313-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/template/spec7.C b/gcc/testsuite/g++.dg/template/spec7.C
new file mode 100644 (file)
index 0000000..18d3c90
--- /dev/null
@@ -0,0 +1,27 @@
+// { dg-do compile }
+
+// PR c++/6440: Specialization of member class template.
+
+template<class T> struct A
+{
+  template<class U> struct B {};
+}; 
+
+template<> template<class U>
+struct A<int>::B
+{
+  void f();
+  template <class V> void g(V);
+};
+
+template<> template<> template <class V> void A<int>::B<char>::g(V)
+{
+}
+
+A<int>::B<char> b;
+
+int h()
+{
+  b.f();
+  b.g(0);
+}
diff --git a/gcc/testsuite/g++.dg/template/spec8.C b/gcc/testsuite/g++.dg/template/spec8.C
new file mode 100644 (file)
index 0000000..26d207b
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+// Specialization of member class template.
+
+template<class T1> struct A
+{
+  template<class T2> struct B {};
+}; 
+
+template <> template <> struct A<int>::B<int> {};
+template <> template <class U> struct A<int>::B {}; // { dg-error "specialization" }