OSDN Git Service

* call.c (add_template_candidate): Adjust for changes to
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 11 May 1998 07:25:25 +0000 (07:25 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 11 May 1998 07:25:25 +0000 (07:25 +0000)
fn_type_unification.
(add_template_candidate_real): Likewise.
(add_template_conv_candidate): Likewise.
(build_user_type_conversion_1): Likewise.
(build_new_function_call): Likewise.
(build_object_call): Likewise.
(build_new_op): Likewise.
(build_new_method_call): Likewise.
* class.c (instantiate_type): Likewise.
* cp-tree.h (unification_kind_t): New type.
(fn_type_unification): Adjust prototype.
(type_unificaiton): Likewise.
* pt.c (UNIFY_ALLOW_NONE): New macro.
(UNIFY_ALLOW_MORE_CV_QUAL): Likewise.
(UNIFY_ALLOW_LESS_CV_QUAL): Likewise.
(UNIFY_ALLOW_DERIVED): Likewise.
(unify): Change prototype.
(maybe_adjust_types_for_deduction): New function.
(check_cv_quals_for_unify): Likewise.
(determine_specialization): Adjust.
(fn_type_unification): Likewise.
(type_unification): Likewise.
(type_unification_real): Likewise.  Use
maybe_adjust_types_for_deduction.  Fix mishandling of
back-unification of template functions passed as arguments.  Pass
appropriate combination of UNIFY_ALLOW_* to unify.
(unify): Remove unused NTPARMS parameter.  Use
check_cv_quals_for_unify.  Remove bogus code that allowed
too-generous unification in order to adhere more closely to standard.
(get_bindings_real): Adjust.
(get_class_bindings): Likewise.
* method.c (build_overload_identifier): Only use the innermost
template arguments when mangling.
* pt.c (tsubst_template_argument_vector): New function.
(complete_template_args): Deal with the situation where the
extra_args contain more than one level of arguments.
(lookup_template_class): Deal with member template classes, which
may have more than one level of arguments.
(tsubst): Don't tsbust into the TREE_TYPE of an IDENTIFIER_NODE.
Improve handling of member template classes.  Use
DECL_PRIMARY_TEMPLATE instead of inline expansion.  Use
tsubst_template_argument_vector where appropriate.
(regenerate_decl_from_template): Break out from ...
(instantiate_decl): Here.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@19663 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/method.c
gcc/cp/pt.c
gcc/testsuite/g++.old-deja/g++.pt/conv1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/memclass9.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/unify3.C [new file with mode: 0644]

index 6e9b82d..03fae3f 100644 (file)
@@ -1,5 +1,52 @@
 Mon May 11 07:16:30 1998  Mark Mitchell  <mmitchell@usa.net>
 
+       * call.c (add_template_candidate): Adjust for changes to
+       fn_type_unification. 
+       (add_template_candidate_real): Likewise.
+       (add_template_conv_candidate): Likewise.
+       (build_user_type_conversion_1): Likewise.
+       (build_new_function_call): Likewise.
+       (build_object_call): Likewise.
+       (build_new_op): Likewise.
+       (build_new_method_call): Likewise.
+       * class.c (instantiate_type): Likewise.
+       * cp-tree.h (unification_kind_t): New type.
+       (fn_type_unification): Adjust prototype.
+       (type_unificaiton): Likewise.
+       * pt.c (UNIFY_ALLOW_NONE): New macro.
+       (UNIFY_ALLOW_MORE_CV_QUAL): Likewise.
+       (UNIFY_ALLOW_LESS_CV_QUAL): Likewise.
+       (UNIFY_ALLOW_DERIVED): Likewise.
+       (unify): Change prototype.
+       (maybe_adjust_types_for_deduction): New function.
+       (check_cv_quals_for_unify): Likewise.
+       (determine_specialization): Adjust.
+       (fn_type_unification): Likewise.
+       (type_unification): Likewise.
+       (type_unification_real): Likewise.  Use
+       maybe_adjust_types_for_deduction.  Fix mishandling of
+       back-unification of template functions passed as arguments.  Pass
+       appropriate combination of UNIFY_ALLOW_* to unify.
+       (unify): Remove unused NTPARMS parameter.  Use
+       check_cv_quals_for_unify.  Remove bogus code that allowed
+       too-generous unification in order to adhere more closely to standard.
+       (get_bindings_real): Adjust.
+       (get_class_bindings): Likewise.
+
+       * method.c (build_overload_identifier): Only use the innermost
+       template arguments when mangling.
+       * pt.c (tsubst_template_argument_vector): New function.
+       (complete_template_args): Deal with the situation where the
+       extra_args contain more than one level of arguments.
+       (lookup_template_class): Deal with member template classes, which
+       may have more than one level of arguments.
+       (tsubst): Don't tsbust into the TREE_TYPE of an IDENTIFIER_NODE.
+       Improve handling of member template classes.  Use
+       DECL_PRIMARY_TEMPLATE instead of inline expansion.  Use
+       tsubst_template_argument_vector where appropriate.
+       (regenerate_decl_from_template): Break out from ...
+       (instantiate_decl): Here.
+       
        * lex.c (yyprint): Remove TYPENAME_ELLIPSIS.
        * parse.h: Regenerated.
        * parse.c: Really regenerated.
index e9ca9af..5eafd87 100644 (file)
@@ -61,9 +61,11 @@ 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, tree, tree, int));
+       PROTO((struct z_candidate *, tree, tree, tree, tree, int,
+              unification_kind_t));
 static struct z_candidate * add_template_candidate_real
-       PROTO((struct z_candidate *, tree, tree, tree, tree, int, tree));
+       PROTO((struct z_candidate *, tree, tree, tree, tree, int,
+              tree, unification_kind_t));
 static struct z_candidate * add_template_conv_candidate 
         PROTO((struct z_candidate *, tree, tree, tree, tree));
 static struct z_candidate * add_builtin_candidates
@@ -1865,11 +1867,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
 static struct z_candidate*
 add_template_candidate_real (candidates, tmpl, explicit_targs,
                             arglist, return_type, flags,
-                            obj)
+                            obj, strict)
      struct z_candidate *candidates;
      tree tmpl, explicit_targs, arglist, return_type;
      int flags;
      tree obj;
+     unification_kind_t strict;
 {
   int ntparms = DECL_NTPARMS (tmpl);
   tree targs = make_scratch_vec (ntparms);
@@ -1878,7 +1881,7 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
   tree fn;
 
   i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
-                          return_type, 0, NULL_TREE); 
+                          return_type, strict, NULL_TREE);
 
   if (i != 0)
     return candidates;
