cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove.
authorMark Mitchell <mark@markmitchell.com>
Sat, 5 Sep 1998 20:14:21 +0000 (20:14 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sat, 5 Sep 1998 20:14:21 +0000 (20:14 +0000)
* cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove.
* class.c (finish_struct): Remove hackery to deal with explicit
specializations in class scope.
* decl.c (grokfndecl): Improve error-recovery.
* decl2.c (grokfield): Likewise.
* pt.c (check_specialization_scope): New function.
(begin_specialization): Call it.
(process_partial_specialization): New function, split out from
push_template_decl.  Check partial specializations more
stringently.
(push_template_decl): Call it.
(check_explicit_specialization): Don't attempt to handle explicit
specializations in class scope.
(template_parm_data): Document.  Add current_arg and
arg_uses_template_parms.
(mark_template_parm): Set it.
(tsubst_arg_types): Remove unused variable.
* semantics.c (begin_class_definition): Tweak.

From-SVN: r22271

23 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.old-deja/g++.pt/explicit12.C
gcc/testsuite/g++.old-deja/g++.pt/explicit13.C
gcc/testsuite/g++.old-deja/g++.pt/explicit35.C
gcc/testsuite/g++.old-deja/g++.pt/memclass7.C
gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C
gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C
gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C
gcc/testsuite/g++.old-deja/g++.pt/spec10.C
gcc/testsuite/g++.old-deja/g++.pt/spec11.C
gcc/testsuite/g++.old-deja/g++.pt/spec12.C
gcc/testsuite/g++.old-deja/g++.pt/spec13.C
gcc/testsuite/g++.old-deja/g++.pt/spec15.C
gcc/testsuite/g++.old-deja/g++.pt/spec20.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/spec21.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/spec22.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/spec6.C

index 0beacd2e8eda2bd933e0fc1a083e57c148f7072d..c092ea215c10908184095236267f70b46d45fac3 100644 (file)
@@ -1,3 +1,24 @@
+1998-09-05  Mark Mitchell  <mark@markmitchell.com>
+
+       * cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove.
+       * class.c (finish_struct): Remove hackery to deal with explicit
+       specializations in class scope.
+       * decl.c (grokfndecl): Improve error-recovery.
+       * decl2.c (grokfield): Likewise.
+       * pt.c (check_specialization_scope): New function.
+       (begin_specialization): Call it.
+       (process_partial_specialization): New function, split out from
+       push_template_decl.  Check partial specializations more
+       stringently.
+       (push_template_decl): Call it.
+       (check_explicit_specialization): Don't attempt to handle explicit
+       specializations in class scope.
+       (template_parm_data): Document.  Add current_arg and
+       arg_uses_template_parms. 
+       (mark_template_parm): Set it.
+       (tsubst_arg_types): Remove unused variable.
+       * semantics.c (begin_class_definition): Tweak.
+       
 1998-09-04  Mark Mitchell  <mark@markmitchell.com>
 
        * inc/typeinfo (type_info::type_info(const char*)): Make
index bcdf9571d47d755d19fa5ff1c05fa00da383a183..173c69a283091ead42ba0d8d61d73cb895878ce2 100644 (file)
@@ -4148,8 +4148,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
 {
   tree fields = NULL_TREE;
   tree *tail = &TYPE_METHODS (t);
-  tree specializations = NULL_TREE;
-  tree *specialization_tail = &specializations;
   tree name = TYPE_NAME (t);
   tree x, last_x = NULL_TREE;
   tree access;
@@ -4259,19 +4257,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
              if (last_x)
                TREE_CHAIN (last_x) = next_x;
 
-             if (DECL_TEMPLATE_SPECIALIZATION (x))
-               /* We don't enter the specialization into the class
-                  method vector since specializations don't affect
-                  overloading.  Instead we keep track of the
-                  specializations, and process them after the method
-                  vector is complete.  */
-               {
-                 *specialization_tail = x;
-                 specialization_tail = &TREE_CHAIN (x);
-                 TREE_CHAIN (x) = NULL_TREE;
-                 continue;
-               }
-
              /* Link x onto end of TYPE_METHODS.  */
              *tail = x;
              tail = &TREE_CHAIN (x);
@@ -4359,27 +4344,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
     t = finish_struct_1 (t, warn_anon);
 
   TYPE_BEING_DEFINED (t) = 0;
-
-  /* Now, figure out which member templates we're specializing.  */
-  for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x))
-    {
-      int pending_specialization;
-
-      pending_specialization 
-       = TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x));
-      check_explicit_specialization 
-       (lookup_template_function (DECL_NAME (x), DECL_TI_ARGS (x)),
-        x, 0, 1 | (8 * pending_specialization));
-      TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x)) = 0;
-
-      /* Now, the assembler name will be correct for fn, so we
-        make its RTL.  */
-      DECL_RTL (x) = 0;
-      make_decl_rtl (x, NULL_PTR, 1);
-      DECL_RTL (DECL_TI_TEMPLATE (x)) = 0;
-      make_decl_rtl (DECL_TI_TEMPLATE (x), NULL_PTR, 1);
-    }
-
   if (current_class_type)
     popclass (0);
   else
