error.c (dump_function_name): Don't let the user see __comp_ctor.
[gcc.git] / gcc / cp / pt.c
index f132fa525d0d0ffbc0743f3847862af44e0767dc..87d4195b3175da953e435beca08f0cfdad497a58 100644 (file)
@@ -1,5 +1,6 @@
 /* Handle parameterized types (templates) for GNU C++.
-   Copyright (C) 1992, 93-97, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
    Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
    Rewritten by Jason Merrill (jason@cygnus.com).
 
@@ -42,6 +43,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "defaults.h"
 #include "ggc.h"
+#include "timevar.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -49,9 +51,6 @@ typedef int (*tree_fn_t) PARAMS ((tree, void*));
 
 extern struct obstack permanent_obstack;
 
-extern int lineno;
-extern char *input_filename;
-
 /* The PENDING_TEMPLATES is a TREE_LIST of templates whose
    instantiations have been deferred, either because their definitions
    were not yet available, or because we were putting off doing the
@@ -72,6 +71,13 @@ static tree saved_trees;
 static varray_type inline_parm_levels;
 static size_t inline_parm_levels_used;
 
+static tree current_tinst_level;
+
+/* A map from local variable declarations in the body of the template
+   presently being instantiated to the corresponding instantiated
+   local variables.  */
+static htab_t local_specializations;
+
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
@@ -94,9 +100,10 @@ static int try_one_overload PARAMS ((tree, tree, tree, tree, tree,
 static int unify PARAMS ((tree, tree, tree, tree, int));
 static void add_pending_template PARAMS ((tree));
 static int push_tinst_level PARAMS ((tree));
+static void reopen_tinst_level PARAMS ((tree));
 static tree classtype_mangled_name PARAMS ((tree));
-static char *mangle_class_name_for_template PARAMS ((char *, tree, tree));
-static tree tsubst_expr_values PARAMS ((tree, tree));
+static char *mangle_class_name_for_template PARAMS ((const char *, tree, tree));
+static tree tsubst_initializer_list PARAMS ((tree, tree));
 static int list_eq PARAMS ((tree, tree));
 static tree get_class_bindings PARAMS ((tree, tree, tree));
 static tree coerce_template_parms PARAMS ((tree, tree, tree, int, int));
@@ -118,9 +125,9 @@ static tree build_template_parm_index PARAMS ((int, int, int, tree, tree));
 static int inline_needs_template_parms PARAMS ((tree));
 static void push_inline_template_parms_recursive PARAMS ((tree, int));
 static tree retrieve_specialization PARAMS ((tree, tree));
-static tree retrieve_local_specialization PARAMS ((tree, tree));
+static tree retrieve_local_specialization PARAMS ((tree));
 static tree register_specialization PARAMS ((tree, tree, tree));
-static tree register_local_specialization PARAMS ((tree, tree, tree));
+static tree register_local_specialization PARAMS ((tree, tree));
 static int unregister_specialization PARAMS ((tree, tree));
 static tree reduce_template_parm_level PARAMS ((tree, tree, int));
 static tree build_template_decl PARAMS ((tree, tree));
@@ -150,14 +157,15 @@ static tree tsubst_call_declarator_parms PARAMS ((tree, tree, int, tree));
 static tree get_template_base_recursive PARAMS ((tree, tree,
                                               tree, tree, tree, int)); 
 static tree get_template_base PARAMS ((tree, tree, tree, tree));
+static int verify_class_unification PARAMS ((tree, tree, tree));
 static tree try_class_unification PARAMS ((tree, tree, tree, tree));
 static int coerce_template_template_parms PARAMS ((tree, tree, int,
                                                 tree, tree));
 static tree determine_specialization PARAMS ((tree, tree, tree *, int));
 static int template_args_equal PARAMS ((tree, tree));
-static void print_template_context PARAMS ((int));
 static void tsubst_default_arguments PARAMS ((tree));
 static tree for_each_template_parm_r PARAMS ((tree *, int *, void *));
+static tree instantiate_clone PARAMS ((tree, tree));
 
 /* Called once to initialize pt.c.  */
 
@@ -167,6 +175,7 @@ init_pt ()
   ggc_add_tree_root (&pending_templates, 1);
   ggc_add_tree_root (&maybe_templates, 1);
   ggc_add_tree_root (&saved_trees, 1);
+  ggc_add_tree_root (&current_tinst_level, 1);
 }
 
 /* Do any processing required when DECL (a member template declaration
@@ -320,7 +329,7 @@ push_inline_template_parms_recursive (parmlist, levels)
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) 
     {
       tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
-      my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (parm)) == 'd', 0);
+      my_friendly_assert (DECL_P (parm), 0);
 
       switch (TREE_CODE (parm))
        {
@@ -337,7 +346,7 @@ push_inline_template_parms_recursive (parmlist, levels)
               available.  */
            tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
                                    TREE_TYPE (parm));
-           SET_DECL_ARTIFICIAL (decl);
+           DECL_ARTIFICIAL (decl) = 1;
            DECL_INITIAL (decl) = DECL_INITIAL (parm);
            SET_DECL_TEMPLATE_PARM_P (decl);
            pushdecl (decl);
@@ -469,9 +478,7 @@ is_member_template_class (t)
 #endif
 
 /* Return a new template argument vector which contains all of ARGS,
-   but has as its innermost set of arguments the EXTRA_ARGS.  The
-   resulting vector will be built on a temporary obstack, and so must
-   be explicitly copied to the permanent obstack, if required.  */
+   but has as its innermost set of arguments the EXTRA_ARGS.  */
 
 static tree
 add_to_template_args (args, extra_args)
@@ -530,6 +537,39 @@ add_outermost_template_args (args, extra_args)
   return new_args;
 }
 
+/* Return the N levels of innermost template arguments from the ARGS.  */
+
+tree
+get_innermost_template_args (args, n)
+     tree args;
+     int n;
+{
+  tree new_args;
+  int extra_levels;
+  int i;
+
+  my_friendly_assert (n >= 0, 20000603);
+
+  /* If N is 1, just return the innermost set of template arguments.  */
+  if (n == 1)
+    return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
+  
+  /* If we're not removing anything, just return the arguments we were
+     given.  */
+  extra_levels = TMPL_ARGS_DEPTH (args) - n;
+  my_friendly_assert (extra_levels >= 0, 20000603);
+  if (extra_levels == 0)
+    return args;
+
+  /* Make a new set of arguments, not containing the outer arguments.  */
+  new_args = make_tree_vec (n);
+  for (i = 1; i <= n; ++i)
+    SET_TMPL_ARGS_LEVEL (new_args, i, 
+                        TMPL_ARGS_LEVEL (args, i + extra_levels));
+
+  return new_args;
+}
+
 /* We've got a template header coming up; push to a new level for storing
    the parms.  */
 
@@ -550,8 +590,7 @@ begin_template_parm_list ()
 
      pushtag contains special code to call pushdecl_with_scope on the
      TEMPLATE_DECL for S2.  */
-  pushlevel (0);
-  declare_pseudo_global_level ();
+  begin_scope (sk_template_parms);
   ++processing_template_decl;
   ++processing_template_parmlist;
   note_template_header (0);
@@ -595,16 +634,18 @@ check_specialization_scope ()
 void
 begin_specialization ()
 {
+  begin_scope (sk_template_spec);
   note_template_header (1);
   check_specialization_scope ();
 }
 
-/* Called at then end of processing a declaration preceeded by
+/* Called at then end of processing a declaration preceded by
    template<>.  */
 
 void 
 end_specialization ()
 {
+  finish_scope ();
   reset_specialization ();
 }
 
@@ -655,7 +696,7 @@ maybe_process_partial_specialization (type)
   if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
     {
       if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
-         && TYPE_SIZE (type) == NULL_TREE)
+         && !COMPLETE_TYPE_P (type))
        {
          if (current_namespace
              != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
@@ -706,16 +747,13 @@ retrieve_specialization (tmpl, args)
   return NULL_TREE;
 }
 
-/* Like retrieve_speciailization, but for local declarations.  FN is
-   the function in which we are looking for an instantiation.  */
+/* Like retrieve_specialization, but for local declarations.  */
 
 static tree
-retrieve_local_specialization (tmpl, fn)
+retrieve_local_specialization (tmpl)
      tree tmpl;
-     tree fn;
 {
-  tree s = purpose_member (fn, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
-  return s ? TREE_VALUE (s) : NULL_TREE;
+  return (tree) htab_find (local_specializations, tmpl);
 }
 
 /* Returns non-zero iff DECL is a specialization of TMPL.  */
@@ -743,8 +781,7 @@ is_specialization_of (decl, tmpl)
           t != NULL_TREE;
           t = CLASSTYPE_USE_TEMPLATE (t)
             ? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE)
-       if (same_type_p (TYPE_MAIN_VARIANT (t), 
-                        TYPE_MAIN_VARIANT (TREE_TYPE (tmpl))))
+       if (same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (tmpl)))
          return 1;
     }  
 
@@ -882,18 +919,18 @@ unregister_specialization (spec, tmpl)
   return 0;
 }
 
-/* Like register_specialization, but for local declarations.  FN is
-   the function in which we are registering SPEC, an instantiation of
-   TMPL.  */
+/* Like register_specialization, but for local declarations.  We are
+   registering SPEC, an instantiation of TMPL.  */
 
 static tree
-register_local_specialization (spec, tmpl, fn)
+register_local_specialization (spec, tmpl)
      tree spec;
      tree tmpl;
-     tree fn;
 {
-  DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
-     = tree_cons (fn, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+  void **slot;
+
+  slot = htab_find_slot (local_specializations, tmpl, INSERT);
+  *slot = spec;
 
   return spec;
 }
@@ -1103,7 +1140,7 @@ determine_specialization (template_id, decl, targs_out,
     }
 
   /* It was a specialization of a template.  */
-  targs = DECL_TI_ARGS (DECL_RESULT (TREE_VALUE (templates)));
+  targs = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (TREE_VALUE (templates)));
   if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))
     {
       *targs_out = copy_node (targs);
@@ -1165,117 +1202,127 @@ check_explicit_specialization (declarator, decl, template_count, flags)
   int specialization = 0;
   int explicit_instantiation = 0;
   int member_specialization = 0;
-
   tree ctype = DECL_CLASS_CONTEXT (decl);
   tree dname = DECL_NAME (decl);
+  tmpl_spec_kind tsk;
 
-  if (processing_specialization) 
-    {
-      /* The last template header was of the form template <>.  */
-         
-      if (template_header_count > template_count) 
-       {
-         /* There were more template headers than qualifying template
-            classes.  */
-         if (template_header_count - template_count > 1)
-           /* There shouldn't be that many template parameter lists.
-              There can be at most one parameter list for every
-              qualifying class, plus one for the function itself.  */
-           cp_error ("too many template parameter lists in declaration of `%D'", decl);
+  tsk = current_tmpl_spec_kind (template_count);
 
-         SET_DECL_TEMPLATE_SPECIALIZATION (decl);
-         if (ctype)
-           member_specialization = 1;
-         else
-           specialization = 1;
-       }
-      else if (template_header_count == template_count)
+  switch (tsk)
+    {
+    case tsk_none:
+      if (processing_specialization) 
        {
-         /* The counts are equal.  So, this might be a
-            specialization, but it is not a specialization of a
-            member template.  It might be something like
-                
-            template <class T> struct S { 
-            void f(int i); 
-            };
-            template <>
-            void S<int>::f(int i) {}  */
          specialization = 1;
          SET_DECL_TEMPLATE_SPECIALIZATION (decl);
        }
-      else 
+      else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
        {
-         /* This cannot be an explicit specialization.  There are not
-            enough headers for all of the qualifying classes.  For
-            example, we might have:
-            
-            template <>
-            void S<int>::T<char>::f();
+         if (is_friend)
+           /* This could be something like:
 
-            But, we're missing another template <>.  */
-         cp_error("too few template parameter lists in declaration of `%D'", decl);
-         return decl;
-       } 
-    }
-  else if (processing_explicit_instantiation)
-    {
-      if (template_header_count)
-       cp_error ("template parameter list used in explicit instantiation");
-         
+              template <class T> void f(T);
+              class S { friend void f<>(int); }  */
+           specialization = 1;
+         else
+           {
+             /* This case handles bogus declarations like template <>
+                template <class T> void f<int>(); */
+
+             cp_error ("template-id `%D' in declaration of primary template",
+                       declarator);
+             return decl;
+           }
+       }
+      break;
+
+    case tsk_invalid_member_spec:
+      /* The error has already been reported in
+        check_specialization_scope.  */
+      return error_mark_node;
+
+    case tsk_invalid_expl_inst:
+      cp_error ("template parameter list used in explicit instantiation");
+
+      /* Fall through.  */
+
+    case tsk_expl_inst:
       if (have_def)
        cp_error ("definition provided for explicit instantiation");
-
+      
       explicit_instantiation = 1;
-    }
-  else if (ctype != NULL_TREE
-          && !TYPE_BEING_DEFINED (ctype)
-          && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)
-          && !is_friend)
-    {
-      /* This case catches outdated code that looks like this:
-
-        template <class T> struct S { void f(); };
-        void S<int>::f() {} // Missing template <>
+      break;
 
-        We disable this check when the type is being defined to
-        avoid complaining about default compiler-generated
-        constructors, destructors, and assignment operators.
-        Since the type is an instantiation, not a specialization,
-        these are the only functions that can be defined before
-        the class is complete.  */
+    case tsk_excessive_parms:
+      cp_error ("too many template parameter lists in declaration of `%D'", 
+               decl);
+      return error_mark_node;
 
-         /* If they said
-              template <class T> void S<int>::f() {}
-            that's bogus.  */
+      /* Fall through.  */
+    case tsk_expl_spec:
+      SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+      if (ctype)
+       member_specialization = 1;
+      else
+       specialization = 1;
+      break;
+     
+    case tsk_insufficient_parms:
       if (template_header_count)
        {
-         cp_error ("template parameters specified in specialization");
+         cp_error("too few template parameter lists in declaration of `%D'", 
+                  decl);
          return decl;
        }
+      else if (ctype != NULL_TREE
+              && !TYPE_BEING_DEFINED (ctype)
+              && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)
+              && !is_friend)
+       {
+         /* For backwards compatibility, we accept:
 
-      if (pedantic)
-       cp_pedwarn
-         ("explicit specialization not preceded by `template <>'");
-      specialization = 1;
-      SET_DECL_TEMPLATE_SPECIALIZATION (decl);
-    }
-  else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
-    {
-      if (is_friend)
-       /* This could be something like:
+              template <class T> struct S { void f(); };
+              void S<int>::f() {} // Missing template <>
 
-          template <class T> void f(T);
-          class S { friend void f<>(int); }  */
-       specialization = 1;
-      else
+            That used to be legal C++.  */
+         if (pedantic)
+           cp_pedwarn
+             ("explicit specialization not preceded by `template <>'");
+         specialization = 1;
+         SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+       }
+      break;
+
+    case tsk_template:
+      if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
        {
          /* This case handles bogus declarations like template <>
             template <class T> void f<int>(); */
 
-         cp_error ("template-id `%D' in declaration of primary template",
-                   declarator);
+         if (uses_template_parms (declarator))
+           cp_error ("partial specialization `%D' of function template",
+                     declarator);
+         else
+           cp_error ("template-id `%D' in declaration of primary template",
+                     declarator);
          return decl;
        }
+
+      if (ctype && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
+       /* This is a specialization of a member template, without
+          specialization the containing class.  Something like:
+
+            template <class T> struct S {
+              template <class U> void f (U); 
+             };
+            template <> template <class U> void S<int>::f(U) {}
+            
+          That's a specialization -- but of the entire template.  */
+       specialization = 1;
+      break;
+
+    default:
+      my_friendly_abort (20000309);
     }
 
   if (specialization || member_specialization)
@@ -1384,7 +1431,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
              name = is_constructor ? ctor_identifier : dtor_identifier;
            }
 
-         if (!IDENTIFIER_TYPENAME_P (name))
+         if (!DECL_CONV_FN_P (decl))
            {
              idx = lookup_fnfields_1 (ctype, name);
              if (idx >= 0)
@@ -1461,7 +1508,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
                  /* If TMPL is not the most general template (for
                     example, if TMPL is a friend template that is
                     injected into namespace scope), then there will
-                    be too many levels fo TARGS.  Remove some of them
+                    be too many levels of TARGS.  Remove some of them
                     here.  */
                  int i;
                  tree new_targs;
@@ -1473,17 +1520,26 @@ check_explicit_specialization (declarator, decl, template_count, flags)
                  targs = new_targs;
                }
                  
-             decl = instantiate_template (tmpl, targs);
-             return decl;
+             return instantiate_template (tmpl, targs);
            }