@@ -1920,14 +1923,16 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
 
 static struct z_candidate *
 add_template_candidate (candidates, tmpl, explicit_targs, 
-                       arglist, return_type, flags)
+                       arglist, return_type, flags, strict)
      struct z_candidate *candidates;
      tree tmpl, explicit_targs, arglist, return_type;
      int flags;
+     unification_kind_t strict;
 {
   return 
     add_template_candidate_real (candidates, tmpl, explicit_targs,
-                                arglist, return_type, flags, NULL_TREE);
+                                arglist, return_type, flags,
+                                NULL_TREE, strict);
 }
 
 
@@ -1938,7 +1943,7 @@ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
 {
   return 
     add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist,
-                                return_type, 0, obj);
+                                return_type, 0, obj, DEDUCE_CONV);
 }
 
 
@@ -2058,7 +2063,8 @@ build_user_type_conversion_1 (totype, expr, flags)
          templates = scratch_tree_cons (NULL_TREE, ctor, templates);
          candidates = 
            add_template_candidate (candidates, ctor,
-                                   NULL_TREE, args, NULL_TREE, flags);
+                                   NULL_TREE, args, NULL_TREE, flags,
+                                   DEDUCE_CALL);
        } 
       else 
        candidates = add_function_candidate (candidates, ctor,
@@ -2107,7 +2113,8 @@ build_user_type_conversion_1 (totype, expr, flags)
                templates = scratch_tree_cons (NULL_TREE, fn, templates);
                candidates = 
                  add_template_candidate (candidates, fn, NULL_TREE,
-                                         args, totype, flags);
+                                         args, totype, flags,
+                                         DEDUCE_CONV);
              } 
            else 
              candidates = add_function_candidate (candidates, fn,
@@ -2261,7 +2268,7 @@ build_new_function_call (fn, args)
              templates = scratch_tree_cons (NULL_TREE, t, templates);
              candidates = add_template_candidate
                (candidates, t, explicit_targs, args, NULL_TREE,
-                LOOKUP_NORMAL);  
+                LOOKUP_NORMAL, DEDUCE_CALL);  
            }
          else if (! template_only)
            candidates = add_function_candidate
@@ -2346,7 +2353,7 @@ build_object_call (obj, args)
              candidates 
                = add_template_candidate (candidates, fn, NULL_TREE,
                                          mem_args, NULL_TREE, 
-                                         LOOKUP_NORMAL);
+                                         LOOKUP_NORMAL, DEDUCE_CALL);
            }
          else
            candidates = add_function_candidate
@@ -2603,7 +2610,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
          candidates 
            = add_template_candidate (candidates, fn, NULL_TREE,
                                      arglist, TREE_TYPE (fnname),
-                                     flags); 
+                                     flags, DEDUCE_CALL); 
        }
       else
        candidates = add_function_candidate (candidates, fn, arglist, flags);
@@ -2639,7 +2646,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
              candidates 
                = add_template_candidate (candidates, fn, NULL_TREE,
                                          this_arglist,  TREE_TYPE (fnname),
-                                         flags); 
+                                         flags, DEDUCE_CALL); 
            }
          else
            candidates = add_function_candidate
@@ -3591,7 +3598,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
              candidates = 
                add_template_candidate (candidates, t, explicit_targs,
                                        this_arglist,
-                                       TREE_TYPE (name), flags); 
+                                       TREE_TYPE (name), flags, DEDUCE_CALL); 
            }
          else if (! template_only)
            candidates = add_function_candidate (candidates, t,
index 9ba2824..17cfe2b 100644 (file)
@@ -5151,7 +5151,7 @@ instantiate_type (lhstype, rhs, complain)
                i = type_unification
                  (DECL_INNERMOST_TEMPLATE_PARMS (elem), t,
                   TYPE_ARG_TYPES (TREE_TYPE (elem)),
-                  TYPE_ARG_TYPES (lhstype), explicit_targs, 1, 1);
+                  TYPE_ARG_TYPES (lhstype), explicit_targs, DEDUCE_EXACT, 1);
                if (i == 0)
                  {
                    if (save_elem)
index f044553..e76c85b 100644 (file)
@@ -1683,6 +1683,16 @@ extern tree null_node;
 
 /* in pt.c  */
 
+/* These values are used for the `STRICT' parameter to type_unfication and
+   fn_type_unification.  Their meanings are described with the
+   documentation for fn_type_unification.  */
+
+typedef enum unification_kind_t {
+  DEDUCE_CALL,
+  DEDUCE_CONV,
+  DEDUCE_EXACT
+} unification_kind_t;
+
 extern tree current_template_parms;
 extern HOST_WIDE_INT processing_template_decl;
 extern tree last_tree;
@@ -2504,8 +2514,8 @@ extern int uses_template_parms                    PROTO((tree));
 extern tree instantiate_class_template         PROTO((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, tree, int, tree));
-extern int type_unification                    PROTO((tree, tree, tree, tree, tree, int, int));
+extern int fn_type_unification                  PROTO((tree, tree, tree, tree, tree, unification_kind_t, tree));
+extern int type_unification                    PROTO((tree, tree, tree, tree, tree, unification_kind_t, int));
 struct tinst_level *tinst_for_decl             PROTO((void));
 extern void mark_decl_instantiated             PROTO((tree, int));
 extern int more_specialized                    PROTO((tree, tree, tree));
index 9d8b8f0..ef048f3 100644 (file)
@@ -893,7 +893,7 @@ build_overload_identifier (name)
     {
       tree template, parmlist, arglist, tname;
       template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
-      arglist = TREE_VALUE (template);
+      arglist = innermost_args (TREE_VALUE (template), 0);
       template = TREE_PURPOSE (template);
       tname = DECL_NAME (template);
       parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
index f30164f..e9e6304 100644 (file)
@@ -70,7 +70,12 @@ static tree saved_trees;
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-static int unify PROTO((tree, tree, int, tree, tree, int, int*));
+#define UNIFY_ALLOW_NONE 0
+#define UNIFY_ALLOW_MORE_CV_QUAL 1
+#define UNIFY_ALLOW_LESS_CV_QUAL 2
+#define UNIFY_ALLOW_DERIVED 4
+
+static int unify PROTO((tree, tree, tree, tree, int, int*));
 static void add_pending_template PROTO((tree));
 static int push_tinst_level PROTO((tree));
 static tree classtype_mangled_name PROTO((tree));
@@ -81,8 +86,10 @@ 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));
+static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
+                                                   tree*)); 
 static int  type_unification_real PROTO((tree, tree, tree, tree,
-                                        int, int, int, int*));
+                                        int, unification_kind_t, int, int*));
 static tree complete_template_args PROTO((tree, tree, int));
 static void note_template_header PROTO((int));
 static tree maybe_fold_nontype_arg PROTO((tree));
