]> gcc.gnu.org Git - gcc.git/commitdiff
class.c (grow_method): Remove check for redeclaration.
authorJason Merrill <jason@gcc.gnu.org>
Sat, 6 Sep 1997 08:10:07 +0000 (04:10 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 6 Sep 1997 08:10:07 +0000 (04:10 -0400)
* class.c (grow_method): Remove check for redeclaration.

Fri Sep  5 01:37:17 1997  Mark Mitchell  <mmitchell@usa.net>

* cp-tree.h (INNERMOST_TEMPLATE_PARMS): New macro.
(DECL_INNERMOST_TEMPLATE_PARMS): Likewise.
(PRIMARY_TEMPLATE_P): Use it.
* call.c (build_overload_call_real): Use it.
* class.c (instantiate_type): Likewise.
* decl.c (decls_match): Likewise.
* method.c (build_overload_identifier): Likewise.
* pt.c (push_template_decl): Likewise.
(classtype_mangled_name): Likewise.
(lookup_template_class): Likewise.

* cp-tree.h (DECL_NTPARMS): Change name from DECL_NT_PARMS to
DECL_NTPARMS to conform to usage elsewhere.
* call.c (add_template_candidate): Likewise.
* class.c (instantiate_type): Likewise.
* pt.c (instantiate_template): Likewise.
(get_bindings): Likewise.

* class.c (grow_method): Use DECL_FUNCTION_TEMPLATE_P instead of
is_member_template.

* pt.c (unify): Undo changes to allow multiple levels of template
parameters.
(type_unification): Likewise.
(fn_type_unification): Likewise.
(get_class_bindings): Likewise.
* cp-tree.h (Likewise).

* decl.c (replace_defarg): Check that the type of the default
parameter does not invlove a template type before complaining
about the initialization.

* error.c (dump_expr): Deal with template constant parameters in
member templates correctly.

* pt.c (is_member_template): Deal with class specializations
correctly.
(tsubst): Handle "partial instantiation" of member templates
correctly.

Wed Sep  3 12:30:24 1997  Mark Mitchell  <mmitchell@usa.net>

* pt.c (type_unification): Change calling squence to allow for
multiple levels of template parameters.
(tsubst_expr): Likewise.
(tsubst): Likewise.
(tsubst_copy): Likewise.
(instantiate_template): Likewise.
(unify): Likewise.
* call.c (build_overload_call_real): Use it.
(add_builtin_candidate): Use it.
(build_new_method_call): Use it.
* class.c (instantiate_type): Use it.
* decl.c (grokdeclarator): Use it.
* decl2.c (finish_file): Use it.
* method.c (build_overload_identifier): Use it.

* call.c (add_template_candidate):  Add additional parameter for
the function return type.  Call fn_type_unification istead of
type_unification.
(build_user_type_conversion_1): Handle member templates.
(build_new_function_call): Likewise.
(build_new_op): Likewise.
(build_new_method_call): Likewise.

* class.c (grow_method): Don't give an error message indicating
  that two member templates with the same name are ambiguous.
(finish_struct): Treat member template functions just like member
  functions.

* cp-tree.h (check_member_template): Add declaration.
(begin_member_template_processing): Likewise.
(end_member_template_processing): Likewise.
(fn_type_unification): Likewise.
(is_member_template): Likewise.
(tsubst): Change prototype.
(tsubst_expr): Likewise.
(tsubst_copy): Likewise.
(instantiate_template): Likewise.
(get_bindings): Likewise.

* decl.c (decls_match): Handle multiple levels of template
parameters.
(pushdecl): Handle template type params just like other type
declarations.
(push_class_level_binding): Return immediately if the
class_binding_level is NULL.
(grokfndecl): If check_classfn() returns a member_template, use
the result of the template, not the template itself.

* decl2.c (check_member_template): New function.  Check to see
that the entity declared to be a member template can be one.
(check_classfn): Allow redeclaration of member template functions
with different types; the new functions can be specializations or
explicit instantiations.

* error.c (dump_decl): Handle multiple levels of template
parameters.
(dump_function_decl): Update to handle function templates.

* lex.c (do_pending_inlines): Set up template parameter context
for member templates.
(process_next_inline): Likewise.

* method. (build_overload_identifier): Adjust for multiple levels
of template parameters.

* parse.y (fn.def2): Add member templates.
(component_decl_1): Likewise.

* pt.c (begin_member_template_processing): New function.
(end_member_template_processing): Likewise.
(is_member_template): Likewise.
(fn_type_unification): Likewise.
(current_template_parms): Return a vector of all the template
parms, not just the innermost level of parms.
(push_template_decl): Deal with the possibility of member
templates.
(lookup_template_class): Likewise.
(uses_template_parms): Likewise.
(tsubst): Modify processing to TEMPLATE_TYPE_PARM and
TEMPLATE_CONST_PARM to deal with multiple levels of template
arguments.   Add processing of TEMPLATE_DECL to produce new
TEMPLATE_DECLs from old ones.
(do_decl_instantiation): Handle member templates.

* search.c (lookup_fnfields_1): Handle member template conversion
operators.

* tree.c (cp_tree_equal): Check the levels, as well as the
indices, of TEMPLATE_CONST_PARMs.

* typeck.c (comptypes): Check the levels, as well as the indices,
fo TEMPLATE_TYPE_PARMs.
(build_x_function_call): Treat member templates like member
functions.

Member templates.

From-SVN: r15130

15 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/tree.c
gcc/cp/typeck.c

index 21f2c6c982ea5860d296ff60bf2e3c056f9ccc02..effd43423c1d859a996dde963235e4764468e87a 100644 (file)
@@ -1,3 +1,104 @@
+Fri Sep  5 17:27:38 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * class.c (grow_method): Remove check for redeclaration.
+
+Wed Sep  3 12:30:24 1997  Mark Mitchell  <mmitchell@usa.net>
+
+       * pt.c (type_unification): Change calling squence to allow for
+       multiple levels of template parameters.
+       (tsubst_expr): Likewise.
+       (tsubst): Likewise.
+       (tsubst_copy): Likewise.
+       (instantiate_template): Likewise.
+       (unify): Likewise.
+       * call.c (build_overload_call_real): Use it.
+       (add_builtin_candidate): Use it.
+       (build_new_method_call): Use it.
+       * class.c (instantiate_type): Use it.
+       * decl.c (grokdeclarator): Use it.
+       * decl2.c (finish_file): Use it.
+       * method.c (build_overload_identifier): Use it.
+       
+       * call.c (add_template_candidate):  Add additional parameter for
+       the function return type.  Call fn_type_unification istead of
+       type_unification.
+       (build_user_type_conversion_1): Handle member templates.
+       (build_new_function_call): Likewise.
+       (build_new_op): Likewise.
+       (build_new_method_call): Likewise.
+       
+       * class.c (grow_method): Don't give an error message indicating
+       that two member templates with the same name are ambiguous.
+       (finish_struct): Treat member template functions just like member
+       functions.
+       
+       * cp-tree.h (check_member_template): Add declaration.
+       (begin_member_template_processing): Likewise.
+       (end_member_template_processing): Likewise.
+       (fn_type_unification): Likewise.
+       (is_member_template): Likewise.
+       (tsubst): Change prototype.
+       (tsubst_expr): Likewise.
+       (tsubst_copy): Likewise.
+       (instantiate_template): Likewise.
+       (get_bindings): Likewise.
+
+       * decl.c (decls_match): Handle multiple levels of template
+       parameters. 
+       (pushdecl): Handle template type params just like other type
+       declarations. 
+       (push_class_level_binding): Return immediately if the
+       class_binding_level is NULL.
+       (grokfndecl): If check_classfn() returns a member_template, use
+       the result of the template, not the template itself.
+       
+       * decl2.c (check_member_template): New function.  Check to see
+       that the entity declared to be a member template can be one.
+       (check_classfn): Allow redeclaration of member template functions
+       with different types; the new functions can be specializations or
+       explicit instantiations.
+       
+       * error.c (dump_decl): Handle multiple levels of template
+       parameters. 
+       (dump_function_decl): Update to handle function templates.
+
+       * lex.c (do_pending_inlines): Set up template parameter context
+       for member templates.
+       (process_next_inline): Likewise.
+
+       * method. (build_overload_identifier): Adjust for multiple levels
+       of template parameters.
+       
+       * parse.y (fn.def2): Add member templates.
+       (component_decl_1): Likewise.
+
+       * pt.c (begin_member_template_processing): New function.
+       (end_member_template_processing): Likewise.
+       (is_member_template): Likewise.
+       (fn_type_unification): Likewise.
+       (current_template_parms): Return a vector of all the template
+       parms, not just the innermost level of parms.
+       (push_template_decl): Deal with the possibility of member
+       templates. 
+       (lookup_template_class): Likewise.
+       (uses_template_parms): Likewise.
+       (tsubst): Modify processing to TEMPLATE_TYPE_PARM and
+       TEMPLATE_CONST_PARM to deal with multiple levels of template
+       arguments.   Add processing of TEMPLATE_DECL to produce new
+       TEMPLATE_DECLs from old ones.
+       (do_decl_instantiation): Handle member templates.
+
+       * search.c (lookup_fnfields_1): Handle member template conversion
+       operators. 
+
+       * tree.c (cp_tree_equal): Check the levels, as well as the
+       indices, of TEMPLATE_CONST_PARMs.
+
+       * typeck.c (comptypes): Check the levels, as well as the indices,
+       fo TEMPLATE_TYPE_PARMs.
+       (build_x_function_call): Treat member templates like member
+       functions. 
+       
 Wed Sep  3 11:09:25 1997  Jason Merrill  <jason@yorick.cygnus.com>
 
        * typeck.c (c_expand_return): Always convert_for_initialization
index b30f78fcd4a0b00298da79399370987b768cc38c..06316143a2ba35acb5138fc137a6de6233cdc334 100644 (file)
@@ -77,7 +77,7 @@ static tree build_this PROTO((tree));
 static struct z_candidate * splice_viable PROTO((struct z_candidate *));
 static int any_viable PROTO((struct z_candidate *));
 static struct z_candidate * add_template_candidate
-       PROTO((struct z_candidate *, tree, tree, int));
+       PROTO((struct z_candidate *, tree, tree, tree, int));
 static struct z_candidate * add_builtin_candidates
        PROTO((struct z_candidate *, enum tree_code, enum tree_code,
               tree, tree *, int));
@@ -2838,11 +2838,12 @@ build_overload_call_real (fnname, parms, flags, final_cp, require_complete)
        }
       if (TREE_CODE (function) == TEMPLATE_DECL)
        {
-         int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (function));
-         tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
+         int ntparms = DECL_NTPARMS (function);
+         tree targs = make_tree_vec (ntparms);
          int i;
 