-         
+
+         /* If this is a specialization of a member template of a
+            template class.  In we want to return the TEMPLATE_DECL,
+            not the specialization of it.  */
+         if (tsk == tsk_template)
+           {
+             SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
+             DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE;
+             return tmpl;
+           }
+
          /* If we though that the DECL was a member function, but it
             turns out to be specializing a static member function,
             make DECL a static member function as well.  */
          if (DECL_STATIC_FUNCTION_P (tmpl)
              && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
            {
-             revert_static_member_fn (&decl, 0, 0);
+             revert_static_member_fn (decl);
              last_function_parms = TREE_CHAIN (last_function_parms);
            }
 
@@ -1503,7 +1559,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
             we do not mangle S<int>::f() here.  That's because it's
             just an ordinary member function and doesn't need special
             treatment.  We do this here so that the ordinary,
-            non-template, name-mangling algorith will not be used
+            non-template, name-mangling algorithm will not be used
             later.  */
          if ((is_member_template (tmpl) || ctype == NULL_TREE)
              && name_mangling_version >= 1)
@@ -1649,8 +1705,7 @@ check_template_shadow (decl)
      that OLDDECL might be an OVERLOAD (or perhaps even an
      ERROR_MARK), so we can't just blithely assume it to be a _DECL
      node.  */
-  if (TREE_CODE_CLASS (TREE_CODE (olddecl)) != 'd'
-      || !DECL_TEMPLATE_PARM_P (olddecl))
+  if (!DECL_P (olddecl) || !DECL_TEMPLATE_PARM_P (olddecl))
     return;
 
   /* We check for decl != olddecl to avoid bogus errors for using a
@@ -1741,10 +1796,8 @@ process_template_parm (list, next)
     {
       tree p = TREE_VALUE (tree_last (list));
 
-      if (TREE_CODE (p) == TYPE_DECL)
+      if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
        idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
-      else if (TREE_CODE (p) == TEMPLATE_DECL)
-       idx = TEMPLATE_TYPE_IDX (TREE_TYPE (DECL_TEMPLATE_RESULT (p)));
       else
        idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
       ++idx;
@@ -1817,7 +1870,7 @@ process_template_parm (list, next)
                                     processing_template_decl,
                                     decl, TREE_TYPE (parm));
     }
-  SET_DECL_ARTIFICIAL (decl);
+  DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
   pushdecl (decl);
   parm = build_tree_list (defval, parm);
@@ -1862,11 +1915,10 @@ end_template_decl ()
     return;
 
   /* This matches the pushlevel in begin_template_parm_list.  */
-  poplevel (0, 0, 0);
+  finish_scope ();
 
   --processing_template_decl;
   current_template_parms = TREE_CHAIN (current_template_parms);
-  (void) get_pending_sizes (); /* Why? */
 }
 
 /* Given a template argument vector containing the template PARMS.
@@ -1934,10 +1986,15 @@ build_template_decl (decl, parms)
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   if (DECL_LANG_SPECIFIC (decl))
     {
-      DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
+      if (CAN_HAVE_FULL_LANG_DECL_P (decl))
+       DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
       DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
       DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
       DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
+      DECL_ASSIGNMENT_OPERATOR_P (tmpl) = DECL_ASSIGNMENT_OPERATOR_P (decl);
+      if (DECL_OVERLOADED_OPERATOR_P (decl))
+       SET_OVERLOADED_OPERATOR_CODE (tmpl, 
+                                     DECL_OVERLOADED_OPERATOR_P (decl));
     }
 
   return tmpl;
@@ -2010,7 +2067,7 @@ process_partial_specialization (decl)
   tree type = TREE_TYPE (decl);
   tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
   tree specargs = CLASSTYPE_TI_ARGS (type);
-  tree inner_args = innermost_args (specargs);
+  tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
   tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
   tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
   int nargs = TREE_VEC_LENGTH (inner_args);
@@ -2052,10 +2109,10 @@ process_partial_specialization (decl)
      or some such would have been OK.  */
   tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
   tpd.parms = alloca (sizeof (int) * ntparms);
-  bzero ((PTR) tpd.parms, sizeof (int) * ntparms);
+  memset ((PTR) tpd.parms, 0, sizeof (int) * ntparms);
 
   tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs);
-  bzero ((PTR) tpd.arg_uses_template_parms, sizeof (int) * nargs);
+  memset ((PTR) tpd.arg_uses_template_parms, 0, sizeof (int) * nargs);
   for (i = 0; i < nargs; ++i)
     {
       tpd.current_arg = i;
@@ -2067,7 +2124,7 @@ process_partial_specialization (decl)
     if (tpd.parms[i] == 0)
       {
        /* One of the template parms was not used in the
-           specialization.  */
+          specialization.  */
        if (!did_error_intro)
          {
            cp_error ("template parameters not used in partial specialization:");
@@ -2082,9 +2139,10 @@ process_partial_specialization (decl)
 
      The argument list of the specialization shall not be identical to
      the implicit argument list of the primary template.  */
-  if (comp_template_args (inner_args, 
-                         innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE
-                                                            (maintmpl)))))
+  if (comp_template_args 
+      (inner_args, 
+       INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE
+                                                  (maintmpl)))))
     cp_error ("partial specialization `%T' does not specialize any template arguments", type);
 
   /* [temp.class.spec]
@@ -2102,7 +2160,7 @@ process_partial_specialization (decl)
     {
       tree arg = TREE_VEC_ELT (inner_args, i);
       if (/* These first two lines are the `non-type' bit.  */
-         TREE_CODE_CLASS (TREE_CODE (arg)) != 't'
+         !TYPE_P (arg)
          && TREE_CODE (arg) != TEMPLATE_DECL
          /* This next line is the `argument expression is not just a
             simple identifier' condition and also the `specialized
@@ -2138,7 +2196,7 @@ process_partial_specialization (decl)
                 template, not in the specialization.  */
              tpd2.current_arg = i;
              tpd2.arg_uses_template_parms[i] = 0;
-             bzero ((PTR) tpd2.parms, sizeof (int) * nargs);
+             memset ((PTR) tpd2.parms, 0, sizeof (int) * nargs);
              for_each_template_parm (type,
                                      &mark_template_parm,
                                      &tpd2);
@@ -2167,7 +2225,7 @@ process_partial_specialization (decl)
     /* We've already got this specialization.  */
     return decl;
 
-  DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
+  DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
     = tree_cons (inner_args, inner_parms,
                 DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
   TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
@@ -2358,7 +2416,7 @@ push_template_decl_real (decl, is_friend)
        it is defined.  */
     ctx = CP_DECL_CONTEXT (decl);
   else
-    /* Otherwise, if we're currently definining some class, the DECL
+    /* Otherwise, if we're currently defining some class, the DECL
        is assumed to be a member of the class.  */
     ctx = current_scope ();
 
@@ -2369,7 +2427,7 @@ push_template_decl_real (decl, is_friend)
     DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
 
   /* See if this is a primary template.  */
-  primary = pseudo_global_level_p ();
+  primary = template_parm_scope_p ();
 
   if (primary)
     {
@@ -2443,9 +2501,6 @@ push_template_decl_real (decl, is_friend)
       tree a, t, current, parms;
       int i;
 
-      if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
-       cp_error ("must specialize `%#T' before defining member `%#D'",
-                 ctx, decl);
       if (TREE_CODE (decl) == TYPE_DECL)
        {
          if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
@@ -2490,7 +2545,9 @@ push_template_decl_real (decl, is_friend)
          DECL_TEMPLATE_INFO (new_tmpl) 
            = tree_cons (tmpl, args, NULL_TREE);
 
-         register_specialization (new_tmpl, tmpl, args);
+         register_specialization (new_tmpl, 
+                                  most_general_template (tmpl), 
+                                  args);
          return decl;
        }
 
@@ -2645,7 +2702,7 @@ redeclare_class_template (type, parms)
 
 /* Attempt to convert the non-type template parameter EXPR to the
    indicated TYPE.  If the conversion is successful, return the
-   converted value.  If the conversion is unsuccesful, return
+   converted value.  If the conversion is unsuccessful, return
    NULL_TREE if we issued an error message, or error_mark_node if we
    did not.  We issue error messages for out-and-out bad template
    parameters, but not simply because the conversion failed, since we
@@ -2685,7 +2742,7 @@ convert_nontype_argument (type, expr)
      enumerators.  Simplify things by folding them to their values,
      unless we're about to bind the declaration to a reference
      parameter.  */
-  if (INTEGRAL_TYPE_P (expr_type) && TREE_READONLY_DECL_P (expr)
+  if (INTEGRAL_TYPE_P (expr_type)
       && TREE_CODE (type) != REFERENCE_TYPE)
     expr = decl_constant_value (expr);
 
@@ -2712,8 +2769,9 @@ convert_nontype_argument (type, expr)
       tree e = expr;
       STRIP_NOPS (e);
 
-      if (TREE_CODE (type) == REFERENCE_TYPE
-         || TREE_CODE (expr_type) == ARRAY_TYPE)
+      if (TREE_CODE (expr_type) == ARRAY_TYPE
+         || (TREE_CODE (type) == REFERENCE_TYPE
+             && TREE_CODE (e) != ADDR_EXPR))
        referent = e;
       else
        {
@@ -2741,9 +2799,8 @@ convert_nontype_argument (type, expr)
 
       if (TREE_CODE (referent) == STRING_CST)
        {
-         cp_error ("string literal %E is not a valid template argument", 
+         cp_error ("string literal %E is not a valid template argument because it is the address of an object with static linkage", 
                    referent);
-         error ("because it is the address of an object with static linkage");
          return NULL_TREE;
        }
 
@@ -2752,7 +2809,7 @@ convert_nontype_argument (type, expr)
        ;
       else if (TREE_CODE (referent) != VAR_DECL)
        goto bad_argument;
-      else if (!TREE_PUBLIC (referent))
+      else if (!DECL_EXTERNAL_LINKAGE_P (referent))
        {
          cp_error ("address of non-extern `%E' cannot be used as template argument", referent); 
          return error_mark_node;
@@ -2854,12 +2911,12 @@ convert_nontype_argument (type, expr)
            else
              fns = expr;
 
-           fn = instantiate_type (type_pointed_to, fns, 0);
+           fn = instantiate_type (type_pointed_to, fns, itf_none);
 
            if (fn == error_mark_node)
              return error_mark_node;
 
-           if (!TREE_PUBLIC (fn))
+           if (!DECL_EXTERNAL_LINKAGE_P (fn))
              {
                if (really_overloaded_fn (fns))
                  return error_mark_node;
@@ -2901,6 +2958,15 @@ convert_nontype_argument (type, expr)
       {
        tree type_referred_to = TREE_TYPE (type);
 
+       /* If this expression already has reference type, get the
+          underling object.  */
+       if (TREE_CODE (expr_type) == REFERENCE_TYPE) 
+         {
+           my_friendly_assert (TREE_CODE (expr) == ADDR_EXPR, 20000604);
+           expr = TREE_OPERAND (expr, 0);
+           expr_type = TREE_TYPE (expr);
+         }
+
        if (TREE_CODE (type_referred_to) == FUNCTION_TYPE)
          {
            /* For a non-type template-parameter of type reference to
@@ -2908,17 +2974,16 @@ convert_nontype_argument (type, expr)
               template-argument represents a set of overloaded
               functions, the matching function is selected from the
               set (_over.over_).  */
-           tree fns = expr;
            tree fn;
 
-           fn = instantiate_type (type_referred_to, fns, 0);
+           fn = instantiate_type (type_referred_to, expr, itf_none);
 
            if (fn == error_mark_node)
              return error_mark_node;
 
-           if (!TREE_PUBLIC (fn))
+           if (!DECL_EXTERNAL_LINKAGE_P (fn))
              {
-               if (really_overloaded_fn (fns))
+               if (really_overloaded_fn (expr))
                  /* Don't issue an error here; we might get a different
                     function if the overloading had worked out
                     differently.  */
@@ -2931,7 +2996,7 @@ convert_nontype_argument (type, expr)
                                             TREE_TYPE (fn)),
                                0);
 
-           return fn;
+           expr = fn;
          }
        else
          {
@@ -2941,15 +3006,16 @@ convert_nontype_argument (type, expr)
               identical) type of the template-argument.  The
               template-parameter is bound directly to the
               template-argument, which must be an lvalue.  */
-           if ((TYPE_MAIN_VARIANT (expr_type)
-                != TYPE_MAIN_VARIANT (type_referred_to))
+           if (!same_type_p (TYPE_MAIN_VARIANT (expr_type),
+                             TYPE_MAIN_VARIANT (type_referred_to))
                || !at_least_as_qualified_p (type_referred_to,
                                             expr_type)
                || !real_lvalue_p (expr))
              return error_mark_node;
-           else
-             return expr;
          }
+
+       mark_addressable (expr);
+       return build1 (ADDR_EXPR, type, expr);
       }
       break;
 
@@ -2985,7 +3051,7 @@ convert_nontype_argument (type, expr)
        if (TREE_CODE (expr) != ADDR_EXPR)
          return error_mark_node;
 
-       expr = instantiate_type (type, expr, 0);
+       expr = instantiate_type (type, expr, itf_none);
        
        if (expr == error_mark_node)
          return error_mark_node;
@@ -3113,7 +3179,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
   tree inner_args;
   int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
   
-  inner_args = innermost_args (args);
+  inner_args = INNERMOST_TEMPLATE_ARGS (args);
 
   if (TREE_CODE (arg) == TREE_LIST 
       && TREE_TYPE (arg) != NULL_TREE
@@ -3141,8 +3207,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
   is_tmpl_type 
     = ((TREE_CODE (arg) == TEMPLATE_DECL
        && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
-       || (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
-          && !TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (arg))
+       || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
        || (TREE_CODE (arg) == RECORD_TYPE
           && CLASSTYPE_TEMPLATE_INFO (arg)
           && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
@@ -3154,13 +3219,12 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
   else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
     arg = CLASSTYPE_TI_TEMPLATE (arg);
 
-  is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't' || is_tmpl_type;
+  is_type = TYPE_P (arg) || is_tmpl_type;
 
   if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
       && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
     {
-      cp_pedwarn ("to refer to a type member of a template parameter,");
-      cp_pedwarn ("  use `typename %E'", arg);
+      cp_pedwarn ("to refer to a type member of a template parameter, use `typename %E'", arg);
       
       arg = make_typename_type (TREE_OPERAND (arg, 0),
                                TREE_OPERAND (arg, 1),
@@ -3270,7 +3334,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
           the standard.  Accepting this is not merely an
           extension, since deciding whether or not these
           conversions can occur is part of determining which
-          function template to call, or whether a given epxlicit
+          function template to call, or whether a given explicit
           argument specification is legal.  */
        val = convert_nontype_argument (t, arg);
       else
@@ -3296,10 +3360,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
    If REQUIRE_ALL_ARGUMENTS is non-zero, all arguments must be
    provided in ARGLIST, or else trailing parameters must have default
    values.  If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
-   deduction for any unspecified trailing arguments.  
-
-   The resulting TREE_VEC is allocated on a temporary obstack, and
-   must be explicitly copied if it will be permanent.  */
+   deduction for any unspecified trailing arguments.  */
    
 static tree
 coerce_template_parms (parms, args, in_decl,
@@ -3315,7 +3376,7 @@ coerce_template_parms (parms, args, in_decl,
   tree new_args;
   tree new_inner_args;
 
-  inner_args = innermost_args (args);
+  inner_args = INNERMOST_TEMPLATE_ARGS (args);
   nargs = NUM_TMPL_ARGS (inner_args);
   nparms = TREE_VEC_LENGTH (parms);
 
@@ -3404,13 +3465,14 @@ template_args_equal (ot, nt)
 {
   if (nt == ot)
     return 1;
-  if (TREE_CODE (nt) != TREE_CODE (ot))
-    return 0;
+
   if (TREE_CODE (nt) == TREE_VEC)
     /* For member templates */
-    return comp_template_args (ot, nt);
-  else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
-    return same_type_p (ot, nt);
+    return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
+  else if (TYPE_P (nt))
+    return TYPE_P (ot) && same_type_p (ot, nt);
+  else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
+    return 0;
   else
     return (cp_tree_equal (ot, nt) > 0);
 }
@@ -3443,7 +3505,7 @@ comp_template_args (oldargs, newargs)
 
 static char *
 mangle_class_name_for_template (name, parms, arglist)
-     char *name;
+     const char *name;
      tree parms, arglist;
 {
   static struct obstack scratch_obstack;
@@ -3462,7 +3524,7 @@ mangle_class_name_for_template (name, parms, arglist)
   cat (name);
   ccat ('<');
   nparms = TREE_VEC_LENGTH (parms);
-  arglist = innermost_args (arglist);
+  arglist = INNERMOST_TEMPLATE_ARGS (arglist);
   my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
   for (i = 0; i < nparms; i++)
     {
@@ -3474,7 +3536,7 @@ mangle_class_name_for_template (name, parms, arglist)
 
       if (TREE_CODE (parm) == TYPE_DECL)
        {
-         cat (type_as_string (arg, TS_CHASE_TYPEDEFS));
+         cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
          continue;
        }
       else if (TREE_CODE (parm) == TEMPLATE_DECL)
@@ -3491,14 +3553,14 @@ mangle_class_name_for_template (name, parms, arglist)
                   my_friendly_assert (TREE_CODE (context) == NAMESPACE_DECL
                                       || CLASS_TYPE_P (context), 
                                       980422);
-                 cat(decl_as_string (DECL_CONTEXT (arg), 0));
+                 cat(decl_as_string (DECL_CONTEXT (arg), TFF_PLAIN_IDENTIFIER));
                  cat("::");
                }
              cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
            }
          else
            /* Output the parameter declaration */
-           cat (type_as_string (arg, TS_CHASE_TYPEDEFS));
+           cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
          continue;
        }
       else
@@ -3513,7 +3575,7 @@ mangle_class_name_for_template (name, parms, arglist)
        }
       /* No need to check arglist against parmlist here; we did that
         in coerce_template_parms, called from lookup_template_class.  */
-      cat (expr_as_string (arg, 0));
+      cat (expr_as_string (arg, TFF_PLAIN_IDENTIFIER));
     }
   {
     char *bufp = obstack_next_free (&scratch_obstack);
@@ -3564,19 +3626,28 @@ static void
 add_pending_template (d)
      tree d;
 {
-  tree ti;
-
-  if (TREE_CODE_CLASS (TREE_CODE (d)) == 't')
-    ti = CLASSTYPE_TEMPLATE_INFO (d);
-  else
-    ti = DECL_TEMPLATE_INFO (d);
+  tree ti = (TYPE_P (d)
+            ? CLASSTYPE_TEMPLATE_INFO (d)
+            : DECL_TEMPLATE_INFO (d));
+  int level;
 
   if (TI_PENDING_TEMPLATE_FLAG (ti))
     return;
 
-  *template_tail = tree_cons (build_srcloc_here (), d, NULL_TREE);
+  /* We are called both from instantiate_decl, where we've already had a
+     tinst_level pushed, and instantiate_template, where we haven't.
+     Compensate.  */
+  level = !(current_tinst_level && TINST_DECL (current_tinst_level) == d);
+
+  if (level)
+    push_tinst_level (d);
+
+  *template_tail = tree_cons (current_tinst_level, d, NULL_TREE);
   template_tail = &TREE_CHAIN (*template_tail);
   TI_PENDING_TEMPLATE_FLAG (ti) = 1;
+
+  if (level)
+    pop_tinst_level ();
 }
 
 
@@ -3631,9 +3702,7 @@ maybe_get_template_decl_from_type_decl (decl)
    D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
    (Actually ARGLIST may be either a TREE_LIST or a TREE_VEC.  It will
    be a TREE_LIST if called directly from the parser, and a TREE_VEC
-   otherwise.)  Since ARGLIST is build on the temp_decl_obstack, we must
-   copy it here to keep it from being reclaimed when the decl storage
-   is reclaimed.
+   otherwise.)
 
    IN_DECL, if non-NULL, is the template declaration we are trying to
    instantiate.  
@@ -3688,36 +3757,30 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
        }
     }
   else if (TREE_CODE (d1) == ENUMERAL_TYPE 
-          || (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' 
-              && IS_AGGR_TYPE (d1)))
+          || (TYPE_P (d1) && IS_AGGR_TYPE (d1)))
     {
       template = TYPE_TI_TEMPLATE (d1);
       d1 = DECL_NAME (template);
     }
   else if (TREE_CODE (d1) == TEMPLATE_DECL
-          && TREE_CODE (DECL_RESULT (d1)) == TYPE_DECL)
+          && TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
     {
       template = d1;
       d1 = DECL_NAME (template);
       context = DECL_CONTEXT (template);
     }
-  else
-    my_friendly_abort (272);
 
   /* With something like `template <class T> class X class X { ... };'
      we could end up with D1 having nothing but an IDENTIFIER_VALUE.
      We don't want to do that, but we have to deal with the situation,
      so let's give them some syntax errors to chew on instead of a
-     crash.  */
+     crash. Alternatively D1 might not be a template type at all.  */
   if (! template)
     {
       cp_error ("`%T' is not a template", d1);
       return error_mark_node;
     }
 
-  if (context == NULL_TREE)
-    context = global_namespace;
-
   if (TREE_CODE (template) != TEMPLATE_DECL)
     {
       cp_error ("non-template type `%T' used as a template", d1);
@@ -3731,8 +3794,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
       /* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
          template arguments */
 
-      tree parm = copy_template_template_parm (TREE_TYPE (template));
-      tree template2 = TYPE_STUB_DECL (parm);
+      tree parm;
       tree arglist2;
 
       parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
@@ -3741,8 +3803,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
       if (arglist2 == error_mark_node)
        return error_mark_node;
 
-      TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm)
-       = tree_cons (template2, arglist2, NULL_TREE);
+      parm = copy_template_template_parm (TREE_TYPE (template), arglist2);
       TYPE_SIZE (parm) = 0;
       return parm;
     }
@@ -3823,7 +3884,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
       else
        arglist
          = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
-                                  innermost_args (arglist),
+                                  INNERMOST_TEMPLATE_ARGS (arglist),
                                   template, 1, 1);
 
       if (arglist == error_mark_node)
@@ -3849,12 +3910,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
              
              /* Note that we use DECL_CONTEXT, rather than
                 CP_DECL_CONTEXT, so that the termination test is
-                always just `ctx'.  We're not interested in namepace
+                always just `ctx'.  We're not interested in namespace
                 scopes.  */
              for (ctx = current_class_type; 
                   ctx; 
-                  ctx = (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't') 
-                    ? TYPE_CONTEXT (ctx) : DECL_CONTEXT (ctx))
+                  ctx = (TYPE_P (ctx)) ? TYPE_CONTEXT (ctx) : DECL_CONTEXT (ctx))
                if (same_type_p (ctx, template_type))
                  break;
              
@@ -3865,23 +3925,16 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
                found = NULL_TREE;
            }
        }
-      
-      if (!found)
-       {
-         for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
-              found; found = TREE_CHAIN (found))
-           if (comp_template_args (TREE_PURPOSE (found), arglist))
-             break;
-
-         if (found)
-           found = TREE_VALUE (found);
-       }
-
       if (found)
-       return found;
+        return found;
+      
+      for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+          found; found = TREE_CHAIN (found))
+       if (comp_template_args (TREE_PURPOSE (found), arglist))
+          return TREE_VALUE (found);
 
       /* This type is a "partial instantiation" if any of the template
-        arguments still inolve template parameters.  Note that we set
+        arguments still involve template parameters.  Note that we set
         IS_PARTIAL_INSTANTIATION for partial specializations as
         well.  */
       is_partial_instantiation = uses_template_parms (arglist);
@@ -3896,11 +3949,19 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
          return found;
        }
       