@@ -104,6 +111,9 @@ static tree tsubst_friend_class PROTO((tree, tree));
 static tree get_bindings_real PROTO((tree, tree, tree, int));
 static int template_decl_level PROTO((tree));
 static tree maybe_get_template_decl_from_type_decl PROTO((tree));
+static int check_cv_quals_for_unify PROTO((int, tree, tree));
+static tree tsubst_template_arg_vector PROTO((tree, tree));
+static void regenerate_decl_from_template PROTO((tree, tree));
 
 /* Do any processing required when DECL (a member template declaration
    using TEMPLATE_PARAMETERS as its innermost parameter list) is
@@ -360,7 +370,7 @@ is_member_template (t)
 }
 
 /* Return a new template argument vector which contains all of ARGS
-   for all outer templates TYPE is contained in, but has as its 
+   for all outer templates TMPL is contained in, but has as its 
    innermost set of arguments the EXTRA_ARGS.  If UNBOUND_ONLY, we
    are only interested in unbound template arguments, not arguments from
    enclosing templates that have been instantiated already.  */
@@ -373,10 +383,16 @@ complete_template_args (tmpl, extra_args, unbound_only)
   /* depth is the number of levels of enclosing args we're adding.  */
   int depth, i;
   tree args, new_args, spec_args = NULL_TREE;
-  
+  int extra_arg_depth;
+
   my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
   my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
 
+  if (TREE_CODE (TREE_VEC_ELT (extra_args, 0)) == TREE_VEC)
+    extra_arg_depth = TREE_VEC_LENGTH (extra_args);
+  else
+    extra_arg_depth = 1;
+
   if (DECL_TEMPLATE_INFO (tmpl) && !unbound_only)
     {
       /* A specialization of a member template of a template class shows up
@@ -405,7 +421,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
           template args.  */
        depth = 0;
 
-      new_args = make_tree_vec (depth + 1 + (!!spec_args));
+      new_args = make_tree_vec (depth + extra_arg_depth + (!!spec_args));
 
       if (depth == 1)
        TREE_VEC_ELT (new_args, 0) = args;
@@ -427,7 +443,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
       if (depth == 0)
        return extra_args;
 
-      new_args = make_tree_vec (depth + 1);
+      new_args = make_tree_vec (depth + extra_arg_depth);
 
       /* If this isn't a member template, extra_args is for the innermost
         template class, so skip over it.  */
@@ -447,10 +463,14 @@ complete_template_args (tmpl, extra_args, unbound_only)
          }
     }
 
-  TREE_VEC_ELT (new_args, depth) = extra_args;
+  if (extra_arg_depth == 1)
+    TREE_VEC_ELT (new_args, depth++) = extra_args;
+  else
+    for (i = 0; i < extra_arg_depth; ++i)
+      TREE_VEC_ELT (new_args, depth++) = TREE_VEC_ELT (extra_args, i);
 
   if (spec_args)
-    TREE_VEC_ELT (new_args, depth + 1) = spec_args;
+    TREE_VEC_ELT (new_args, depth) = spec_args;
 
   return new_args;
 }
@@ -776,7 +796,7 @@ determine_specialization (template_id, decl, targs_out,
                                NULL_TREE,
                                NULL_TREE,  
                                targs_in,
-                               1, 1);
+                               DEDUCE_EXACT, 1);
       
          if (i == 0) 
            /* Unification was successful.  */
@@ -1814,8 +1834,15 @@ push_template_decl_real (decl, is_friend)
          cp_error ("  but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
        }
     }
-  /* Get the innermost set of template arguments. */
-  args = innermost_args (args, 0);
+  /* Get the innermost set of template arguments.  We don't do this
+     for a non-template member function of a nested template class
+     because there we will never get a `partial instantiation' of the
+     function containing the outer arguments, and so we must save all
+     of the arguments here.  */
+  if (TREE_CODE (decl) != FUNCTION_DECL 
+      || template_class_depth (ctx) <= 1
+      || primary)
+    args = innermost_args (args, 0);
 
   DECL_TEMPLATE_RESULT (tmpl) = decl;
   TREE_TYPE (tmpl) = TREE_TYPE (decl);
@@ -2904,11 +2931,36 @@ lookup_template_class (d1, arglist, in_decl, context)
           || (TREE_CODE (TYPE_CONTEXT (TREE_TYPE (template))) 
               == FUNCTION_DECL))
     {
+      tree arglist_for_mangling;
+
       parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
 
-      arglist = coerce_template_parms (parmlist, arglist, template,
-                                      1, 1, 0);
-      if (arglist == error_mark_node)
+      if (/* ARGLIST can be NULL_TREE if there are default arguments.  */
+         arglist != NULL_TREE
+         && TREE_CODE (arglist) == TREE_VEC 
+         && TREE_VEC_LENGTH (arglist) > 1
+         && list_length (DECL_TEMPLATE_PARMS (template)) > 1)
+       {
+         /* We have multiple levels of arguments to coerce, at once.  */
+         tree new_args = 
+           make_tree_vec (list_length (DECL_TEMPLATE_PARMS (template)));
+         int i;
+         
+         for (i = TREE_VEC_LENGTH (arglist) - 1, 
+                t = DECL_TEMPLATE_PARMS (template); 
+              i >= 0 && t != NULL_TREE;
+              --i, t = TREE_CHAIN (t))
+           TREE_VEC_ELT (new_args, i) =
+             coerce_template_parms (TREE_VALUE (t),
+                                    TREE_VEC_ELT (arglist, i),
+                                    template, 1, 1, 0);
+         arglist = new_args;
+       }
+      else
+       arglist = coerce_template_parms (parmlist, 
+                                        innermost_args (arglist, 0),
+                                        template, 1, 1, 0);
+     if (arglist == error_mark_node)
        return error_mark_node;
       if (uses_template_parms (arglist))
        {
@@ -2937,10 +2989,15 @@ lookup_template_class (d1, arglist, in_decl, context)
            }
        }
 
+      if (TREE_CODE (arglist) == TREE_VEC)
+       arglist_for_mangling = innermost_args (arglist, 0);
+      else
+       arglist_for_mangling = arglist;
+
       /* FIXME avoid duplication.  */
       mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
                                                     parmlist,
-                                                    arglist,
+                                                    arglist_for_mangling,
                                                     id_context);
       id = get_identifier (mangled_name);
       IDENTIFIER_TEMPLATE (id) = d1;