index 8bf6c5c86216ff2d3f3ee36ef9bebb9a1411ca6d..3c3a8588139a35f60b8931bb6288f566e5d6bf83 100644 (file)
@@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA.  */
       (TREE_MANGLED) (in IDENTIFIER_NODE) (commented-out).
    1:  IDENTIFIER_VIRTUAL_P.
       TI_PENDING_TEMPLATE_FLAG.
-      TI_PENDING_SPECIALIZATION_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
       DELETE_EXPR_USE_VEC (in DELETE_EXPR).
       (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
@@ -1267,11 +1266,6 @@ struct lang_decl
 #define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE))
 #define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
 
-/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates
-   that the template is a specialization of a member template, but
-   that we don't yet know which one.  */
-#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
-
 /* The TEMPLATE_DECL instantiated or specialized by NODE.  This
    TEMPLATE_DECL will be the immediate parent, not the most general
    template.  For example, in:
index 75538c4a41501d87b49b658b7846b4d776768203..42748ff151666c79f4d3875e90e3cf624b68b59d 100644 (file)
@@ -8016,6 +8016,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
                                            template_count, 
                                            2 * (funcdef_flag != 0) + 
                                            4 * (friendp != 0));
+      if (decl == error_mark_node)
+       return error_mark_node;
 
       if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
          && check)
@@ -8063,6 +8065,9 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
                                            template_count, 
                                            2 * (funcdef_flag != 0) + 
                                            4 * (friendp != 0));
+      if (decl == error_mark_node)
+       return error_mark_node;
+
       if (ctype != NULL_TREE
          && (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
          && check)
@@ -10392,10 +10397,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                if (decl && DECL_NAME (decl))
                  {
                    if (template_class_depth (current_class_type) == 0)
-                     decl 
-                       = check_explicit_specialization 
-                       (declarator, decl,
-                        template_count, 2 * (funcdef_flag != 0) + 4);
+                     {
+                       decl 
+                         = check_explicit_specialization 
+                         (declarator, decl,
+                          template_count, 2 * (funcdef_flag != 0) + 4);
+                       if (decl == error_mark_node)
+                         return error_mark_node;
+                     }
+
                    t = do_friend (ctype, declarator, decl,
                                   last_function_parms, flags, quals,
                                   funcdef_flag);
index c01bda29c432cae2b6b492f86ebeb25654c9f74c..be8689ce189a2c48c2ea3a65824b2257a93a6bc7 100644 (file)
@@ -1606,8 +1606,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
     init = NULL_TREE;
 
   value = grokdeclarator (declarator, declspecs, FIELD, init != 0, NULL_TREE);
-  if (! value)
-    return value; /* friend or constructor went bad.  */
+  if (! value || value == error_mark_node)
+    return NULL_TREE; /* friend or constructor went bad.  */
 
   /* Pass friendly classes back.  */
   if (TREE_CODE (value) == VOID_TYPE)
index b27621b89d0206a34f993a84834b6e39edfe1f4b..04c9fd65fdabfef2d543f57c3487f8b678a01f14 100644 (file)
@@ -127,6 +127,8 @@ static int template_class_depth_real PROTO((tree, int));
 static tree tsubst_aggr_type PROTO((tree, tree, tree, int));
 static tree tsubst_decl PROTO((tree, tree, tree, tree));
 static tree tsubst_arg_types PROTO((tree, tree, tree));
+static void check_specialization_scope PROTO((void));
+static tree process_partial_specialization PROTO((tree));
 
 /* We use TREE_VECs to hold template arguments.  If there is only one
    level of template arguments, then the TREE_VEC contains the
@@ -575,12 +577,44 @@ begin_template_parm_list ()
   note_template_header (0);
 }
 
+/* This routine is called when a specialization is declared.  If it is
+   illegal to declare a specialization here, an error is reported.  */
+
+void
+check_specialization_scope ()
+{
+  tree scope = current_scope ();
+  /* [temp.expl.spec] 
+     
+     An explicit specialization shall be declared in the namespace of
+     which the template is a member, or, for member templates, in the
+     namespace of which the enclosing class or enclosing class
+     template is a member.  An explicit specialization of a member
+     function, member class or static data member of a class template
+     shall be declared in the namespace of which the class template
+     is a member.  */
+  if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
+    cp_error ("explicit specialization in non-namespace scope `%D'",
+             scope);
+  /* [temp.expl.spec] 
+
+     In an explicit specialization declaration for a member of a class
+     template or a member template that appears in namespace scope,
+     the member template and some of its enclosing class templates may
+     remain unspecialized, except that the declaration shall not
+     explicitly specialize a class member template if its enclosing
+     class templates are not explicitly specialized as well.  */
+  if (current_template_parms) 
+    cp_error ("enclosing class templates are not explicit specialized");
+}
+
 /* We've just seen template <>. */
 
 void
 begin_specialization ()
 {
   note_template_header (1);
+  check_specialization_scope ();
 }
 
 /* Called at then end of processing a declaration preceeded by
@@ -1209,17 +1243,10 @@ check_explicit_specialization (declarator, decl, template_count, flags)
       if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype))
        {
          if (!explicit_instantiation)
-           {
-             /* Since finish_struct_1 has not been called yet, we
-                can't call lookup_fnfields.  We note that this
-                template is a specialization, and proceed, letting
-                finish_struct fix this up later.  */
-             tree ti = perm_tree_cons (NULL_TREE, 
-                                       TREE_OPERAND (declarator, 1),
-                                       NULL_TREE);
-             TI_PENDING_SPECIALIZATION_FLAG (ti) = 1;
-             DECL_TEMPLATE_INFO (decl) = ti;
-           }
+           /* A specialization in class scope.  This is illegal,
+              but the error will already have been flagged by
+              check_specialization_scope.  */
+           return error_mark_node;
          else
            /* It's not legal to write an explicit instantiation in
               class scope, e.g.:
@@ -1759,8 +1786,23 @@ build_template_decl (decl, parms)
 
 struct template_parm_data
 {
+  /* The level of the template parameters we are currently
+     processing.  */
   int level;
