Support partial specialization of member class templates.
authorJason Merrill <jason@yorick.cygnus.com>
Fri, 27 Feb 1998 12:15:17 +0000 (12:15 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 27 Feb 1998 12:15:17 +0000 (07:15 -0500)
* pt.c (get_class_bindings): Add outer_args parm.
(most_specialized_class): Likewise.
(instantiate_class_template): Pass it.
(more_specialized_class): Likewise.
(lookup_template_class): Get context from template if none
was specified.
(finish_member_template_decl): Don't do anything with a
partial specialization.
* decl2.c (check_member_template): Use IS_AGGR_TYPE instead of
AGGREGATE_TYPE_P.
* class.c (finish_struct): Member class templates have already been
checked for name clashes.
* decl.c (pushdecl_with_scope): Handle pushing at class level.

From-SVN: r18285

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c

index 319136f50c8c2aedfa6d9fa5c84353e8c5dfa09c..136a71ae3779f27f386784eb86950b9ec9370d95 100644 (file)
@@ -1,3 +1,19 @@
+Fri Feb 27 11:17:50 1998  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (get_class_bindings): Add outer_args parm.
+       (most_specialized_class): Likewise.
+       (instantiate_class_template): Pass it.
+       (more_specialized_class): Likewise.
+       (lookup_template_class): Get context from template if none
+       was specified.
+       (finish_member_template_decl): Don't do anything with a
+       partial specialization.
+       * decl2.c (check_member_template): Use IS_AGGR_TYPE instead of
+       AGGREGATE_TYPE_P.
+       * class.c (finish_struct): Member class templates have already been
+       checked for name clashes.
+       * decl.c (pushdecl_with_scope): Handle pushing at class level.
+
 Fri Feb 27 02:25:16 1998  Jason Merrill  <jason@yorick.cygnus.com>
 
        * pt.c (tsubst, TEMPLATE_DECL): Support member class templates.
index 9868928b70631c9915f25ebf844a8e12dac115ec..6d64e982a509069c69c5aff6d2bc3cac4d0a9a1f 100644 (file)
@@ -4375,6 +4375,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
          /* Check for inconsistent use of this name in the class body.
              Enums, types and static vars have already been checked.  */
          if (TREE_CODE (x) != TYPE_DECL && TREE_CODE (x) != USING_DECL
+             && ! (TREE_CODE (x) == TEMPLATE_DECL
+                   && TREE_CODE (DECL_RESULT (x)) == TYPE_DECL)
              && TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
            {
              tree name = DECL_NAME (x);
index 9f96b4af0a5da68b76bf5f624c2260bdccd9e01e..eedf3e2800074440561b9cb0479b964ff311cb83 100644 (file)
@@ -2458,7 +2458,7 @@ extern void end_tree                            PROTO((void));
 extern void add_maybe_template                 PROTO((tree, tree));
 extern void pop_tinst_level                    PROTO((void));
 extern tree most_specialized                   PROTO((tree, tree, tree));
-extern tree most_specialized_class             PROTO((tree, tree));
+extern tree most_specialized_class             PROTO((tree, tree, tree));
 extern int more_specialized_class              PROTO((tree, tree));
 extern void do_pushlevel                       PROTO((void));
 extern int is_member_template                   PROTO((tree));
index 0002891352bcd0c303e6c44eb05e8086dda63f2b..b61d44a7e376c896c2e7692e4b2fead1c9237853 100644 (file)
@@ -3503,13 +3503,24 @@ pushdecl_with_scope (x, level)
      tree x;
      struct binding_level *level;
 {
-  register struct binding_level *b = current_binding_level;
+  register struct binding_level *b;
   tree function_decl = current_function_decl;
 
   current_function_decl = NULL_TREE;
-  current_binding_level = level;
-  x = pushdecl (x);
-  current_binding_level = b;
+  if (level->parm_flag == 2)
+    {
+      b = class_binding_level;
+      class_binding_level = level;
+      pushdecl_class_level (x);
+      class_binding_level = b;
+    }
+  else
+    {
+      b = current_binding_level;
+      current_binding_level = level;
+      x = pushdecl (x);
+      current_binding_level = b;
+    }
   current_function_decl = function_decl;
   return x;
 }
index cb786f91c03a922c9a3bb454735fc68b1c6be83a..fa39b9e4b8ddebdb03460c32dcc89c4714bc86ed 100644 (file)
@@ -1386,8 +1386,8 @@ check_member_template (tmpl)
         with member templates.  */ 
       DECL_IGNORED_P (tmpl) = 1;
     } 
-  else if (TREE_CODE (decl) == TYPE_DECL &&
-          AGGREGATE_TYPE_P (TREE_TYPE (decl)))
+  else if (TREE_CODE (decl) == TYPE_DECL
+          && IS_AGGR_TYPE (TREE_TYPE (decl)))
     {
       if (current_function_decl)
        /* 14.5.2.2 [temp.mem]
index fe66bf43b47cf9b05c8d8601c351c4753d11ee9c..d5362aae34bf5e2ae8652b72c447727926ae6cb7 100644 (file)
@@ -77,7 +77,7 @@ static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree));
 static tree tsubst_expr_values PROTO((tree, tree));
 static int comp_template_args PROTO((tree, tree));
 static int list_eq PROTO((tree, tree));
-static tree get_class_bindings PROTO((tree, tree, tree));
+static tree get_class_bindings PROTO((tree, tree, tree, tree));
 static tree coerce_template_parms PROTO((tree, tree, tree, int, int, int));
 static tree tsubst_enum        PROTO((tree, tree, tree *));
 static tree add_to_template_args PROTO((tree, tree));
@@ -109,12 +109,14 @@ finish_member_template_decl (template_parameters, decl)
     {
       /* Assume that the class is the only declspec.  */
       decl = TREE_VALUE (decl);
-      if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl))
+      if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl)
+         && ! CLASSTYPE_TEMPLATE_SPECIALIZATION (decl))
        {
          tree tmpl = CLASSTYPE_TI_TEMPLATE (decl);
          check_member_template (tmpl);
          return tmpl;
        }