@@ -3875,11 +3932,46 @@ innermost_args (args, is_spec)
      tree args;
      int is_spec;
 {
-  if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+  if (args != NULL_TREE && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
     return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
   return args;
 }
 
+/* Substitute ARGS into the vector of template arguments T.  */
+
+tree
+tsubst_template_arg_vector (t, args)
+     tree t;
+     tree args;
+{
+  int len = TREE_VEC_LENGTH (t), need_new = 0, i;
+  tree *elts = (tree *) alloca (len * sizeof (tree));
+  
+  bzero ((char *) elts, len * sizeof (tree));
+  
+  for (i = 0; i < len; i++)
+    {
+      if (TREE_VEC_ELT (t, i) != NULL_TREE
+         && TREE_CODE (TREE_VEC_ELT (t, i)) == TREE_VEC)
+       elts[i] = tsubst_template_arg_vector (TREE_VEC_ELT (t, i), args);
+      else
+       elts[i] = maybe_fold_nontype_arg
+         (tsubst_expr (TREE_VEC_ELT (t, i), args, NULL_TREE));
+      
+      if (elts[i] != TREE_VEC_ELT (t, i))
+       need_new = 1;
+    }
+  
+  if (!need_new)
+    return t;
+  
+  t = make_tree_vec (len);
+  for (i = 0; i < len; i++)
+    TREE_VEC_ELT (t, i) = elts[i];
+  
+  return t;
+}
+
 /* Take the tree structure T and replace template parameters used therein
    with the argument vector ARGS.  IN_DECL is an associated decl for
    diagnostics.
@@ -3907,7 +3999,9 @@ tsubst (t, args, in_decl)
     type = TREE_TYPE (t);
   if (type == unknown_type_node)
     my_friendly_abort (42);
+
   if (type && TREE_CODE (t) != FUNCTION_DECL
+      && TREE_CODE (t) != IDENTIFIER_NODE
       && TREE_CODE (t) != TYPENAME_TYPE
       && TREE_CODE (t) != TEMPLATE_DECL
       && TREE_CODE (t) != IDENTIFIER_NODE)
@@ -3932,14 +4026,33 @@ tsubst (t, args, in_decl)
          tree context;
          tree r;
 
-         context = 
-           TYPE_CONTEXT (t) 
-           ? tsubst (TYPE_CONTEXT (t), args, in_decl) : NULL_TREE;
+         if (TYPE_CONTEXT (t) != NULL_TREE)
+           {
+             context = tsubst (TYPE_CONTEXT (t), args, in_decl);
+         
+             if (TREE_CODE (context) != FUNCTION_DECL
+                 && TREE_CODE (context) != NAMESPACE_DECL)
+               {
+                 /* For a member class template, we need all the
+                    template arguments.  */
+                 if (CLASSTYPE_IS_TEMPLATE (TYPE_CONTEXT (t)))
+                   argvec = 
+                     add_to_template_args (CLASSTYPE_TI_ARGS (context),
+                                           argvec);
+
+                 if (CLASSTYPE_TEMPLATE_INFO (context))
+                   argvec = 
+                     complete_template_args (CLASSTYPE_TI_TEMPLATE (context),
+                                             argvec, 0);
+               }
+           }
+         else
+           context = NULL_TREE;
 
          r = lookup_template_class (t, argvec, in_decl, context);
 
          return cp_build_type_variant (r, TYPE_READONLY (t),
-                               TYPE_VOLATILE (t));
+                                       TYPE_VOLATILE (t));
        }
 
       /* else fall through */
@@ -4208,7 +4321,7 @@ tsubst (t, args, in_decl)
          }
 
        if (PRIMARY_TEMPLATE_P (t))
-         TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl;
+         DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
 
        /* We don't partially instantiate partial specializations.  */
        if (TREE_CODE (decl) == TYPE_DECL)
@@ -4646,30 +4759,8 @@ tsubst (t, args, in_decl)
        }
 
       /* Otherwise, a vector of template arguments.  */