-         i = type_unification (DECL_TEMPLATE_PARMS (function), targs,
+         i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (function),
+                               &TREE_VEC_ELT (targs, 0),
                                TYPE_ARG_TYPES (TREE_TYPE (function)),
                                parms, &template_cost, 0, 0);
          if (i == 0)
@@ -4144,20 +4145,19 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
 }
 
 static struct z_candidate *
-add_template_candidate (candidates, tmpl, arglist, flags)
+add_template_candidate (candidates, tmpl, arglist, return_type, flags)
      struct z_candidate *candidates;
-     tree tmpl, arglist;
+     tree tmpl, arglist, return_type;
      int flags;
 {
-  int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
-  tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
+  int ntparms = DECL_NTPARMS (tmpl);
+  tree targs = make_tree_vec (ntparms);
   struct z_candidate *cand;
-  int i, dummy = 0;
+  int i;
   tree fn;
 
-  i = type_unification (DECL_TEMPLATE_PARMS (tmpl), targs,
-                       TYPE_ARG_TYPES (TREE_TYPE (tmpl)),
-                       arglist, &dummy, 0, 0);
+  i = fn_type_unification (tmpl, targs, arglist, return_type, 0);
+
   if (i != 0)
     return candidates;
 
@@ -4253,6 +4253,7 @@ build_user_type_conversion_1 (totype, expr, flags)
   tree fromtype = TREE_TYPE (expr);
   tree ctors = NULL_TREE, convs = NULL_TREE, *p;
   tree args;
+  tree templates = NULL_TREE;
 
   if (IS_AGGR_TYPE (totype))
     ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
@@ -4279,9 +4280,22 @@ build_user_type_conversion_1 (totype, expr, flags)
       if (DECL_NONCONVERTING_P (ctors))
        continue;
 
-      candidates = add_function_candidate (candidates, ctors, args, flags);
-      candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
-      candidates->basetype_path = TYPE_BINFO (totype);
+      if (TREE_CODE (ctors) == TEMPLATE_DECL) 
+       {
+         templates = decl_tree_cons (NULL_TREE, ctors, templates);
+         candidates = 
+           add_template_candidate (candidates, ctors,
+                                   args, NULL_TREE, flags);
+       } 
+      else 
+       candidates = add_function_candidate (candidates, ctors,
+                                            args, flags); 
+
+      if (candidates) 
+       {
+         candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
+         candidates->basetype_path = TYPE_BINFO (totype);
+       } 
     }
 
   if (convs)
@@ -4308,11 +4322,24 @@ build_user_type_conversion_1 (totype, expr, flags)
       else if (ics)
        for (; fn; fn = DECL_CHAIN (fn))
          {
-           candidates = add_function_candidate (candidates, fn, args, flags);
-           candidates->second_conv = ics;
-           candidates->basetype_path = TREE_PURPOSE (convs);
-           if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
-             candidates->viable = -1;
+           if (TREE_CODE (fn) == TEMPLATE_DECL)
+             {
+               templates = decl_tree_cons (NULL_TREE, fn, templates);
+               candidates = 
+                 add_template_candidate (candidates, fn, args,
+                                         totype, flags);
+             } 
+           else 
+             candidates = add_function_candidate (candidates, fn,
+                                                  args, flags); 
+
+           if (candidates) 
+             {
+               candidates->second_conv = ics;
+               candidates->basetype_path = TREE_PURPOSE (convs);
+               if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
+                 candidates->viable = -1;
+             }
          }
     }
 
@@ -4354,6 +4381,13 @@ build_user_type_conversion_1 (totype, expr, flags)
   for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
     p = &(TREE_OPERAND (*p, 0));
 
+  /* Pedantically, normal function declarations are never considered
+     to refer to template instantiations, but we won't implement that
+     until we implement full template instantiation syntax.  */
+  if (templates && ! cand->template && ! DECL_INITIAL (cand->fn)
+      && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
+    add_maybe_template (cand->fn, templates);
+
   *p = build
     (USER_CONV,
      (DECL_CONSTRUCTOR_P (cand->fn)
@@ -4427,7 +4461,7 @@ build_new_function_call (fn, args, obj)
            {
              templates = decl_tree_cons (NULL_TREE, t, templates);
              candidates = add_template_candidate
-               (candidates, t, args, LOOKUP_NORMAL);
+               (candidates, t, args, NULL_TREE, LOOKUP_NORMAL);
            }
          else
            candidates = add_function_candidate
@@ -4713,7 +4747,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
        {
          templates = decl_tree_cons (NULL_TREE, fns, templates);
          candidates = add_template_candidate
-           (candidates, fns, arglist, flags);
+           (candidates, fns, arglist, TREE_TYPE (fnname), flags);
        }
       else
        candidates = add_function_candidate (candidates, fns, arglist, flags);
@@ -4730,13 +4764,27 @@ build_new_op (code, flags, arg1, arg2, arg3)
       mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
       for (; fn; fn = DECL_CHAIN (fn))
        {
+         tree this_arglist;
+
          if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
-           candidates = add_function_candidate
-             (candidates, fn, mem_arglist, flags);
+           this_arglist = mem_arglist;
          else
-           candidates = add_function_candidate (candidates, fn, arglist, flags);
-         
-         candidates->basetype_path = TREE_PURPOSE (fns);
+           this_arglist = arglist;
+
+         if (TREE_CODE (fn) == TEMPLATE_DECL)
+           {
+             /* A member template. */
+             templates = decl_tree_cons (NULL_TREE, fn, templates);
+             candidates = add_template_candidate
+               (candidates, fn, this_arglist, 
+                TREE_TYPE (fnname), LOOKUP_NORMAL);
+           }
+         else
+           candidates = add_function_candidate
+             (candidates, fn, this_arglist, flags);
+
+         if (candidates) 
+           candidates->basetype_path = TREE_PURPOSE (fns);
        }
     }
 
@@ -4827,9 +4875,9 @@ build_new_op (code, flags, arg1, arg2, arg3)
       if (DECL_FUNCTION_MEMBER_P (cand->fn))
        enforce_access (cand->basetype_path, cand->fn);
 
-      /* Pedantically, it is ill-formed to define a function that could
-        also be a template instantiation, but we won't implement that
-        until things settle down.  */
+      /* Pedantically, normal function declarations are never considered
+        to refer to template instantiations, but we won't implement that
+        until we implement full template instantiation syntax.  */
       if (templates && ! cand->template && ! DECL_INITIAL (cand->fn)
          && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
        add_maybe_template (cand->fn, templates);
@@ -5188,8 +5236,7 @@ build_over_call (fn, convs, args, flags)
       if (DECL_TEMPLATE_INFO (fn))
        /* This came from a template.  Instantiate the default arg here,
           not in tsubst.  */
-       arg = tsubst_expr (arg,
-                          &TREE_VEC_ELT (DECL_TI_ARGS (fn), 0),
+       arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
                           TREE_VEC_LENGTH (DECL_TI_ARGS (fn)), NULL_TREE);
       converted_args = tree_cons
        (NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
@@ -5332,6 +5379,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
   tree basetype, mem_args, fns, instance_ptr;
   tree pretty_name;
   tree user_args = args;
+  tree templates = NULL_TREE;
 
   /* If there is an extra argument for controlling virtual bases,
      remove it for error reporting.  */
@@ -5412,17 +5460,34 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       mem_args = tree_cons (NULL_TREE, instance_ptr, args);
       for (; t; t = DECL_CHAIN (t))
        {
+         tree this_arglist;
+
          /* We can end up here for copy-init of same or base class.  */
          if (name == ctor_identifier
              && (flags & LOOKUP_ONLYCONVERTING)
              && DECL_NONCONVERTING_P (t))
            continue;
          if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
-           candidates = add_function_candidate
-             (candidates, t, mem_args, flags);
+           this_arglist = mem_args;
          else
-           candidates = add_function_candidate (candidates, t, args, flags);
-         candidates->basetype_path = TREE_PURPOSE (fns);
+           this_arglist = args;
+
+         if (TREE_CODE (t) == TEMPLATE_DECL)
+           {
+             /* A member template. */
+             templates = decl_tree_cons (NULL_TREE, t, templates);
+             candidates = 
+               add_template_candidate (candidates, t,
+                                       this_arglist,
+                                       TREE_TYPE (name), 
+                                       LOOKUP_NORMAL); 
+           }
+         else 
+           candidates = add_function_candidate (candidates, t,
+                                                this_arglist, flags);
+
+         if (candidates)
+           candidates->basetype_path = TREE_PURPOSE (fns);
        }
     }
 
@@ -5464,6 +5529,12 @@ build_new_method_call (instance, name, args, basetype_path, flags)
          || resolves_to_fixed_type_p (instance, 0)))
     flags |= LOOKUP_NONVIRTUAL;
 
+  /* Pedantically, normal function declarations are never considered
+     to refer to template instantiations, but we won't implement that
+     until we implement full template instantiation syntax.  */
+  if (templates && ! cand->template && ! DECL_INITIAL (cand->fn))
+    add_maybe_template (cand->fn, templates);
+
   return build_over_call
     (cand->fn, cand->convs,
      TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
index a9624a6deaf3f90faade9fb9549c7651bb176f4f..af735e98fcf4df2042a52a11ace322add4e02885 100644 (file)
@@ -1872,33 +1872,10 @@ grow_method (fndecl, method_vec_ptr)
 
   if (testp < (tree *) obstack_next_free (&class_obstack))
     {
-      tree x, prev_x;
-
-      for (x = *testp; x; x = DECL_CHAIN (x))
-       {
-         if (DECL_NAME (fndecl) == ansi_opname[(int) DELETE_EXPR]
-             || DECL_NAME (fndecl) == ansi_opname[(int) VEC_DELETE_EXPR])
-           {
-             /* ANSI C++ June 5 1992 WP 12.5.5.1 */
-             cp_error_at ("`%D' overloaded", fndecl);
-             cp_error_at ("previous declaration as `%D' here", x);
-           }
-         if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (x))
-           {
-             /* Friend-friend ambiguities are warned about outside
-                this loop.  */
-             cp_error_at ("ambiguous method `%#D' in structure", fndecl);
-             break;
-           }
-         prev_x = x;
-       }
-      if (x == 0)
-       {
-         if (*testp)
-           DECL_CHAIN (prev_x) = fndecl;
-         else
-           *testp = fndecl;
-       }
+      tree *p;
+      for (p = testp; *p; )
+       p = &DECL_CHAIN (*p);
+      *p = fndecl;
     }
   else
     {
@@ -4384,7 +4361,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
                }
            }
 