+
+  /* The index of the specialization argument we are currently
+     processing.  */
+  int current_arg;
+
+  /* An array whose size is the number of template parameters.  The
+     elements are non-zero if the parameter has been used in any one
+     of the arguments processed so far.  */
   int* parms;
+
+  /* An array whose size is the number of template arguments.  The
+     elements are non-zero if the argument makes use of template
+     parameters of this level.  */
+  int* arg_uses_template_parms;
 };
 
 /* Subroutine of push_template_decl used to see if each template
@@ -1790,13 +1832,205 @@ mark_template_parm (t, data)
     }
 
   if (level == tpd->level)
-    tpd->parms[idx] = 1;
+    {
+      tpd->parms[idx] = 1;
+      tpd->arg_uses_template_parms[tpd->current_arg] = 1;
+    }
 
   /* Return zero so that for_each_template_parm will continue the
      traversal of the tree; we want to mark *every* template parm.  */
   return 0;
 }
 
+/* Process the partial specialization DECL.  */
+
+tree
+process_partial_specialization (decl)
+     tree decl;
+{
+  tree type = TREE_TYPE (decl);
+  tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
+  tree specargs = CLASSTYPE_TI_ARGS (type);
+  tree inner_args = innermost_args (specargs);
+  tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+  tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
+  int nargs = TREE_VEC_LENGTH (inner_args);
+  int ntparms = TREE_VEC_LENGTH (inner_parms);
+  int  i;
+  int did_error_intro = 0;
+  int issued_default_arg_message = 0;
+  struct template_parm_data tpd;
+  struct template_parm_data tpd2;
+
+  /* [temp.class.spec]
+     
+     The template parameter list of a specialization shall not
+     contain default template argument values.  */
+  for (i = 0; i < ntparms; ++i) 
+    {
+      if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
+       {
+         if (!issued_default_arg_message)
+           {
+             cp_error ("default argument in partial specialization `%T'", 
+                       type);
+             issued_default_arg_message = 1;
+           }
+         TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
+       }
+    }
+
+  /* We check that each of the template parameters given in the
+     partial specialization is used in the argument list to the
+     specialization.  For example:
+
+       template <class T> struct S;
+       template <class T> struct S<T*>;
+
+     The second declaration is OK because `T*' uses the template
+     parameter T, whereas
+
+       template <class T> struct S<int>;
+
+     is no good.  Even trickier is:
+
+       template <class T>
+       struct S1
+       {
+         template <class U>
+         struct S2;
+         template <class U>
+         struct S2<T>;
+       };
+
+     The S2<T> declaration is actually illegal; it is a
+     full-specialization.  Of course, 
+
+         template <class U>
+         struct S2<T (*)(U)>;
+
+     or some such would have been OK.  */
+  tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
+  tpd.parms = alloca (sizeof (int) * ntparms);
+  bzero (tpd.parms, sizeof (int) * nargs);
+
+  tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs);
+  bzero (tpd.arg_uses_template_parms, sizeof (int) * nargs);
+  for (i = 0; i < nargs; ++i)
+    {
+      tpd.current_arg = i;
+      for_each_template_parm (TREE_VEC_ELT (inner_args, i),
+                             &mark_template_parm,
+                             &tpd);
+    }
+  for (i = 0; i < ntparms; ++i)
+    if (tpd.parms[i] == 0)
+      {
+       /* One of the template parms was not used in the
+           specialization.  */
+       if (!did_error_intro)
+         {
+           cp_error ("template parameters not used in partial specialization:");
+           did_error_intro = 1;
+         }
+
+       cp_error ("        `%D'", 
+                 TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
+      }
+
+  /* [temp.class.spec]
+
+     The argument list of the specialization shall not be identical to
+     the implicit argument list of the primary template.  */
+  if (comp_template_args (inner_args, 
+                         innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE
+                                                            (maintmpl)))))
+    cp_error ("partial specialization `%T' does not specialize any template arguments", type);
+
+  /* [temp.class.spec]
+
+     A partially specialized non-type argument expression shall not
+     involve template parameters of the partial specialization except
+     when the argument expression is a simple identifier.
+
+     The type of a template parameter corresponding to a specialized
+     non-type argument shall not be dependent on a parameter of the
+     specialization.  */
+  my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0);
+  tpd2.parms = 0;
+  for (i = 0; i < nargs; ++i)
+    {
+      tree arg = TREE_VEC_ELT (inner_args, i);
+      if (/* These first two lines are the `non-type' bit.  */
+         TREE_CODE_CLASS (TREE_CODE (arg)) != 't'
+         && TREE_CODE (arg) != TEMPLATE_DECL
+         /* This next line is the `argument expression is not just a
+            simple identifier' condition and also the `specialized
+            non-type argument' bit.  */
+         && TREE_CODE (arg) != TEMPLATE_PARM_INDEX)
+       {
+         if (tpd.arg_uses_template_parms[i])
+           cp_error ("template argument `%E' involves template parameter(s)", arg);
+         else 
+           {
+             /* Look at the corresponding template parameter,
+                marking which template parameters its type depends
+                upon.  */
+             tree type = 
+               TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms, 
+                                                    i)));
+
+             if (!tpd2.parms)
+               {
+                 /* We haven't yet initialized TPD2.  Do so now.  */
+                 tpd2.arg_uses_template_parms 
+                   =  (int*) alloca (sizeof (int) * nargs);
+                 tpd2.parms = (int*) alloca (sizeof (int) * nargs);
+                 tpd2.level = 
+                   TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
+               }
+
+             /* Mark the template paramters.  But this time, we're
+                looking for the template parameters of the main
+                template, not in the specialization.  */
+             tpd2.current_arg = i;
+             tpd2.arg_uses_template_parms[i] = 0;
+             bzero (tpd.parms, sizeof (int) * nargs);
+             for_each_template_parm (type,
+                                     &mark_template_parm,
+                                     &tpd2);
+                 
+             if (tpd2.arg_uses_template_parms [i])
+               {
+                 /* The type depended on some template parameters.
+                    If they are fully specialized in the
+                    specialization, that's OK.  */
+                 int j;
+                 for (j = 0; j < nargs; ++j)
+                   if (tpd2.parms[j] != 0
+                       && tpd.arg_uses_template_parms [j])
+                     {
+                       cp_error ("type `%T' of template argument `%E' depends on template paramter(s)", 
+                                 type,
+                                 arg);
+                       break;
+                     }
+               }
+           }
+       }
+    }
+
+  if (retrieve_specialization (maintmpl, specargs))
+    /* We've already got this specialization.  */
+    return decl;
+
+  DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
+    = perm_tree_cons (inner_args, inner_parms,
+                     DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
+  TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+  return decl;
+}
+
 /* Creates a TEMPLATE_DECL for the indicated DECL using the template
    parameters given by current_template_args, or reuses a
    previously existing one, if appropriate.  Returns the DECL, or an
@@ -1868,92 +2102,7 @@ push_template_decl_real (decl, is_friend)
   if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
       && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
       && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
-    {
-      tree type = TREE_TYPE (decl);
-      tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
-      tree specargs = CLASSTYPE_TI_ARGS (type);
-
-      /* We check that each of the template parameters given in the
-        partial specialization is used in the argument list to the
-        specialization.  For example:
-        
-          template <class T> struct S;
-          template <class T> struct S<T*>;
-
-        The second declaration is OK because `T*' uses the template
-        parameter T, whereas
-       
-           template <class T> struct S<int>;
-
-        is no good.  Even trickier is:
-
-          template <class T>
-          struct S1
-          {
-             template <class U>
-             struct S2;
-             template <class U>
-             struct S2<T>;
-          };
-          
-        The S2<T> declaration is actually illegal; it is a
-        full-specialization.  Of course, 
-
-              template <class U>
-              struct S2<T (*)(U)>;
-
-         or some such would have been OK.  */
-      int  i;
-      struct template_parm_data tpd;
-      int ntparms 
-       = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (current_template_parms));
-      int did_error_intro = 0;
-
-      tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
-      tpd.parms = alloca (sizeof (int) * ntparms);
-      for (i = 0; i < ntparms; ++i)
-       tpd.parms[i] = 0;
-      for (i = 0; i < TREE_VEC_LENGTH (specargs); ++i)
-       for_each_template_parm (TREE_VEC_ELT (specargs, i),
-                               &mark_template_parm,
-                               &tpd);
-      for (i = 0; i < ntparms; ++i)
-       if (tpd.parms[i] == 0)
-         {
-           /* One of the template parms was not used in the
-              specialization.  */
-           if (!did_error_intro)
-             {
-               cp_error ("template parameters not used in partial specialization:");
-               did_error_intro = 1;
-             }
-
-           cp_error ("        `%D'", 
-                     TREE_VALUE (TREE_VEC_ELT 
-                                 (TREE_VALUE (current_template_parms),
-                                  i)));
-         }
-
-      /* [temp.class.spec]
-
-        The argument list of the specialization shall not be
-        identical to the implicit argument list of the primary
-        template.  */
-      if (comp_template_args (specargs, 
-                             CLASSTYPE_TI_ARGS (TREE_TYPE (maintmpl))))
-       cp_error ("partial specialization `%T' does not specialize any template arguments", type);
-                          
-      if (retrieve_specialization (maintmpl, specargs))
-       /* We've already got this specialization.  */
-       return decl;
-
-      DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
-       = perm_tree_cons (innermost_args (specargs),
-                         INNERMOST_TEMPLATE_PARMS (current_template_parms),
-                         DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
-      TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
-      return decl;
-    }
+    return process_partial_specialization (decl);
 
   args = current_template_args ();
 