+      context = tsubst (DECL_CONTEXT (template), arglist,
+                       /*complain=*/0, in_decl);
+      if (!context)
+       context = global_namespace;
+
       /* Create the type.  */
       if (TREE_CODE (template_type) == ENUMERAL_TYPE)
        {
          if (!is_partial_instantiation)
-           t = start_enum (TYPE_IDENTIFIER (template_type));
+           {
+             set_current_access_from_decl (TYPE_NAME (template_type));
+             t = start_enum (TYPE_IDENTIFIER (template_type));
+           }
          else
            /* We don't want to call start_enum for this type, since
               the values for the enumeration constants may involve
@@ -3948,9 +4009,8 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
        found = template;
       else
        {
-         /* This is a full instantiation of a member template.  There
-            should be some partial instantiation of which this is an
-            instance.  */
+         /* This is a full instantiation of a member template.  Look
+            for a partial instantiation of which this is an instance.  */
 
          for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
               found; found = TREE_CHAIN (found))
@@ -3986,11 +4046,24 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
            }
 
          if (!found)
-           my_friendly_abort (0);
+           {
+             /* There was no partial instantiation. This happens
+                 where C<T> is a member template of A<T> and it's used
+                 in something like
+                
+                  template <typename T> struct B { A<T>::C<int> m; };
+                  B<float>;
+                
+                 Create the partial instantiation.
+               */
+              TREE_VEC_LENGTH (arglist)--;
+              template = tsubst (template, arglist, /*complain=*/0, NULL_TREE);
+              TREE_VEC_LENGTH (arglist)++;
+              found = template;
+            }
        }
 
-      SET_TYPE_TEMPLATE_INFO (t,
-                             tree_cons (found, arglist, NULL_TREE));  
+      SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));  
       DECL_TEMPLATE_INSTANTIATIONS (template) 
        = tree_cons (arglist, t, 
                     DECL_TEMPLATE_INSTANTIATIONS (template));
@@ -4013,8 +4086,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
       DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
       if (!is_partial_instantiation)
        {
-         DECL_ASSEMBLER_NAME (type_decl)
-           = get_identifier (build_overload_name (t, 1, 1));
+         if (flag_new_abi)
+           DECL_ASSEMBLER_NAME (type_decl) = mangle_decl (type_decl);
+         else
+           DECL_ASSEMBLER_NAME (type_decl)
+             = get_identifier (build_overload_name (t, 1, 1));
 
          /* For backwards compatibility; code that uses
             -fexternal-templates expects looking up a template to
@@ -4054,14 +4130,14 @@ for_each_template_parm_r (tp, walk_subtrees, d)
   tree_fn_t fn = pfd->fn;
   void *data = pfd->data;
   
-  if (TREE_CODE_CLASS (TREE_CODE (t)) == 't'
+  if (TYPE_P (t)
       && for_each_template_parm (TYPE_CONTEXT (t), fn, data))
     return error_mark_node;
 
   switch (TREE_CODE (t))
     {
     case RECORD_TYPE:
-      if (TYPE_PTRMEMFUNC_FLAG (t))
+      if (TYPE_PTRMEMFUNC_P (t))
        break;
       /* Fall through.  */
 
@@ -4118,13 +4194,13 @@ for_each_template_parm_r (tp, walk_subtrees, d)
        return error_mark_node;
       break;
 
-    case TEMPLATE_TEMPLATE_PARM:
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
       /* Record template parameters such as `T' inside `TT<T>'.  */
-      if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t)
-         && for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
+      if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
        return error_mark_node;
       /* Fall through.  */
 
+    case TEMPLATE_TEMPLATE_PARM:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_PARM_INDEX:
       if (fn && (*fn)(t, data))
@@ -4186,8 +4262,9 @@ for_each_template_parm_r (tp, walk_subtrees, d)
   return NULL_TREE;
 }
 
-/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or
-   TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA.
+/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, 
+   BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T, 
+   call FN with the parameter and the DATA.
    If FN returns non-zero, the iteration is terminated, and
    for_each_template_parm returns 1.  Otherwise, the iteration
    continues.  If FN never returns a non-zero value, the value
@@ -4207,7 +4284,9 @@ for_each_template_parm (t, fn, data)
   pfd.data = data;
 
   /* Walk the tree.  */
-  return walk_tree (&t, for_each_template_parm_r, &pfd) != NULL_TREE;
+  return walk_tree_without_duplicates (&t, 
+                                      for_each_template_parm_r, 
+                                      &pfd) != NULL_TREE;
 }
 
 int
@@ -4217,8 +4296,6 @@ uses_template_parms (t)
   return for_each_template_parm (t, 0, 0);
 }
 
-static struct tinst_level *current_tinst_level;
-static struct tinst_level *free_tinst_level;
 static int tinst_depth;
 extern int max_tinst_depth;
 #ifdef GATHER_STATISTICS
@@ -4227,68 +4304,14 @@ int depth_reached;
 static int tinst_level_tick;
 static int last_template_error_tick;
 
-/* Print out all the template instantiations that we are currently
-   working on.  If ERR, we are being called from cp_thing, so do
-   the right thing for an error message.  */
-
-static void
-print_template_context (err)
-     int err;
-{
-  struct tinst_level *p = current_tinst_level;
-  int line = lineno;
-  char *file = input_filename;
-
-  if (err && p)
-    {
-      if (current_function_decl != p->decl
-         && current_function_decl != NULL_TREE)
-       /* We can get here during the processing of some synthesized
-          method.  Then, p->decl will be the function that's causing
-          the synthesis.  */
-       ;
-      else
-       {
-         if (current_function_decl == p->decl)
-           /* Avoid redundancy with the the "In function" line.  */;
-         else 
-           fprintf (stderr, "%s: In instantiation of `%s':\n",
-                    file, decl_as_string (p->decl, TS_DECL_TYPE | TS_FUNC_NORETURN));
-         
-         line = p->line;
-         file = p->file;
-         p = p->next;
-       }
-    }
-
-  for (; p; p = p->next)
-    {
-      fprintf (stderr, "%s:%d:   instantiated from `%s'\n", file, line,
-              decl_as_string (p->decl, TS_DECL_TYPE | TS_FUNC_NORETURN));
-      line = p->line;
-      file = p->file;
-    }
-  fprintf (stderr, "%s:%d:   instantiated from here\n", file, line);
-}
-
-/* Called from cp_thing to print the template context for an error.  */
-
-void
-maybe_print_template_context ()
-{
-  if (last_template_error_tick == tinst_level_tick
-      || current_tinst_level == 0)
-    return;
-
-  last_template_error_tick = tinst_level_tick;
-  print_template_context (1);
-}
+/* We're starting to instantiate D; record the template instantiation context
+   for diagnostics and to restore it later.  */
 
 static int
 push_tinst_level (d)
      tree d;
 {
-  struct tinst_level *new;
+  tree new;
 
   if (tinst_depth >= max_tinst_depth)
     {
@@ -4299,28 +4322,16 @@ push_tinst_level (d)
        return 0;
 
       last_template_error_tick = tinst_level_tick;
-      error ("template instantiation depth exceeds maximum of %d",
-            max_tinst_depth);
-      error (" (use -ftemplate-depth-NN to increase the maximum)");
-      cp_error ("  instantiating `%D'", d);
+      cp_error ("template instantiation depth exceeds maximum of %d (use -ftemplate-depth-NN to increase the maximum) instantiating `%D'",
+            max_tinst_depth, d);
 
-      print_template_context (0);
+      print_instantiation_context ();
 
       return 0;
     }
 
-  if (free_tinst_level)
-    {
-      new = free_tinst_level;
-      free_tinst_level = new->next;
-    }
-  else
-    new = (struct tinst_level *) xmalloc (sizeof (struct tinst_level));
-
-  new->decl = d;
-  new->line = lineno;
-  new->file = input_filename;
-  new->next = current_tinst_level;
+  new = build_expr_wfl (d, input_filename, lineno, 0);
+  TREE_CHAIN (new) = current_tinst_level;
   current_tinst_level = new;
 
   ++tinst_depth;
@@ -4333,31 +4344,53 @@ push_tinst_level (d)
   return 1;
 }
 
+/* We're done instantiating this template; return to the instantiation
+   context.  */
+
 void
 pop_tinst_level ()
 {
-  struct tinst_level *old = current_tinst_level;
+  tree old = current_tinst_level;
 
   /* Restore the filename and line number stashed away when we started
      this instantiation.  */
-  lineno = old->line;
-  input_filename = old->file;
+  lineno = TINST_LINE (old);
+  input_filename = TINST_FILE (old);
   extract_interface_info ();
   
-  current_tinst_level = old->next;
-  old->next = free_tinst_level;
-  free_tinst_level = old;
+  current_tinst_level = TREE_CHAIN (old);
   --tinst_depth;
   ++tinst_level_tick;
 }
 
-struct tinst_level *
+/* We're instantiating a deferred template; restore the template
+   instantiation context in which the instantiation was requested, which
+   is one step out from LEVEL.  */
+
+static void
+reopen_tinst_level (level)
+     tree level;
+{
+  tree t;
+
+  tinst_depth = 0;
+  for (t = level; t; t = TREE_CHAIN (t))
+    ++tinst_depth;
+
+  current_tinst_level = level;
+  pop_tinst_level ();
+}
+
+/* Return the outermost template instantiation context, for use with
+   -falt-external-templates.  */
+
+tree
 tinst_for_decl ()
 {
-  struct tinst_level *p = current_tinst_level;
+  tree p = current_tinst_level;
 
   if (p)
-    for (; p->next ; p = p->next )
+    for (; TREE_CHAIN (p) ; p = TREE_CHAIN (p))
       ;
   return p;
 }
@@ -4365,7 +4398,7 @@ tinst_for_decl ()
 /* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL.  ARGS is the
    vector of template arguments, as for tsubst.
 
-   Returns an appropriate tsbust'd friend declaration.  */
+   Returns an appropriate tsubst'd friend declaration.  */
 
 static tree
 tsubst_friend_function (decl, args)