-         if (TREE_CODE (x) == FUNCTION_DECL)
+         if (TREE_CODE (x) == FUNCTION_DECL 
+             || DECL_FUNCTION_TEMPLATE_P (x))
            {
              DECL_CLASS_CONTEXT (x) = t;
              if (last_x)
@@ -5062,12 +5040,13 @@ instantiate_type (lhstype, rhs, complain)
              for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem))
                if (TREE_CODE (elem) == TEMPLATE_DECL)
                  {
-                   int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem));
-                   tree *t = (tree *) alloca (sizeof (tree) * n);
+                   int n = DECL_NTPARMS (elem);
+                   tree t = make_tree_vec (n);
                    int i, d = 0;
-                   i = type_unification (DECL_TEMPLATE_PARMS (elem), t,
-                                         TYPE_ARG_TYPES (TREE_TYPE (elem)),
-                                         TYPE_ARG_TYPES (lhstype), &d, 0, 1);
+                   i = type_unification
+                     (DECL_INNERMOST_TEMPLATE_PARMS (elem), 
+                      &TREE_VEC_ELT (t, 0), TYPE_ARG_TYPES (TREE_TYPE (elem)),
+                      TYPE_ARG_TYPES (lhstype), &d, 0, 1);
                    if (i == 0)
                      {
                        if (save_elem)
index a92bf8a6f112383b74e3933230c773cc9d58d769..6c6dff78c5cf70adb50394b06a020bd7d5763d32 100644 (file)
@@ -91,7 +91,7 @@ DEFTREECODE (TYPENAME_TYPE, "typename_type", "t", 0)
 
 /* Index into a template parameter list.  This parameter must not be a
    type.  */
-DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2)
+DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 3)
 
 /* A thunk is a stub function.
 
index e13839787057003db1f06e8386429355453472ac..0daf874dde4077cf5f815a15a12aed9330597a29 100644 (file)
@@ -1091,6 +1091,7 @@ struct lang_decl
 #define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
 #define CLASSTYPE_TI_ARGS(NODE)     TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
 #define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE))
+#define INNERMOST_TEMPLATE_PARMS(NODE)  TREE_VALUE(NODE)
 
 #define DECL_SAVED_TREE(NODE)          DECL_MEMFUNC_POINTER_TO (NODE)
 #define COMPOUND_STMT_NO_SCOPE(NODE)   TREE_LANG_FLAG_0 (NODE)
@@ -1334,6 +1335,10 @@ extern int flag_new_for_scope;
 
 /* Accessor macros for C++ template decl nodes.  */
 #define DECL_TEMPLATE_PARMS(NODE)       DECL_ARGUMENTS(NODE)
+#define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
+   INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
+#define DECL_NTPARMS(NODE) \
+   TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE))
 /* For class templates.  */
 #define DECL_TEMPLATE_SPECIALIZATIONS(NODE)     DECL_SIZE(NODE)
 /* For function, method, class-data templates.  */
@@ -1346,7 +1351,7 @@ extern int flag_new_for_scope;
    && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
 
 #define PRIMARY_TEMPLATE_P(NODE) \
-  (TREE_TYPE (DECL_TEMPLATE_PARMS (NODE)) == (NODE))
+  (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) == (NODE))
 
 #define CLASSTYPE_TEMPLATE_LEVEL(NODE) \
   (TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE))))
@@ -2112,6 +2117,7 @@ extern tree grok_alignof                  PROTO((tree));
 extern tree grok_array_decl                    PROTO((tree, tree));
 extern tree delete_sanity                      PROTO((tree, tree, int, int));
 extern tree check_classfn                      PROTO((tree, tree));
+extern void check_member_template               PROTO((tree));
 extern tree grokfield                          PROTO((tree, tree, tree, tree, tree));
 extern tree grokbitfield                       PROTO((tree, tree, tree));
 extern tree groktypefield                      PROTO((tree, tree));
@@ -2299,10 +2305,12 @@ extern void synthesize_method                   PROTO((tree));
 extern tree get_id_2                           PROTO((char *, tree));
 
 /* in pt.c */
-extern tree tsubst                             PROTO ((tree, tree*, int, tree));
-extern tree tsubst_expr                                PROTO ((tree, tree*, int, tree));
-extern tree tsubst_copy                                PROTO ((tree, tree*, int, tree));
+extern tree tsubst                             PROTO ((tree, tree, int, tree));
+extern tree tsubst_expr                                PROTO ((tree, tree, int, tree));
+extern tree tsubst_copy                                PROTO ((tree, tree, int, tree));
 extern tree tsubst_chain                       PROTO((tree, tree));
+extern void begin_member_template_processing    PROTO((tree));
+extern void end_member_template_processing      PROTO((void));
 extern void begin_template_parm_list           PROTO((void));
 extern tree process_template_parm              PROTO((tree, tree));
 extern tree end_template_parm_list             PROTO((tree));
@@ -2312,8 +2320,9 @@ extern void push_template_decl                    PROTO((tree));
 extern tree lookup_template_class              PROTO((tree, tree, tree));
 extern int uses_template_parms                 PROTO((tree));
 extern tree instantiate_class_template         PROTO((tree));
-extern tree instantiate_template               PROTO((tree, tree *));
+extern tree instantiate_template               PROTO((tree, tree));
 extern void overload_template_name             PROTO((tree));
+extern int fn_type_unification                  PROTO((tree, tree, tree, tree, int));
 extern int type_unification                    PROTO((tree, tree *, tree, tree, int *, int, int));
 struct tinst_level *tinst_for_decl             PROTO((void));
 extern void mark_decl_instantiated             PROTO((tree, int));
@@ -2324,7 +2333,7 @@ extern void do_type_instantiation         PROTO((tree, tree));
 extern tree instantiate_decl                   PROTO((tree));
 extern tree lookup_nested_type_by_name         PROTO((tree, tree));
 extern tree do_poplevel                                PROTO((void));
-extern tree *get_bindings                      PROTO((tree, tree));
+extern tree get_bindings                       PROTO((tree, tree));
 /* CONT ... */
 extern void add_tree                           PROTO((tree));
 extern void add_maybe_template                 PROTO((tree, tree));
@@ -2333,6 +2342,7 @@ extern tree most_specialized                      PROTO((tree, tree));
 extern tree most_specialized_class             PROTO((tree, tree));
 extern int more_specialized_class              PROTO((tree, tree));
 extern void do_pushlevel                       PROTO((void));
+extern int is_member_template                   PROTO((tree));
 
 /* in repo.c */
 extern void repo_template_used                 PROTO((tree));
index eb574e81a91a3f9af3b206ba178caef7bd326007..c77dac80396cfca91286f6abf28aaaf2a2419a97 100644 (file)
@@ -2306,23 +2306,40 @@ decls_match (newdecl, olddecl)
     {
        tree newargs = DECL_TEMPLATE_PARMS (newdecl);
        tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
-       int i, len = TREE_VEC_LENGTH (newargs);
+       int i;
 
-       if (TREE_VEC_LENGTH (oldargs) != len)
-         return 0;
-       
-       for (i = 0; i < len; i++)
+       /* Run through all the levels of template parmaters, checking
+          that they match.  */
+       while (newargs && oldargs) 
          {
-           tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i));
-           tree oldarg = TREE_VALUE (TREE_VEC_ELT (oldargs, i));
-           if (TREE_CODE (newarg) != TREE_CODE (oldarg))
-             return 0;
-           else if (TREE_CODE (newarg) == TYPE_DECL)
-             /* continue */;
-           else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
+           int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (newargs));
+
+           if (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (oldargs)) != len)
              return 0;