+      return NULL_TREE;
     }
   else if (DECL_TEMPLATE_INFO (decl) &&
           !DECL_TEMPLATE_SPECIALIZATION (decl))
@@ -2380,6 +2382,8 @@ lookup_template_class (d1, arglist, in_decl, context)
          if (! template)
            template = IDENTIFIER_CLASS_VALUE (d1);
        }
+      if (template)
+       context = DECL_CONTEXT (template);
     }
   else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
     {
@@ -2938,7 +2942,7 @@ instantiate_class_template (type)
      tree type;
 {
   tree template, template_info, args, pattern, t, *field_chain;
-  tree typedecl;
+  tree typedecl, outer_args;
 
   if (type == error_mark_node)
     return error_mark_node;
@@ -2954,14 +2958,15 @@ instantiate_class_template (type)
 
   if (DECL_TEMPLATE_INFO (template))
     {
-      args = add_to_template_args (DECL_TI_ARGS (template), args);
+      outer_args = DECL_TI_ARGS (template);
       while (DECL_TEMPLATE_INFO (template))
        template = DECL_TI_TEMPLATE (template);
     }
+  else
+    outer_args = NULL_TREE;
 
-  /* FIXME deal with partial specializations of member templates.  */
   t = most_specialized_class
-    (DECL_TEMPLATE_SPECIALIZATIONS (template), args);
+    (DECL_TEMPLATE_SPECIALIZATIONS (template), args, outer_args);
 
   if (t == error_mark_node)
     {
@@ -2969,7 +2974,8 @@ instantiate_class_template (type)
       cp_error ("ambiguous class template instantiation for `%#T'", type);
       for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
        {
-         if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
+         if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+                                 args, outer_args))
            {
              cp_error_at ("%s %+#T", str, TREE_TYPE (t));
              str = "               ";
@@ -2987,7 +2993,11 @@ instantiate_class_template (type)
     return type;
 
   if (t)
-    args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
+    args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+                              args, outer_args);
+
+  if (outer_args)
+    args = add_to_template_args (outer_args, args);
 
   if (pedantic && uses_template_parms (args))
     /* If there are still template parameters amongst the args, then
@@ -3617,7 +3627,7 @@ tsubst (t, args, in_decl)
        if (PRIMARY_TEMPLATE_P (t))
          TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl;
 
-       /* FIXME deal with partial specializations.  */
+       /* We don't partially instantiate partial specializations.  */
        if (TREE_CODE (decl) == TYPE_DECL)
          return tmpl;
 
@@ -5651,12 +5661,14 @@ more_specialized_class (pat1, pat2)
   int winner = 0;
 
   targs = get_class_bindings
-    (TREE_VALUE (pat1), TREE_PURPOSE (pat1), TREE_PURPOSE (pat2));
+    (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
+     TREE_PURPOSE (pat2), NULL_TREE);
   if (targs)
     --winner;
 
   targs = get_class_bindings
-    (TREE_VALUE (pat2), TREE_PURPOSE (pat2), TREE_PURPOSE (pat1));
+    (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
+     TREE_PURPOSE (pat1), NULL_TREE);
   if (targs)
     ++winner;
 
@@ -5718,12 +5730,18 @@ get_bindings (fn, decl, explicit_args)
 }
 
 static tree
-get_class_bindings (tparms, parms, args)
-     tree tparms, parms, args;
+get_class_bindings (tparms, parms, args, outer_args)
+     tree tparms, parms, args, outer_args;
 {
   int i, dummy, ntparms = TREE_VEC_LENGTH (tparms);
   tree vec = make_temp_vec (ntparms);
 
+  if (outer_args)
+    {
+      tparms = tsubst (tparms, outer_args, NULL_TREE);
+      parms = tsubst (parms, outer_args, NULL_TREE);
+    }
+
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
     {
       switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms,
@@ -5803,15 +5821,16 @@ most_specialized (fns, decl, explicit_args)
    SPECS that can produce an instantiation matching ARGS.  */
 
 tree
-most_specialized_class (specs, mainargs)
-     tree specs, mainargs;
+most_specialized_class (specs, mainargs, outer_args)
+     tree specs, mainargs, outer_args;
 {
   tree list = NULL_TREE, t, args, champ;
   int fate;
 
   for (t = specs; t; t = TREE_CHAIN (t))
     {
-      args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), mainargs);
+      args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+                                mainargs, outer_args);
       if (args)
        {
          list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);