@@ -4374,7 +4407,7 @@ tsubst_friend_function (decl, args)
 {
   tree new_friend;
   int line = lineno;
-  char *file = input_filename;
+  const char *file = input_filename;
 
   lineno = DECL_SOURCE_LINE (decl);
   input_filename = DECL_SOURCE_FILE (decl);
@@ -4391,17 +4424,22 @@ tsubst_friend_function (decl, args)
        function declaration.  Now, we have to figure out what
        instantiation of what template.  */
     {
-      tree template_id;
+      tree template_id, arglist, fns;
       tree new_args;
       tree tmpl;
-
-      template_id
-       = lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
-                                                args, /*complain=*/1, 
-                                                NULL_TREE),
-                                   tsubst (DECL_TI_ARGS (decl),
-                                           args, /*complain=*/1, 
-                                           NULL_TREE));
+      tree ns = CP_DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));
+      
+      /* Friend functions are looked up in the containing namespace scope.
+         We must enter that scope, to avoid finding member functions of the
+         current cless with same name.  */
+      push_nested_namespace (ns);
+      fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
+                         /*complain=*/1, NULL_TREE);
+      pop_nested_namespace (ns);
+      arglist = tsubst (DECL_TI_ARGS (decl), args,
+                        /*complain=*/1, NULL_TREE);
+      template_id = lookup_template_function (fns, arglist);
+      
       new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
       tmpl = determine_specialization (template_id, new_friend,
                                       &new_args, 
@@ -4424,7 +4462,11 @@ tsubst_friend_function (decl, args)
      instantiation of anything.  */
   DECL_USE_TEMPLATE (new_friend) = 0;
   if (TREE_CODE (decl) == TEMPLATE_DECL)
-    DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
+    {
+      DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
+      DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
+       = DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
+    }
 
   /* The mangled name for the NEW_FRIEND is incorrect.  The call to
      tsubst will have resulted in a call to
@@ -4459,9 +4501,9 @@ tsubst_friend_function (decl, args)
          DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
          
          new_friend_is_defn 
-           = DECL_INITIAL (DECL_RESULT (new_friend)) != NULL_TREE;
+           = DECL_INITIAL (DECL_TEMPLATE_RESULT (new_friend)) != NULL_TREE;
          new_friend_result_template_info
-           = DECL_TEMPLATE_INFO (DECL_RESULT (new_friend));
+           = DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (new_friend));
        }
       else
        {
@@ -4534,7 +4576,7 @@ tsubst_friend_function (decl, args)
                  tree t;
                  tree new_friend_args;
 
-                 DECL_TEMPLATE_INFO (DECL_RESULT (old_decl)) 
+                 DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (old_decl)) 
                    = new_friend_result_template_info;
                    
                  new_friend_args = TI_ARGS (new_friend_template_info);
@@ -4568,7 +4610,7 @@ tsubst_friend_function (decl, args)
          new_friend = old_decl;
        }
     }
-  else if (TYPE_SIZE (DECL_CONTEXT (new_friend)))
+  else if (COMPLETE_TYPE_P (DECL_CONTEXT (new_friend)))
     {
       /* Check to see that the declaration is really present, and,
         possibly obtain an improved declaration.  */
@@ -4588,7 +4630,8 @@ tsubst_friend_function (decl, args)
 /* FRIEND_TMPL is a friend TEMPLATE_DECL.  ARGS is the vector of
    template arguments, as for tsubst.
 
-   Returns an appropriate tsbust'd friend type.  */
+   Returns an appropriate tsubst'd friend type or error_mark_node on
+   failure.  */
 
 static tree
 tsubst_friend_class (friend_tmpl, args)
@@ -4629,6 +4672,8 @@ tsubst_friend_class (friend_tmpl, args)
       tree parms 
        = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
                                 args, /*complain=*/1);
+      if (!parms)
+        return error_mark_node;
       redeclare_class_template (TREE_TYPE (tmpl), parms);
       friend_type = TREE_TYPE (tmpl);
     }
@@ -4664,7 +4709,7 @@ instantiate_class_template (type)
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type))
+  if (TYPE_BEING_DEFINED (type) || COMPLETE_TYPE_P (type))
     return type;
 
   /* Figure out which template is being instantiated.  */
@@ -4740,7 +4785,7 @@ instantiate_class_template (type)
 
   /* If the template we're instantiating is incomplete, then clearly
      there's nothing we can do.  */
-  if (TYPE_SIZE (pattern) == NULL_TREE)
+  if (!COMPLETE_TYPE_P (pattern))
     return type;
 
   /* If this is a partial instantiation, don't tsubst anything.  We will
@@ -4754,9 +4799,11 @@ instantiate_class_template (type)
       TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
       TYPE_METHODS (type) = TYPE_METHODS (pattern);
       CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
+      CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
+      
       /* Pretend that the type is complete, so that we will look
         inside it during name lookup and such.  */
-      TYPE_SIZE (type) = integer_zero_node;
+      TYPE_SIZE (type) = bitsize_zero_node;
       return type;
     }
 
@@ -4829,7 +4876,8 @@ instantiate_class_template (type)
   TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
   TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
   TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
-  TYPE_GETS_NEW (type) = TYPE_GETS_NEW (pattern);
+  TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
+  TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
   TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
   TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
   TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
@@ -4847,6 +4895,7 @@ instantiate_class_template (type)
     = TYPE_USES_VIRTUAL_BASECLASSES (pattern);
   TYPE_PACKED (type) = TYPE_PACKED (pattern);
   TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
+  TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (pattern);
   TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
   if (ANON_AGGR_TYPE_P (pattern))
     SET_ANON_AGGR_TYPE_P (type);
@@ -4867,7 +4916,7 @@ instantiate_class_template (type)
 
          pbase = TREE_VEC_ELT (pbases, i);
 
-         /* Substitue to figure out the base class.  */
+         /* Substitute to figure out the base class.  */
          base = tsubst (BINFO_TYPE (pbase), args, 
                         /*complain=*/1, NULL_TREE);
          if (base == error_mark_node)
@@ -4912,7 +4961,7 @@ instantiate_class_template (type)
 
   /* Now that our base classes are set up, enter the scope of the
      class, so that name lookups into base classes, etc. will work
-     corectly.  This is precisely analagous to what we do in
+     correctly.  This is precisely analogous to what we do in
      begin_class_definition when defining an ordinary non-template
      class.  */
   pushclass (type, 1);
@@ -5051,7 +5100,8 @@ instantiate_class_template (type)
           information.  */
        ++processing_template_decl;
 
-      make_friend_class (type, new_friend_type);
+      if (new_friend_type != error_mark_node)
+        make_friend_class (type, new_friend_type);
 
       if (TREE_CODE (friend_type) == TEMPLATE_DECL)
        --processing_template_decl;
@@ -5085,7 +5135,7 @@ instantiate_class_template (type)
   if (!PRIMARY_TEMPLATE_P (template))
     for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
       if (TREE_CODE (t) == FUNCTION_DECL 
-         /* Implicitly generated member functions will not have tmplate
+         /* Implicitly generated member functions will not have template
             information; they are not instantiations, but instead are
             created "fresh" for each instantiation.  */
          && DECL_TEMPLATE_INFO (t))
@@ -5126,8 +5176,7 @@ maybe_fold_nontype_arg (arg)
   if (! processing_template_decl)
     return arg;
 
-  if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't'
-      && !uses_template_parms (arg))
+  if (!TYPE_P (arg) && !uses_template_parms (arg))
     {
       /* Sometimes, one of the args was an expression involving a
         template constant parameter, like N - 1.  Now that we've
@@ -5145,17 +5194,6 @@ maybe_fold_nontype_arg (arg)
   return arg;
 }
 
-/* Return the TREE_VEC with the arguments for the innermost template header,
-   where ARGS is either that or the VEC of VECs for all the
-   arguments.  */
-
-tree
-innermost_args (args)
-     tree args;
-{
-  return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
-}
-
 /* Substitute ARGS into the vector of template arguments T.  */
 
 static tree
@@ -5167,7 +5205,7 @@ tsubst_template_arg_vector (t, args, complain)
   int len = TREE_VEC_LENGTH (t), need_new = 0, i;
   tree *elts = (tree *) alloca (len * sizeof (tree));
   
-  bzero ((char *) elts, len * sizeof (tree));
+  memset ((char *) elts, 0, len * sizeof (tree));
   
   for (i = 0; i < len; i++)
     {
@@ -5180,6 +5218,9 @@ tsubst_template_arg_vector (t, args, complain)
          (tsubst_expr (TREE_VEC_ELT (t, i), args, complain,
                        NULL_TREE));
       
+      if (elts[i] == error_mark_node)
+       return error_mark_node;
+
       if (elts[i] != TREE_VEC_ELT (t, i))
        need_new = 1;
     }
@@ -5246,7 +5287,7 @@ tsubst_template_parms (parms, args, complain)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
    ENTERING_SCOPE is non-zero, T is the context for a template which
-   we are presently tsubst'ing.  Return the subsituted value.  */
+   we are presently tsubst'ing.  Return the substituted value.  */
 
 static tree
 tsubst_aggr_type (t, args, complain, in_decl, entering_scope)
@@ -5299,6 +5340,8 @@ tsubst_aggr_type (t, args, complain, in_decl, entering_scope)
             S we only want {double}.  */
          argvec = tsubst_template_arg_vector (TYPE_TI_ARGS (t), args,
                                               complain);
+         if (argvec == error_mark_node)
+           return error_mark_node;
 
          r = lookup_template_class (t, argvec, in_decl, context,
                                     entering_scope);
@@ -5388,7 +5431,7 @@ tsubst_decl (t, args, type, in_decl)
      tree in_decl;
 {
   int saved_lineno;
-  char* saved_filename;
+  const char *saved_filename;
   tree r = NULL_TREE;
 
   /* Set the filename and linenumber to improve error-reporting.  */
@@ -5415,7 +5458,7 @@ tsubst_decl (t, args, type, in_decl)
               plus the innermost args from the template decl.  */
            tree tmpl_args = DECL_CLASS_TEMPLATE_P (t) 
              ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))
-             : DECL_TI_ARGS (DECL_RESULT (t));
+             : DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
            tree full_args;
            
            full_args = tsubst_template_arg_vector (tmpl_args, args,
@@ -5439,15 +5482,14 @@ tsubst_decl (t, args, type, in_decl)
           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.  */
-       r = copy_node (t);
-       copy_lang_decl (r);
+       r = copy_decl (t);
        my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
        TREE_CHAIN (r) = NULL_TREE;
 
        if (is_template_template_parm)
          {
            tree new_decl = tsubst (decl, args, /*complain=*/1, in_decl);
-           DECL_RESULT (r) = new_decl;
+           DECL_TEMPLATE_RESULT (r) = new_decl;
            TREE_TYPE (r) = TREE_TYPE (new_decl);
            break;
          }
@@ -5468,13 +5510,14 @@ tsubst_decl (t, args, type, in_decl)
                                    /*complain=*/1, in_decl);
            TREE_TYPE (r) = new_type;
            CLASSTYPE_TI_TEMPLATE (new_type) = r;
-           DECL_RESULT (r) = TYPE_MAIN_DECL (new_type);
+           DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);
            DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
          }
        else
          {
            tree new_decl = tsubst (decl, args, /*complain=*/1, in_decl);
-           DECL_RESULT (r) = new_decl;
+
+           DECL_TEMPLATE_RESULT (r) = new_decl;
            DECL_TI_TEMPLATE (new_decl) = r;
            TREE_TYPE (r) = TREE_TYPE (new_decl);
            DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
@@ -5498,63 +5541,9 @@ tsubst_decl (t, args, type, in_decl)
        if (TREE_CODE (decl) == TYPE_DECL)
          break;
 
-       for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
-            spec != NULL_TREE;
-            spec = TREE_CHAIN (spec))
-         {
-           /* It helps to consider example here.  Consider:
-
-              template <class T>
-              struct S {
-                template <class U>
-                void f(U u);
-
-                template <>
-                void f(T* t) {}
-              };
-              
-              Now, for example, we are instantiating S<int>::f(U u).  
-              We want to make a template:
-
-              template <class U>
-              void S<int>::f(U);
-
-              It will have a specialization, for the case U = int*, of
-              the form:
-
-              template <>
-              void S<int>::f<int*>(int*);
-
-              This specialization will be an instantiation of
-              the specialization given in the declaration of S, with
-              argument list int*.  */
-
-           tree fn = TREE_VALUE (spec);
-           tree spec_args;
-           tree new_fn;
-
-           if (!DECL_TEMPLATE_SPECIALIZATION (fn))
-             /* Instantiations are on the same list, but they're of
-                no concern to us.  */
-             continue;
-
-           if (TREE_CODE (fn) != TEMPLATE_DECL)
-             /* A full specialization.  There's no need to record
-                that here.  */
-             continue;
-
-           spec_args = tsubst (DECL_TI_ARGS (fn), args,
-                               /*complain=*/1, in_decl); 
-           new_fn = tsubst (DECL_RESULT (most_general_template (fn)), 
-                            spec_args, /*complain=*/1, in_decl); 
-           DECL_TI_TEMPLATE (new_fn) = fn;
-           register_specialization (new_fn, r, 
-                                    innermost_args (spec_args));
-         }
-
        /* Record this partial instantiation.  */
        register_specialization (r, t, 
-                                DECL_TI_ARGS (DECL_RESULT (r)));
+                                DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)));
 
       }
       break;
@@ -5594,12 +5583,24 @@ tsubst_decl (t, args, type, in_decl)
                break;
              }
 
-           /* Here, we deal with the peculiar case:
+           /* We can see more levels of arguments than parameters if
+              there was a specialization of a member template, like
+              this:
+
+                template <class T> struct S { template <class U> void f(); }
+                template <> template <class U> void S<int>::f(U); 
+
+              Here, we'll be substituting into the specialization,
+              because that's where we can find the code we actually
+              want to generate, but we'll have enough arguments for
+              the most general template.              
+
+              We also deal with the peculiar case:
 
                 template <class T> struct S { 
                   template <class U> friend void f();
                 };
-                template <class U> friend void f() {}
+                template <class U> void f() {}
                 template S<int>;
                 template void f<double>();
 
@@ -5619,21 +5620,7 @@ tsubst_decl (t, args, type, in_decl)
              TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t))); 
            if (args_depth > parms_depth
                && !DECL_TEMPLATE_SPECIALIZATION (t))
-             {
-               my_friendly_assert (DECL_FRIEND_P (t), 0);
-
-               if (parms_depth > 1)
-                 {
-                   int i;
-
-                   args = make_tree_vec (parms_depth);
-                   for (i = 0; i < parms_depth; ++i)
-                     TREE_VEC_ELT (args, i) = 
-                       TREE_VEC_ELT (args, i + (args_depth - parms_depth));
-                 }
-               else
-                 args = TREE_VEC_ELT (args, args_depth - parms_depth);
-             }
+             args = get_innermost_template_args (args, parms_depth);
          }
        else
          {
@@ -5677,10 +5664,8 @@ tsubst_decl (t, args, type, in_decl)
        /* We do NOT check for matching decls pushed separately at this
            point, as they may not represent instantiations of this
            template, and in any case are considered separate under the
-           discrete model.  Instead, see add_maybe_template.  */
-
-       r = copy_node (t);
-       copy_lang_decl (r);
+           discrete model.  */
+       r = copy_decl (t);
        DECL_USE_TEMPLATE (r) = 0;
        TREE_TYPE (r) = type;
 
@@ -5690,15 +5675,19 @@ tsubst_decl (t, args, type, in_decl)
                              /*complain=*/1, t,
                              /*entering_scope=*/1);
 
-       if (member && IDENTIFIER_TYPENAME_P (DECL_NAME (r)))
-         /* Type-conversion operator.  Reconstruct the name, in
-            case it's the name of one of the template's parameters.  */
-         DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
+       if (member && DECL_CONV_FN_P (r)) 
+         {
+           /* Type-conversion operator.  Reconstruct the name, in
+              case it's the name of one of the template's parameters.  */
+           if (flag_new_abi)
+             DECL_NAME (r) = mangle_conv_op_name_for_type (TREE_TYPE (type));
+           else
+             DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
+         }
 
        DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,
                                     /*complain=*/1, t);
-       DECL_MAIN_VARIANT (r) = r;
-       DECL_RESULT (r) = NULL_TREE;
+       DECL_TEMPLATE_RESULT (r) = NULL_TREE;
 
        TREE_STATIC (r) = 0;
        TREE_PUBLIC (r) = TREE_PUBLIC (t);
@@ -5708,7 +5697,15 @@ tsubst_decl (t, args, type, in_decl)
        TREE_CHAIN (r) = NULL_TREE;
        DECL_PENDING_INLINE_INFO (r) = 0;
        DECL_PENDING_INLINE_P (r) = 0;
+       DECL_SAVED_TREE (r) = NULL_TREE;
        TREE_USED (r) = 0;
+       if (DECL_CLONED_FUNCTION (r))
+         {
+           DECL_CLONED_FUNCTION (r) = tsubst (DECL_CLONED_FUNCTION (t),
+                                              args, /*complain=*/1, t);
+           TREE_CHAIN (r) = TREE_CHAIN (DECL_CLONED_FUNCTION (r));
+           TREE_CHAIN (DECL_CLONED_FUNCTION (r)) = r;
+         }
 
        /* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
           name.  There's no need to do this in the special friend
@@ -5721,8 +5718,13 @@ tsubst_decl (t, args, type, in_decl)
            register_specialization (r, gen_tmpl, argvec);
 
            /* Set the mangled name for R.  */
-           if (DECL_DESTRUCTOR_P (t))
-             DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+           if (DECL_DESTRUCTOR_P (t)) 
+             {
+               if (flag_new_abi)
+                 set_mangled_name_for_decl (r);
+               else
+                 DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+             }
            else 
              {
                /* Instantiations of template functions must be mangled
@@ -5781,12 +5783,15 @@ tsubst_decl (t, args, type, in_decl)
                                            in_decl);
          }
 
-       if (DECL_CONSTRUCTOR_P (r))
+       if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))
          {
            maybe_retrofit_in_chrg (r);
-           grok_ctor_properties (ctx, r);
+           if (DECL_CONSTRUCTOR_P (r))
+             grok_ctor_properties (ctx, r);
+           if (PRIMARY_TEMPLATE_P (gen_tmpl))
+             clone_function_decl(r, /*update_method_vec_p=*/0);
          }
-       else if (DECL_OVERLOADED_OPERATOR_P (r))
+       else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
          grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
       }
       break;