+           
+           for (i = 0; i < len; i++)
+             {
+               tree newarg = 
+                 TREE_VALUE (TREE_VEC_ELT 
+                             (INNERMOST_TEMPLATE_PARMS (newargs), i));
+               tree oldarg = 
+                 TREE_VALUE (TREE_VEC_ELT 
+                             (INNERMOST_TEMPLATE_PARMS (oldargs), i));
+               if (TREE_CODE (newarg) != TREE_CODE (oldarg))
+                 return 0;
+               else if (TREE_CODE (newarg) == TYPE_DECL)
+                 /* continue */;
+               else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
+                 return 0;
+             }
+           newargs = TREE_CHAIN (newargs);
+           oldargs = TREE_CHAIN (oldargs);
          }
 
+       if ((newargs == NULL_TREE) != (oldargs == NULL_TREE))
+         /* One declaration has more levels that the other. */
+         return 0;
+
        if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
          types_match = 1;
        else
@@ -3003,7 +3020,7 @@ pushdecl (x)
   /* Type are looked up using the DECL_NAME, as that is what the rest of the
      compiler wants to use.  */
   if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
-      || TREE_CODE (x) == NAMESPACE_DECL)
+      || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM)
     name = DECL_NAME (x);
 
   if (name)
@@ -3493,6 +3510,11 @@ push_class_level_binding (name, x)
      tree name;
      tree x;
 {
+  /* The class_binding_level will be NULL if x is a template 
+     parameter name in a member template.  */
+  if (!class_binding_level)
+    return;
+
   if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
       && purpose_member (name, class_binding_level->class_shadowed))
     return;