-      {
-       int len = TREE_VEC_LENGTH (t), need_new = 0, i;
-       tree *elts = (tree *) alloca (len * sizeof (tree));
-
-       bzero ((char *) elts, len * sizeof (tree));
-
-       for (i = 0; i < len; i++)
-         {
-           elts[i] = maybe_fold_nontype_arg
-             (tsubst_expr (TREE_VEC_ELT (t, i), args, in_decl));
-
-           if (elts[i] != TREE_VEC_ELT (t, i))
-             need_new = 1;
-         }
-
-       if (!need_new)
-         return t;
+      return tsubst_template_arg_vector (t, args);
 
-       t = make_tree_vec (len);
-       for (i = 0; i < len; i++)
-         TREE_VEC_ELT (t, i) = elts[i];
-       
-       return t;
-      }
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       {
@@ -5493,7 +5584,7 @@ int
 fn_type_unification (fn, explicit_targs, targs, args, return_type,
                     strict, extra_fn_arg)
      tree fn, explicit_targs, targs, args, return_type;
-     int strict;
+     unification_kind_t strict;
      tree extra_fn_arg;
 {
   int i;
@@ -5553,22 +5644,37 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
    a function or method parameter of a function template), so don't zero
    out targs and don't fail on an incomplete match.
 
-   If STRICT is 1, the match must be exact (for casts of overloaded
-   addresses, explicit instantiation, and more_specialized).  */
+   The parameter STRICT is one of:
+
+   DEDUCE_CALL: 
+     We are deducing arguments for a function call, as in
+     [temp.deduct.call].
+
+   DEDUCE_CONV:
+     We are deducing arguments for a conversion function, as in 
+     [temp.deduct.conv].
+
+   DEDUCE_EXACT:
+     We are deducing arguments when calculating the partial
+     ordering between specializations of function or class
+     templates, as in [temp.func.order] and [temp.class.order],
+     when doing an explicit instantiation as in [temp.explicit],
+     when determiningan explicit specialization as in
+     [temp.expl.spec], or when taking the address of a function
+     template, as in [temp.deduct.funcaddr].  */
 
 int
 type_unification (tparms, targs, parms, args, targs_in,
                  strict, allow_incomplete)
      tree tparms, targs, parms, args, targs_in;
-     int strict, allow_incomplete;
+     unification_kind_t strict;
+     int allow_incomplete;
 {
-  int ntparms = TREE_VEC_LENGTH (tparms);
   tree arg;
   int* explicit_mask;
   int i;
-  int r;
 
-  for (i = 0; i < ntparms; i++)
+  for (i = 0; i < TREE_VEC_LENGTH (tparms); i++)
     TREE_VEC_ELT (targs, i) = NULL_TREE;
 
   if (targs_in != NULL_TREE)
@@ -5596,10 +5702,84 @@ type_unification (tparms, targs, parms, args, targs_in,
   else
     explicit_mask = 0;
 
-  r = type_unification_real (tparms, targs, parms, args, 0,
-                            strict, allow_incomplete, explicit_mask); 
+  return 
+    type_unification_real (tparms, targs, parms, args, 0,
+                          strict, allow_incomplete, explicit_mask); 
+}
+
+/* Adjust types before performing type deduction, as described in
+   [temp.deduct.call] and [temp.deduct.conv].  The rules in these two
+   sections are symmetric.  For calls, the value passed as PARM should
+   be a parameter to the template function, while ARG should be the
+   actual argument used in the call.  For conversions, PARM should be
+   the type required as the result of the conversion, while ARG should
+   be the return type of the template conversion function.  */
+
+void
+maybe_adjust_types_for_deduction (strict, parm, arg)
+     unification_kind_t strict;
+     tree* parm;
+     tree* arg;
+{
+  switch (strict)
+    {
+    case DEDUCE_CALL:
+      break;
+
+    case DEDUCE_CONV:
+      {
+       /* Swap PARM and ARG; the handling is precisely symmetric since
+          PARM will initialize ARG rather than vice versa.  */
+       tree* temp = parm;
+       parm = arg;
+       arg = temp;
+       break;
+      }
+
+    case DEDUCE_EXACT:
+      /* There is nothing to do in this case.  */
+      return;
+
+    default:
+      my_friendly_abort (0);
+    }
 
-  return r;
+  if (TREE_CODE (*parm) != REFERENCE_TYPE)
+    {
+      /* [temp.deduct.call]
+        
+        If P is not a reference type:
+        
+        --If A is an array type, the pointer type produced by the
+        array-to-pointer standard conversion (_conv.array_) is
+        used in place of A for type deduction; otherwise,
+        
+        --If A is a function type, the pointer type produced by
+        the function-to-pointer standard conversion
+        (_conv.func_) is used in place of A for type deduction;
+        otherwise,
+        
+        --If A is a cv-qualified type, the top level
+        cv-qualifiers of A's type are ignored for type
+        deduction.  */
+      if (TREE_CODE (*arg) == ARRAY_TYPE)
+       *arg = build_pointer_type (TREE_TYPE (*arg));
+      else if (TREE_CODE (*arg) == FUNCTION_TYPE
+         || TREE_CODE (*arg) == METHOD_TYPE)
+       *arg = build_pointer_type (*arg);
+      else
+       *arg = TYPE_MAIN_VARIANT (*arg);
+    }
+  
+  /* [temp.deduct.call]
+     
+     If P is a cv-qualified type, the top level cv-qualifiers
+     of P's type are ignored for type deduction.  If P is a
+     reference type, the type referred to by P is used for
+     type deduction.  */
+  *parm = TYPE_MAIN_VARIANT (*parm);
+  if (TREE_CODE (*parm) == REFERENCE_TYPE)
+    *parm = TREE_TYPE (*parm);
 }
 
 /* Like type_unfication.  EXPLICIT_MASK, if non-NULL, is an array of
@@ -5610,12 +5790,15 @@ static int
 type_unification_real (tparms, targs, parms, args, subr,
                       strict, allow_incomplete, explicit_mask)
      tree tparms, targs, parms, args;
-     int subr, strict, allow_incomplete;
+     int subr;
+     unification_kind_t strict;
+     int allow_incomplete;
      int* explicit_mask;
 {
   tree parm, arg;
   int i;
   int ntparms = TREE_VEC_LENGTH (tparms);
+  int sub_strict;
 
   my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
   my_friendly_assert (parms == NULL_TREE 
@@ -5626,6 +5809,24 @@ type_unification_real (tparms, targs, parms, args, subr,
     my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
   my_friendly_assert (ntparms > 0, 292);
 
+  switch (strict)
+    {
+    case DEDUCE_CALL:
+      sub_strict = UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_DERIVED;
+      break;
+      
+    case DEDUCE_CONV:
+      sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
+      break;
+
+    case DEDUCE_EXACT:
+      sub_strict = UNIFY_ALLOW_NONE;
+      break;
+      
+    default:
+      my_friendly_abort (0);
+    }
+
   while (parms
         && parms != void_list_node
         && args
@@ -5657,7 +5858,7 @@ type_unification_real (tparms, targs, parms, args, subr,
              arg = NULL_TREE;
            }
 
-         if (strict)
+         if (strict == DEDUCE_EXACT)
            {
              if (comptypes (parm, type, 1))
                continue;
@@ -5683,20 +5884,20 @@ type_unification_real (tparms, targs, parms, args, subr,
          if (TREE_CODE (arg) == OVERLOAD
              && TREE_CODE (OVL_FUNCTION (arg)) == TEMPLATE_DECL)
            {
-             int ntparms;
              tree targs;
+             tree arg_type;
 
              /* Have to back unify here */
              arg = OVL_FUNCTION (arg);
-             ntparms = DECL_NTPARMS (arg);
-             targs = make_scratch_vec (ntparms);
+             targs = make_scratch_vec (DECL_NTPARMS (arg));
+             arg_type = TREE_TYPE (arg);
+             maybe_adjust_types_for_deduction (strict, &parm, &arg_type);
              parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
+             arg_type = scratch_tree_cons (NULL_TREE, arg_type, NULL_TREE);
              return 
                type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg), 
-                                 targs,
-                                 TYPE_ARG_TYPES (TREE_TYPE (arg)),
-                                 parm, NULL_TREE, strict,
-                                 allow_incomplete); 
+                                 targs, arg_type, parm, NULL_TREE,
+                                 DEDUCE_EXACT, allow_incomplete); 
            }
          arg = TREE_TYPE (arg);
        }
@@ -5707,21 +5908,10 @@ type_unification_real (tparms, targs, parms, args, subr,
          arg = ptr_type_node;
        }
 
-      if (! subr && TREE_CODE (arg) == REFERENCE_TYPE)
-       arg = TREE_TYPE (arg);
+      if (!subr)
+       maybe_adjust_types_for_deduction (strict, &parm, &arg);
 