@@ -5817,8 +5822,7 @@ tsubst_decl (t, args, type, in_decl)
 
     case FIELD_DECL:
       {
-       r = copy_node (t);
-       copy_lang_decl (r);
+       r = copy_decl (t);
        TREE_TYPE (r) = type;
        c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
 
@@ -5842,54 +5846,53 @@ tsubst_decl (t, args, type, in_decl)
       break;
 
     case TYPE_DECL:
-      if (DECL_IMPLICIT_TYPEDEF_P (t))
+      if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+         || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
        {
-         /* For an implicit typedef, we just want the implicit
-            typedef for the tsubst'd type.  We've already got the
-            tsubst'd type, as TYPE, so we just need it's associated
-            declaration.  */
+         /* If this is the canonical decl, we don't have to mess with
+             instantiations, and often we can't (for typename, template
+            type parms and such).  Note that TYPE_NAME is not correct for
+            the above test if we've copied the type for a typedef.  */
          r = TYPE_NAME (type);
          break;
        }
-      else if (!DECL_LANG_SPECIFIC (t))
-       {
-         /* For a template type parameter, we don't have to do
-            anything special.  */
-         r= TYPE_NAME (type);
-         break;
-       }
 
       /* Fall through.  */
 
     case VAR_DECL:
       {
-       tree argvec;
-       tree gen_tmpl;
+       tree argvec = NULL_TREE;
+       tree gen_tmpl = NULL_TREE;
        tree spec;
-       tree tmpl;
+       tree tmpl = NULL_TREE;
        tree ctx;
+       int local_p;
 
-       /* Nobody should be tsubst'ing into non-template variables.  */
-       my_friendly_assert (DECL_LANG_SPECIFIC (t) 
-                           && DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
+       /* Assume this is a non-local variable.  */
+       local_p = 0;
 
        if (TYPE_P (CP_DECL_CONTEXT (t)))
          ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, 
                                  /*complain=*/1,
                                  in_decl, /*entering_scope=*/1);
        else
-         /* Subsequent calls to pushdecl will fill this in.  */
-         ctx = NULL_TREE;
+         {
+           /* Subsequent calls to pushdecl will fill this in.  */
+           ctx = NULL_TREE;
+           if (!DECL_NAMESPACE_SCOPE_P (t))
+             local_p = 1;
+         }
 
        /* Check to see if we already have this specialization.  */
-       tmpl = DECL_TI_TEMPLATE (t);
-       gen_tmpl = most_general_template (tmpl);
-       argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
-       if (ctx)
-         spec = retrieve_specialization (gen_tmpl, argvec);
+       if (!local_p)
+         {
+           tmpl = DECL_TI_TEMPLATE (t);
+           gen_tmpl = most_general_template (tmpl);
+           argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
+           spec = retrieve_specialization (gen_tmpl, argvec);
+         }
        else
-         spec = retrieve_local_specialization (gen_tmpl,
-                                               current_function_decl);
+         spec = retrieve_local_specialization (t);
 
        if (spec)
          {
@@ -5897,10 +5900,7 @@ tsubst_decl (t, args, type, in_decl)
            break;
          }
 
-       /* This declaration is going to have to be around for a while,
-          so me make sure it is on a saveable obstack.  */
-       r = copy_node (t);
-       
+       r = copy_decl (t);
        TREE_TYPE (r) = type;
        c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
        DECL_CONTEXT (r) = ctx;
@@ -5909,8 +5909,7 @@ tsubst_decl (t, args, type, in_decl)
           this variable; otherwise we run into circular dependencies.  */
        DECL_INITIAL (r) = NULL_TREE;
        DECL_RTL (r) = 0;
-       DECL_SIZE (r) = 0;
-       copy_lang_decl (r);
+       DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
 
        /* For __PRETTY_FUNCTION__ we have to adjust the initializer.  */
        if (DECL_PRETTY_FUNCTION_P (r))
@@ -5922,29 +5921,25 @@ tsubst_decl (t, args, type, in_decl)
            TREE_TYPE (r) = TREE_TYPE (DECL_INITIAL (r));
          }
 
-       /* If the template variable was marked TREE_ASM_WRITTEN, that
-          means we don't need to write out any of the instantiations
-          either.  (__FUNCTION__ and its ilk are marked thusly.)  */
-       TREE_ASM_WRITTEN (r) = TREE_ASM_WRITTEN (t);
-
        /* Even if the original location is out of scope, the newly
           substituted one is not.  */
        if (TREE_CODE (r) == VAR_DECL)
          DECL_DEAD_FOR_LOCAL (r) = 0;
 
-       /* A static data member declaration is always marked external
-          when it is declared in-class, even if an initializer is
-          present.  We mimic the non-template processing here.  */
-       if (ctx)
-         DECL_EXTERNAL (r) = 1;
+       if (!local_p)
+         {
+           /* A static data member declaration is always marked
+              external when it is declared in-class, even if an
+              initializer is present.  We mimic the non-template
+              processing here.  */
+           DECL_EXTERNAL (r) = 1;
 
-       DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
-       SET_DECL_IMPLICIT_INSTANTIATION (r);
-       if (ctx)
-         register_specialization (r, gen_tmpl, argvec);
+           register_specialization (r, gen_tmpl, argvec);
+           DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
+           SET_DECL_IMPLICIT_INSTANTIATION (r);
+         }
        else
-         register_local_specialization (r, gen_tmpl,
-                                        current_function_decl);
+         register_local_specialization (r, t);
 
        TREE_CHAIN (r) = NULL_TREE;
        if (TREE_CODE (r) == VAR_DECL && TREE_CODE (type) == VOID_TYPE)
@@ -6156,7 +6151,7 @@ tsubst (t, args, complain, in_decl)
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
+  if (DECL_P (t))
     return tsubst_decl (t, args, type, in_decl);
 
   switch (TREE_CODE (t))
@@ -6173,6 +6168,7 @@ tsubst (t, args, complain, in_decl)
     case VOID_TYPE:
     case REAL_TYPE:
     case COMPLEX_TYPE:
+    case VECTOR_TYPE:
     case BOOLEAN_TYPE:
     case INTEGER_CST:
     case REAL_CST:
@@ -6196,7 +6192,7 @@ tsubst (t, args, complain, in_decl)
 
        /* See if we can reduce this expression to something simpler.  */
        max = maybe_fold_nontype_arg (max);
-       if (!processing_template_decl && TREE_READONLY_DECL_P (max))
+       if (!processing_template_decl)
          max = decl_constant_value (max);
 
        if (processing_template_decl 
@@ -6244,6 +6240,7 @@ tsubst (t, args, complain, in_decl)
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
     case TEMPLATE_PARM_INDEX:
       {
        int idx;
@@ -6253,7 +6250,8 @@ tsubst (t, args, complain, in_decl)
        r = NULL_TREE;
 
        if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
-           || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+           || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+           || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
          {
            idx = TEMPLATE_TYPE_IDX (t);
            level = TEMPLATE_TYPE_LEVEL (t);
@@ -6278,44 +6276,38 @@ tsubst (t, args, complain, in_decl)
              {
                if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
                  {
-                   my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
-                                       == 't', 0);
+                   my_friendly_assert (TYPE_P (arg), 0);
                    return cp_build_qualified_type_real
                      (arg, CP_TYPE_QUALS (arg) | CP_TYPE_QUALS (t),
                       complain);
                  }
-               else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+               else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
                  {
-                   if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
-                     {
-                       /* We are processing a type constructed from
-                          a template template parameter */
-                       tree argvec = tsubst (TYPE_TI_ARGS (t),
-                                             args, complain, in_decl);
-                       if (argvec == error_mark_node)
-                         return error_mark_node;
+                   /* We are processing a type constructed from
+                      a template template parameter */
+                   tree argvec = tsubst (TYPE_TI_ARGS (t),
+                                         args, complain, in_decl);
+                   if (argvec == error_mark_node)
+                     return error_mark_node;
                        
-                       /* We can get a TEMPLATE_TEMPLATE_PARM here when 
-                          we are resolving nested-types in the signature of 
-                          a member function templates.
-                          Otherwise ARG is a TEMPLATE_DECL and is the real 
-                          template to be instantiated.  */
-                       if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
-                         arg = TYPE_NAME (arg);
-
-                       r = lookup_template_class (DECL_NAME (arg), 
-                                                  argvec, in_decl, 
-                                                  DECL_CONTEXT (arg),
-                                                  /*entering_scope=*/0);
-                       return cp_build_qualified_type_real (r, 
-                                                            TYPE_QUALS (t),
-                                                            complain);
-                     }
-                   else
-                     /* We are processing a template argument list.  */ 
-                     return arg;
+                   /* We can get a TEMPLATE_TEMPLATE_PARM here when 
+                      we are resolving nested-types in the signature of 
+                      a member function templates.
+                      Otherwise ARG is a TEMPLATE_DECL and is the real 
+                      template to be instantiated.  */
+                   if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+                     arg = TYPE_NAME (arg);
+
+                   r = lookup_template_class (arg, 
+                                              argvec, in_decl, 
+                                              DECL_CONTEXT (arg),
+                                              /*entering_scope=*/0);
+                   return cp_build_qualified_type_real (r, 
+                                                        TYPE_QUALS (t),
+                                                        complain);
                  }
                else
+                 /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.  */
                  return arg;
              }
          }
@@ -6335,25 +6327,34 @@ tsubst (t, args, complain, in_decl)
          {
          case TEMPLATE_TYPE_PARM:
          case TEMPLATE_TEMPLATE_PARM:
-           r = copy_node (t);
-           TEMPLATE_TYPE_PARM_INDEX (r)
-             = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
-                                           r, levels);
-           TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
-           TYPE_MAIN_VARIANT (r) = r;
-           TYPE_POINTER_TO (r) = NULL_TREE;
-           TYPE_REFERENCE_TO (r) = NULL_TREE;
-
-           if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
-               && TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
+         case BOUND_TEMPLATE_TEMPLATE_PARM:
+           if (CP_TYPE_QUALS (t))
              {
-               tree argvec = tsubst (TYPE_TI_ARGS (t), args,
-                                     complain, in_decl); 
-               if (argvec == error_mark_node)
-                 return error_mark_node;
+               r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
+               r = cp_build_qualified_type_real (r, CP_TYPE_QUALS (t),
+                                                 complain);
+             }
+           else
+             {
+               r = copy_node (t);
+               TEMPLATE_TYPE_PARM_INDEX (r)
+                 = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+                                               r, levels);
+               TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
+               TYPE_MAIN_VARIANT (r) = r;
+               TYPE_POINTER_TO (r) = NULL_TREE;
+               TYPE_REFERENCE_TO (r) = NULL_TREE;
+
+               if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+                 {
+                   tree argvec = tsubst (TYPE_TI_ARGS (t), args,
+                                         complain, in_decl); 
+                   if (argvec == error_mark_node)
+                     return error_mark_node;
 
-               TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
-                 = tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
+                   TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
+                     = tree_cons (TYPE_TI_TEMPLATE (t), argvec, NULL_TREE);
+                 }
              }
            break;
 
@@ -6452,7 +6453,7 @@ tsubst (t, args, complain, in_decl)
            || (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
          {
            static int   last_line = 0;
-           static char* last_file = 0;
+           static const char* last_file = 0;
 
            /* We keep track of the last time we issued this error
               message to avoid spewing a ton of messages during a
@@ -6478,8 +6479,10 @@ tsubst (t, args, complain, in_decl)
          r = build_reference_type (type);
        r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
 
-       /* Will this ever be needed for TYPE_..._TO values?  */
-       layout_type (r);
+       if (r != error_mark_node)
+         /* Will this ever be needed for TYPE_..._TO values?  */
+         layout_type (r);
+       
        return r;
       }
     case OFFSET_TYPE:
@@ -6618,7 +6621,7 @@ tsubst (t, args, complain, in_decl)
               point, so here CTX really should have complete type, unless
               it's a partial instantiation.  */
            ctx = complete_type (ctx);
-           if (!TYPE_SIZE (ctx))
+           if (!COMPLETE_TYPE_P (ctx))
              {
                if (complain)
                  incomplete_type_error (NULL_TREE, ctx);
@@ -7044,6 +7047,7 @@ tsubst_copy (t, args, complain, in_decl)
     case INTEGER_TYPE:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
     case TEMPLATE_PARM_INDEX:
     case POINTER_TYPE:
     case REFERENCE_TYPE:
@@ -7056,12 +7060,14 @@ tsubst_copy (t, args, complain, in_decl)
       return tsubst (t, args, complain, in_decl);
 
     case IDENTIFIER_NODE:
-      if (IDENTIFIER_TYPENAME_P (t)
-         /* Make sure it's not just a variable named `__opr', for instance,
-            which can occur in some existing code.  */
-         && TREE_TYPE (t))
-       return build_typename_overload
-         (tsubst (TREE_TYPE (t), args, complain, in_decl));
+      if (IDENTIFIER_TYPENAME_P (t))
+       {
+         tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+         if (flag_new_abi)
+           return mangle_conv_op_name_for_type (new_type);
+         else
+           return (build_typename_overload (new_type));
+       }
       else
        return t;
 
@@ -7076,7 +7082,7 @@ tsubst_copy (t, args, complain, in_decl)
       }
 
     case VA_ARG_EXPR:
-      return build_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
+      return build_x_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
                                        in_decl),
                           tsubst (TREE_TYPE (t), args, complain, in_decl));
 
@@ -7115,14 +7121,19 @@ tsubst_expr (t, args, complain, in_decl)
       break;
 
     case CTOR_INITIALIZER:
-      prep_stmt (t);
-      current_member_init_list
-       = tsubst_expr_values (TREE_OPERAND (t, 0), args);
-      current_base_init_list
-       = tsubst_expr_values (TREE_OPERAND (t, 1), args);
-      setup_vtbl_ptr ();
-      tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
-      break;
+      {
+       tree member_init_list;
+       tree base_init_list;
+
+       prep_stmt (t);
+       member_init_list
+         = tsubst_initializer_list (TREE_OPERAND (t, 0), args);
+       base_init_list
+         = tsubst_initializer_list (TREE_OPERAND (t, 1), args);
+       setup_vtbl_ptr (member_init_list, base_init_list);
+       tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
+       break;
+      }
 
     case RETURN_STMT:
       prep_stmt (t);
@@ -7150,17 +7161,23 @@ tsubst_expr (t, args, complain, in_decl)
            init = DECL_INITIAL (decl);
            decl = tsubst (decl, args, complain, in_decl);
            init = tsubst_expr (init, args, complain, in_decl);
-           if (init)
-             DECL_INITIAL (decl) = error_mark_node;
-           /* By marking the declaration as instantiated, we avoid
-              trying to instantiate it.  Since instantiate_decl can't
-              handle local variables, and since we've already done
-              all that needs to be done, that's the right thing to
-              do.  */
-           if (TREE_CODE (decl) == VAR_DECL)
-             DECL_TEMPLATE_INSTANTIATED (decl) = 1;
-           maybe_push_decl (decl);
-           cp_finish_decl (decl, init, NULL_TREE, 0);
+           if (decl != error_mark_node)
+             {
+                if (TREE_CODE (decl) != TYPE_DECL)
+                  /* Make sure the type is instantiated now. */
+                  complete_type (TREE_TYPE (decl));
+               if (init)
+                 DECL_INITIAL (decl) = error_mark_node;
+               /* By marking the declaration as instantiated, we avoid
+                  trying to instantiate it.  Since instantiate_decl can't
+                  handle local variables, and since we've already done
+                  all that needs to be done, that's the right thing to
+                  do.  */
+               if (TREE_CODE (decl) == VAR_DECL)
+                 DECL_TEMPLATE_INSTANTIATED (decl) = 1;
+               maybe_push_decl (decl);
+               cp_finish_decl (decl, init, NULL_TREE, 0);
+             }
          }
        return decl;
       }
@@ -7180,7 +7197,7 @@ tsubst_expr (t, args, complain, in_decl)
        tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
        finish_for_expr (tmp, stmt);
        tsubst_expr (FOR_BODY (t), args, complain, in_decl);
-       finish_for_stmt (tmp, stmt);
+       finish_for_stmt (stmt);
       }
       break;
 
@@ -7268,14 +7285,15 @@ tsubst_expr (t, args, complain, in_decl)
        val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
        finish_switch_cond (val, stmt);
        tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
-       finish_switch_stmt (val, stmt);
+       finish_switch_stmt (stmt);
       }
       break;
 
     case CASE_LABEL:
       prep_stmt (t);
       finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl),
-                        tsubst_expr (CASE_HIGH (t), args, complain, in_decl));
+                        tsubst_expr (CASE_HIGH (t), args, complain,
+                                     in_decl));
       break;
 
     case LABEL_STMT:
@@ -7379,6 +7397,43 @@ tsubst_expr (t, args, complain, in_decl)
   return NULL_TREE;
 }
 
+/* TMPL is a TEMPLATE_DECL for a cloned constructor or destructor.
+   Instantiate it with the ARGS.  */
+
+static tree
+instantiate_clone (tmpl, args)
+     tree tmpl;
+     tree args;
+{
+  tree spec;
+  tree clone;
+
+  /* Instantiated the cloned function, rather than the clone.  */
+  spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), args);
+
+  /* Then, see if we've already cloned the instantiation.  */
+  for (clone = TREE_CHAIN (spec);
+       clone && DECL_CLONED_FUNCTION_P (clone);
+       clone = TREE_CHAIN (clone))
+    if (DECL_NAME (clone) == DECL_NAME (tmpl))
+      return clone;
+
+  /* If we haven't, do so know.  */
+  if (!clone)
+    clone_function_decl (spec, /*update_method_vec_p=*/0);
+
+  /* Look again.  */
+  for (clone = TREE_CHAIN (spec);
+       clone && DECL_CLONED_FUNCTION_P (clone);
+       clone = TREE_CHAIN (clone))
+    if (DECL_NAME (clone) == DECL_NAME (tmpl))
+      return clone;
+
+  /* We should always have found the clone by now.  */
+  my_friendly_abort (20000411);
+  return NULL_TREE;
+}
+
 /* Instantiate the indicated variable or function template TMPL with
    the template arguments in TARG_PTR.  */
 