@@ -7232,6 +7254,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
       if (check)
        {
          tmp = check_classfn (ctype, decl);
+
+         if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
+           tmp = DECL_TEMPLATE_RESULT(tmp);
+
          if (tmp && DECL_ARTIFICIAL (tmp))
            cp_error ("definition of implicitly-declared `%D'", tmp);
          if (tmp && duplicate_decls (decl, tmp))
@@ -7270,6 +7296,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
       if (ctype != NULL_TREE && check)
        {
          tmp = check_classfn (ctype, decl);
+
+         if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
+           tmp = DECL_TEMPLATE_RESULT(tmp);
+             
          if (tmp && DECL_STATIC_FUNCTION_P (tmp)
              && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
            {
@@ -8934,8 +8964,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                    && uses_template_parms (current_class_type))
                  {
                    tree args = current_template_args ();
-                   type = tsubst (type, &TREE_VEC_ELT (args, 0),
-                                  TREE_VEC_LENGTH (args), NULL_TREE);
+                   type = tsubst (type, args,
+                                  TREE_VEC_LENGTH (TREE_VEC_ELT
+                                                   (args, 0)),
+                                  NULL_TREE);
                  }
 
                /* This pop_nested_class corresponds to the
@@ -10038,7 +10070,7 @@ void
 replace_defarg (arg, init)
      tree arg, init;
 {
-  if (! processing_template_decl
+  if (! processing_template_decl && ! uses_template_parms (TREE_VALUE (arg))
       && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
     cp_pedwarn ("invalid type `%T' for default argument to `%T'",
                TREE_TYPE (init), TREE_VALUE (arg));
index e78b00d25a79c3f33e1f17134f776d660a53d848..2de7fcede6e93add4039894841523f823e9ad500 100644 (file)
@@ -1282,6 +1282,59 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
     }
 }
 
+/* Report an error if the indicated template declaration is not the
+   sort of thing that should be a member template.  */
+
+void
+check_member_template (tmpl)
+     tree tmpl;
+{
+  tree decl;
+
+  my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+  decl = DECL_TEMPLATE_RESULT (tmpl);
+
+  if (TREE_CODE (decl) == FUNCTION_DECL) 
+    {
+      if (current_function_decl)
+       /* 14.5.2.2 [temp.mem]
+          
+          A local class shall not have member templates. */
+       cp_error ("declaration of of member template `%#D' in local class",
+                 decl);
+      
+      if (DECL_VIRTUAL_P (decl)) 
+       {
+         /* 14.5.2.3 [temp.mem]
+
+            A member function template shall not be virtual.  */
+         cp_error 
+           ("invalid use of `virtual' in template declaration of `%#D'",
+            decl);
+         DECL_VIRTUAL_P (decl) = 0;
+       }
+
+      /* The debug-information generating code doesn't know what to do
+        with member templates.  */ 
+      DECL_IGNORED_P (tmpl) = 1;
+    } 
+  else if (TREE_CODE (decl) == TYPE_DECL &&
+          AGGREGATE_TYPE_P (TREE_TYPE (decl)))
+    {
+      if (current_function_decl)
+       /* 14.5.2.2 [temp.mem]
+
+          A local class shall not have member templates.  */
+       cp_error ("declaration of of member template `%#D' in local class",
+                 decl);
+
+      /* We don't handle member template classes yet. */
+      sorry ("member templates classes");
+    }
+  else
+    cp_error ("template declaration of `%#D'", decl);
+}
+
 /* Sanity check: report error if this function FUNCTION is not
    really a member of the class (CTYPE) it is supposed to belong to.
    CNAME is the same here as it is for grokclassfn above.  */
@@ -1295,6 +1348,7 @@ check_classfn (ctype, function)
   tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
   tree *methods = 0;
   tree *end = 0;
+  tree templates = NULL_TREE;
 
   if (method_vec != 0)
     {
@@ -1311,6 +1365,7 @@ check_classfn (ctype, function)
 
       while (++methods != end)
        {
+         fndecl = *methods;
          if (fn_name == DECL_NAME (*methods))
            {
            got_it:
@@ -1342,14 +1397,39 @@ check_classfn (ctype, function)
                                     TREE_TYPE (TREE_TYPE (fndecl)), 1)
                          && compparms (p1, p2, 3))
                        return fndecl;
+
+                     if (is_member_template (fndecl)) 
+                       /* This function might be an instantiation
+                          or specialization of fndecl.  */
+                       templates = 
+                         tree_cons (NULL_TREE, fndecl, templates);
                    }
 #endif
                  fndecl = DECL_CHAIN (fndecl);
                }
              break;            /* loser */
            }
-       }
-    }
+         else if (TREE_CODE (fndecl) == TEMPLATE_DECL 
+                  && IDENTIFIER_TYPENAME_P (DECL_NAME (fndecl))
+                  && IDENTIFIER_TYPENAME_P (fn_name))
+           /* The method in the class is a member template
+              conversion operator.  We are declaring another
+              conversion operator.  It is possible that even though
+              the names don't match, there is some specialization
+              occurring.  */
+           templates = 
+             tree_cons (NULL_TREE, fndecl, templates);
+       }
+    }
+
+  if (templates)
+    /* This function might be an instantiation or a specialization.
+       We should verify that this is possible.  If it is, we must
+       somehow add the new declaration to the method vector for the
+       class.  Perhaps we should use add_method?  For now, we simply
+       return NULL_TREE, which lets the caller know that this
+       function is new, but we don't print an error message.  */
+    return NULL_TREE;
 
   if (methods != end)
     {
@@ -2792,7 +2872,7 @@ finish_file ()
 
   for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
     {
-      tree *args, fn, decl = TREE_VALUE (fnname);
+      tree args, fn, decl = TREE_VALUE (fnname);
 
       if (DECL_INITIAL (decl))
        continue;
@@ -2800,7 +2880,6 @@ finish_file ()
       fn = TREE_PURPOSE (fnname);
       args = get_bindings (fn, decl);
       fn = instantiate_template (fn, args);
-      free (args);
       instantiate_decl (fn);
     }
 
index b3d68ce0668f91a7db30a2d0e20318b197b8e652..ce2bc3b88dc59d72395c0fb327b1d167acf2074f 100644 (file)
@@ -722,33 +722,42 @@ dump_decl (t, v)
 
     case TEMPLATE_DECL:
       {
-       tree args = DECL_TEMPLATE_PARMS (t);
-       int i, len = args ? TREE_VEC_LENGTH (args) : 0;
-       OB_PUTS ("template <");
-       for (i = 0; i < len; i++)
+       tree orig_args = DECL_TEMPLATE_PARMS (t);
+       tree args;
+       int i; 
+       for (args = orig_args = nreverse (orig_args); 
+            args;
+            args = TREE_CHAIN (args))
          {
-           tree arg = TREE_VEC_ELT (args, i);
-           tree defval = TREE_PURPOSE (arg);
-           arg = TREE_VALUE (arg);
-           if (TREE_CODE (arg) == TYPE_DECL)
-             {
-               OB_PUTS ("class ");
-               OB_PUTID (DECL_NAME (arg));
-             }
-           else
-             dump_decl (arg, 1);
+           int len = TREE_VEC_LENGTH (TREE_VALUE (args));
 
-           if (defval)
+           OB_PUTS ("template <");
+           for (i = 0; i < len; i++)
              {
-               OB_PUTS (" = ");
-               dump_decl (defval, 1);
-             }
+               tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
+               tree defval = TREE_PURPOSE (arg);
+               arg = TREE_VALUE (arg);
+               if (TREE_CODE (arg) == TYPE_DECL)
+                 {
+                   OB_PUTS ("class ");
+                   OB_PUTID (DECL_NAME (arg));
+                 }
+               else
+                 dump_decl (arg, 1);
+               
+               if (defval)
+                 {
+                   OB_PUTS (" = ");
+                   dump_decl (defval, 1);
+                 }
                
-           OB_PUTC2 (',', ' ');
+               OB_PUTC2 (',', ' ');
+             }
+           if (len != 0)
+             OB_UNPUT (2);
+           OB_PUTC2 ('>', ' ');
          }
-       if (len != 0)
-         OB_UNPUT (2);
-       OB_PUTC2 ('>', ' ');
+       nreverse(orig_args);
 
        if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
          dump_type (TREE_TYPE (t), v);
@@ -801,11 +810,18 @@ dump_function_decl (t, v)
      tree t;
      int v;
 {
-  tree name = DECL_ASSEMBLER_NAME (t);
-  tree fntype = TREE_TYPE (t);
-  tree parmtypes = TYPE_ARG_TYPES (fntype);
+  tree name;
+  tree fntype;
+  tree parmtypes;
   tree cname = NULL_TREE;
 
+  if (TREE_CODE (t) == TEMPLATE_DECL)
+    t = DECL_TEMPLATE_RESULT (t);
+
+  name = DECL_ASSEMBLER_NAME (t);
+  fntype = TREE_TYPE (t);
+  parmtypes = TYPE_ARG_TYPES (fntype);
+
   /* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT.  */
   if (DECL_CONTEXT (t))
     cname = DECL_CLASS_CONTEXT (t);
@@ -1349,8 +1365,17 @@ dump_expr (t, nop)
     case TEMPLATE_CONST_PARM:
       if (current_template_parms)
        {
-         tree r = TREE_VEC_ELT (TREE_VALUE (current_template_parms),
-                                TEMPLATE_CONST_IDX (t));
+         int i;
+         tree parms;
+         tree r;
+
+         for (parms = current_template_parms;
+              TREE_CHAIN (parms);
+              parms = TREE_CHAIN (parms))
+           ;
+
+         r = TREE_VEC_ELT (TREE_VALUE (parms),
+                           TEMPLATE_CONST_IDX (t));
          dump_decl (TREE_VALUE (r), -1);
        }
       else
index 83ac1a7de5bd4eca0852a07e051611b39d6af5d0..7fca8a2138d430913d03940d50d772aa1b347db8 100644 (file)
@@ -1190,6 +1190,8 @@ do_pending_inlines ()
   context = hack_decl_function_context (t->fndecl);
   if (context)
     push_cp_function_context (context);
+  if (is_member_template (t->fndecl))
+    begin_member_template_processing (DECL_TI_ARGS (t->fndecl));
   if (t->len > 0)
     {
       feed_input (t->buf, t->len);
@@ -1226,7 +1228,9 @@ process_next_inline (t)
 {
   tree context;
   struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
-  context = hack_decl_function_context (i->fndecl);
+  context = hack_decl_function_context (i->fndecl);  
+  if (is_member_template (i->fndecl))
+    end_member_template_processing ();
   if (context)
     pop_cp_function_context (context);
   i = i->next;
@@ -1249,6 +1253,8 @@ process_next_inline (t)
       context = hack_decl_function_context (i->fndecl);
       if (context)
        push_cp_function_context (context);
+      if (is_member_template (i->fndecl))
+       begin_member_template_processing (DECL_TI_ARGS (i->fndecl));
       feed_input (i->buf, i->len);
       lineno = i->lineno;
       input_filename = i->filename;
index 0a67b802f7bff4538e7d8488f1c3679893127ef4..8a50dabac993941a6de554295837bf3fb1a8bcbc 100644 (file)
@@ -648,7 +648,7 @@ build_overload_identifier (name)
       arglist = TREE_VALUE (template);
       template = TREE_PURPOSE (template);
       tname = DECL_NAME (template);
-      parmlist = DECL_ARGUMENTS (template);
+      parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
       nparms = TREE_VEC_LENGTH (parmlist);
       OB_PUTC ('t');
       icat (IDENTIFIER_LENGTH (tname));
@@ -666,7 +666,7 @@ build_overload_identifier (name)
            }
          else
            {
-             parm = tsubst (parm, &TREE_VEC_ELT (arglist, 0),
+             parm = tsubst (parm, arglist,
                             TREE_VEC_LENGTH (arglist), NULL_TREE);
              /* It's a PARM_DECL.  */
              build_overload_name (TREE_TYPE (parm), 0, 0);
index 47302a0cc578e1c0db0996b96152cd99fc2a06a4..7d9d5db7a343d8294e17ea4eff0052042c7db017 100644 (file)
@@ -699,6 +699,22 @@ fn.def2:
                  $$ = start_method (specs, $2); goto rest_of_mdef; }
        | constructor_declarator
                { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+        | template_header fn.def2 
+                { 
+                 end_template_decl (); 
+                 if ($2 && DECL_TEMPLATE_INFO ($2))
+                   {
+                     $$ = DECL_TI_TEMPLATE ($2); 
+                     check_member_template ($$);
+                   }
+                 else if ($2)
+                   $$ = $2;
+                 else 
+                   {
+                     cp_error("invalid member template declaration");
+                     $$ = NULL_TREE;
+                   }
+               }
        ;
 
 return_id:
@@ -2711,7 +2727,22 @@ component_decl_1:
                                  build_tree_list ($3, NULL_TREE)); }
        | using_decl
                { $$ = do_class_using_decl ($1); }
-       ;
+        | template_header component_decl_1 
+                { 
+                 end_template_decl (); 
+                 if ($2 && DECL_TEMPLATE_INFO ($2))
+                   {
+                     $$ = DECL_TI_TEMPLATE ($2); 
+                     check_member_template ($$);
+                   }
+                 else if ($2)
+                   $$ = $2;
+                 else
+                   {
+                     cp_error("invalid member template declaration");
+                     $$ = NULL_TREE;
+                   }
+               }
 
 /* The case of exactly one component is handled directly by component_decl.  */
 /* ??? Huh? ^^^ */
index 9ba46ac21b2b92a2d43fd3883c517948928e2bda..3620253a6b5848f9247c73a683777b8a2c65d529 100644 (file)
@@ -76,7 +76,148 @@ 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 coerce_template_parms PROTO((tree, tree, tree));
-static tree tsubst_enum        PROTO((tree, tree *, int));
+static tree tsubst_enum        PROTO((tree, tree, int));
+static tree add_to_template_args PROTO((tree, tree));
+
+/* Restore the template parameter context. */
+
+void 
+begin_member_template_processing (parms)
+     tree parms;
+{
+  int i;
+
+  ++processing_template_decl;
+  current_template_parms 
+    = tree_cons (build_int_2 (0, processing_template_decl),
+                parms, current_template_parms);
+  for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) 
+    {
+      tree parm = TREE_VEC_ELT (parms, i);
+
+      switch (TREE_CODE (parm))
+       {
+       case TEMPLATE_TYPE_PARM:
+         pushdecl (TYPE_NAME (parm));
+         break;
+
+       case TEMPLATE_CONST_PARM:
+         pushdecl (parm);
+         break;
+         
+       default:
+         my_friendly_abort (0);
+       }
+    }
+}
+
+/* Undo the effects of begin_member_template_processing. */
+
+void 
+end_member_template_processing ()
+{
+  if (! processing_template_decl)
+    return;
+
+  --processing_template_decl;
+  current_template_parms = TREE_CHAIN (current_template_parms);
+}
+
+/* Returns non-zero iff T is a member template function.  Works if T
+   is either a FUNCTION_DECL or a TEMPLATE_DECL.  */
+
+int
+is_member_template (t)
+     tree t;
+{
+  int r = 0;
+
+  if (DECL_FUNCTION_MEMBER_P (t) ||
+      (TREE_CODE (t) == TEMPLATE_DECL && 
+       DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
+    {
+      tree tmpl = NULL_TREE;
+
+      if (DECL_FUNCTION_TEMPLATE_P (t))
+       tmpl = t;
+      else if (DECL_TEMPLATE_INFO (t) 
+              && DECL_FUNCTION_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
+       tmpl = DECL_TI_TEMPLATE (t);
+
+      if (tmpl) 
+       {
+         tree parms = DECL_TEMPLATE_PARMS (tmpl);
+         int parm_levels = list_length (parms);
+         int template_class_levels = 0;
+         tree ctx = DECL_CLASS_CONTEXT (t);
+
+         if (CLASSTYPE_TEMPLATE_INFO (ctx))
+           {
+             tree args;
+
+             /* Here, we should really count the number of levels
+                deep ctx is, making sure not to count any levels that
+                are just specializations.  Since there are no member
+                template classes yet, we don't have to do all that.  */
+
+             if (!CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
+               template_class_levels = 1;
+             else
+               {
+                 int i;
+
+                 args = CLASSTYPE_TI_ARGS (ctx);
+
+                 if (args == NULL_TREE)
+                   template_class_levels = 1;
+                 else 
+                   for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+                     if (uses_template_parms (TREE_VEC_ELT (args, i)))
+                       {
+                         template_class_levels++;
+                         break;
+                       }
+               }
+           }
+
+         if (parm_levels > template_class_levels)
+           r = 1;
+       }
+    }
+
+  return r;
+}
+
+/* Return a new template argument vector which contains all of ARGS,
+   but has as its innermost set of arguments the EXTRA_ARGS.  */
+
+tree
+add_to_template_args (args, extra_args)
+     tree args;
+     tree extra_args;
+{
+  tree new_args;
+
+  if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
+    {
+      new_args = make_tree_vec (2);
+      TREE_VEC_ELT (new_args, 0) = args;
+    }
+  else 
+    {
+      int i;
+
+      new_args = make_tree_vec (TREE_VEC_LENGTH (args) - 1);
+
+      for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+       TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
+    }
+         
+  TREE_VEC_ELT (new_args, 
+               TREE_VEC_LENGTH (new_args) - 1) = extra_args;
+
+  return new_args;
+}
 
 /* We've got a template header coming up; push to a new level for storing
    the parms.  */
@@ -216,7 +357,10 @@ tree
 current_template_args ()
 {
   tree header = current_template_parms;
-  tree args = NULL_TREE;
+  int length = list_length (header);
+  tree args = make_tree_vec (length);
+  int l = length;
+
   while (header)
     {
       tree a = copy_node (TREE_VALUE (header));
@@ -224,20 +368,26 @@ current_template_args ()
       TREE_TYPE (a) = NULL_TREE;
       while (i--)
        {
-         tree t = TREE_VALUE (TREE_VEC_ELT (a, i));
-         if (TREE_CODE (t) == TYPE_DECL)
-           t = TREE_TYPE (t);
-         else
-           t = DECL_INITIAL (t);
+         tree t = TREE_VEC_ELT (a, i);
+
+         /* t will be a list if we are called from within a
+            begin/end_template_parm_list pair, but a vector directly
+            if within a begin/end_member_template_processing pair.  */
+         if (TREE_CODE (t) == TREE_LIST) 
+           {
+             t = TREE_VALUE (t);
+             
+             if (TREE_CODE (t) == TYPE_DECL)
+               t = TREE_TYPE (t);
+             else
+               t = DECL_INITIAL (t);
+           }
+
          TREE_VEC_ELT (a, i) = t;
        }
-      args = tree_cons (TREE_PURPOSE (header), a, args);
+      TREE_VEC_ELT (args, --l) = a;
       header = TREE_CHAIN (header);
     }
-  args = nreverse (args);
-
-  /* FIXME Remove this when we support member templates.  */
-  args = TREE_VALUE (args);
 
   return args;
 }
@@ -290,12 +440,15 @@ push_template_decl (decl)
   if (! ctx || TYPE_BEING_DEFINED (ctx))
     {
       tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
-      DECL_TEMPLATE_PARMS (tmpl) = TREE_VALUE (current_template_parms);
+      DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
       DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
+      if (DECL_LANG_SPECIFIC (decl))
+       DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
     }
   else
     {
       tree t;
+      tree a;
 
       if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
        cp_error ("must specialize `%#T' before defining member `%#D'",
@@ -309,19 +462,54 @@ push_template_decl (decl)
        }
       else
        tmpl = DECL_TI_TEMPLATE (decl);
+      
+      if (is_member_template (tmpl))
+       {
+         a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+         t = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
+         if (TREE_VEC_LENGTH (t) 
+             != TREE_VEC_LENGTH (a))
+           {
+             cp_error ("got %d template parameters for `%#D'",
+                       TREE_VEC_LENGTH (a), decl);
+             cp_error ("  but %d required", TREE_VEC_LENGTH (t));
+           }
+         if (TREE_VEC_LENGTH (args) > 1)
+           /* Get the template parameters for the enclosing template
+              class.  */ 
+           a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 2);
+         else
+           a = NULL_TREE;
+       }
+      else 
+       a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+
+      t = NULL_TREE;
 
       if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
-       t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx));
-      else
-       t = DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
+       {
+         /* When processing an inline member template of a
+            specialized class, there is no CLASSTYPE_TI_SPEC_INFO.  */
+         if (CLASSTYPE_TI_SPEC_INFO (ctx))
+           t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx));
+       }
+      else if (CLASSTYPE_TEMPLATE_INFO (ctx))
+       t = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
+
+      /* There should be template arguments if and only if there is a
+        template class.  */
+      my_friendly_assert((a != NULL_TREE) == (t != NULL_TREE), 0);
 
-      if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (args))
+      if (t != NULL_TREE 
+         && TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
        {
          cp_error ("got %d template parameters for `%#D'",
-                   TREE_VEC_LENGTH (args), decl);
+                   TREE_VEC_LENGTH (a), decl);
          cp_error ("  but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
        }
     }
+  /* Get the innermost set of template arguments. */
+  args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
 
   DECL_TEMPLATE_RESULT (tmpl) = decl;
   TREE_TYPE (tmpl) = TREE_TYPE (decl);
@@ -330,7 +518,7 @@ push_template_decl (decl)
     tmpl = pushdecl_top_level (tmpl);
 
   if (primary)
-    TREE_TYPE (DECL_TEMPLATE_PARMS (tmpl)) = tmpl;
+    TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl;
 
   info = perm_tree_cons (tmpl, args, NULL_TREE);
 
@@ -345,8 +533,6 @@ push_template_decl (decl)
     DECL_TEMPLATE_INFO (decl) = info;
 }
 