-      if (! subr && TREE_CODE (parm) != REFERENCE_TYPE)
-       {
-         if (TREE_CODE (arg) == FUNCTION_TYPE
-             || TREE_CODE (arg) == METHOD_TYPE)
-           arg = build_pointer_type (arg);
-         else if (TREE_CODE (arg) == ARRAY_TYPE)
-           arg = build_pointer_type (TREE_TYPE (arg));
-         else
-           arg = TYPE_MAIN_VARIANT (arg);
-       }
-
-      switch (unify (tparms, targs, ntparms, parm, arg, strict,
+      switch (unify (tparms, targs, parm, arg, sub_strict,
                     explicit_mask)) 
        {
        case 0:
@@ -5771,12 +5961,43 @@ template_decl_level (decl)
     }
 }
 
-/* Tail recursion is your friend.  */
+/* Decide whether ARG can be unified with PARM, considering only the
+   cv-qualifiers of each type, given STRICT as documented for unify.
+   Returns non-zero iff the unification is OK on that basis.*/
 
-static int
-unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
+int
+check_cv_quals_for_unify (strict, arg, parm)
+     int strict;
+     tree arg;
+     tree parm;
+{
+  return !((!(strict & UNIFY_ALLOW_MORE_CV_QUAL)
+           && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
+               || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm)))
+          || (!(strict & UNIFY_ALLOW_LESS_CV_QUAL)
+              && (TYPE_READONLY (arg) > TYPE_READONLY (parm)
+                  || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))));
+}
+
+/* Takes parameters as for type_unification.  Returns 0 if the
+   type deduction suceeds, 1 otherwise.  The parameter STRICT is a
+   bitwise or of the following flags:
+
+     UNIFY_ALLOW_NONE:
+       Require an exact match between PARM and ARG.
+     UNIFY_ALLOW_MORE_CV_QUAL:
+       Allow the deduced ARG to be more cv-qualified than ARG.
+     UNIFY_ALLOW_LESS_CV_QUAL:
+       Allow the deduced ARG to be less cv-qualified than ARG.
+     UNIFY_ALLOW_DERIVED:
+       Allow the deduced ARG to be a template base class of ARG,
+       or a pointer to a template base class of the type pointed to by
+       ARG.  */
+
+int
+unify (tparms, targs, parm, arg, strict, explicit_mask)
      tree tparms, targs, parm, arg;
-     int ntparms, strict;
+     int strict;
      int* explicit_mask;
 {
   int idx;
@@ -5801,11 +6022,16 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
   if (arg == parm && !uses_template_parms (parm))
     return 0;
 
-  /* We can't remove cv-quals when strict.  */
-  if (strict && TREE_CODE (arg) == TREE_CODE (parm)
+  /* Immediately reject some pairs that won't unify because of
+     cv-qualification mismatches.  */
+  if (TREE_CODE (arg) == TREE_CODE (parm)
       && TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
-      && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
-         || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm)))
+      /* We check the cv-qualifiers when unifying with template type
+        parameters below.  We want to allow ARG `const T' to unify with
+        PARM `T' for example, when computing which of two templates
+        is more specialized, for example.  */
+      && TREE_CODE (arg) != TEMPLATE_TYPE_PARM
+      && !check_cv_quals_for_unify (strict, arg, parm))
     return 1;
 
   switch (TREE_CODE (parm))
@@ -5885,8 +6111,9 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
 
                    /* This argument can be deduced.  */
 
-                   if (unify (tparms, targs, ntparms, t, 
-                              TREE_VEC_ELT (argvec, i), strict, explicit_mask))
+                   if (unify (tparms, targs, t, 
+                              TREE_VEC_ELT (argvec, i), 
+                              UNIFY_ALLOW_NONE, explicit_mask))
                      return 1;
                  }
              }
@@ -5895,25 +6122,20 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
        }
       else
        {
-         if (strict && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
-                        || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm)))
+         /* If PARM is `const T' and ARG is only `int', we don't have
+            a match unless we are allowing additional qualification.
+            If ARG is `const int' and PARM is just `T' that's OK;
+            that binds `const int' to `T'.  */
+         if (!check_cv_quals_for_unify (strict | UNIFY_ALLOW_LESS_CV_QUAL, 
+                                        arg, parm))
            return 1;
 
-#if 0
-         /* Template type parameters cannot contain cv-quals; i.e.
-            template <class T> void f (T& a, T& b) will not generate
-            void f (const int& a, const int& b).  */
-         if (TYPE_READONLY (arg) > TYPE_READONLY (parm)
-             || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))
-           return 1;
-         arg = TYPE_MAIN_VARIANT (arg);
-#else
-         {
-           int constp = TYPE_READONLY (arg) > TYPE_READONLY (parm);
-           int volatilep = TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm);
-           arg = cp_build_type_variant (arg, constp, volatilep);
-         }
-#endif
+         /* Consider the case where ARG is `const volatile int' and
+            PARM is `const T'.  Then, T should be `volatile int'.  */
+         arg = 
+           cp_build_type_variant (arg, 
+                                  TYPE_READONLY (arg) > TYPE_READONLY (parm),
+                                  TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm));
        }
 
       /* Simple cases: Value already set, does match or doesn't.  */
@@ -5954,20 +6176,48 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
       return 0;
 
     case POINTER_TYPE:
-      if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
-       return unify (tparms, targs, ntparms, parm,
-                     TYPE_PTRMEMFUNC_FN_TYPE (arg), strict, explicit_mask);
+      {
+       int sub_strict;
 
-      if (TREE_CODE (arg) != POINTER_TYPE)
-       return 1;
-      return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
-                   strict, explicit_mask);
+       if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
+         return (unify (tparms, targs, parm, 
+                        TYPE_PTRMEMFUNC_FN_TYPE (arg), strict,
+                        explicit_mask)); 
+       
+       if (TREE_CODE (arg) != POINTER_TYPE)
+         return 1;
+       
+       /* [temp.deduct.call]
+
+          A can be another pointer or pointer to member type that can
+          be converted to the deduced A via a qualification
+          conversion (_conv.qual_).
+
+          We pass down STRICT here rather than UNIFY_ALLOW_NONE.
+          This will allow for additional cv-qualification of the
+          pointed-to types if appropriate.  In general, this is a bit
+          too generous; we are only supposed to allow qualification
+          conversions and this method will allow an ARG of char** and
+          a deduced ARG of const char**.  However, overload
+          resolution will subsequently invalidate the candidate, so
+          this is probably OK.  */
+       sub_strict = strict;
+       
+       if (TREE_CODE (TREE_TYPE (arg)) != RECORD_TYPE
+           || TYPE_PTRMEMFUNC_FLAG (TREE_TYPE (arg)))
+         /* The derived-to-base conversion only persists through one
+            level of pointers.  */
+         sub_strict &= ~UNIFY_ALLOW_DERIVED;
+
+       return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE
+                     (arg), sub_strict,  explicit_mask);
+      }
 
     case REFERENCE_TYPE:
-      if (TREE_CODE (arg) == REFERENCE_TYPE)
-       arg = TREE_TYPE (arg);
-      return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg,
-                   strict, explicit_mask);
+      if (TREE_CODE (arg) != REFERENCE_TYPE)
+       return 1;
+      return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
+                   UNIFY_ALLOW_NONE, explicit_mask);
 
     case ARRAY_TYPE:
       if (TREE_CODE (arg) != ARRAY_TYPE)