@@ -7386,6 +7441,7 @@ tree
 instantiate_template (tmpl, targ_ptr)
      tree tmpl, targ_ptr;
 {
+  tree clone;
   tree fndecl;
   tree gen_tmpl;
   tree spec;
@@ -7397,49 +7453,51 @@ instantiate_template (tmpl, targ_ptr)
 
   my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
 
+  /* If this function is a clone, handle it specially.  */
+  if (DECL_CLONED_FUNCTION_P (tmpl))
+    return instantiate_clone (tmpl, targ_ptr);
+
   /* Check to see if we already have this specialization.  */
   spec = retrieve_specialization (tmpl, targ_ptr);
   if (spec != NULL_TREE)
     return spec;
 
-  if (DECL_TEMPLATE_INFO (tmpl))
+  gen_tmpl = most_general_template (tmpl);
+  if (tmpl != gen_tmpl)
     {
       /* The TMPL is a partial instantiation.  To get a full set of
         arguments we must add the arguments used to perform the
         partial instantiation.  */
       targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
                                              targ_ptr);
-      gen_tmpl = most_general_template (tmpl);
 
       /* Check to see if we already have this specialization.  */
       spec = retrieve_specialization (gen_tmpl, targ_ptr);
       if (spec != NULL_TREE)
        return spec;
     }
-  else
-    gen_tmpl = tmpl;
 
   len = DECL_NTPARMS (gen_tmpl);
-  inner_args = innermost_args (targ_ptr);
+  inner_args = INNERMOST_TEMPLATE_ARGS (targ_ptr);
   i = len;
   while (i--)
     {
       tree t = TREE_VEC_ELT (inner_args, i);
-      if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+      if (TYPE_P (t))
        {
          tree nt = target_type (t);
          if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt)))
            {
              cp_error ("type `%T' composed from a local class is not a valid template-argument", t);
              cp_error ("  trying to instantiate `%D'", gen_tmpl);
-             fndecl = error_mark_node;
-             goto out;
+             return error_mark_node;
            }
        }
     }
 
   /* substitute template parameters */
-  fndecl = tsubst (DECL_RESULT (gen_tmpl), targ_ptr, /*complain=*/1, gen_tmpl);
+  fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
+                  targ_ptr, /*complain=*/1, gen_tmpl);
   /* The DECL_TI_TEMPLATE should always be the immediate parent
      template, not the most general template.  */
   DECL_TI_TEMPLATE (fndecl) = tmpl;
@@ -7447,7 +7505,13 @@ instantiate_template (tmpl, targ_ptr)
   if (flag_external_templates)
     add_pending_template (fndecl);
 
- out:
+  /* If we've just instantiated the main entry point for a function,
+     instantiate all the alternate entry points as well.  */
+  for (clone = TREE_CHAIN (gen_tmpl);
+       clone && DECL_CLONED_FUNCTION_P (clone);
+       clone = TREE_CHAIN (clone))
+    instantiate_template (clone, targ_ptr);
+
   return fndecl;
 }
 
@@ -7465,7 +7529,7 @@ overload_template_name (type)
     return;
 
   decl = build_decl (TYPE_DECL, id, type);
-  SET_DECL_ARTIFICIAL (decl);
+  DECL_ARTIFICIAL (decl) = 1;
   pushdecl_class_level (decl);
 }
 
@@ -7561,12 +7625,18 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
 
   if (DECL_CONV_FN_P (fn))
     {
-      /* This is a template conversion operator.  Use the return types
-         as well as the argument types.  We use it instead of 'this', since
+      /* This is a template conversion operator.  Remove `this', since
          we could be comparing conversions from different classes.  */
-      parms = tree_cons (NULL_TREE, TREE_TYPE (fntype),
-                        TREE_CHAIN (parms));
-      args = tree_cons (NULL_TREE, return_type, TREE_CHAIN (args));
+      parms = TREE_CHAIN (parms);
+      args = TREE_CHAIN (args);
+      my_friendly_assert (return_type != NULL_TREE, 20000227);
+    }
+  
+  if (return_type)
+    {
+      /* We've been given a return type to match, prepend it.  */
+      parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
+      args = tree_cons (NULL_TREE, return_type, args);
     }
 
   /* We allow incomplete unification without an error message here
@@ -7599,7 +7669,7 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
    sections are symmetric.  PARM is the type of a function parameter
    or the return type of the conversion function.  ARG is the type of
    the argument passed to the call, or the type of the value
-   intialized with the result of the conversion function.  */
+   initialized with the result of the conversion function.  */
 
 static void
 maybe_adjust_types_for_deduction (strict, parm, arg)
@@ -7668,7 +7738,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
     *parm = TREE_TYPE (*parm);
 }
 
-/* Like type_unfication.
+/* Like type_unification.
 
    If SUBR is 1, we're being called recursively (to unify the
    arguments of a function or method parameter of a function
@@ -7739,7 +7809,7 @@ type_unification_real (tparms, targs, parms, args, subr,
        {
          tree type;
 
-         if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
+         if (!TYPE_P (arg))
            type = TREE_TYPE (arg);
          else
            {
@@ -7761,7 +7831,7 @@ type_unification_real (tparms, targs, parms, args, subr,
          return 1;
        }
        
-      if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
+      if (!TYPE_P (arg))
        {
          my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
          if (type_unknown_p (arg))
@@ -7784,13 +7854,8 @@ type_unification_real (tparms, targs, parms, args, subr,
       if (!subr)
        maybe_adjust_types_for_deduction (strict, &parm, &arg);
 
-      switch (unify (tparms, targs, parm, arg, sub_strict))
-       {
-       case 0:
-         break;
-       case 1:
-         return 1;
-       }
+      if (unify (tparms, targs, parm, arg, sub_strict))
+        return 1;
     }
   /* Fail if we've reached the end of the parm list, and more args
      are present, and the parm list isn't variadic.  */
@@ -7859,7 +7924,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
          if (TREE_CODE (fn) != TEMPLATE_DECL)
            continue;
 
-         subargs = get_bindings_overload (fn, DECL_RESULT (fn), expl_subargs);
+         subargs = get_bindings_overload (fn, DECL_TEMPLATE_RESULT (fn),
+                                          expl_subargs);
          if (subargs)
            {
              elem = tsubst (TREE_TYPE (fn), subargs, /*complain=*/0,
@@ -7977,6 +8043,52 @@ try_one_overload (tparms, orig_targs, targs, parm, arg, strict,
   return 1;
 }
 
+/* Verify that nondeduce template argument agrees with the type
+   obtained from argument deduction.  Return nonzero if the
+   verification fails.
+
+   For example:
+
+     struct A { typedef int X; };
+     template <class T, class U> struct C {};
+     template <class T> struct C<T, typename T::X> {};
+
+   Then with the instantiation `C<A, int>', we can deduce that
+   `T' is `A' but unify () does not check whether `typename T::X'
+   is `int'.  This function ensure that they agree.
+
+   TARGS, PARMS are the same as the arguments of unify.
+   ARGS contains template arguments from all levels.  */
+
+static int
+verify_class_unification (targs, parms, args)
+     tree targs, parms, args;
+{
+  int i;
+  int nparms = TREE_VEC_LENGTH (parms);
+  tree new_parms = tsubst (parms, add_outermost_template_args (args, targs),
+                          /*complain=*/0, NULL_TREE);
+  if (new_parms == error_mark_node)
+    return 1;
+
+  args = INNERMOST_TEMPLATE_ARGS (args);
+
+  for (i = 0; i < nparms; i++)
+    {
+      tree parm = TREE_VEC_ELT (new_parms, i);
+      tree arg = TREE_VEC_ELT (args, i);
+
+      /* In case we are deducing from a function argument of a function
+        templates, some parameters may not be deduced yet.  So we
+        make sure that only fully substituted elements of PARM are
+        compared below.  */
+
+      if (!uses_template_parms (parm) && !template_args_equal (parm, arg))
+       return 1;
+    }
+  return 0;
+}
+
 /* PARM is a template class (perhaps with unbound template
    parameters).  ARG is a fully instantiated type.  If ARG can be
    bound to PARM, return ARG, otherwise return NULL_TREE.  TPARMS and
@@ -7989,7 +8101,6 @@ try_class_unification (tparms, targs, parm, arg)
      tree parm;
      tree arg;
 {
-  int i;
   tree copy_of_targs;
 
   if (!CLASSTYPE_TEMPLATE_INFO (arg)
@@ -8027,18 +8138,17 @@ try_class_unification (tparms, targs, parm, arg)
      with S<I, I, I>.  If we kept the already deduced knowledge, we
      would reject the possibility I=1.  */
   copy_of_targs = make_tree_vec (TREE_VEC_LENGTH (targs));
-  i = unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
-            CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE);
   
   /* If unification failed, we're done.  */
-  if (i != 0)
+  if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
+            CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
     return NULL_TREE;
-  else
-    return arg;
+
+  return arg;
 }
 
 /* Subroutine of get_template_base.  RVAL, if non-NULL, is a base we
-   have alreay discovered to be satisfactory.  ARG_BINFO is the binfo
+   have already discovered to be satisfactory.  ARG_BINFO is the binfo
    for the base class of ARG that we are currently examining.  */
 
 static tree
@@ -8185,7 +8295,7 @@ check_cv_quals_for_unify (strict, arg, parm)
 }
 
 /* Takes parameters as for type_unification.  Returns 0 if the
-   type deduction suceeds, 1 otherwise.  The parameter STRICT is a
+   type deduction succeeds, 1 otherwise.  The parameter STRICT is a
    bitwise or of the following flags:
 
      UNIFY_ALLOW_NONE:
@@ -8235,7 +8345,7 @@ unify (tparms, targs, parm, arg, strict)
   /* 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_P (arg)
       /* 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
@@ -8254,6 +8364,7 @@ unify (tparms, targs, parm, arg, strict)
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
       tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
 
       if (TEMPLATE_TYPE_LEVEL (parm)
@@ -8273,53 +8384,61 @@ unify (tparms, targs, parm, arg, strict)
              && TREE_CODE (tparm) != TEMPLATE_DECL))
        return 1;
 
-      if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
+      if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
        {
-         if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm))
-           {
-             /* We arrive here when PARM does not involve template 
-                specialization.  */
+         /* ARG must be constructed from a template class.  */
+         if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
+           return 1;
 
-             /* ARG must be constructed from a template class.  */
-             if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
-               return 1;
+         {
+           tree parmtmpl = TYPE_TI_TEMPLATE (parm);
+           tree parmvec = TYPE_TI_ARGS (parm);
+           tree argvec = CLASSTYPE_TI_ARGS (arg);
+           tree argtmplvec
+             = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
+           int i;
 
-             {
-               tree parmtmpl = TYPE_TI_TEMPLATE (parm);
-               tree parmvec = TYPE_TI_ARGS (parm);
-               tree argvec = CLASSTYPE_TI_ARGS (arg);
-               tree argtmplvec
-                 = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
-               int i;
-
-               /* The parameter and argument roles have to be switched here 
-                  in order to handle default arguments properly.  For example, 
-                  template<template <class> class TT> void f(TT<int>) 
-                  should be able to accept vector<int> which comes from 
-                  template <class T, class Allocator = allocator> 
-                  class vector.  */
-
-               if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
-                   == error_mark_node)
-                 return 1;
+           /* The parameter and argument roles have to be switched here 
+              in order to handle default arguments properly.  For example, 
+              template<template <class> class TT> void f(TT<int>) 
+              should be able to accept vector<int> which comes from 
+              template <class T, class Allocator = allocator> 
+              class vector.  */
+
+           if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
+               == error_mark_node)
+             return 1;
          
-               /* Deduce arguments T, i from TT<T> or TT<i>.  
-                  We check each element of PARMVEC and ARGVEC individually
-                  rather than the whole TREE_VEC since they can have
-                  different number of elements.  */
+           /* Deduce arguments T, i from TT<T> or TT<i>.  
+              We check each element of PARMVEC and ARGVEC individually
+              rather than the whole TREE_VEC since they can have
+              different number of elements.  */
 
-               for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
-                 {
-                   tree t = TREE_VEC_ELT (parmvec, i);
+           for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
+             {
+               tree t = TREE_VEC_ELT (parmvec, i);
 
-                   if (unify (tparms, targs, t, 
-                              TREE_VEC_ELT (argvec, i), 
-                              UNIFY_ALLOW_NONE))
-                     return 1;
-                 }
+               if (unify (tparms, targs, t, 
+                          TREE_VEC_ELT (argvec, i), 
+                          UNIFY_ALLOW_NONE))
+                 return 1;
              }
-             arg = CLASSTYPE_TI_TEMPLATE (arg);
-           }
+         }
+         arg = CLASSTYPE_TI_TEMPLATE (arg);
+
+         /* Fall through to deduce template name.  */
+       }
+
+      if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
+         || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+       {
+         /* Deduce template name TT from TT, TT<>, TT<T> and TT<i>.  */
+
+         /* Simple cases: Value already set, does match or doesn't.  */
+         if (targ != NULL_TREE && template_args_equal (targ, arg))
+           return 0;
+         else if (targ)
+           return 1;
        }
       else
        {
@@ -8340,13 +8459,13 @@ unify (tparms, targs, parm, arg, strict)
                                          /*complain=*/0);
          if (arg == error_mark_node)
            return 1;
-       }
 
-      /* Simple cases: Value already set, does match or doesn't.  */
-      if (targ != NULL_TREE && same_type_p (targ, arg))
-       return 0;
-      else if (targ)
-       return 1;
+         /* Simple cases: Value already set, does match or doesn't.  */
+         if (targ != NULL_TREE && same_type_p (targ, arg))
+           return 0;
+         else if (targ)
+           return 1;
+       }
 
       /* Make sure that ARG is not a variable-sized array.  (Note that
         were talking about variable-sized arrays (like `int[n]'),
@@ -8394,8 +8513,10 @@ unify (tparms, targs, parm, arg, strict)
         parameter-list and, if the corresponding template-argument is
         deduced, the template-argument type shall match the type of the
         template-parameter exactly, except that a template-argument
-        deduced from an array bound may be of any integral type.  */
-      if (same_type_p (TREE_TYPE (arg), TREE_TYPE (parm)))
+        deduced from an array bound may be of any integral type. 
+        The non-type parameter might use already deduced type parameters.  */
+      if (same_type_p (TREE_TYPE (arg),
+                       tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE)))
        /* OK */;
       else if ((strict & UNIFY_ALLOW_INTEGER)
               && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
@@ -8460,6 +8581,7 @@ unify (tparms, targs, parm, arg, strict)
 
     case REAL_TYPE:
     case COMPLEX_TYPE:
+    case VECTOR_TYPE:
     case INTEGER_TYPE:
     case BOOLEAN_TYPE:
     case VOID_TYPE:
@@ -8478,11 +8600,9 @@ unify (tparms, targs, parm, arg, strict)
                        TYPE_MAX_VALUE (arg), UNIFY_ALLOW_INTEGER))
            return 1;
        }
-      /* We use the TYPE_MAIN_VARIANT since we have already
-        checked cv-qualification at the top of the
+      /* We have already checked cv-qualification at the top of the
         function.  */
-      else if (!same_type_p (TYPE_MAIN_VARIANT (arg),
-                            TYPE_MAIN_VARIANT (parm)))
+      else if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
        return 1;
 
       /* As far as unification is concerned, this wins.         Later checks
@@ -8506,7 +8626,7 @@ unify (tparms, targs, parm, arg, strict)
          return 1;
        if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
          return 1;
-       for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
+       for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
          if (unify (tparms, targs,
                     TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
                     UNIFY_ALLOW_NONE))
@@ -8565,14 +8685,13 @@ unify (tparms, targs, parm, arg, strict)
               Then, we should unify `int' and `U'.  */
            t = arg;
          else
-           /* There's no chance of unication succeeding.  */
+           /* There's no chance of unification succeeding.  */
            return 1;
 
          return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
                        CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
        }
-      else if (!same_type_p (TYPE_MAIN_VARIANT (parm),
-                            TYPE_MAIN_VARIANT (arg)))
+      else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
        return 1;
       return 0;
 
@@ -8628,25 +8747,33 @@ unify (tparms, targs, parm, arg, strict)
 
     default:
       if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