-tree tsubst            PROTO ((tree, tree*, int, tree));
-
 /* Convert all template arguments to their appropriate types, and return
    a vector containing the resulting values.  If any error occurs, return
    error_mark_node.  */
@@ -401,10 +587,10 @@ coerce_template_parms (parms, arglist, in_decl)
          else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i)))
                   == TYPE_DECL)
            arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
-                         &TREE_VEC_ELT (vec, 0), i, in_decl);
+                         vec, i, in_decl);
          else
            arg = tsubst_expr (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
-                              &TREE_VEC_ELT (vec, 0), i, in_decl);
+                              vec, i, in_decl);
 
          TREE_VEC_ELT (vec, i) = arg;
        }
@@ -460,7 +646,7 @@ coerce_template_parms (parms, arglist, in_decl)
        }
       else
        {
-         tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
+         tree t = tsubst (TREE_TYPE (parm), vec,
                           TREE_VEC_LENGTH (vec), in_decl);
          if (processing_template_decl)
            val = arg;
@@ -656,7 +842,7 @@ classtype_mangled_name (t)
       tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
       char *mangled_name = mangle_class_name_for_template
        (IDENTIFIER_POINTER (name),
-        DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
+        DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
         CLASSTYPE_TI_ARGS (t));
       tree id = get_identifier (mangled_name);
       IDENTIFIER_TEMPLATE (id) = name;
@@ -740,7 +926,7 @@ lookup_template_class (d1, arglist, in_decl)
 
   if (PRIMARY_TEMPLATE_P (template))
     {
-      parmlist = DECL_TEMPLATE_PARMS (template);
+      parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
 
       arglist = coerce_template_parms (parmlist, arglist, template);
       if (arglist == error_mark_node)
@@ -1209,7 +1395,7 @@ instantiate_class_template (type)
            tree elt;
 
            TREE_VEC_ELT (bases, i) = elt
-             = tsubst (TREE_VEC_ELT (pbases, i), &TREE_VEC_ELT (args, 0),
+             = tsubst (TREE_VEC_ELT (pbases, i), args,
                        TREE_VEC_LENGTH (args), NULL_TREE);
            BINFO_INHERITANCE_CHAIN (elt) = binfo;
 
@@ -1241,7 +1427,7 @@ instantiate_class_template (type)
       /* These will add themselves to CLASSTYPE_TAGS for the new type.  */
       if (TREE_CODE (tag) == ENUMERAL_TYPE)
        {
-         tree e, newtag = tsubst_enum (tag, &TREE_VEC_ELT (args, 0),
+         tree e, newtag = tsubst_enum (tag, args, 
                                        TREE_VEC_LENGTH (args));
 
          *field_chain = grok_enum_decls (newtag, NULL_TREE);
@@ -1252,7 +1438,7 @@ instantiate_class_template (type)
            }
        }
       else
-       tsubst (tag, &TREE_VEC_ELT (args, 0),
+       tsubst (tag, args,
                TREE_VEC_LENGTH (args), NULL_TREE);
     }
 
@@ -1260,7 +1446,7 @@ instantiate_class_template (type)
   for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
     if (TREE_CODE (t) != CONST_DECL)
       {
-       tree r = tsubst (t, &TREE_VEC_ELT (args, 0),
+       tree r = tsubst (t, args,
                         TREE_VEC_LENGTH (args), NULL_TREE);
        if (TREE_CODE (r) == VAR_DECL)
          {
@@ -1288,18 +1474,18 @@ instantiate_class_template (type)
 
   DECL_FRIENDLIST (TYPE_MAIN_DECL (type))
     = tsubst (DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)),
-             &TREE_VEC_ELT (args, 0), TREE_VEC_LENGTH (args), NULL_TREE);
+             args, TREE_VEC_LENGTH (args), NULL_TREE);
 
   {
     tree d = CLASSTYPE_FRIEND_CLASSES (type)
-      = tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), &TREE_VEC_ELT (args, 0),
+      = tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), args,
                TREE_VEC_LENGTH (args), NULL_TREE);
 
     /* This does injection for friend classes.  */
     for (; d; d = TREE_CHAIN (d))
       TREE_VALUE (d) = xref_tag_from_type (TREE_VALUE (d), NULL_TREE, 1);
 
-    d = tsubst (DECL_TEMPLATE_INJECT (template), &TREE_VEC_ELT (args, 0),
+    d = tsubst (DECL_TEMPLATE_INJECT (template), args,
                TREE_VEC_LENGTH (args), NULL_TREE);
 
     for (; d; d = TREE_CHAIN (d))
@@ -1382,7 +1568,7 @@ lookup_nested_type_by_name (ctype, name)
 
 tree
 tsubst (t, args, nargs, in_decl)
-     tree t, *args;
+     tree t, args;
      int nargs;
      tree in_decl;
 {
@@ -1471,15 +1657,108 @@ tsubst (t, args, nargs, in_decl)
       }
 
     case TEMPLATE_TYPE_PARM:
+    case TEMPLATE_CONST_PARM:
       {
-       tree arg = args[TEMPLATE_TYPE_IDX (t)];
-       return cp_build_type_variant
-         (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
-          TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+       int idx;
+       int level;
+
+       if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+         {
+           idx = TEMPLATE_TYPE_IDX (t);
+           level = TEMPLATE_TYPE_LEVEL (t);
+         }
+       else
+         {
+           idx = TEMPLATE_CONST_IDX (t);
+           level = TEMPLATE_CONST_LEVEL (t);
+         }
+
+       if (TREE_VEC_LENGTH (args) > 0) 
+         {
+           tree arg = NULL_TREE;
+
+           if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+             {
+               if (TREE_VEC_LENGTH (args) >= level - 1)
+                 arg = TREE_VEC_ELT
+                   (TREE_VEC_ELT (args, level - 1), idx);
+             }
+           else if (level == 1)
+             arg = TREE_VEC_ELT (args, idx);
+
+           if (arg != NULL_TREE)
+             {
+               if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+                 return cp_build_type_variant
+                   (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
+                    TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+               else
+                 return arg;
+             }
+         }
+
+       /* If we get here, we must have been looking at a parm for a
+          more deeply nested template.  */
+       my_friendly_assert((TREE_CODE (t) == TEMPLATE_CONST_PARM 
+                           && TEMPLATE_CONST_LEVEL (t) > 1) 
+                          || (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+                              && TEMPLATE_TYPE_LEVEL (t) > 1),
+                          0);
+       return t;
       }
 
-    case TEMPLATE_CONST_PARM:
-      return args[TEMPLATE_CONST_IDX (t)];
+    case TEMPLATE_DECL:
+      {
+       /* We can get here when processing a member template function
+          of a template class.  */
+       tree tmpl;
+       tree decl = DECL_TEMPLATE_RESULT (t);
+       tree new_decl;
+       tree parms;
+       int i;
+
+       /* We might already have an instance of this template. */
+       tree instances = DECL_TEMPLATE_INSTANTIATIONS (t);
+       tree ctx = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, in_decl); 
+         
+       for (; instances; instances = TREE_CHAIN (instances))
+         if (DECL_CLASS_CONTEXT (TREE_VALUE (instances)) == ctx)
+           return TREE_VALUE (instances);
+
+       /* Make a new template decl.  It will be similar to the
+          original, but will record the current template arguments. 
+          We also create a new function declaration, which is just
+          like the old one, but points to this new template, rather
+          than the old one.  */
+       tmpl = copy_node (t);
+       copy_lang_decl (tmpl);
+       my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
+       DECL_CHAIN (tmpl) = NULL_TREE;
+       TREE_CHAIN (tmpl) = NULL_TREE;
+       DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
+       new_decl = tsubst (decl, args, nargs, in_decl);
+       DECL_RESULT (tmpl) = new_decl;
+       DECL_INITIAL (new_decl) = DECL_INITIAL (decl);
+       DECL_TI_TEMPLATE (new_decl) = tmpl;
+       TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
+       DECL_TEMPLATE_INSTANTIATIONS(tmpl) = NULL_TREE;
+
+       /* The template parameters for this new template are all the
+          template parameters for the old template, except the
+          outermost level of parameters. */
+       DECL_TEMPLATE_PARMS (tmpl)
+         = copy_node (DECL_TEMPLATE_PARMS (tmpl));
+       for (parms = DECL_TEMPLATE_PARMS (tmpl);
+            TREE_CHAIN (parms) != NULL_TREE;
+            parms = TREE_CHAIN (parms))
+         TREE_CHAIN (parms) = copy_node (TREE_CHAIN (parms));
+
+       /* Record this partial instantiation. */
+       DECL_TEMPLATE_INSTANTIATIONS (t)
+         = perm_tree_cons (NULL_TREE, tmpl,
+                           DECL_TEMPLATE_INSTANTIATIONS (t));
+       return tmpl;
+      }
 
     case FUNCTION_DECL:
       {
@@ -1516,7 +1795,7 @@ tsubst (t, args, nargs, in_decl)
        /* Do we already have this instantiation?  */
        if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
          {
-           tree tmpl = TREE_PURPOSE (DECL_TEMPLATE_INFO (t));
+           tree tmpl = DECL_TI_TEMPLATE (t);
            tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
 
            for (; decls; decls = TREE_CHAIN (decls))
@@ -1622,8 +1901,10 @@ tsubst (t, args, nargs, in_decl)
          {
            tree tmpl = DECL_TI_TEMPLATE (t);
            tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
-           tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
-                                 args, nargs, in_decl);
+           tree argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
+
+           if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
+             argvec = add_to_template_args (DECL_TI_ARGS (tmpl), argvec);
 
            DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
            *declsp = perm_tree_cons (argvec, r, *declsp);
@@ -1727,8 +2008,7 @@ tsubst (t, args, nargs, in_decl)
          {
            tree tmpl = DECL_TI_TEMPLATE (t);
            tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
-           tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
-                                 args, nargs, in_decl);
+           tree argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
 
            DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
            *declsp = perm_tree_cons (argvec, r, *declsp);
@@ -2013,7 +2293,7 @@ do_poplevel ()
 
 tree
 tsubst_copy (t, args, nargs, in_decl)
-     tree t, *args;
+     tree t, args;
      int nargs;
      tree in_decl;
 {
@@ -2048,6 +2328,12 @@ tsubst_copy (t, args, nargs, in_decl)
       mark_used (t);
       return t;
 
+    case TEMPLATE_DECL:
+      if (is_member_template (t))
+       return tsubst (t, args, nargs, in_decl);
+      else
+       return t;
+
 #if 0
     case IDENTIFIER_NODE:
       return do_identifier (t, 0);
@@ -2241,7 +2527,7 @@ tsubst_copy (t, args, nargs, in_decl)
 
 tree
 tsubst_expr (t, args, nargs, in_decl)
-     tree t, *args;
+     tree t, args;
      int nargs;
      tree in_decl;
 {
@@ -2543,7 +2829,7 @@ tsubst_expr (t, args, nargs, in_decl)
 
 tree
 instantiate_template (tmpl, targ_ptr)
-     tree tmpl, *targ_ptr;
+     tree tmpl, targ_ptr;
 {
   tree fndecl;
   int i, len;
@@ -2555,12 +2841,12 @@ instantiate_template (tmpl, targ_ptr)
   function_maybepermanent_obstack = &permanent_obstack;
 
   my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
-  len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
+  len = DECL_NTPARMS (tmpl);
 
   i = len;
   while (i--)
     {
-      tree t = targ_ptr [i];
+      tree t = TREE_VEC_ELT (targ_ptr, i);
       if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
        {
          tree nt = target_type (t);
@@ -2572,9 +2858,12 @@ instantiate_template (tmpl, targ_ptr)
              goto out;
            }
        }
-      targ_ptr[i] = copy_to_permanent (t);
+      TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t);
     }
 
+  if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
+    targ_ptr = add_to_template_args (DECL_TI_ARGS (tmpl), targ_ptr);
+
   /* substitute template parameters */
   fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl);
 
@@ -2606,6 +2895,42 @@ overload_template_name (type)
   pushdecl_class_level (decl);
 }
 
+/* Like type_unfication but designed specially to handle conversion
+   operators.  */
+
+int
+fn_type_unification (fn, targs, args, return_type, strict)
+     tree fn, targs, args, return_type;
+     int strict;
+{
+  int i, dummy = 0;
+  tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+  tree decl_arg_types = args;
+
+  my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
+
+  if (IDENTIFIER_TYPENAME_P (DECL_NAME (fn))) 
+    {
+      /* This is a template conversion operator.  Use the return types
+         as well as the argument types.  */
+      fn_arg_types = tree_cons (NULL_TREE, 
+                               TREE_TYPE (TREE_TYPE (fn)),
+                               fn_arg_types);
+      decl_arg_types = tree_cons (NULL_TREE,
+                                 return_type,
+                                 decl_arg_types);
+    }
+
+  i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn), 
+                       &TREE_VEC_ELT (targs, 0), 
+                       fn_arg_types,
+                       decl_arg_types,
+                       &dummy, 0, strict);
+
+  return i;
+}
+
+
 /* Type unification.
 
    We have a function template signature with one or more references to
@@ -2718,10 +3043,11 @@ type_unification (tparms, targs, parms, args, nsubsts, subr, strict)
              /* Have to back unify here */
              arg = TREE_VALUE (arg);
              nsubsts = 0;
-             ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg));
+             ntparms = DECL_NTPARMS (arg);
              targs = (tree *) alloca (sizeof (tree) * ntparms);
              parm = tree_cons (NULL_TREE, parm, NULL_TREE);