@@ -5194,7 +5343,6 @@ tsubst_decl (t, args, type, in_decl)
   return r;
 }
 
-
 /* Substitue into the ARG_TYPES of a function type.  */
 
 tree
@@ -5204,7 +5352,6 @@ tsubst_arg_types (arg_types, args, in_decl)
      tree in_decl;
 {
   tree remaining_arg_types;
-  tree result;
   tree type;
 
   if (!arg_types || arg_types == void_list_node)
index 89aca96b8d94cf6416de828c01ac27e09946cf55..eee6616698e05dcaec977b0f70440094ec4c2373 100644 (file)
@@ -1234,9 +1234,9 @@ begin_class_definition (t)
       && TREE_CODE (TYPE_CONTEXT (t)) != NAMESPACE_DECL
       && ! current_class_type)
     push_template_decl (TYPE_STUB_DECL (t));
+  maybe_process_partial_specialization (t);
   pushclass (t, 0);
   TYPE_BEING_DEFINED (t) = 1;
-  maybe_process_partial_specialization (t);
   /* Reset the interface data, at the earliest possible
      moment, as it might have been set via a class foo;
      before.  */
index 83ebcc16cc7879dfe87183f94c3e33aa45e8f11f..0defb196116e475b8ace8bfea6932547a17c6b9c 100644 (file)
@@ -5,11 +5,13 @@ struct S
 {
   template <class T>
   void foo(T t);
-
-  template <>
-  void foo<int>(int) {}
 };
 