-       /* We're looking at an expression.  This can happen with
-          something like: 
+       {
+
+         /* We're looking at an expression.  This can happen with
+            something like: 
           
-            template <int I>
-            void foo(S<I>, S<I + 2>);
+              template <int I>
+              void foo(S<I>, S<I + 2>);
 
-          This is a "nondeduced context":
+            This is a "nondeduced context":
 
-            [deduct.type]
+              [deduct.type]
           
-            The nondeduced contexts are:
+              The nondeduced contexts are:
 
-            --A type that is a template-id in which one or more of
-              the template-arguments is an expression that references
-              a template-parameter.  
+              --A type that is a template-id in which one or more of
+                the template-arguments is an expression that references
+                a template-parameter.  
 
-          In these cases, we assume deduction succeeded, but don't
-          actually infer any unifications.  */
-       return 0;
+            In these cases, we assume deduction succeeded, but don't
+            actually infer any unifications.  */
+
+         if (!uses_template_parms (parm)
+             && !template_args_equal (parm, arg))
+           return 1;
+         else
+           return 0;
+       }
       else
        sorry ("use of `%s' in template type unification",
               tree_code_name [(int) TREE_CODE (parm)]);
@@ -8669,6 +8796,14 @@ mark_decl_instantiated (result, extern_p)
        set correctly by tsubst.  */
     TREE_PUBLIC (result) = 1;
 
+  /* We used to set this unconditionally; we moved that to
+     do_decl_instantiation so it wouldn't get set on members of
+     explicit class template instantiations.  But we still need to set
+     it here for the 'extern template' case in order to suppress
+     implicit instantiations.  */
+  if (extern_p)
+    SET_DECL_EXPLICIT_INSTANTIATION (result);
+
   if (! extern_p)
     {
       DECL_INTERFACE_KNOWN (result) = 1;
@@ -8683,7 +8818,7 @@ mark_decl_instantiated (result, extern_p)
        maybe_make_one_only (result);
     }
   else if (TREE_CODE (result) == FUNCTION_DECL)
-    mark_inline_for_output (result);
+    defer_fn (result);
 }
 
 /* Given two function templates PAT1 and PAT2, and explicit template
@@ -8700,11 +8835,13 @@ more_specialized (pat1, pat2, explicit_args)
   tree targs;
   int winner = 0;
 
-  targs = get_bindings_overload (pat1, DECL_RESULT (pat2), explicit_args);
+  targs
+    = get_bindings_overload (pat1, DECL_TEMPLATE_RESULT (pat2), explicit_args);
   if (targs)
     --winner;
 
-  targs = get_bindings_overload (pat2, DECL_RESULT (pat1), explicit_args);
+  targs
+    = get_bindings_overload (pat2, DECL_TEMPLATE_RESULT (pat1), explicit_args);
   if (targs)
     ++winner;
 
@@ -8792,22 +8929,13 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
 
   i = fn_type_unification (fn, explicit_args, targs, 
                           decl_arg_types,
-                          TREE_TYPE (decl_type),
+                          (check_rettype || DECL_CONV_FN_P (fn)
+                           ? TREE_TYPE (decl_type) : NULL_TREE),
                           DEDUCE_EXACT);
 
   if (i != 0)
     return NULL_TREE;
 
-  if (check_rettype)
-    {
-      /* Check to see that the resulting return type is also OK.  */
-      tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), targs,
-                      /*complain=*/0, NULL_TREE);
-
-      if (!same_type_p (t, TREE_TYPE (TREE_TYPE (decl))))
-       return NULL_TREE;
-    }
-
   return targs;
 }
 
@@ -8851,24 +8979,26 @@ get_class_bindings (tparms, parms, args)
   int i, ntparms = TREE_VEC_LENGTH (tparms);
   tree vec = make_tree_vec (ntparms);
 
-  args = innermost_args (args);
-
-  if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE))
+  if (unify (tparms, vec, parms, INNERMOST_TEMPLATE_ARGS (args),
+            UNIFY_ALLOW_NONE))
     return NULL_TREE;
 
   for (i =  0; i < ntparms; ++i)
     if (! TREE_VEC_ELT (vec, i))
       return NULL_TREE;
 
+  if (verify_class_unification (vec, parms, args))
+    return NULL_TREE;
+
   return vec;
 }
 
 /* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
    Pick the most specialized template, and return the corresponding
    instantiation, or if there is no corresponding instantiation, the
-   template itself.  EXPLICIT_ARGS is any template arguments explicity
+   template itself.  EXPLICIT_ARGS is any template arguments explicitly
    mentioned in a template-id.  If there is no most specialized
-   tempalte, error_mark_node is returned.  If there are no templates
+   template, error_mark_node is returned.  If there are no templates
    at all, NULL_TREE is returned.  */
 
 tree
@@ -8936,7 +9066,9 @@ most_specialized (fns, decl, explicit_args)
 }
 
 /* If DECL is a specialization of some template, return the most
-   general such template.  For example, given:
+   general such template.  Otherwise, returns NULL_TREE.
+
+   For example, given:
 
      template <class T> struct S { template <class U> void f(U); };
 
@@ -8953,12 +9085,37 @@ tree
 most_general_template (decl)
      tree decl;
 {
-  while (DECL_TEMPLATE_INFO (decl)
-        /* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or
-           IDENTIFIER_NODE in some cases.  (See cp-tree.h for
-           details.)  */
-        && TREE_CODE (DECL_TI_TEMPLATE (decl)) == TEMPLATE_DECL)
-    decl = DECL_TI_TEMPLATE (decl);
+  /* If DECL is a FUNCTION_DECL, find the TEMPLATE_DECL of which it is
+     an immediate specialization.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      if (DECL_TEMPLATE_INFO (decl)) {
+       decl = DECL_TI_TEMPLATE (decl);
+
+       /* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE for a
+          template friend.  */
+       if (TREE_CODE (decl) != TEMPLATE_DECL)
+         return NULL_TREE;
+      } else
+       return NULL_TREE;
+    }
+
+  /* Look for more and more general templates.  */
+  while (DECL_TEMPLATE_INFO (decl))
+    {
+      /* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or IDENTIFIER_NODE
+        in some cases.  (See cp-tree.h for details.)  */
+      if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
+       break;
+
+      /* Stop if we run into an explicitly specialized class template.  */
+      if (!DECL_NAMESPACE_SCOPE_P (decl)
+         && DECL_CONTEXT (decl)
+         && CLASSTYPE_TEMPLATE_SPECIALIZATION (DECL_CONTEXT (decl)))
+       break;
+
+      decl = DECL_TI_TEMPLATE (decl);
+    }
 
   return decl;
 }
@@ -8984,7 +9141,7 @@ most_specialized_class (tmpl, args)
        = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
       if (spec_args)
        {
-         list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
+         list = tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
          TREE_TYPE (list) = TREE_TYPE (t);
        }
     }
@@ -9033,7 +9190,7 @@ do_decl_instantiation (declspecs, declarator, storage)
   int extern_p = 0;
 
   if (!decl)
-    /* An error ocurred, for which grokdeclarator has already issued
+    /* An error occurred, for which grokdeclarator has already issued
        an appropriate message.  */
     return;
   else if (! DECL_LANG_SPECIFIC (decl))
@@ -9091,7 +9248,7 @@ do_decl_instantiation (declspecs, declarator, storage)
         We check DECL_INTERFACE_KNOWN so as not to complain when the first
         instantiation was `extern' and the second is not, and EXTERN_P for
         the opposite case.  If -frepo, chances are we already got marked
-        as an explicit instantion because of the repo file.  */
+        as an explicit instantiation because of the repo file.  */
       if (DECL_INTERFACE_KNOWN (result) && !extern_p && !flag_use_repository)
        cp_pedwarn ("duplicate explicit instantiation of `%#D'", result);
 
@@ -9118,7 +9275,7 @@ do_decl_instantiation (declspecs, declarator, storage)
   else if (storage == ridpointers[(int) RID_EXTERN])
     {
       if (pedantic)
-       cp_pedwarn ("ANSI C++ forbids the use of `extern' on explicit instantiations");
+       cp_pedwarn ("ISO C++ forbids the use of `extern' on explicit instantiations");
       extern_p = 1;
     }
   else
@@ -9129,7 +9286,7 @@ do_decl_instantiation (declspecs, declarator, storage)
   mark_decl_instantiated (result, extern_p);
   repo_template_instantiated (result, extern_p);
   if (! extern_p)
-    instantiate_decl (result);
+    instantiate_decl (result, /*defer_ok=*/1);
 }
 
 void
@@ -9149,9 +9306,15 @@ mark_class_instantiated (t, extern_p)
     }
 }     
 
+/* Perform an explicit instantiation of template class T.  STORAGE, if
+   non-null, is the RID for extern, inline or static.  COMPLAIN is
+   non-zero if this is called from the parser, zero if called recursively,
+   since the standard is unclear (as detailed below).  */
 void
-do_type_instantiation (t, storage)
+do_type_instantiation (t, storage, complain)
      tree t, storage;
+     int complain;
 {
   int extern_p = 0;
   int nomem_p = 0;
@@ -9173,17 +9336,18 @@ do_type_instantiation (t, storage)
   if (flag_external_templates)
     return;
 
-  if (TYPE_SIZE (t) == NULL_TREE)
+  if (!COMPLETE_TYPE_P (t))
     {
-      cp_error ("explicit instantiation of `%#T' before definition of template",
-               t);
+      if (complain)
+       cp_error ("explicit instantiation of `%#T' before definition of template",
+                 t);
       return;
     }
 
   if (storage != NULL_TREE)
     {
       if (pedantic)
-       cp_pedwarn("ANSI C++ forbids the use of `%s' on explicit instantiations", 
+       cp_pedwarn("ISO C++ forbids the use of `%s' on explicit instantiations", 
                   IDENTIFIER_POINTER (storage));
 
       if (storage == ridpointers[(int) RID_INLINE])
@@ -9206,8 +9370,11 @@ do_type_instantiation (t, storage)
 
         No program shall both explicitly instantiate and explicitly
         specialize a template.  */
-      cp_error ("explicit instantiation of `%#T' after", t);
-      cp_error_at ("explicit specialization here", t);
+      if (complain)
+       {
+         cp_error ("explicit instantiation of `%#T' after", t);
+         cp_error_at ("explicit specialization here", t);
+       }
       return;
     }
   else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t))
@@ -9221,7 +9388,8 @@ do_type_instantiation (t, storage)
         was `extern'.  If EXTERN_P then the second is.  If -frepo, chances
         are we already got marked as an explicit instantion because of the
         repo file.  All these cases are OK.  */
-      if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository)
+      if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository
+         && complain)
        cp_pedwarn ("duplicate explicit instantiation of `%#T'", t);
       
       /* If we've already instantiated the template, just return now.  */
@@ -9251,7 +9419,7 @@ do_type_instantiation (t, storage)
 
        Of course, we can't instantiate member template classes, since
        we don't have any arguments for them.  Note that the standard
-       is unclear on whether the instatiation of the members are
+       is unclear on whether the instantiation of the members are
        *explicit* instantiations or not.  We choose to be generous,
        and not set DECL_EXPLICIT_INSTANTIATION.  Therefore, we allow
        the explicit instantiation of a class where some of the members
@@ -9265,7 +9433,7 @@ do_type_instantiation (t, storage)
            mark_decl_instantiated (tmp, extern_p);
            repo_template_instantiated (tmp, extern_p);
            if (! extern_p)
-             instantiate_decl (tmp);
+             instantiate_decl (tmp, /*defer_ok=*/1);
          }
 
     for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
@@ -9274,13 +9442,13 @@ do_type_instantiation (t, storage)
          mark_decl_instantiated (tmp, extern_p);
          repo_template_instantiated (tmp, extern_p);
          if (! extern_p)
-           instantiate_decl (tmp);
+           instantiate_decl (tmp, /*defer_ok=*/1);
        }
 
     for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
       if (IS_AGGR_TYPE (TREE_VALUE (tmp))
          && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
-       do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
+       do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage, 0);
   }
 }
 
@@ -9309,10 +9477,13 @@ regenerate_decl_from_template (decl, tmpl)
      tree decl;
      tree tmpl;
 {
+  /* The most general version of TMPL.  */
+  tree gen_tmpl;
+  /* The arguments used to instantiate DECL, from the most general
+     template.  */
   tree args;
   tree code_pattern;
   tree new_decl;
-  tree gen_tmpl;
   int unregistered;
 
   args = DECL_TI_ARGS (decl);
@@ -9368,6 +9539,7 @@ regenerate_decl_from_template (decl, tmpl)
   DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
   DECL_ASSEMBLER_NAME (new_decl) = DECL_ASSEMBLER_NAME (decl);
   DECL_RTL (new_decl) = DECL_RTL (decl);
+  DECL_USE_TEMPLATE (new_decl) = DECL_USE_TEMPLATE (decl);
 
   /* Call duplicate decls to merge the old and new declarations.  */
   duplicate_decls (new_decl, decl);
@@ -9376,11 +9548,14 @@ regenerate_decl_from_template (decl, tmpl)
   register_specialization (decl, gen_tmpl, args);
 }
 
-/* Produce the definition of D, a _DECL generated from a template.  */
+/* Produce the definition of D, a _DECL generated from a template.  If
+   DEFER_OK is non-zero, then we don't have to actually do the
+   instantiation now; we just have to do it sometime.  */
 
 tree
-instantiate_decl (d)
+instantiate_decl (d, defer_ok)
      tree d;
+     int defer_ok;
 {
   tree tmpl = DECL_TI_TEMPLATE (d);
   tree args = DECL_TI_ARGS (d);
@@ -9388,20 +9563,23 @@ instantiate_decl (d)
   tree code_pattern;
   tree spec;
   tree gen_tmpl;
-  int nested = in_function_p ();
   int pattern_defined;
   int line = lineno;
-  char *file = input_filename;
-  tree old_fn = current_function_decl;
+  const char *file = input_filename;
 
   /* This function should only be used to instantiate templates for
      functions and static member variables.  */
   my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
                      || TREE_CODE (d) == VAR_DECL, 0);
 
+  /* Don't instantiate cloned functions.  Instead, instantiate the
+     functions they cloned.  */
+  if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
+    d = DECL_CLONED_FUNCTION (d);
+
   if (DECL_TEMPLATE_INSTANTIATED (d))
     /* D has already been instantiated.  It might seem reasonable to
-       check whether or not D is an explict instantiation, and, if so,
+       check whether or not D is an explicit instantiation, and, if so,
        stop here.  But when an explicit instantiation is deferred
        until the end of the compilation, DECL_EXPLICIT_INSTANTIATION
        is set, even though we still need to do the instantiation.  */
@@ -9421,6 +9599,8 @@ instantiate_decl (d)
   if (! push_tinst_level (d))
     return d;
 
+  timevar_push (TV_PARSE);
+
   /* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
      for the instantiation.  This is not always the most general
      template.  Consider, for example:
@@ -9432,32 +9612,30 @@ instantiate_decl (d)
      and an instantiation of S<double>::f<int>.  We want TD to be the
      specialization S<T>::f<int>, not the more general S<T>::f<U>.  */
   td = tmpl;