-             return type_unification (DECL_TEMPLATE_PARMS (arg), targs,
+             return type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg), 
+                                      targs,
                                       TYPE_ARG_TYPES (TREE_TYPE (arg)),
                                       parm, &nsubsts, 0, strict);
            }
@@ -3022,20 +3348,18 @@ int
 more_specialized (pat1, pat2)
      tree pat1, pat2;
 {
-  tree *targs;
+  tree targs;
   int winner = 0;
 
   targs = get_bindings (pat1, pat2);
   if (targs)
     {
-      free (targs);
       --winner;
     }
 
   targs = get_bindings (pat2, pat1);
   if (targs)
     {
-      free (targs);
       ++winner;
     }
 
@@ -3071,20 +3395,21 @@ more_specialized_class (pat1, pat2)
 /* Return the template arguments that will produce the function signature
    DECL from the function template FN.  */
 
-tree *
+tree 
 get_bindings (fn, decl)
      tree fn, decl;
 {
-  int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
-  tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
-  int i, dummy = 0;
-  i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
-                       TYPE_ARG_TYPES (TREE_TYPE (fn)),
-                       TYPE_ARG_TYPES (TREE_TYPE (decl)),
-                       &dummy, 0, 1);
+  int ntparms = DECL_NTPARMS (fn);
+  tree targs = make_tree_vec (ntparms);
+  int i;
+
+  i = fn_type_unification (fn, targs, 
+                          TYPE_ARG_TYPES (TREE_TYPE (decl)), 
+                          TREE_TYPE (TREE_TYPE (decl)),
+                          1);
+
   if (i == 0)
     return targs;
-  free (targs);
   return 0;
 }
 