@@ -5976,11 +6226,11 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
          != (TYPE_DOMAIN (arg) == NULL_TREE))
        return 1;
       if (TYPE_DOMAIN (parm) != NULL_TREE
-         && unify (tparms, targs, ntparms, TYPE_DOMAIN (parm),
-                   TYPE_DOMAIN (arg), strict, explicit_mask) != 0)
+         && unify (tparms, targs, TYPE_DOMAIN (parm),
+                   TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE, explicit_mask) != 0)
        return 1;
-      return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
-                   strict, explicit_mask);
+      return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
+                   UNIFY_ALLOW_NONE, explicit_mask);
 
     case REAL_TYPE:
     case COMPLEX_TYPE:
@@ -5993,16 +6243,20 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
       if (TREE_CODE (parm) == INTEGER_TYPE)
        {
          if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
-             && unify (tparms, targs, ntparms, TYPE_MIN_VALUE (parm),
-                       TYPE_MIN_VALUE (arg), strict, explicit_mask))
+             && unify (tparms, targs, TYPE_MIN_VALUE (parm),
+                       TYPE_MIN_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
            return 1;
          if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
-             && unify (tparms, targs, ntparms, TYPE_MAX_VALUE (parm),
-                       TYPE_MAX_VALUE (arg), strict, explicit_mask))
+             && unify (tparms, targs, TYPE_MAX_VALUE (parm),
+                       TYPE_MAX_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
            return 1;
        }
       else if (TREE_CODE (parm) == REAL_TYPE
-              && TYPE_MAIN_VARIANT (arg) != TYPE_MAIN_VARIANT (parm))
+              /* We use the TYPE_MAIN_VARIANT since we have already
+                 checked cv-qualification at the top of the
+                 function.  */
+              && !comptypes (TYPE_MAIN_VARIANT (arg),
+                             TYPE_MAIN_VARIANT (parm), 1))
        return 1;
 
       /* As far as unification is concerned, this wins.         Later checks
@@ -6027,28 +6281,32 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
        if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
          return 1;
        for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
-         if (unify (tparms, targs, ntparms,
+         if (unify (tparms, targs,
                     TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
-                    strict, explicit_mask))
+                    UNIFY_ALLOW_NONE, explicit_mask))
            return 1;
        return 0;
       }
 
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_FLAG (parm))
-       return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm),
+       return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm),
                      arg, strict, explicit_mask);
 
-      /* Allow trivial conversions.  */
-      if (TREE_CODE (arg) != RECORD_TYPE
-         || TYPE_READONLY (parm) < TYPE_READONLY (arg)
-         || TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg))
+      if (TREE_CODE (arg) != RECORD_TYPE)
        return 1;
-
+  
       if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
        {
          tree t = NULL_TREE;
-         if (! strict)
+         if (strict & UNIFY_ALLOW_DERIVED)
+           /* [temp.deduct.call]
+
+              If P is a class, and P has the form template-id, then A
+              can be a derived class of the deduced A.  Likewise, if
+              P is a pointer to a class of the form template-id, A
+              can be a pointer to a derived class pointed to by the
+              deduced A.  */
            t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
          else if
            (CLASSTYPE_TEMPLATE_INFO (arg)
@@ -6057,40 +6315,38 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
          if (! t || t == error_mark_node)
            return 1;
 
-         return unify (tparms, targs, ntparms, CLASSTYPE_TI_ARGS (parm),
-                       CLASSTYPE_TI_ARGS (t), strict, explicit_mask);
+         return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
+                       CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE,
+                       explicit_mask);
        }
-      else if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg))
+      else if (!comptypes (TYPE_MAIN_VARIANT (parm),
+                          TYPE_MAIN_VARIANT (arg), 1))
        return 1;
       return 0;
 
     case METHOD_TYPE:
-      if (TREE_CODE (arg) != METHOD_TYPE)
-       return 1;
-      goto check_args;
-
     case FUNCTION_TYPE:
-      if (TREE_CODE (arg) != FUNCTION_TYPE)
+      if (TREE_CODE (arg) != TREE_CODE (parm))
        return 1;
-     check_args:
-      if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
-                TREE_TYPE (arg), strict, explicit_mask))
+
+      if (unify (tparms, targs, TREE_TYPE (parm),
+                TREE_TYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
        return 1;
       return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
                                    TYPE_ARG_TYPES (arg), 1, 
-                                   strict, 0, explicit_mask);
+                                   DEDUCE_EXACT, 0, explicit_mask);
 
     case OFFSET_TYPE:
       if (TREE_CODE (arg) != OFFSET_TYPE)
        return 1;
-      if (unify (tparms, targs, ntparms, TYPE_OFFSET_BASETYPE (parm),
-                TYPE_OFFSET_BASETYPE (arg), strict, explicit_mask))
+      if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+                TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
        return 1;
-      return unify (tparms, targs, ntparms, TREE_TYPE (parm),
-                   TREE_TYPE (arg), strict, explicit_mask);
+      return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
+                   UNIFY_ALLOW_NONE, explicit_mask);
 
     case CONST_DECL:
-      if (arg != decl_constant_value (parm))
+      if (arg != decl_constant_value (parm)) 
        return 1;
       return 0;
 
@@ -6138,13 +6394,13 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
                                                 integer_type_node,
                                                 arg, t2));
 
-             return unify (tparms, targs, ntparms, t1, t,
-                           strict, explicit_mask);
+             return unify (tparms, targs, t1, t, UNIFY_ALLOW_NONE,
+                           explicit_mask);
            }
 
          if (!IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc)))
            /* Good, we mangaged to simplify the exression.  */