-  for (td = tmpl;
-       /* An instantiation cannot have a definition, so we need a
-         more general template.  */
-       DECL_TEMPLATE_INSTANTIATION (td)
-        /* We must also deal with friend templates.  Given:
-
-             template <class T> struct S { 
-               template <class U> friend void f() {};
-             };
-        
-           S<int>::f<U> say, is not an instantiation of S<T>::f<U>,
-           so far as the language is concerned, but that's still
-           where we get the pattern for the instantiation from.  On
-           ther hand, if the definition comes outside the class, say:
-
-             template <class T> struct S { 
-               template <class U> friend void f();
-              };
-             template <class U> friend void f() {}
-
-           we don't need to look any further.  That's what the check for
-           DECL_INITIAL is for.  */
-       || (TREE_CODE (d) == FUNCTION_DECL
-           && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td)
-           && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td)));
-       )
+  while (/* An instantiation cannot have a definition, so we need a
+           more general template.  */
+        DECL_TEMPLATE_INSTANTIATION (td)
+          /* We must also deal with friend templates.  Given:
+
+               template <class T> struct S { 
+                 template <class U> friend void f() {};
+               };
+
+             S<int>::f<U> say, is not an instantiation of S<T>::f<U>,
+             so far as the language is concerned, but that's still
+             where we get the pattern for the instantiation from.  On
+             other hand, if the definition comes outside the class, say:
+
+               template <class T> struct S { 
+                 template <class U> friend void f();
+               };
+               template <class U> friend void f() {}
+
+             we don't need to look any further.  That's what the check for
+             DECL_INITIAL is for.  */
+         || (TREE_CODE (d) == FUNCTION_DECL
+             && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td)
+             && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td))))
     {
       /* The present template, TD, should not be a definition.  If it
         were a definition, we should be using it!  Note that we
@@ -9507,26 +9685,23 @@ instantiate_decl (d)
        import_export_decl (d);
     }
 
-  /* Reject all external templates except inline functions.  */
-  if (DECL_INTERFACE_KNOWN (d)
-      && ! DECL_NOT_REALLY_EXTERN (d)
-      && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
-    goto out;
-
+  /* We need to set up DECL_INITIAL regardless of pattern_defined if
+     the variable is a static const initialized in the class body.  */
   if (TREE_CODE (d) == VAR_DECL 
       && TREE_READONLY (d)
       && DECL_INITIAL (d) == NULL_TREE
       && DECL_INITIAL (code_pattern) != NULL_TREE)
-    /* We need to set up DECL_INITIAL regardless of pattern_defined if
-       the variable is a static const initialized in the class body.  */;
-  else if (pattern_defined && nested
-          && TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
-    /* An inline function used in another function; instantiate it now so
-       we can inline it.  */;
-  else if (! pattern_defined || ! at_eof)
-    {
-      /* Defer all other templates.  We restore the source position
-         here because it's used by add_pending_template.  */
+    ;
+  /* Reject all external templates except inline functions.  */
+  else if (DECL_INTERFACE_KNOWN (d)
+          && ! DECL_NOT_REALLY_EXTERN (d)
+          && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
+    goto out;
+  /* Defer all other templates, unless we have been explicitly
+     forbidden from doing so.  We restore the source position here
+     because it's used by add_pending_template.  */
+  else if (! pattern_defined || defer_ok)
+    {
       lineno = line;
       input_filename = file;
 
@@ -9546,25 +9721,6 @@ instantiate_decl (d)
       goto out;
     }
 
-  /* If this instantiation is COMDAT, we don't know whether or not we
-     will really need to write it out.  If we can't be sure, mark it
-     DECL_DEFER_OUTPUT.  NOTE: This increases memory consumption,
-     since we keep some instantiations in memory rather than write
-     them out immediately and forget them.  A better approach would be
-     to wait until we know we need them to do the instantiation, but
-     that would break templates with static locals, because we
-     generate the functions to destroy statics before we determine
-     which functions are needed.  A better solution would be to
-     generate the ctor and dtor functions as we go.  */
-
-  if (TREE_CODE (d) == FUNCTION_DECL
-      && DECL_COMDAT (d)
-      && ! DECL_NEEDED_P (d)
-      /* If the function that caused us to be instantiated is needed, we
-        will be needed, too.  */
-      && (! nested || (old_fn && ! DECL_NEEDED_P (old_fn))))
-    DECL_DEFER_OUTPUT (d) = 1;
-
   /* We're now committed to instantiating this template.  Mark it as
      instantiated so that recursive calls to instantiate_decl do not
      try to instantiate it again.  */
@@ -9593,22 +9749,40 @@ instantiate_decl (d)
     }
   else if (TREE_CODE (d) == FUNCTION_DECL)
     {
+      htab_t saved_local_specializations;
+
+      /* Save away the current list, in case we are instantiating one
+        template from within the body of another.  */
+      saved_local_specializations = local_specializations;
+
+      /* Set up the list of local specializations.  */
+      local_specializations = htab_create (37, 
+                                          htab_hash_pointer,
+                                          htab_eq_pointer,
+                                          NULL);
+
       /* Set up context.  */
       start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
-      store_parm_decls ();
 
       /* We already set up __FUNCTION__, etc., so we don't want to do
         it again now.  */
-      current_function_name_declared = 1;
+      function_name_declared_p = 1;
 
       /* Substitute into the body of the function.  */
       tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
                   /*complain=*/1, tmpl);
 
+      /* We don't need the local specializations any more.  */
+      htab_delete (local_specializations);
+      local_specializations = saved_local_specializations;
+
       /* Finish the function.  */
-      expand_body (finish_function (lineno, 0));
+      expand_body (finish_function (0));
     }
 
+  /* We're not deferring instantiation any more.  */
+  TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0;
+
 out:
   lineno = line;
   input_filename = file;
@@ -9616,6 +9790,8 @@ out:
   pop_from_top_level ();
   pop_tinst_level ();
 
+  timevar_pop (TV_PARSE);
+
   return d;
 }
 
@@ -9636,17 +9812,15 @@ instantiate_pending_templates ()
       t = &pending_templates;
       while (*t)
        {
-         tree srcloc = TREE_PURPOSE (*t);
          tree instantiation = TREE_VALUE (*t);
 
-         input_filename = SRCLOC_FILE (srcloc);
-         lineno = SRCLOC_LINE (srcloc);
+         reopen_tinst_level (TREE_PURPOSE (*t));
 
-         if (TREE_CODE_CLASS (TREE_CODE (instantiation)) == 't')
+         if (TYPE_P (instantiation))
            {
              tree fn;
 
-             if (!TYPE_SIZE (instantiation))
+             if (!COMPLETE_TYPE_P (instantiation))
                {
                  instantiate_class_template (instantiation);
                  if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
@@ -9654,15 +9828,15 @@ instantiate_pending_templates ()
                         fn;
                         fn = TREE_CHAIN (fn))
                      if (! DECL_ARTIFICIAL (fn))
-                       instantiate_decl (fn);
-                 if (TYPE_SIZE (instantiation))
+                       instantiate_decl (fn, /*defer_ok=*/0);
+                 if (COMPLETE_TYPE_P (instantiation))
                    {
                      instantiated_something = 1;
                      reconsider = 1;
                    }
                }
 
-             if (TYPE_SIZE (instantiation))
+             if (COMPLETE_TYPE_P (instantiation))
                /* If INSTANTIATION has been instantiated, then we don't
                   need to consider it again in the future.  */
                *t = TREE_CHAIN (*t);
@@ -9671,10 +9845,11 @@ instantiate_pending_templates ()
            }
          else
            {
-             if (DECL_TEMPLATE_INSTANTIATION (instantiation)
+             if (!DECL_TEMPLATE_SPECIALIZATION (instantiation)
                  && !DECL_TEMPLATE_INSTANTIATED (instantiation))
                {
-                 instantiation = instantiate_decl (instantiation);
+                 instantiation = instantiate_decl (instantiation,
+                                                   /*defer_ok=*/0);
                  if (DECL_TEMPLATE_INSTANTIATED (instantiation))
                    {
                      instantiated_something = 1;
@@ -9682,7 +9857,7 @@ instantiate_pending_templates ()
                    }
                }
 
-             if (!DECL_TEMPLATE_INSTANTIATION (instantiation)
+             if (DECL_TEMPLATE_SPECIALIZATION (instantiation)
                  || DECL_TEMPLATE_INSTANTIATED (instantiation))
                /* If INSTANTIATION has been instantiated, then we don't
                   need to consider it again in the future.  */
@@ -9690,6 +9865,8 @@ instantiate_pending_templates ()
              else 
                t = &TREE_CHAIN (*t);
            }
+         tinst_depth = 0;
+         current_tinst_level = NULL_TREE;
        }
       template_tail = t;
 
@@ -9714,7 +9891,7 @@ instantiate_pending_templates ()
              template = TREE_PURPOSE (*t);
              args = get_bindings (template, fn, NULL_TREE);
              fn = instantiate_template (template, args);
-             instantiate_decl (fn);
+             instantiate_decl (fn, /*defer_ok=*/0);
              reconsider = 1;
            }
        
@@ -9728,12 +9905,13 @@ instantiate_pending_templates ()
   return instantiated_something;
 }
 
-/* Substitute ARGVEC into T, which is a TREE_LIST.  In particular, it
-   is an initializer list: the TREE_PURPOSEs are DECLs, and the
-   TREE_VALUEs are initializer values.  Used by instantiate_decl.  */
+/* Substitute ARGVEC into T, which is a list of initializers for
+   either base class or a non-static data member.  The TREE_PURPOSEs
+   are DECLs, and the TREE_VALUEs are the initializer values.  Used by
+   instantiate_decl.  */
 
 static tree
-tsubst_expr_values (t, argvec)
+tsubst_initializer_list (t, argvec)
      tree t, argvec;
 {
   tree first = NULL_TREE;
@@ -9741,42 +9919,27 @@ tsubst_expr_values (t, argvec)
 
   for (; t; t = TREE_CHAIN (t))
     {
-      tree pur = tsubst_copy (TREE_PURPOSE (t), argvec,
-                             /*complain=*/1, NULL_TREE);
-      tree val = tsubst_expr (TREE_VALUE (t), argvec, /*complain=*/1, 
-                             NULL_TREE);
-      *p = build_tree_list (pur, val);
-      p = &TREE_CHAIN (*p);
-    }
-  return first;
-}
+      tree decl;
+      tree init;
+      tree val;
 
-/* D is an undefined function declaration in the presence of templates with
-   the same name, listed in FNS.  If one of them can produce D as an
-   instantiation, remember this so we can instantiate it at EOF if D has
-   not been defined by that time.  */
+      decl = tsubst_copy (TREE_PURPOSE (t), argvec, /*complain=*/1,
+                         NULL_TREE);
+      init = tsubst_expr (TREE_VALUE (t), argvec, /*complain=*/1,
+                         NULL_TREE);
 
-void
-add_maybe_template (d, fns)
-     tree d, fns;
-{
-  tree t;
-
-  if (DECL_MAYBE_TEMPLATE (d))
-    return;
+      if (!init)
+       ;
+      else if (TREE_CODE (init) == TREE_LIST)
+       for (val = init; val; val = TREE_CHAIN (val))
+         TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val));
+      else
+       init = convert_from_reference (init);
 
-  t = most_specialized (fns, d, NULL_TREE);
-  if (! t)
-    return;
-  if (t == error_mark_node)
-    {
-      cp_error ("ambiguous template instantiation for `%D'", d);
-      return;
+      *p = build_tree_list (decl, init);
+      p = &TREE_CHAIN (*p);
     }
-
-  *maybe_template_tail = tree_cons (t, d, NULL_TREE);
-  maybe_template_tail = &TREE_CHAIN (*maybe_template_tail);
-  DECL_MAYBE_TEMPLATE (d) = 1;
+  return first;
 }
 
 /* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL.  */
@@ -9823,6 +9986,82 @@ tsubst_enum (tag, newtag, args)
     }
 
   finish_enum (newtag);
+  DECL_SOURCE_LINE (TYPE_NAME (newtag)) = DECL_SOURCE_LINE (TYPE_NAME (tag));
+  DECL_SOURCE_FILE (TYPE_NAME (newtag)) = DECL_SOURCE_FILE (TYPE_NAME (tag));
+}
+
+/* DECL is a FUNCTION_DECL that is a template specialization.  Return
+   its type -- but without substituting the innermost set of template
+   arguments.  So, innermost set of template parameters will appear in
+   the type.  If CONTEXTP is non-NULL, then the partially substituted
+   DECL_CONTEXT (if any) will also be filled in.  Similarly, TPARMSP
+   will be filled in with the substituted template parameters, if it
+   is non-NULL.  */
+
+tree 
+get_mostly_instantiated_function_type (decl, contextp, tparmsp)
+     tree decl;
+     tree *contextp;
+     tree *tparmsp;
+{
+  tree context = NULL_TREE;
+  tree fn_type;
+  tree tmpl;
+  tree targs;
+  tree tparms;
+  int parm_depth;
+
+  tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+  targs = DECL_TI_ARGS (decl);
+  tparms = DECL_TEMPLATE_PARMS (tmpl);
+  parm_depth = TMPL_PARMS_DEPTH (tparms);
+
+  /* There should be as many levels of arguments as there are levels
+     of parameters.  */
+  my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
+
+  fn_type = TREE_TYPE (tmpl);
+  if (DECL_STATIC_FUNCTION_P (decl))
+    context = DECL_CONTEXT (decl);
+
+  if (parm_depth == 1)
+    /* No substitution is necessary.  */
+    ;
+  else
+    {
+      int i;
+      tree partial_args;
+
+      /* Replace the innermost level of the TARGS with NULL_TREEs to
+        let tsubst know not to substitute for those parameters.  */
+      partial_args = make_tree_vec (TREE_VEC_LENGTH (targs));
+      for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
+       SET_TMPL_ARGS_LEVEL (partial_args, i,
+                            TMPL_ARGS_LEVEL (targs, i));
+      SET_TMPL_ARGS_LEVEL (partial_args,
+                          TMPL_ARGS_DEPTH (targs),
+                          make_tree_vec (DECL_NTPARMS (tmpl)));
+
+      /* Now, do the (partial) substitution to figure out the
+        appropriate function type.  */
+      fn_type = tsubst (fn_type, partial_args, /*complain=*/1, NULL_TREE);
+      if (DECL_STATIC_FUNCTION_P (decl))
+       context = tsubst (context, partial_args, /*complain=*/1, NULL_TREE);
+
+      /* Substitute into the template parameters to obtain the real
+        innermost set of parameters.  This step is important if the
+        innermost set of template parameters contains value
+        parameters whose types depend on outer template parameters.  */
+      TREE_VEC_LENGTH (partial_args)--;
+      tparms = tsubst_template_parms (tparms, partial_args, /*complain=*/1);
+    }
+
+  if (contextp)
+    *contextp = context;
+  if (tparmsp)
+    *tparmsp = tparms;
+
+  return fn_type;
 }
 
 /* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
@@ -9833,19 +10072,23 @@ static void
 set_mangled_name_for_template_decl (decl)
      tree decl;
 {
-  tree saved_namespace;
   tree context = NULL_TREE;
   tree fn_type;
   tree ret_type;
   tree parm_types;
   tree tparms;
   tree targs;
-  tree tmpl;
-  int parm_depth;
 
   my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL, 0);
   my_friendly_assert (DECL_TEMPLATE_INFO (decl) != NULL_TREE, 0);
 
+  /* Under the new ABI, we don't need special machinery.  */
+  if (flag_new_abi)
+    {
+      set_mangled_name_for_decl (decl);
+      return;
+    }
+
   /* The names of template functions must be mangled so as to indicate
      what template is being specialized with what template arguments.
      For example, each of the following three functions must get
@@ -9861,14 +10104,6 @@ set_mangled_name_for_template_decl (decl)
        mangle the name of such an entity.  */
     return;
 
-  tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
-  tparms = DECL_TEMPLATE_PARMS (tmpl);
-  parm_depth = TMPL_PARMS_DEPTH (tparms);
-
-  /* There should be as many levels of arguments as there are levels
-     of parameters.  */
-  my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
-
   /* We now compute the PARMS and RET_TYPE to give to
      build_decl_overload_real.  The PARMS and RET_TYPE are the
      parameter and return types of the template, after all but the
@@ -9887,46 +10122,12 @@ set_mangled_name_for_template_decl (decl)
      {int, U}.  Thus, the args that we want to subsitute into the
      return and parameter type for the function are those in TARGS,
      with the innermost level omitted.  */
-  fn_type = TREE_TYPE (tmpl);
-  if (DECL_STATIC_FUNCTION_P (decl))
-    context = DECL_CONTEXT (decl);
-
-  if (parm_depth == 1)
-    /* No substitution is necessary.  */
-    ;
-  else
-    {
-      int i;
-      tree partial_args;
-
-      /* Replace the innermost level of the TARGS with NULL_TREEs to
-        let tsubst know not to subsitute for those parameters.  */
-      partial_args = make_tree_vec (TREE_VEC_LENGTH (targs));
-      for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
-       SET_TMPL_ARGS_LEVEL (partial_args, i,
-                            TMPL_ARGS_LEVEL (targs, i));
-      SET_TMPL_ARGS_LEVEL (partial_args,
-                          TMPL_ARGS_DEPTH (targs),
-                          make_tree_vec (DECL_NTPARMS (tmpl)));
-
-      /* Now, do the (partial) substitution to figure out the
-        appropriate function type.  */
-      fn_type = tsubst (fn_type, partial_args, /*complain=*/1, NULL_TREE);
-      if (DECL_STATIC_FUNCTION_P (decl))
-       context = tsubst (context, partial_args, /*complain=*/1, NULL_TREE);
-
-      /* Substitute into the template parameters to obtain the real
-        innermost set of parameters.  This step is important if the
-        innermost set of template parameters contains value
-        parameters whose types depend on outer template parameters.  */
-      TREE_VEC_LENGTH (partial_args)--;
-      tparms = tsubst_template_parms (tparms, partial_args, /*complain=*/1);
-    }
+  fn_type = get_mostly_instantiated_function_type (decl, &context, &tparms);
 
   /* Now, get the innermost parameters and arguments, and figure out
      the parameter and return types.  */
   tparms = INNERMOST_TEMPLATE_PARMS (tparms);
-  targs = innermost_args (targs);
+  targs = INNERMOST_TEMPLATE_ARGS (targs);
   ret_type = TREE_TYPE (fn_type);
   parm_types = TYPE_ARG_TYPES (fn_type);
 
@@ -9949,21 +10150,31 @@ set_mangled_name_for_template_decl (decl)
   my_friendly_assert (TREE_VEC_LENGTH (tparms) == TREE_VEC_LENGTH (targs),
                      0);
 
-  /* If the template is in a namespace, we need to put that into the
-     mangled name. Unfortunately, build_decl_overload_real does not
-     get the decl to mangle, so it relies on the current
-     namespace. Therefore, we set that here temporarily. */
-  my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702);
-  saved_namespace = current_namespace;
-  current_namespace = CP_DECL_CONTEXT (decl);  
-
-  /* Actually set the DCL_ASSEMBLER_NAME.  */
+  /* Actually set the DECL_ASSEMBLER_NAME.  */
   DECL_ASSEMBLER_NAME (decl)
-    = build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type,
+    = build_decl_overload_real (decl, parm_types, ret_type,
                                tparms, targs, 
                                DECL_FUNCTION_MEMBER_P (decl) 
-                               + DECL_CONSTRUCTOR_P (decl));
+                               + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
+}
 
-  /* Restore the previously active namespace.  */
-  current_namespace = saved_namespace;
+/* Return truthvalue if we're processing a template different from
+   the last one involved in diagnostics.  */
+int
+problematic_instantiation_changed ()
+{
+  return last_template_error_tick != tinst_level_tick;
+}
+
+/* Remember current template involved in diagnostics.  */
+void
+record_last_problematic_instantiation ()
+{
+  last_template_error_tick = tinst_level_tick;
+}
+
+tree
+current_instantiation ()
+{
+  return current_tinst_level;
 }