+
+template <>
+template <>
+void S<char*>::foo<int>(int) {}
+
 int main()
 {
   S<char*> s;
index 73e0e19e85f06242a287f4b451ac100ccdc4a7b2..fbb790130385c6d578dd2c9310a8c5916309ceae 100644 (file)
@@ -7,13 +7,14 @@ struct S
   template <class T>
   void foo(T t);
 
-  template <>
-  void foo(int) { }
-
   template <class T>
   void bar(T t) { this->template foo<U>(3.74); }
 };
 
+template <>
+template <>
+void S<int>::foo(int) { }
+
 int main()
 {
   S<int> s;
index 9f7144274592d2fb5d2b708d39eb8b33e94a4744..c9282632aa182938a97cd0433ba362cf09577004 100644 (file)
@@ -4,11 +4,11 @@ struct S
 {
   template <class T>
   void foo(T t);
-
-  template <>
-  void foo<int>(int i) { }
 };
 
+template <>
+void S::foo<int>(int i) { }
+
 int main()
 {
   S s;
index 08166b0220de22b6c29d5273fe604ba1d30d5e02..1a5cabe67a158e11b3e1afde45df101d2938efe3 100644 (file)
@@ -4,12 +4,13 @@ struct S
   struct Y {
     template <class T>
     void foo(T t);
-
-    template <>
-    void foo<int>(int i) { }
   };
 };
 
+template <>
+template <>
+void S::Y<char>::foo<int>(int i) { }
+
 int main()
 {
   S::Y<char> s;
index d67da394c3e9a889fdd0c76d201981545ba91d54..1fdb055b3574a94d70ca5f6f5a05538781ab446b 100644 (file)
@@ -4,9 +4,6 @@ struct S
 {
   template <class T>
   void foo(T t);
-  
-  template <>
-  void foo(int i);
 };
 
 
index 2efd4d6d73c9b28eefda1b4b0d5082c0820d6b7d..8cfadeffd3ec82fd8b4b92474d7e2ba436194af9 100644 (file)
@@ -4,9 +4,6 @@ struct S
 {
   template <class T>
   void foo(T t);
-  
-  template <>
-  void foo(int i);
 };
 
 
index e6f62cfa38d71003ffb90fd27f80a216c2407e63..ca4cf20e7dfb75831741d07f6b9f56cbcf5658ca 100644 (file)
@@ -7,9 +7,9 @@ struct S3
   static char* h(U);
 };
 
-template <class T>
 template <>
-char* S3<T>::h(int) { return __PRETTY_FUNCTION__; }
+template <>
+char* S3<double>::h(int) { return __PRETTY_FUNCTION__; }
 
 template <>
 template <>
index 10947aa8e8cfed7ba5429e5370bc39eaeb312e29..5d53e2d76b1ddbd268cd8f7f1b5a97c6489a1f74 100644 (file)
@@ -5,14 +5,15 @@ struct S
 {
   template <int i>
   int f(int j) { abort(); return 0; }
-
-  template <>
-  int f<7>(int j) { return j + 7; }
-
-  template <>
-  int f<8>(int j) { return j + 8; }
 };
 
+template <>
+template <>
+int S<double>::f<7>(int j) { return j + 7; }
+
+template <>
+template <>
+int S<double>::f<8>(int j) { return j + 8; }
 
 int main()
 {
index 4369f18f15abf5c7fd99ad9fe4231ce2738479cb..340b58e73ec5f0fef4f0eece790d49fa26fcc5d3 100644 (file)
@@ -7,9 +7,9 @@ struct S
   int f(U u);
 };
 
-template <class T>
 template <>
-int S<T>::f(int i) { return 1; }
+template <>
+int S<char>::f(int i) { return 1; }
 
 int main()
 {
index 71676ff6cbcef2f38a07c949955aac2184e4593d..d9c39654e93a59838115d50e518bcbf7ee6d7c3e 100644 (file)
@@ -8,9 +8,9 @@ struct S
 };
 
 
-template <class T>
 template <>
-int S<T>::f<int>(int i) { return 1; }
+template <>
+int S<char>::f<int>(int i) { return 1; }
 
 int main()
 {
index 8f94570db8482d10f22332d54abdc15f48aed9fd..e5748f56c14ed373a38dc6137b23c3ca18552ce6 100644 (file)
@@ -14,11 +14,11 @@ struct S1
 
   template <class T>
   void f(T* t);
-
-  template <>
-  void f(int* ip) {}
 };
 
+template <>
+void S1::f(int* ip) {}
+
 template <class U>
 struct S2
 {
@@ -27,11 +27,12 @@ struct S2
 
   template <class T>
   void f(T* t);
-
-  template <>
-  void f(int* ip) {}
 };
 
+template <>
+template <>
+void S2<double>::f(int* ip) {}
+
 int main()
 {
   int* ip;
index 0aec14336af8e8d023e2e8f8682138c5b9a507ce..2e97b04626534f6c80f592f434e63d84c828e0e2 100644 (file)
@@ -28,9 +28,9 @@ struct S3
   static int h(U);
 };
 
-template <class T>
 template <>
-int S3<T>::h(int) { return 0; }
+template <>
+int S3<double>::h(int) { return 0; }
 
 template <>
 template <>
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
new file mode 100644 (file)
index 0000000..497a32d
--- /dev/null
@@ -0,0 +1,11 @@
+// Build don't link:
+
+template <class T> 
+struct S {
+  template <class U> void f(U);
+  template <> void f<int>(int); // ERROR - specialization
+
+  template <class V> struct I {};
+  template <class V> struct I<V*> {};
+  template <> struct I<int>; // ERROR - specialization
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec21.C b/gcc/testsuite/g++.old-deja/g++.pt/spec21.C
new file mode 100644 (file)
index 0000000..95e12d2
--- /dev/null
@@ -0,0 +1,16 @@
+// Build don't link:
+
+template <class T> struct S {};
+template <class T = int> struct S<T*> {}; // ERROR - default argument
+
+template <int I, int J> struct A {};
+template <int I> struct A<I+5, I*2> {}; // ERROR - argument involves parameter
+
+template <class T, T t> struct C {};
+template <class T> struct C<T, 1>;  // ERROR - type depends on parameter
+int i;
+template <class T> struct C<T*, &i>; // ERROR - type depends on parameter
+
+template< int X, int (*array_ptr)[X] > class B {};
+int array[5];
+template< int X > class B<X,&array> { }; // ERROR - type depends on parameter
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec22.C b/gcc/testsuite/g++.old-deja/g++.pt/spec22.C
new file mode 100644 (file)
index 0000000..88d55d3
--- /dev/null
@@ -0,0 +1,15 @@
+// Build don't link:
+
+template <class T>
+struct S
+{
+  template <class U>
+  void f();
+};
+
+
+template <class T> 
+template <> // ERROR - enclosing classes not specialized
+void S<T>::f<int> () 
+{
+}
index b41ad9d8da685dc7caeba2b8bb1bcabb238f73b1..4ef8e651594a1a95fffbedf57845b097647d34ef 100644 (file)
@@ -4,21 +4,23 @@ struct S1
 {
   template <class T>
   void f(T t1, T t2);
-
-  template <>
-  void f(int i1, int i2);
 };
 
+
+template <>
+void S1::f(int i1, int i2);
+
 template <class U>
 struct S2
 {
   template <class T>
   void f(T t1, T t2);
-
-  template <>
-  void f(int i1, int i2);
 };
 
+template <>
+template <>
+void S2<char>::f(int i1, int i2);
+
 void h()
 {
   S1 s1;