-           return unify (tparms, targs, ntparms, t, arg, strict,
+           return unify (tparms, targs, t, arg, UNIFY_ALLOW_NONE,
                          explicit_mask);
          else
            /* Bad, we couldn't simplify this.  Assume it doesn't
@@ -6282,7 +6538,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
   i = fn_type_unification (fn, explicit_args, targs, 
                           decl_arg_types,
                           TREE_TYPE (TREE_TYPE (decl)),
-                          1,
+                          DEDUCE_EXACT,
                           extra_fn_arg);
 
   if (i != 0)
@@ -6335,9 +6591,9 @@ get_class_bindings (tparms, parms, args, outer_args)
 
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
     {
-      switch (unify (tparms, vec, ntparms,
+      switch (unify (tparms, vec, 
                     TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
-                    1, 0))
+                    UNIFY_ALLOW_NONE, 0))
        {
        case 0:
          break;
@@ -6628,6 +6884,75 @@ do_type_instantiation (t, storage)
   }
 }
 
+/* Given a function DECL, which is a specialization of TEMP, modify
+   DECL to be a re-instantiation of TEMPL with the same template
+   arguments.
+
+   One reason for doing this is a scenario like this:
+
+     template <class T>
+     void f(const T&, int i);
+
+     void g() { f(3, 7); }
+
+     template <class T>
+     void f(const T& t, const int i) { }
+
+   Note that when the template is first instantiated, with
+   instantiate_template, the resulting DECL will have no name for the
+   first parameter, and the wrong type for the second.  So, when we go
+   to instantiate the DECL, we regenerate it.  */
+
+void
+regenerate_decl_from_template (decl, tmpl)
+     tree decl;
+     tree tmpl;
+{
+  tree args;
+  tree save_ti;
+  tree code_pattern;
+  tree new_decl;
+
+  args = DECL_TI_ARGS (decl);
+  code_pattern = DECL_TEMPLATE_RESULT (tmpl);
+
+  /* Trick tsubst into giving us a new decl.  CODE_PATTERN must be the
+     most distant ancestor of DECL, since that's the one that will
+     actually be altered by a redefinition.  */
+  save_ti = DECL_TEMPLATE_INFO (code_pattern);
+  DECL_TEMPLATE_INFO (code_pattern) = NULL_TREE;
+  new_decl = tsubst (code_pattern, args, NULL_TREE);
+  SET_DECL_IMPLICIT_INSTANTIATION (new_decl);
+  DECL_TEMPLATE_INFO (code_pattern) = save_ti;
+
+  if (TREE_CODE (decl) == VAR_DECL)
+    {
+      /* Set up DECL_INITIAL, since tsubst doesn't.  */
+      pushclass (DECL_CONTEXT (decl), 2);
+      DECL_INITIAL (new_decl) = 
+       tsubst_expr (DECL_INITIAL (code_pattern), args, 
+                    DECL_TI_TEMPLATE (decl));
+      popclass (1);
+    }
+
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
+        new decl.  */ 
+      DECL_INITIAL (new_decl) = error_mark_node;
+
+      if (DECL_TEMPLATE_SPECIALIZATION (new_decl) 
+         && !DECL_TEMPLATE_INFO (new_decl))
+       /* Set up the information about what is being specialized. */
+       DECL_TEMPLATE_INFO (new_decl) = DECL_TEMPLATE_INFO (decl);
+    }
+
+  duplicate_decls (new_decl, decl);
+
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    DECL_INITIAL (new_decl) = NULL_TREE;
+}
+
 /* Produce the definition of D, a _DECL generated from a template.  */
 
 tree
@@ -6637,7 +6962,7 @@ instantiate_decl (d)
   tree ti = DECL_TEMPLATE_INFO (d);
   tree tmpl = TI_TEMPLATE (ti);
   tree args = TI_ARGS (ti);
-  tree td, temp;
+  tree td;
   tree decl_pattern, code_pattern;
   tree save_ti;
   int nested = in_function_p ();
@@ -6747,38 +7072,7 @@ instantiate_decl (d)
   lineno = DECL_SOURCE_LINE (d);
   input_filename = DECL_SOURCE_FILE (d);
 
-  /* Trick tsubst into giving us a new decl in case the template changed.  */
-  save_ti = DECL_TEMPLATE_INFO (decl_pattern);
-  DECL_TEMPLATE_INFO (decl_pattern) = NULL_TREE;
-  /* decl_pattern has all but one level of template parms bound.  Only pass
-     in that one level of args.  */
-  temp = innermost_args (args, DECL_TEMPLATE_SPECIALIZATION (decl_pattern));
-  td = tsubst (decl_pattern, temp, tmpl);
-  SET_DECL_IMPLICIT_INSTANTIATION (td);
-  DECL_TEMPLATE_INFO (decl_pattern) = save_ti;
-
-  /* And set up DECL_INITIAL, since tsubst doesn't.  */
-  if (TREE_CODE (td) == VAR_DECL)
-    {
-      pushclass (DECL_CONTEXT (d), 2);
-      DECL_INITIAL (td) = tsubst_expr (DECL_INITIAL (code_pattern), args,
-                                      tmpl);
-      popclass (1);
-    }
-
-  if (TREE_CODE (d) == FUNCTION_DECL)
-    {
-      /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
-        new decl.  */ 
-      DECL_INITIAL (td) = error_mark_node;
-
-      if (DECL_TEMPLATE_SPECIALIZATION (td) && !DECL_TEMPLATE_INFO (td))
-       /* Set up the information about what is being specialized. */
-       DECL_TEMPLATE_INFO (td) = DECL_TEMPLATE_INFO (d);
-    }
-  duplicate_decls (td, d);
-  if (TREE_CODE (d) == FUNCTION_DECL)
-    DECL_INITIAL (td) = 0;
+  regenerate_decl_from_template (d, td);
 
   if (TREE_CODE (d) == VAR_DECL)
     {
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/conv1.C b/gcc/testsuite/g++.old-deja/g++.pt/conv1.C
new file mode 100644 (file)
index 0000000..19e433e
--- /dev/null
@@ -0,0 +1,19 @@
+// Build don't link:
+
+template <class T>
+struct S1 {};
+
+struct S2
+{
+  template <class T>
+  operator S1<T>*();
+};
+
+struct D: public S1<int> {
+};
+
+void f()
+{
+  S2 s;
+  (D*) s; // ERROR - cannot convert
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass9.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass9.C
new file mode 100644 (file)
index 0000000..824ee76
--- /dev/null
@@ -0,0 +1,32 @@
+// Build don't link:
+
+template <class T>
+struct S1
+{
+  template <class U>
+  struct S2
+  { 
+    S2(U);
+
+    void g() 
+      {
+       S2<U> s2u (u);
+      }
+
+    U& u;
+  };
+
+  template <class U>
+  void f(U u)
+    {
+      S2<U> s2u(u);
+      s2u.g();
+    }
+};
+
+void g()
+{
+  S1<int> s1;
+  s1.f(3.0);
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify3.C b/gcc/testsuite/g++.old-deja/g++.pt/unify3.C
new file mode 100644 (file)
index 0000000..847dc0e
--- /dev/null
@@ -0,0 +1,22 @@
+// Build don't link:
+
+template <class T1, class T2>
+struct ComputeBinaryType
+{
+};
+
+template<class T1>
+struct ComputeBinaryType<T1, double> {
+  void g();
+};
+
+template<class T1>
+struct ComputeBinaryType<T1&, double> {
+  void h();
+};
+
+void f()
+{ 
+  ComputeBinaryType<double, double> cb;
+  cb.g();
+}