@@ -3122,7 +3447,7 @@ tree
 most_specialized (fns, decl)
      tree fns, decl;
 {
-  tree fn, champ, *args, *p;
+  tree fn, champ, args, *p;
   int fate;
 
   for (p = &fns; *p; )
@@ -3130,7 +3455,6 @@ most_specialized (fns, decl)
       args = get_bindings (TREE_VALUE (*p), decl);
       if (args)
        {
-         free (args);
          p = &TREE_CHAIN (*p);
        }
       else
@@ -3234,6 +3558,7 @@ do_decl_instantiation (declspecs, declarator, storage)
   tree fn;
   tree result = NULL_TREE;
   int extern_p = 0;
+  tree templates = NULL_TREE;
 
   if (! DECL_LANG_SPECIFIC (decl))
     {
@@ -3261,43 +3586,61 @@ do_decl_instantiation (declspecs, declarator, storage)
               fn = IDENTIFIER_GLOBAL_VALUE (name),
               fn && DECL_TEMPLATE_INSTANTIATION (fn))
        result = fn;
+      else 
+       {
+         /* Maybe this is an instantiation of a member template
+            function.  */
+         tree ctype = DECL_CONTEXT (decl);
+
+         name = DECL_NAME (decl);
+         fn = lookup_fnfields (TYPE_BINFO (ctype), name, 1);
+         if (fn)
+           fn = TREE_VALUE (fn);
+
+         for (; fn; fn = DECL_CHAIN (fn))
+           if (decls_match (fn, decl) && DECL_DEFER_OUTPUT (fn))
+             {
+               result = fn;
+               break;
+             }
+           else if (TREE_CODE (fn) == TEMPLATE_DECL)
+             templates = decl_tree_cons (NULL_TREE, fn, templates);
+       }
     }
   else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
     {
-      tree templates = NULL_TREE;
       for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
-       if (decls_match (fn, decl)
-           && DECL_DEFER_OUTPUT (fn))
+       if (decls_match (fn, decl) && DECL_DEFER_OUTPUT (fn))
          {
            result = fn;
            break;
          }
        else if (TREE_CODE (fn) == TEMPLATE_DECL)
          templates = decl_tree_cons (NULL_TREE, fn, templates);
+    }
 
-      if (! result)
+  if (templates && !result)
+    {
+      tree args;
+      result = most_specialized (templates, decl);
+      if (result == error_mark_node)
        {
-         tree *args;
-         result = most_specialized (templates, decl);
-         if (result == error_mark_node)
+         char *str = "candidates are:";
+         cp_error ("ambiguous template instantiation for `%D' requested", decl);
+         for (fn = templates; fn; fn = TREE_CHAIN (fn))
            {
-             char *str = "candidates are:";
-             cp_error ("ambiguous template instantiation for `%D' requested", decl);
-             for (fn = templates; fn; fn = TREE_CHAIN (fn))
-               {
-                 cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
-                 str = "               ";
-               }
-             return;
-           }
-         else if (result)
-           {
-             args = get_bindings (result, decl);
-             result = instantiate_template (result, args);
-             free (args);
+             cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
+             str = "               ";
            }
+         return;
+       }
+      else if (result)
+       {
+         args = get_bindings (result, decl);
+         result = instantiate_template (result, args);
        }
     }
+
   if (! result)
     {
       cp_error ("no matching template for `%D' found", decl);
@@ -3477,7 +3820,7 @@ instantiate_decl (d)
     {
       pushclass (DECL_CONTEXT (d), 2);
       DECL_INITIAL (d) = tsubst_expr
-       (DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0),
+       (DECL_INITIAL (pattern), args,
         TREE_VEC_LENGTH (args), tmpl);
       popclass (1);
     }
@@ -3527,7 +3870,7 @@ instantiate_decl (d)
   /* Trick tsubst into giving us a new decl in case the template changed.  */
   save_ti = DECL_TEMPLATE_INFO (pattern);
   DECL_TEMPLATE_INFO (pattern) = NULL_TREE;
-  td = tsubst (pattern, &TREE_VEC_ELT (args, 0), TREE_VEC_LENGTH (args), tmpl);
+  td = tsubst (pattern, args, TREE_VEC_LENGTH (args), tmpl);
   DECL_TEMPLATE_INFO (pattern) = save_ti;
 
   /* And set up DECL_INITIAL, since tsubst doesn't.  */
@@ -3535,7 +3878,7 @@ instantiate_decl (d)
     {
       pushclass (DECL_CONTEXT (d), 2);
       DECL_INITIAL (td) = tsubst_expr
-       (DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0),
+       (DECL_INITIAL (pattern), args,
         TREE_VEC_LENGTH (args), tmpl);
       popclass (1);
     }
@@ -3570,7 +3913,7 @@ instantiate_decl (d)
        {
          store_return_init
            (TREE_OPERAND (t, 0),
-            tsubst_expr (TREE_OPERAND (t, 1), &TREE_VEC_ELT (args, 0),
+            tsubst_expr (TREE_OPERAND (t, 1), args,
                          TREE_VEC_LENGTH (args), tmpl));
          t = TREE_CHAIN (t);
        }
@@ -3591,8 +3934,7 @@ instantiate_decl (d)
       keep_next_level ();
 
       my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
-      tsubst_expr (t, &TREE_VEC_ELT (args, 0),
-                  TREE_VEC_LENGTH (args), tmpl);
+      tsubst_expr (t, args, TREE_VEC_LENGTH (args), tmpl);
 
       finish_function (lineno, 0, nested);
     }
@@ -3613,14 +3955,13 @@ tsubst_chain (t, argvec)
 {
   if (t)
     {
-      tree first = tsubst (t, &TREE_VEC_ELT (argvec, 0),
+      tree first = tsubst (t, argvec,
                           TREE_VEC_LENGTH (argvec), NULL_TREE);
       tree last = first;
 
       for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
        {
-         tree x = tsubst (t, &TREE_VEC_ELT (argvec, 0),
-                          TREE_VEC_LENGTH (argvec), NULL_TREE);
+         tree x = tsubst (t, argvec, TREE_VEC_LENGTH (argvec), NULL_TREE);
          TREE_CHAIN (last) = x;
          last = x;
        }
@@ -3639,9 +3980,9 @@ tsubst_expr_values (t, argvec)
 
   for (; t; t = TREE_CHAIN (t))
     {
-      tree pur = tsubst_copy (TREE_PURPOSE (t), &TREE_VEC_ELT (argvec, 0),
+      tree pur = tsubst_copy (TREE_PURPOSE (t), argvec,
                              TREE_VEC_LENGTH (argvec), NULL_TREE);
-      tree val = tsubst_expr (TREE_VALUE (t), &TREE_VEC_ELT (argvec, 0),
+      tree val = tsubst_expr (TREE_VALUE (t), argvec,
                              TREE_VEC_LENGTH (argvec), NULL_TREE);
       *p = build_tree_list (pur, val);
       p = &TREE_CHAIN (*p);
@@ -3691,7 +4032,7 @@ add_maybe_template (d, fns)
 
 static tree
 tsubst_enum (tag, args, nargs)
-     tree tag, *args;
+     tree tag, args;
      int nargs;
 {
   tree newtag = start_enum (TYPE_IDENTIFIER (tag));
index 29f8ef345198f21083b90ae82e524e50415bf009..078793c8cfa454eaeb92bdf239a63f82a53c4775 100644 (file)
@@ -1637,6 +1637,23 @@ lookup_fnfields_1 (type, name)
          if (DECL_NAME (*methods) == name)
            break;
        }
+
+      /* If we didn't find it, it might have been a template
+        conversion operator.  (Note that we don't look for this case
+        above so that we will always find specializations first.)  */
+      if (methods == end 
+         && IDENTIFIER_TYPENAME_P (name)) 
+       {
+         methods = &TREE_VEC_ELT (method_vec, 0) + 1;
+         
+         while (++methods != end)
+           {
+             if (TREE_CODE (*methods) == TEMPLATE_DECL 
+                 && IDENTIFIER_TYPENAME_P (DECL_NAME (*methods)))
+               break;
+           }
+       }
+
       if (methods != end)
        return methods - &TREE_VEC_ELT (method_vec, 0);
     }
index e12050ddd30c19e656192bd2eb8c40d6ee583af0..bf542af547ff2047eef11e354262e2c535c85674 100644 (file)
@@ -2005,7 +2005,8 @@ cp_tree_equal (t1, t2)
       return 0;
 
     case TEMPLATE_CONST_PARM:
-      return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2);
+      return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2)
+       && TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2);
 
     case SIZEOF_EXPR:
       if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
index a442d4ec85a426d46660ebf6ac1f9493bc1b7a80..b000efbead5abe8954e02b41054a9e7d80168abb 100644 (file)
@@ -832,7 +832,8 @@ comptypes (type1, type2, strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2);
+      return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2)
+       && TEMPLATE_TYPE_LEVEL (t1) == TEMPLATE_TYPE_LEVEL (t2);
 
     case TYPENAME_TYPE:
       if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
@@ -2296,7 +2297,8 @@ build_x_function_call (function, params, decl)
     {
       tree basetype = NULL_TREE;
 
-      if (TREE_CODE (function) == FUNCTION_DECL)
+      if (TREE_CODE (function) == FUNCTION_DECL
+         || DECL_FUNCTION_TEMPLATE_P (function))
        {
          basetype = DECL_CLASS_CONTEXT (function);
 
This page took 0.172716 seconds and 5 git commands to generate.