]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/6440 (template specializations cause ICE)
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Sun, 16 Mar 2003 14:28:43 +0000 (14:28 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Sun, 16 Mar 2003 14:28:43 +0000 (14:28 +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: r64437

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog

index d306a402074a915af31d242146d89ce6c7300a1b..6487a59218c6d18bdf3eeb329d1bc938f91766e3 100644 (file)
@@ -1,3 +1,12 @@
+2003-03-16  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 b751ad49e74ed4adcbd9234bfe5da2c63f94f522..a2fed22b77455b484976a25c5df9426ba60c1304 100644 (file)
@@ -695,8 +695,22 @@ void
 maybe_process_partial_specialization (type)
      tree type;
 {
-  if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (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))
        {
@@ -714,6 +728,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);
 }
@@ -9434,6 +9504,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 f2054c9f46eb08a2cc90079d7f96b0ea5b7d99ad..4c04d99b42cc642bd97f1caec74e2bfa4ad12be3 100644 (file)
@@ -1,3 +1,9 @@
+2003-03-16  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  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * gcc.c-torture/compile/20030314-1.c: New test.