OSDN Git Service

Implement DR 757: It's OK for a decl to use a type without linkage
[pf3gnuchains/gcc-fork.git] / gcc / cp / pt.c
index f141b74..36f1b00 100644 (file)
@@ -1,6 +1,7 @@
 /* Handle parameterized types (templates) for GNU C++.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2007, 2008  Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
    Rewritten by Jason Merrill (jason@cygnus.com).
 
@@ -53,7 +54,7 @@ typedef int (*tree_fn_t) (tree, void*);
 /* 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 work.  */
-struct pending_template GTY (()) {
+struct GTY (()) pending_template {
   struct pending_template *next;
   struct tinst_level *tinst;
 };
@@ -81,6 +82,19 @@ static tree cur_stmt_expr;
    local variables.  */
 static htab_t local_specializations;
 
+typedef struct GTY(()) spec_entry
+{
+  tree tmpl;
+  tree args;
+  tree spec;
+} spec_entry;
+
+static GTY ((param_is (spec_entry)))
+  htab_t decl_specializations;
+
+static GTY ((param_is (spec_entry)))
+  htab_t type_specializations;
+
 /* Contains canonical template parameter types. The vector is indexed by
    the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
    TREE_LIST, whose TREE_VALUEs contain the canonical template
@@ -117,8 +131,8 @@ static tree add_outermost_template_args (tree, tree);
 static bool check_instantiated_args (tree, tree, tsubst_flags_t);
 static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
                                             tree);
-static int  type_unification_real (tree, tree, tree, tree,
-                                  int, unification_kind_t, int);
+static int type_unification_real (tree, tree, tree, const tree *,
+                                 unsigned int, int, unification_kind_t, int);
 static void note_template_header (int);
 static tree convert_nontype_argument_function (tree, tree);
 static tree convert_nontype_argument (tree, tree);
@@ -132,6 +146,7 @@ static bool inline_needs_template_parms (tree);
 static void push_inline_template_parms_recursive (tree, int);
 static tree retrieve_local_specialization (tree);
 static void register_local_specialization (tree, tree);
+static hashval_t hash_specialization (const void *p);
 static tree reduce_template_parm_level (tree, tree, int, tree, tsubst_flags_t);
 static int mark_template_parm (tree, void *);
 static int template_parm_this_level_p (tree, void *);
@@ -169,10 +184,13 @@ static int eq_local_specializations (const void *, const void *);
 static bool dependent_template_arg_p (tree);
 static bool any_template_arguments_need_structural_equality_p (tree);
 static bool dependent_type_p_r (tree);
-static tree tsubst (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_expr        (tree, tree, tsubst_flags_t, tree, bool);
 static tree tsubst_copy        (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_decl (tree, tree, tsubst_flags_t);
+static void perform_typedefs_access_check (tree tmpl, tree targs);
+static void append_type_to_template_for_access_check_1 (tree, tree, tree);
+static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -380,7 +398,8 @@ push_inline_template_parms_recursive (tree parmlist, int levels)
               It is ugly that we recreate this here; the original
               version built in process_template_parm is no longer
               available.  */
-           tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
+           tree decl = build_decl (DECL_SOURCE_LOCATION (parm),
+                                   CONST_DECL, DECL_NAME (parm),
                                    TREE_TYPE (parm));
            DECL_ARTIFICIAL (decl) = 1;
            TREE_CONSTANT (decl) = 1;
@@ -710,8 +729,8 @@ check_specialization_namespace (tree tmpl)
     return true;
   else
     {
-      pedwarn ("specialization of %qD in different namespace", tmpl);
-      pedwarn ("  from definition of %q+#D", tmpl);
+      permerror (input_location, "specialization of %qD in different namespace", tmpl);
+      permerror (input_location, "  from definition of %q+#D", tmpl);
       return false;
     }
 }
@@ -728,9 +747,9 @@ check_explicit_instantiation_namespace (tree spec)
      namespace of its template.  */
   ns = decl_namespace_context (spec);
   if (!is_ancestor (current_namespace, ns))
-    pedwarn ("explicit instantiation of %qD in namespace %qD "
-            "(which does not enclose namespace %qD)",
-            spec, current_namespace, ns);
+    permerror (input_location, "explicit instantiation of %qD in namespace %qD "
+              "(which does not enclose namespace %qD)",
+              spec, current_namespace, ns);
 }
 
 /* The TYPE is being declared.  If it is a template type, that means it
@@ -772,7 +791,11 @@ maybe_process_partial_specialization (tree type)
          check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
          SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
          if (processing_template_decl)
-           push_template_decl (TYPE_MAIN_DECL (type));
+           {
+             if (push_template_decl (TYPE_MAIN_DECL (type))
+                 == error_mark_node)
+               return error_mark_node;
+           }
        }
       else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
        error ("specialization of %qT after instantiation", type);
@@ -803,13 +826,13 @@ maybe_process_partial_specialization (tree type)
          && !COMPLETE_TYPE_P (type))
        {
          tree t;
+         tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
 
          if (current_namespace
-             != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+             != decl_namespace_context (tmpl))
            {
-             pedwarn ("specializing %q#T in different namespace", type);
-             pedwarn ("  from definition of %q+#D",
-                      CLASSTYPE_TI_TEMPLATE (type));
+             permerror (input_location, "specializing %q#T in different namespace", type);
+             permerror (input_location, "  from definition of %q+#D", tmpl);
            }
 
          /* Check for invalid specialization after instantiation:
@@ -817,13 +840,38 @@ maybe_process_partial_specialization (tree type)
               template <> template <> class C<int>::D<int>;
               template <> template <class U> class C<int>::D;  */
 
-         for (t = DECL_TEMPLATE_INSTANTIATIONS
-                (most_general_template (CLASSTYPE_TI_TEMPLATE (type)));
+         for (t = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
               t; t = TREE_CHAIN (t))
-           if (TREE_VALUE (t) != type
-               && TYPE_CONTEXT (TREE_VALUE (t)) == context)
-             error ("specialization %qT after instantiation %qT",
-                    type, TREE_VALUE (t));
+           {
+             tree inst = TREE_VALUE (t);
+             if (CLASSTYPE_TEMPLATE_SPECIALIZATION (inst))
+               {
+                 /* We already have a full specialization of this partial
+                    instantiation.  Reassign it to the new member
+                    specialization template.  */
+                 spec_entry elt;
+                 spec_entry **slot;
+
+                 elt.tmpl = most_general_template (tmpl);
+                 elt.args = CLASSTYPE_TI_ARGS (inst);
+                 elt.spec = inst;
+
+                 htab_remove_elt (type_specializations, &elt);
+
+                 elt.tmpl = tmpl;
+                 elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
+
+                 slot = (spec_entry **)
+                   htab_find_slot (type_specializations, &elt, INSERT);
+                 *slot = GGC_NEW (spec_entry);
+                 **slot = elt;
+               }
+             else if (COMPLETE_TYPE_P (inst) || TYPE_BEING_DEFINED (inst))
+               /* But if we've had an implicit instantiation, that's a
+                  problem ([temp.expl.spec]/6).  */
+               error ("specialization %qT after instantiation %qT",
+                      type, inst);
+           }
 
          /* Mark TYPE as a specialization.  And as a result, we only
             have one level of template argument for the innermost
@@ -887,8 +935,7 @@ optimize_specialization_lookup_p (tree tmpl)
    parameter is ignored if TMPL is not a class template.  */
 
 static tree
-retrieve_specialization (tree tmpl, tree args,
-                        bool class_specializations_p)
+retrieve_specialization (tree tmpl, tree args, hashval_t hash)
 {
   if (args == error_mark_node)
     return NULL_TREE;
@@ -913,8 +960,7 @@ retrieve_specialization (tree tmpl, tree args,
         arguments.  */
       class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl));
       class_specialization
-       = retrieve_specialization (class_template, args,
-                                  /*class_specializations_p=*/false);
+       = retrieve_specialization (class_template, args, 0);
       if (!class_specialization)
        return NULL_TREE;
       /* Now, find the appropriate entry in the CLASSTYPE_METHOD_VEC
@@ -928,45 +974,34 @@ retrieve_specialization (tree tmpl, tree args,
       for (fns = VEC_index (tree, methods, idx); fns; fns = OVL_NEXT (fns))
        {
          tree fn = OVL_CURRENT (fns);
-         if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl)
+         if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl
+             /* using-declarations can add base methods to the method vec,
+                and we don't want those here.  */
+             && DECL_CONTEXT (fn) == class_specialization)
            return fn;
        }
       return NULL_TREE;
     }
   else
     {
-      tree *sp;
-      tree *head;
+      spec_entry *found;
+      spec_entry elt;
+      htab_t specializations;
+
+      elt.tmpl = tmpl;
+      elt.args = args;
+      elt.spec = NULL_TREE;
 
-      /* Class templates store their instantiations on the
-        DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
-        DECL_TEMPLATE_SPECIALIZATIONS list.  */
-      if (!class_specializations_p
-         && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL
-         && TAGGED_TYPE_P (TREE_TYPE (tmpl)))
-       sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+      if (DECL_CLASS_TEMPLATE_P (tmpl))
+       specializations = type_specializations;
       else
-       sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
-      head = sp;
-      /* Iterate through the list until we find a matching template.  */
-      while (*sp != NULL_TREE)
-       {
-         tree spec = *sp;
+       specializations = decl_specializations;
 
-         if (comp_template_args (TREE_PURPOSE (spec), args))
-           {
-             /* Use the move-to-front heuristic to speed up future
-                searches.  */
-             if (spec != *head)
-               {
-                 *sp = TREE_CHAIN (*sp);
-                 TREE_CHAIN (spec) = *head;
-                 *head = spec;
-               }
-             return TREE_VALUE (spec);
-           }
-         sp = &TREE_CHAIN (spec);
-       }
+      if (hash == 0)
+       hash = hash_specialization (&elt);
+      found = (spec_entry *) htab_find_with_hash (specializations, &elt, hash);
+      if (found)
+       return found->spec;
     }
 
   return NULL_TREE;
@@ -1018,10 +1053,10 @@ is_specialization_of (tree decl, tree tmpl)
 }
 
 /* Returns nonzero iff DECL is a specialization of friend declaration
-   FRIEND according to [temp.friend].  */
+   FRIEND_DECL according to [temp.friend].  */
 
 bool
-is_specialization_of_friend (tree decl, tree friend)
+is_specialization_of_friend (tree decl, tree friend_decl)
 {
   bool need_template = true;
   int template_depth;
@@ -1029,26 +1064,26 @@ is_specialization_of_friend (tree decl, tree friend)
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
              || TREE_CODE (decl) == TYPE_DECL);
 
-  /* For [temp.friend/6] when FRIEND is an ordinary member function
+  /* For [temp.friend/6] when FRIEND_DECL is an ordinary member function
      of a template class, we want to check if DECL is a specialization
      if this.  */
-  if (TREE_CODE (friend) == FUNCTION_DECL
-      && DECL_TEMPLATE_INFO (friend)
-      && !DECL_USE_TEMPLATE (friend))
+  if (TREE_CODE (friend_decl) == FUNCTION_DECL
+      && DECL_TEMPLATE_INFO (friend_decl)
+      && !DECL_USE_TEMPLATE (friend_decl))
     {
       /* We want a TEMPLATE_DECL for `is_specialization_of'.  */
-      friend = DECL_TI_TEMPLATE (friend);
+      friend_decl = DECL_TI_TEMPLATE (friend_decl);
       need_template = false;
     }
-  else if (TREE_CODE (friend) == TEMPLATE_DECL
-          && !PRIMARY_TEMPLATE_P (friend))
+  else if (TREE_CODE (friend_decl) == TEMPLATE_DECL
+          && !PRIMARY_TEMPLATE_P (friend_decl))
     need_template = false;
 
   /* There is nothing to do if this is not a template friend.  */
-  if (TREE_CODE (friend) != TEMPLATE_DECL)
+  if (TREE_CODE (friend_decl) != TEMPLATE_DECL)
     return false;
 
-  if (is_specialization_of (decl, friend))
+  if (is_specialization_of (decl, friend_decl))
     return true;
 
   /* [temp.friend/6]
@@ -1071,14 +1106,14 @@ is_specialization_of_friend (tree decl, tree friend)
      nonzero.  To determine if DECL is a friend of FRIEND, we first
      check if the enclosing class is a specialization of another.  */
 
-  template_depth = template_class_depth (DECL_CONTEXT (friend));
+  template_depth = template_class_depth (DECL_CONTEXT (friend_decl));
   if (template_depth
       && DECL_CLASS_SCOPE_P (decl)
       && is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
-                              CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend))))
+                              CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend_decl))))
     {
       /* Next, we check the members themselves.  In order to handle
-        a few tricky cases, such as when FRIEND's are
+        a few tricky cases, such as when FRIEND_DECL's are
 
           template <class T> friend void A<T>::g(T t);
           template <class T> template <T t> friend void A<T>::h();
@@ -1118,7 +1153,7 @@ is_specialization_of_friend (tree decl, tree friend)
          tree friend_args_type;
          tree decl_args_type;
 
-         /* Make sure that both DECL and FRIEND are templates or
+         /* Make sure that both DECL and FRIEND_DECL are templates or
             non-templates.  */
          is_template = DECL_TEMPLATE_INFO (decl)
                        && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
@@ -1128,7 +1163,7 @@ is_specialization_of_friend (tree decl, tree friend)
            {
              /* If both are templates, check template parameter list.  */
              tree friend_parms
-               = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+               = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
                                         args, tf_none);
              if (!comp_template_parms
                     (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
@@ -1140,7 +1175,7 @@ is_specialization_of_friend (tree decl, tree friend)
          else
            decl_type = TREE_TYPE (decl);
 
-         friend_type = tsubst_function_type (TREE_TYPE (friend), args,
+         friend_type = tsubst_function_type (TREE_TYPE (friend_decl), args,
                                              tf_none, NULL_TREE);
          if (friend_type == error_mark_node)
            return false;
@@ -1153,7 +1188,7 @@ is_specialization_of_friend (tree decl, tree friend)
             `this' parameter.  */
          friend_args_type = TYPE_ARG_TYPES (friend_type);
          decl_args_type = TYPE_ARG_TYPES (decl_type);
-         if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend))
+         if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend_decl))
            friend_args_type = TREE_CHAIN (friend_args_type);
          if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
            decl_args_type = TREE_CHAIN (decl_args_type);
@@ -1166,7 +1201,7 @@ is_specialization_of_friend (tree decl, tree friend)
          bool is_template;
          tree decl_type = TREE_TYPE (decl);
 
-         /* Make sure that both DECL and FRIEND are templates or
+         /* Make sure that both DECL and FRIEND_DECL are templates or
             non-templates.  */
          is_template
            = CLASSTYPE_TEMPLATE_INFO (decl_type)
@@ -1180,12 +1215,12 @@ is_specialization_of_friend (tree decl, tree friend)
              /* If both are templates, check the name of the two
                 TEMPLATE_DECL's first because is_friend didn't.  */
              if (DECL_NAME (CLASSTYPE_TI_TEMPLATE (decl_type))
-                 != DECL_NAME (friend))
+                 != DECL_NAME (friend_decl))
                return false;
 
              /* Now check template parameter list.  */
              friend_parms
-               = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
+               = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
                                         args, tf_none);
              return comp_template_parms
                (DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (decl_type)),
@@ -1193,7 +1228,7 @@ is_specialization_of_friend (tree decl, tree friend)
            }
          else
            return (DECL_NAME (decl)
-                   == DECL_NAME (friend));
+                   == DECL_NAME (friend_decl));
        }
     }
   return false;
@@ -1205,11 +1240,14 @@ is_specialization_of_friend (tree decl, tree friend)
    equivalent prior declaration, if available.  */
 
 static tree
-register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
+register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
+                        hashval_t hash)
 {
   tree fn;
+  spec_entry **slot = NULL;
+  spec_entry elt;
 
-  gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
+  gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec));
 
   if (TREE_CODE (spec) == FUNCTION_DECL
       && uses_template_parms (DECL_TI_ARGS (spec)))
@@ -1226,8 +1264,27 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
        instantiation unless and until it is actually needed.  */
     return spec;
 
-  fn = retrieve_specialization (tmpl, args,
-                               /*class_specializations_p=*/false);
+  if (optimize_specialization_lookup_p (tmpl))
+    /* We don't put these specializations in the hash table, but we might
+       want to give an error about a mismatch.  */
+    fn = retrieve_specialization (tmpl, args, 0);
+  else
+    {
+      elt.tmpl = tmpl;
+      elt.args = args;
+      elt.spec = spec;
+
+      if (hash == 0)
+       hash = hash_specialization (&elt);
+
+      slot = (spec_entry **)
+       htab_find_slot_with_hash (decl_specializations, &elt, hash, INSERT);
+      if (*slot)
+       fn = (*slot)->spec;
+      else
+       fn = NULL_TREE;
+    }
+
   /* We can sometimes try to re-register a specialization that we've
      already got.  In particular, regenerate_decl_from_template calls
      duplicate_decls which will update the specialization list.  But,
@@ -1285,12 +1342,8 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
                to the primary function; now copy the inline bits to
                the various clones.  */
              FOR_EACH_CLONE (clone, fn)
-               {
-                 DECL_DECLARED_INLINE_P (clone)
-                   = DECL_DECLARED_INLINE_P (fn);
-                 DECL_INLINE (clone)
-                   = DECL_INLINE (fn);
-               }
+               DECL_DECLARED_INLINE_P (clone)
+                 = DECL_DECLARED_INLINE_P (fn);
              check_specialization_namespace (fn);
 
              return fn;
@@ -1307,40 +1360,224 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
          return fn;
        }
     }
+  else if (fn)
+    return duplicate_decls (spec, fn, is_friend);
 
   /* A specialization must be declared in the same namespace as the
      template it is specializing.  */
   if (DECL_TEMPLATE_SPECIALIZATION (spec)
       && !check_specialization_namespace (tmpl))
-    DECL_CONTEXT (spec) = FROB_CONTEXT (decl_namespace_context (tmpl));
+    DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
 
   if (!optimize_specialization_lookup_p (tmpl))
-    DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
-      = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+    {
+      gcc_assert (tmpl && args && spec);
+      *slot = GGC_NEW (spec_entry);
+      **slot = elt;
+      if (TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
+         && PRIMARY_TEMPLATE_P (tmpl)
+         && DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
+       /* TMPL is a forward declaration of a template function; keep a list
+          of all specializations in case we need to reassign them to a friend
+          template later in tsubst_friend_function.  */
+       DECL_TEMPLATE_INSTANTIATIONS (tmpl)
+         = tree_cons (args, spec, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
+    }
 
   return spec;
 }
 
+/* Returns true iff two spec_entry nodes are equivalent.  Only compares the
+   TMPL and ARGS members, ignores SPEC.  */
+
+static int
+eq_specializations (const void *p1, const void *p2)
+{
+  const spec_entry *e1 = (const spec_entry *)p1;
+  const spec_entry *e2 = (const spec_entry *)p2;
+
+  return (e1->tmpl == e2->tmpl
+         && comp_template_args (e1->args, e2->args));
+}
+
+/* Returns a hash for a template TMPL and template arguments ARGS.  */
+
+static hashval_t
+hash_tmpl_and_args (tree tmpl, tree args)
+{
+  hashval_t val = DECL_UID (tmpl);
+  return iterative_hash_template_arg (args, val);
+}
+
+/* Returns a hash for a spec_entry node based on the TMPL and ARGS members,
+   ignoring SPEC.  */
+
+static hashval_t
+hash_specialization (const void *p)
+{
+  const spec_entry *e = (const spec_entry *)p;
+  return hash_tmpl_and_args (e->tmpl, e->args);
+}
+
+/* Recursively calculate a hash value for a template argument ARG, for use
+   in the hash tables of template specializations.  */
+
+static hashval_t
+iterative_hash_template_arg (tree arg, hashval_t val)
+{
+  unsigned HOST_WIDE_INT i;
+  enum tree_code code;
+  char tclass;
+
+  if (arg == NULL_TREE)
+    return iterative_hash_object (arg, val);
+
+  if (!TYPE_P (arg))
+    STRIP_NOPS (arg);
+
+  code = TREE_CODE (arg);
+  tclass = TREE_CODE_CLASS (code);
+
+  val = iterative_hash_object (code, val);
+
+  switch (code)
+    {
+    case ERROR_MARK:
+      return val;
+
+    case IDENTIFIER_NODE:
+      return iterative_hash_object (IDENTIFIER_HASH_VALUE (arg), val);
+
+    case TREE_VEC:
+      {
+       int i, len = TREE_VEC_LENGTH (arg);
+       for (i = 0; i < len; ++i)
+         val = iterative_hash_template_arg (TREE_VEC_ELT (arg, i), val);
+       return val;
+      }
+
+    case TYPE_PACK_EXPANSION:
+    case EXPR_PACK_EXPANSION:
+      return iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
+
+    case ARGUMENT_PACK_SELECT:
+      /* We can get one of these when re-hashing a previous entry in the middle
+         of substituting into a pack expansion.  Just look through it...  */
+      arg = ARGUMENT_PACK_SELECT_FROM_PACK (arg);
+      /* ...and fall through.  */
+    case TYPE_ARGUMENT_PACK:
+    case NONTYPE_ARGUMENT_PACK:
+      return iterative_hash_template_arg (ARGUMENT_PACK_ARGS (arg), val);
+
+    case TREE_LIST:
+      for (; arg; arg = TREE_CHAIN (arg))
+       val = iterative_hash_template_arg (TREE_VALUE (arg), val);
+      return val;
+
+    case OVERLOAD:
+      for (; arg; arg = OVL_CHAIN (arg))
+       val = iterative_hash_template_arg (OVL_FUNCTION (arg), val);
+      return val;
+
+    case CONSTRUCTOR:
+      {
+       tree field, value;
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg), i, field, value)
+         {
+           val = iterative_hash_template_arg (field, val);
+           val = iterative_hash_template_arg (value, val);
+         }
+       return val;
+      }
+
+    case PARM_DECL:
+      val = iterative_hash_object (DECL_PARM_INDEX (arg), val);
+      return iterative_hash_template_arg (TREE_TYPE (arg), val);
+
+    case TARGET_EXPR:
+      return iterative_hash_template_arg (TARGET_EXPR_INITIAL (arg), val);
+
+    case PTRMEM_CST:
+      val = iterative_hash_template_arg (PTRMEM_CST_CLASS (arg), val);
+      return iterative_hash_template_arg (PTRMEM_CST_MEMBER (arg), val);
+
+    case TEMPLATE_PARM_INDEX:
+      val = iterative_hash_template_arg
+       (TREE_TYPE (TEMPLATE_PARM_DECL (arg)), val);
+      val = iterative_hash_object (TEMPLATE_PARM_LEVEL (arg), val);
+      return iterative_hash_object (TEMPLATE_PARM_IDX (arg), val);
+
+    case TRAIT_EXPR:
+      val = iterative_hash_object (TRAIT_EXPR_KIND (arg), val);
+      val = iterative_hash_template_arg (TRAIT_EXPR_TYPE1 (arg), val);
+      return iterative_hash_template_arg (TRAIT_EXPR_TYPE2 (arg), val);
+
+    case BASELINK:
+      val = iterative_hash_template_arg (BINFO_TYPE (BASELINK_BINFO (arg)),
+                                        val);
+      return iterative_hash_template_arg (DECL_NAME (get_first_fn (arg)),
+                                         val);
+
+    case MODOP_EXPR:
+      val = iterative_hash_template_arg (TREE_OPERAND (arg, 0), val);
+      code = TREE_CODE (TREE_OPERAND (arg, 1));
+      val = iterative_hash_object (code, val);
+      return iterative_hash_template_arg (TREE_OPERAND (arg, 2), val);
+
+    default:
+      switch (tclass)
+       {
+       case tcc_type:
+         if (TYPE_CANONICAL (arg))
+           return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
+                                         val);
+         else if (TREE_CODE (arg) == DECLTYPE_TYPE)
+           return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
+         /* Otherwise just compare the types during lookup.  */
+         return val;
+
+       case tcc_declaration:
+       case tcc_constant:
+         return iterative_hash_expr (arg, val);
+
+       default:
+         gcc_assert (IS_EXPR_CODE_CLASS (tclass));
+         {
+           unsigned n = TREE_OPERAND_LENGTH (arg);
+           for (i = 0; i < n; ++i)
+             val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
+           return val;
+         }
+       }
+    }
+  gcc_unreachable ();
+  return 0;
+}
+
 /* Unregister the specialization SPEC as a specialization of TMPL.
    Replace it with NEW_SPEC, if NEW_SPEC is non-NULL.  Returns true
-   if the SPEC was listed as a specialization of TMPL.  */
+   if the SPEC was listed as a specialization of TMPL.
+
+   Note that SPEC has been ggc_freed, so we can't look inside it.  */
 
 bool
-reregister_specialization (tree spec, tree tmpl, tree new_spec)
+reregister_specialization (tree spec, tree tinfo, tree new_spec)
 {
-  tree* s;
+  spec_entry **slot;
+  spec_entry elt;
 
-  for (s = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
-       *s != NULL_TREE;
-       s = &TREE_CHAIN (*s))
-    if (TREE_VALUE (*s) == spec)
-      {
-       if (!new_spec)
-         *s = TREE_CHAIN (*s);
-       else
-         TREE_VALUE (*s) = new_spec;
-       return 1;
-      }
+  elt.tmpl = most_general_template (TI_TEMPLATE (tinfo));
+  elt.args = TI_ARGS (tinfo);
+  elt.spec = NULL_TREE;
+
+  slot = (spec_entry **) htab_find_slot (decl_specializations, &elt, INSERT);
+  if (*slot)
+    {
+      gcc_assert ((*slot)->spec == spec || (*slot)->spec == new_spec);
+      gcc_assert (new_spec != NULL_TREE);
+      (*slot)->spec = new_spec;
+      return 1;
+    }
 
   return 0;
 }
@@ -1696,12 +1933,13 @@ determine_specialization (tree template_id,
   if (candidates)
     {
       tree fn = TREE_VALUE (candidates);
-      /* DECL is a re-declaration of a template function.  */
+      *targs_out = copy_node (DECL_TI_ARGS (fn));
+      /* DECL is a re-declaration or partial instantiation of a template
+        function.  */
       if (TREE_CODE (fn) == TEMPLATE_DECL)
        return fn;
       /* It was a specialization of an ordinary member function in a
         template class.  */
-      *targs_out = copy_node (DECL_TI_ARGS (fn));
       return DECL_TI_TEMPLATE (fn);
     }
 
@@ -2002,8 +2240,8 @@ check_explicit_specialization (tree declarator,
       for (; t; t = TREE_CHAIN (t))
        if (TREE_PURPOSE (t))
          {
-           pedwarn
-             ("default argument specified in explicit specialization");
+           permerror (input_location, 
+                      "default argument specified in explicit specialization");
            break;
          }
     }
@@ -2216,19 +2454,24 @@ check_explicit_specialization (tree declarator,
             the specialization of it.  */
          if (tsk == tsk_template)
            {
+             tree result = DECL_TEMPLATE_RESULT (tmpl);
              SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
-             DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE;
+             DECL_INITIAL (result) = NULL_TREE;
              if (have_def)
                {
+                 tree parm;
                  DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
-                 DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (tmpl))
+                 DECL_SOURCE_LOCATION (result)
                    = DECL_SOURCE_LOCATION (decl);
                  /* We want to use the argument list specified in the
                     definition, not in the original declaration.  */
-                 DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (tmpl))
-                   = DECL_ARGUMENTS (decl);
+                 DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl);
+                 for (parm = DECL_ARGUMENTS (result); parm;
+                      parm = TREE_CHAIN (parm))
+                   DECL_CONTEXT (parm) = result;
                }
-             return tmpl;
+             return register_specialization (tmpl, gen_tmpl, targs,
+                                             is_friend, 0);
            }
 
          /* Set up the DECL_TEMPLATE_INFO for DECL.  */
@@ -2306,7 +2549,7 @@ check_explicit_specialization (tree declarator,
 
          /* Register this specialization so that we can find it
             again.  */
-         decl = register_specialization (decl, gen_tmpl, targs, is_friend);
+         decl = register_specialization (decl, gen_tmpl, targs, is_friend, 0);
        }
     }
 
@@ -2741,9 +2984,9 @@ check_for_bare_parameter_packs (tree t)
             name = DECL_NAME (pack);
 
          if (name)
-           inform ("        %qD", name);
+           inform (input_location, "        %qD", name);
          else
-           inform ("        <anonymous>");
+           inform (input_location, "        <anonymous>");
 
           parameter_packs = TREE_CHAIN (parameter_packs);
         }
@@ -2809,12 +3052,15 @@ expand_template_argument_pack (tree args)
   return result_args;
 }
 
-/* Complain if DECL shadows a template parameter.
+/* Checks if DECL shadows a template parameter.
 
    [temp.local]: A template-parameter shall not be redeclared within its
-   scope (including nested scopes).  */
+   scope (including nested scopes).
 
-void
+   Emits an error and returns TRUE if the DECL shadows a parameter,
+   returns FALSE otherwise.  */
+
+bool
 check_template_shadow (tree decl)
 {
   tree olddecl;
@@ -2822,7 +3068,7 @@ check_template_shadow (tree decl)
   /* If we're not in a template, we can't possibly shadow a template
      parameter.  */
   if (!current_template_parms)
-    return;
+    return true;
 
   /* Figure out what we're shadowing.  */
   if (TREE_CODE (decl) == OVERLOAD)
@@ -2832,24 +3078,25 @@ check_template_shadow (tree decl)
   /* If there's no previous binding for this name, we're not shadowing
      anything, let alone a template parameter.  */
   if (!olddecl)
-    return;
+    return true;
 
   /* If we're not shadowing a template parameter, we're done.  Note
      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 (!DECL_P (olddecl) || !DECL_TEMPLATE_PARM_P (olddecl))
-    return;
+    return true;
 
   /* We check for decl != olddecl to avoid bogus errors for using a
      name inside a class.  We check TPFI to avoid duplicate errors for
      inline member templates.  */
   if (decl == olddecl
       || TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
-    return;
+    return true;
 
   error ("declaration of %q+#D", decl);
   error (" shadows template parm %q+#D", olddecl);
+  return false;
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
@@ -2919,7 +3166,8 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
       tree orig_decl = TEMPLATE_PARM_DECL (index);
       tree decl, t;
 
-      decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
+      decl = build_decl (DECL_SOURCE_LOCATION (orig_decl),
+                        TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
       TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
       TREE_READONLY (decl) = TREE_READONLY (orig_decl);
       DECL_ARTIFICIAL (decl) = 1;
@@ -2946,10 +3194,11 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
 /* Process information from new template parameter PARM and append it to the
    LIST being built.  This new parameter is a non-type parameter iff
    IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  */
+   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
+   PARM_LOC.  */
 
 tree
-process_template_parm (tree list, tree parm, bool is_non_type, 
+process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
                        bool is_parameter_pack)
 {
   tree decl = 0;
@@ -3018,7 +3267,8 @@ process_template_parm (tree list, tree parm, bool is_non_type,
       /* A template parameter is not modifiable.  */
       TREE_CONSTANT (parm) = 1;
       TREE_READONLY (parm) = 1;
-      decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
+      decl = build_decl (parm_loc,
+                        CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
       TREE_CONSTANT (decl) = 1;
       TREE_READONLY (decl) = 1;
       DECL_INITIAL (parm) = DECL_INITIAL (decl)
@@ -3047,7 +3297,8 @@ process_template_parm (tree list, tree parm, bool is_non_type,
        {
          t = cxx_make_type (TEMPLATE_TYPE_PARM);
          /* parm is either IDENTIFIER_NODE or NULL_TREE.  */
-         decl = build_decl (TYPE_DECL, parm, t);
+         decl = build_decl (parm_loc,
+                            TYPE_DECL, parm, t);
        }
 
       TYPE_NAME (t) = decl;
@@ -3208,17 +3459,6 @@ build_template_decl (tree decl, tree parms, bool member_template_p)
   DECL_TEMPLATE_PARMS (tmpl) = parms;
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
-  if (DECL_LANG_SPECIFIC (decl))
-    {
-      DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
-      DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
-      DECL_DESTRUCTOR_P (tmpl) = DECL_DESTRUCTOR_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;
 }
@@ -3288,15 +3528,20 @@ process_partial_specialization (tree decl)
   tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
   tree specargs = CLASSTYPE_TI_ARGS (type);
   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);
+  tree inner_parms;
   int nargs = TREE_VEC_LENGTH (inner_args);
-  int ntparms = TREE_VEC_LENGTH (inner_parms);
+  int ntparms;
   int  i;
   int did_error_intro = 0;
   struct template_parm_data tpd;
   struct template_parm_data tpd2;
 
+  gcc_assert (current_template_parms);
+
+  inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+  ntparms = TREE_VEC_LENGTH (inner_parms);
+
   /* We check that each of the template parameters given in the
      partial specialization is used in the argument list to the
      specialization.  For example:
@@ -3488,10 +3733,8 @@ process_partial_specialization (tree decl)
         }
     }
 
-  if (retrieve_specialization (maintmpl, specargs,
-                              /*class_specializations_p=*/true))
-    /* We've already got this specialization.  */
-    return decl;
+  /* We should only get here once.  */
+  gcc_assert (!COMPLETE_TYPE_P (type));
 
   DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
     = tree_cons (specargs, inner_parms,
@@ -3539,6 +3782,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
   if (current_class_type
       && !TYPE_BEING_DEFINED (current_class_type)
       && DECL_LANG_SPECIFIC (decl)
+      && DECL_DECLARES_FUNCTION_P (decl)
       /* If this is either a friend defined in the scope of the class
         or a member function.  */
       && (DECL_FUNCTION_MEMBER_P (decl)
@@ -3581,7 +3825,8 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
 
               if (TREE_PURPOSE (parm))
                 seen_def_arg_p = 1;
-              else if (seen_def_arg_p)
+              else if (seen_def_arg_p
+                      && !template_parameter_pack_p (TREE_VALUE (parm)))
                 {
                   error ("no default argument for %qD", TREE_VALUE (parm));
                   /* For better subsequent error-recovery, we indicate that
@@ -3592,6 +3837,9 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
              else if (is_primary
                       && !is_partial
                       && !is_friend_decl
+                      /* Don't complain about an enclosing partial
+                         specialization.  */
+                      && parm_level == parms
                       && TREE_CODE (decl) == TYPE_DECL
                       && i < ntparms - 1
                       && template_parameter_pack_p (TREE_VALUE (parm)))
@@ -3745,8 +3993,8 @@ push_template_decl_real (tree decl, bool is_friend)
      [temp.mem].  */
   bool member_template_p = false;
 
-  if (decl == error_mark_node)
-    return decl;
+  if (decl == error_mark_node || !current_template_parms)
+    return error_mark_node;
 
   /* See if this is a partial specialization.  */
   is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
@@ -3967,7 +4215,7 @@ push_template_decl_real (tree decl, bool is_friend)
          register_specialization (new_tmpl,
                                   most_general_template (tmpl),
                                   args,
-                                  is_friend);
+                                  is_friend, 0);
          return decl;
        }
 
@@ -4016,7 +4264,7 @@ push_template_decl_real (tree decl, bool is_friend)
 template arguments to %qD do not match original template %qD",
                 decl, DECL_TEMPLATE_RESULT (tmpl));
          if (!uses_template_parms (TI_ARGS (tinfo)))
-           inform ("use template<> for an explicit specialization");
+           inform (input_location, "use template<> for an explicit specialization");
          /* Avoid crash in import_export_decl.  */
          DECL_INTERFACE_KNOWN (decl) = 1;
          return error_mark_node;
@@ -4137,7 +4385,7 @@ redeclare_class_template (tree type, tree parms)
     {
       error ("redeclared with %d template parameter(s)", 
              TREE_VEC_LENGTH (parms));
-      inform ("previous declaration %q+D used %d template parameter(s)", 
+      inform (input_location, "previous declaration %q+D used %d template parameter(s)", 
              tmpl, TREE_VEC_LENGTH (tmpl_parms));
       return false;
     }
@@ -4182,8 +4430,9 @@ redeclare_class_template (tree type, tree parms)
 
             A template-parameter may not be given default arguments
             by two different declarations in the same scope.  */
-         error ("redefinition of default argument for %q#D", parm);
-         inform ("%Joriginal definition appeared here", tmpl_parm);
+         error_at (input_location, "redefinition of default argument for %q#D", parm);
+         inform (DECL_SOURCE_LOCATION (tmpl_parm),
+                 "original definition appeared here");
          return false;
        }
 
@@ -4237,7 +4486,7 @@ fold_non_dependent_expr (tree expr)
 
 /* EXPR is an expression which is used in a constant-expression context.
    For instance, it could be a VAR_DECL with a constant initializer.
-   Extract the innest constant expression.
+   Extract the innermost constant expression.
 
    This is basically a more powerful version of
    integral_constant_value, which can be used also in templates where
@@ -4395,9 +4644,9 @@ convert_nontype_argument (tree type, tree expr)
      For a non-type template-parameter of integral or enumeration type,
      integral promotions (_conv.prom_) and integral conversions
      (_conv.integral_) are applied.  */
-  if (INTEGRAL_TYPE_P (type))
+  if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
     {
-      if (!INTEGRAL_TYPE_P (expr_type))
+      if (!INTEGRAL_OR_ENUMERATION_TYPE_P (expr_type))
        return error_mark_node;
 
       expr = fold_decl_constant_value (expr);
@@ -4553,6 +4802,13 @@ convert_nontype_argument (tree type, tree expr)
       expr = convert_nontype_argument_function (type, expr);
       if (!expr || expr == error_mark_node)
        return expr;
+
+      if (TREE_CODE (expr) != ADDR_EXPR)
+       {
+         error ("%qE is not a valid template argument for type %qT", expr, type);
+         error ("it must be the address of a function with external linkage");
+         return NULL_TREE;
+       }
     }
   /* [temp.arg.nontype]/5, bullet 5
 
@@ -4566,7 +4822,7 @@ convert_nontype_argument (tree type, tree expr)
        {
          error ("%qE is not a valid template argument for type %qT "
                 "because it is a pointer", expr, type);
-         inform ("try using %qE instead", TREE_OPERAND (expr, 0));
+         inform (input_location, "try using %qE instead", TREE_OPERAND (expr, 0));
          return NULL_TREE;
        }
 
@@ -4604,7 +4860,7 @@ convert_nontype_argument (tree type, tree expr)
          error ("%qE is not a valid template argument for type %qT "
                 "because it is of type %qT", expr, type,
                 TREE_TYPE (expr));
-         inform ("standard conversions are not allowed in this context");
+         inform (input_location, "standard conversions are not allowed in this context");
          return NULL_TREE;
        }
     }
@@ -4679,7 +4935,7 @@ coerce_template_template_parm (tree parm,
           D<int, C> d;
 
         i.e. the parameter list of TT depends on earlier parameters.  */
-      if (!dependent_type_p (TREE_TYPE (arg))
+      if (!uses_template_parms (TREE_TYPE (arg))
          && !same_type_p
                (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
                 TREE_TYPE (arg)))
@@ -4735,6 +4991,9 @@ coerce_template_template_parms (tree parm_parms,
     {
       parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, nparms - 1));
       
+      if (parm == error_mark_node)
+       return 0;
+
       switch (TREE_CODE (parm))
         {
         case TEMPLATE_DECL:
@@ -4938,8 +5197,8 @@ convert_template_argument (tree parm,
   if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
       && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
     {
-      pedwarn ("to refer to a type member of a template parameter, "
-              "use %<typename %E%>", orig_arg);
+      permerror (input_location, "to refer to a type member of a template parameter, "
+                "use %<typename %E%>", orig_arg);
 
       orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
                                     TREE_OPERAND (arg, 1),
@@ -5042,7 +5301,7 @@ convert_template_argument (tree parm,
         the typedef, which is confusing if those future uses do not
         themselves also use the typedef.  */
       if (TYPE_P (val))
-       val = canonical_type_variant (val);
+       val = strip_typedefs (val);
     }
   else
     {
@@ -5051,7 +5310,19 @@ convert_template_argument (tree parm,
       if (invalid_nontype_parm_type_p (t, complain))
        return error_mark_node;
 
-      if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
+      if (template_parameter_pack_p (parm) && ARGUMENT_PACK_P (orig_arg))
+       {
+         if (same_type_p (t, TREE_TYPE (orig_arg)))
+           val = orig_arg;
+         else
+           {
+             /* Not sure if this is reachable, but it doesn't hurt
+                to be robust.  */
+             error ("type mismatch in nontype parameter pack");
+             val = error_mark_node;
+           }
+       }
+      else if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
        /* We used to call digest_init here.  However, digest_init
           will report errors, which we don't want when complain
           is zero.  More importantly, digest_init will try too
@@ -5216,7 +5487,8 @@ coerce_template_parms (tree parms,
   tree inner_args;
   tree new_args;
   tree new_inner_args;
-  bool saved_skip_evaluation;
+  int saved_unevaluated_operand;
+  int saved_inhibit_evaluation_warnings;
 
   /* When used as a boolean value, indicates whether this is a
      variadic template parameter list. Since it's an int, we can also
@@ -5224,10 +5496,6 @@ coerce_template_parms (tree parms,
      parameters.  */
   int variadic_p = 0;
 
-  inner_args 
-    = expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args));
-
-  nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
   nparms = TREE_VEC_LENGTH (parms);
 
   /* Determine if there are any parameter packs.  */
@@ -5235,13 +5503,22 @@ coerce_template_parms (tree parms,
     {
       tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
       if (template_parameter_pack_p (tparm))
-        {
-          variadic_p = 1;
-          break;
-        }
+       ++variadic_p;
     }
 
-  if ((nargs > nparms - variadic_p && !variadic_p)
+  inner_args = INNERMOST_TEMPLATE_ARGS (args);
+  /* If there are 0 or 1 parameter packs, we need to expand any argument
+     packs so that we can deduce a parameter pack from some non-packed args
+     followed by an argument pack, as in variadic85.C.  If there are more
+     than that, we need to leave argument packs intact so the arguments are
+     assigned to the right parameter packs.  This should only happen when
+     dealing with a nested class inside a partial specialization of a class
+     template, as in variadic92.C.  */
+  if (variadic_p <= 1)
+    inner_args = expand_template_argument_pack (inner_args);
+
+  nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
+  if ((nargs > nparms && !variadic_p)
       || (nargs < nparms - variadic_p
          && require_all_args
          && (!use_default_args
@@ -5269,8 +5546,10 @@ coerce_template_parms (tree parms,
 
   /* We need to evaluate the template arguments, even though this
      template-id may be nested within a "sizeof".  */
-  saved_skip_evaluation = skip_evaluation;
-  skip_evaluation = false;
+  saved_unevaluated_operand = cp_unevaluated_operand;
+  cp_unevaluated_operand = 0;
+  saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+  c_inhibit_evaluation_warnings = 0;
   new_inner_args = make_tree_vec (nparms);
   new_args = add_outermost_template_args (args, new_inner_args);
   for (parm_idx = 0, arg_idx = 0; parm_idx < nparms; parm_idx++, arg_idx++)
@@ -5288,42 +5567,48 @@ coerce_template_parms (tree parms,
       }
 
       /* Calculate the next argument.  */
-      if (template_parameter_pack_p (TREE_VALUE (parm)))
+      if (arg_idx < nargs)
+       arg = TREE_VEC_ELT (inner_args, arg_idx);
+      else
+       arg = NULL_TREE;
+
+      if (template_parameter_pack_p (TREE_VALUE (parm))
+         && !(arg && ARGUMENT_PACK_P (arg)))
         {
-          /* All remaining arguments will be placed in the
-             template parameter pack PARM.  */
-          arg = coerce_template_parameter_pack (parms, parm_idx, args, 
-                                                inner_args, arg_idx,
-                                                new_args, &lost,
-                                                in_decl, complain);
-          
+         /* All remaining arguments will be placed in the
+            template parameter pack PARM.  */
+         arg = coerce_template_parameter_pack (parms, parm_idx, args, 
+                                               inner_args, arg_idx,
+                                               new_args, &lost,
+                                               in_decl, complain);
+
           /* Store this argument.  */
           if (arg == error_mark_node)
             lost++;
           TREE_VEC_ELT (new_inner_args, parm_idx) = arg;
 
-          /* We are done with all of the arguments.  */
-          arg_idx = nargs;
-
+         /* We are done with all of the arguments.  */
+         arg_idx = nargs;
+          
           continue;
         }
-      else if (arg_idx < nargs)
-        {
-          arg = TREE_VEC_ELT (inner_args, arg_idx);
-
-          if (arg && PACK_EXPANSION_P (arg))
+      else if (arg)
+       {
+          if (PACK_EXPANSION_P (arg))
             {
              if (complain & tf_error)
                {
+                 /* FIXME this restriction was removed by N2555; see
+                    bug 35722.  */
                  /* If ARG is a pack expansion, but PARM is not a
                     template parameter pack (if it were, we would have
                     handled it above), we're trying to expand into a
                     fixed-length argument list.  */
                  if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
-                   error ("cannot expand %<%E%> into a fixed-length "
+                   sorry ("cannot expand %<%E%> into a fixed-length "
                           "argument list", arg);
                  else
-                   error ("cannot expand %<%T%> into a fixed-length "
+                   sorry ("cannot expand %<%T%> into a fixed-length "
                           "argument list", arg);
                }
              return error_mark_node;
@@ -5357,7 +5642,8 @@ coerce_template_parms (tree parms,
        lost++;
       TREE_VEC_ELT (new_inner_args, arg_idx) = arg;
     }
-  skip_evaluation = saved_skip_evaluation;
+  cp_unevaluated_operand = saved_unevaluated_operand;
+  c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
 
   if (lost)
     return error_mark_node;
@@ -5380,6 +5666,25 @@ template_args_equal (tree ot, tree nt)
     return PACK_EXPANSION_P (nt) 
       && template_args_equal (PACK_EXPANSION_PATTERN (ot),
                               PACK_EXPANSION_PATTERN (nt));
+  else if (ARGUMENT_PACK_P (ot))
+    {
+      int i, len;
+      tree opack, npack;
+
+      if (!ARGUMENT_PACK_P (nt))
+       return 0;
+
+      opack = ARGUMENT_PACK_ARGS (ot);
+      npack = ARGUMENT_PACK_ARGS (nt);
+      len = TREE_VEC_LENGTH (opack);
+      if (TREE_VEC_LENGTH (npack) != len)
+       return 0;
+      for (i = 0; i < len; ++i)
+       if (!template_args_equal (TREE_VEC_ELT (opack, i),
+                                 TREE_VEC_ELT (npack, i)))
+         return 0;
+      return 1;
+    }
   else if (TYPE_P (nt))
     return TYPE_P (ot) && same_type_p (ot, nt);
   else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
@@ -5396,9 +5701,6 @@ comp_template_args (tree oldargs, tree newargs)
 {
   int i;
 
-  oldargs = expand_template_argument_pack (oldargs);
-  newargs = expand_template_argument_pack (newargs);
-
   if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
     return 0;
 
@@ -5532,8 +5834,12 @@ lookup_template_class (tree d1,
                       int entering_scope,
                       tsubst_flags_t complain)
 {
-  tree template = NULL_TREE, parmlist;
+  tree templ = NULL_TREE, parmlist;
   tree t;
+  spec_entry **slot;
+  spec_entry *entry;
+  spec_entry elt;
+  hashval_t hash;
 
   timevar_push (TV_NAME_LOOKUP);
 
@@ -5541,18 +5847,18 @@ lookup_template_class (tree d1,
     {
       tree value = innermost_non_namespace_value (d1);
       if (value && DECL_TEMPLATE_TEMPLATE_PARM_P (value))
-       template = value;
+       templ = value;
       else
        {
          if (context)
            push_decl_namespace (context);
-         template = lookup_name (d1);
-         template = maybe_get_template_decl_from_type_decl (template);
+         templ = lookup_name (d1);
+         templ = maybe_get_template_decl_from_type_decl (templ);
          if (context)
            pop_decl_namespace ();
        }
-      if (template)
-       context = DECL_CONTEXT (template);
+      if (templ)
+       context = DECL_CONTEXT (templ);
     }
   else if (TREE_CODE (d1) == TYPE_DECL && MAYBE_CLASS_TYPE_P (TREE_TYPE (d1)))
     {
@@ -5565,37 +5871,38 @@ lookup_template_class (tree d1,
 
       if (CLASSTYPE_TEMPLATE_INFO (type))
        {
-         template = CLASSTYPE_TI_TEMPLATE (type);
-         d1 = DECL_NAME (template);
+         templ = CLASSTYPE_TI_TEMPLATE (type);
+         d1 = DECL_NAME (templ);
        }
     }
   else if (TREE_CODE (d1) == ENUMERAL_TYPE
           || (TYPE_P (d1) && MAYBE_CLASS_TYPE_P (d1)))
     {
-      template = TYPE_TI_TEMPLATE (d1);
-      d1 = DECL_NAME (template);
+      templ = TYPE_TI_TEMPLATE (d1);
+      d1 = DECL_NAME (templ);
     }
   else if (TREE_CODE (d1) == TEMPLATE_DECL
+           && DECL_TEMPLATE_RESULT (d1)
           && TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
     {
-      template = d1;
-      d1 = DECL_NAME (template);
-      context = DECL_CONTEXT (template);
+      templ = d1;
+      d1 = DECL_NAME (templ);
+      context = DECL_CONTEXT (templ);
     }
 
   /* Issue an error message if we didn't find a template.  */
-  if (! template)
+  if (! templ)
     {
       if (complain & tf_error)
        error ("%qT is not a template", d1);
       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
     }
 
-  if (TREE_CODE (template) != TEMPLATE_DECL
+  if (TREE_CODE (templ) != TEMPLATE_DECL
         /* Make sure it's a user visible template, if it was named by
            the user.  */
-      || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)
-         && !PRIMARY_TEMPLATE_P (template)))
+      || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (templ)
+         && !PRIMARY_TEMPLATE_P (templ)))
     {
       if (complain & tf_error)
        {
@@ -5608,7 +5915,7 @@ lookup_template_class (tree d1,
 
   complain &= ~tf_user;
 
-  if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+  if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
     {
       /* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
         template arguments */
@@ -5617,7 +5924,7 @@ lookup_template_class (tree d1,
       tree arglist2;
       tree outer;
 
-      parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+      parmlist = DECL_INNERMOST_TEMPLATE_PARMS (templ);
 
       /* Consider an example where a template template parameter declared as
 
@@ -5635,7 +5942,7 @@ lookup_template_class (tree d1,
         level 1, and T at level 2, while the template arguments at level 1
         becomes {std::vector} and the inner level 2 is {int}.  */
 
-      outer = DECL_CONTEXT (template);
+      outer = DECL_CONTEXT (templ);
       if (outer)
        outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
       else if (current_template_parms)
@@ -5646,21 +5953,21 @@ lookup_template_class (tree d1,
       if (outer)
        arglist = add_to_template_args (outer, arglist);
 
-      arglist2 = coerce_template_parms (parmlist, arglist, template,
+      arglist2 = coerce_template_parms (parmlist, arglist, templ,
                                        complain,
                                        /*require_all_args=*/true,
                                        /*use_default_args=*/true);
       if (arglist2 == error_mark_node
          || (!uses_template_parms (arglist2)
-             && check_instantiated_args (template, arglist2, complain)))
+             && check_instantiated_args (templ, arglist2, complain)))
        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 
-      parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
+      parm = bind_template_template_parm (TREE_TYPE (templ), arglist2);
       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
     }
   else
     {
-      tree template_type = TREE_TYPE (template);
+      tree template_type = TREE_TYPE (templ);
       tree gen_tmpl;
       tree type_decl;
       tree found = NULL_TREE;
@@ -5668,7 +5975,7 @@ lookup_template_class (tree d1,
       int parm_depth;
       int is_partial_instantiation;
 
-      gen_tmpl = most_general_template (template);
+      gen_tmpl = most_general_template (templ);
       parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
       parm_depth = TMPL_PARMS_DEPTH (parmlist);
       arg_depth = TMPL_ARGS_DEPTH (arglist);
@@ -5688,7 +5995,7 @@ lookup_template_class (tree d1,
             <class U> struct S1<T>::S2'.  We must fill in the missing
             arguments.  */
          arglist
-           = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
+           = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (templ)),
                                           arglist);
          arg_depth = TMPL_ARGS_DEPTH (arglist);
        }
@@ -5698,7 +6005,6 @@ lookup_template_class (tree d1,
 
       /* From here on, we're only interested in the most general
         template.  */
-      template = gen_tmpl;
 
       /* Calculate the BOUND_ARGS.  These will be the args that are
         actually tsubst'd into the definition to create the
@@ -5712,12 +6018,12 @@ lookup_template_class (tree d1,
          tree bound_args = make_tree_vec (parm_depth);
 
          for (i = saved_depth,
-                t = DECL_TEMPLATE_PARMS (template);
+                t = DECL_TEMPLATE_PARMS (gen_tmpl);
               i > 0 && t != NULL_TREE;
               --i, t = TREE_CHAIN (t))
            {
              tree a = coerce_template_parms (TREE_VALUE (t),
-                                             arglist, template,
+                                             arglist, gen_tmpl,
                                              complain,
                                              /*require_all_args=*/true,
                                              /*use_default_args=*/true);
@@ -5748,7 +6054,7 @@ lookup_template_class (tree d1,
        arglist
          = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
                                   INNERMOST_TEMPLATE_ARGS (arglist),
-                                  template,
+                                  gen_tmpl,
                                   complain,
                                   /*require_all_args=*/true,
                                   /*use_default_args=*/true);
@@ -5765,37 +6071,23 @@ lookup_template_class (tree d1,
 
         the `C<T>' is just the same as `C'.  Outside of the
         class, however, such a reference is an instantiation.  */
-      if (comp_template_args (TYPE_TI_ARGS (template_type),
-                             arglist))
-       {
-         found = template_type;
-
-         if (!entering_scope && PRIMARY_TEMPLATE_P (template))
-           {
-             tree ctx;
-
-             for (ctx = current_class_type;
-                  ctx && TREE_CODE (ctx) != NAMESPACE_DECL;
-                  ctx = (TYPE_P (ctx)
-                         ? TYPE_CONTEXT (ctx)
-                         : DECL_CONTEXT (ctx)))
-               if (TYPE_P (ctx) && same_type_p (ctx, template_type))
-                 goto found_ctx;
-
-             /* We're not in the scope of the class, so the
-                TEMPLATE_TYPE is not the type we want after all.  */
-             found = NULL_TREE;
-           found_ctx:;
-           }
-       }
-      if (found)
-       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
+      if ((entering_scope
+          || !PRIMARY_TEMPLATE_P (gen_tmpl)
+          || currently_open_class (template_type))
+         /* comp_template_args is expensive, check it last.  */
+         && comp_template_args (TYPE_TI_ARGS (template_type),
+                                arglist))
+       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, template_type);
 
       /* If we already have this specialization, return it.  */
-      found = retrieve_specialization (template, arglist,
-                                      /*class_specializations_p=*/false);
-      if (found)
-       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
+      elt.tmpl = gen_tmpl;
+      elt.args = arglist;
+      hash = hash_specialization (&elt);
+      entry = (spec_entry *) htab_find_with_hash (type_specializations,
+                                                 &elt, hash);
+
+      if (entry)
+       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->spec);
 
       /* This type is a "partial instantiation" if any of the template
         arguments still involve template parameters.  Note that we set
@@ -5806,22 +6098,22 @@ lookup_template_class (tree d1,
       /* If the deduced arguments are invalid, then the binding
         failed.  */
       if (!is_partial_instantiation
-         && check_instantiated_args (template,
+         && check_instantiated_args (gen_tmpl,
                                      INNERMOST_TEMPLATE_ARGS (arglist),
                                      complain))
        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 
       if (!is_partial_instantiation
-         && !PRIMARY_TEMPLATE_P (template)
-         && TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL)
+         && !PRIMARY_TEMPLATE_P (gen_tmpl)
+         && TREE_CODE (CP_DECL_CONTEXT (gen_tmpl)) == NAMESPACE_DECL)
        {
-         found = xref_tag_from_type (TREE_TYPE (template),
-                                     DECL_NAME (template),
+         found = xref_tag_from_type (TREE_TYPE (gen_tmpl),
+                                     DECL_NAME (gen_tmpl),
                                      /*tag_scope=*/ts_global);
          POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
        }
 
-      context = tsubst (DECL_CONTEXT (template), arglist,
+      context = tsubst (DECL_CONTEXT (gen_tmpl), arglist,
                        complain, in_decl);
       if (!context)
        context = global_namespace;
@@ -5832,14 +6124,20 @@ lookup_template_class (tree d1,
          if (!is_partial_instantiation)
            {
              set_current_access_from_decl (TYPE_NAME (template_type));
-             t = start_enum (TYPE_IDENTIFIER (template_type));
+             t = start_enum (TYPE_IDENTIFIER (template_type),
+                              tsubst (ENUM_UNDERLYING_TYPE (template_type),
+                                      arglist, complain, in_decl),
+                              SCOPED_ENUM_P (template_type));
            }
          else
-           /* We don't want to call start_enum for this type, since
-              the values for the enumeration constants may involve
-              template parameters.  And, no one should be interested
-              in the enumeration constants for such a type.  */
-           t = make_node (ENUMERAL_TYPE);
+            {
+              /* We don't want to call start_enum for this type, since
+                 the values for the enumeration constants may involve
+                 template parameters.  And, no one should be interested
+                 in the enumeration constants for such a type.  */
+              t = make_node (ENUMERAL_TYPE);
+              SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
+            }
        }
       else
        {
@@ -5851,7 +6149,7 @@ lookup_template_class (tree d1,
 
          /* A local class.  Make sure the decl gets registered properly.  */
          if (context == current_function_decl)
-           pushtag (DECL_NAME (template), t, /*tag_scope=*/ts_current);
+           pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
 
          if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
            /* This instantiation is another name for the primary
@@ -5871,7 +6169,7 @@ lookup_template_class (tree d1,
        {
          TYPE_CONTEXT (t) = FROB_CONTEXT (context);
 
-         type_decl = create_implicit_typedef (DECL_NAME (template), t);
+         type_decl = create_implicit_typedef (DECL_NAME (gen_tmpl), t);
          DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
          TYPE_STUB_DECL (t) = type_decl;
          DECL_SOURCE_LOCATION (type_decl)
@@ -5884,8 +6182,6 @@ lookup_template_class (tree d1,
        = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
       TREE_PROTECTED (type_decl)
        = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
-      DECL_IN_SYSTEM_HEADER (type_decl)
-       = DECL_IN_SYSTEM_HEADER (template);
       if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
        {
          DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
@@ -5896,68 +6192,35 @@ lookup_template_class (tree d1,
         template is the immediate parent if this is a full
         instantiation.  */
       if (parm_depth == 1 || is_partial_instantiation
-         || !PRIMARY_TEMPLATE_P (template))
+         || !PRIMARY_TEMPLATE_P (gen_tmpl))
        /* This case is easy; there are no member templates involved.  */
-       found = template;
+       found = gen_tmpl;
       else
        {
-         /* 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))
-           {
-             int success;
-             tree tmpl = CLASSTYPE_TI_TEMPLATE (TREE_VALUE (found));
-
-             /* We only want partial instantiations, here, not
-                specializations or full instantiations.  */
-             if (CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_VALUE (found))
-                 || !uses_template_parms (TREE_VALUE (found)))
-               continue;
-
-             /* Temporarily reduce by one the number of levels in the
-                ARGLIST and in FOUND so as to avoid comparing the
-                last set of arguments.  */
-             TREE_VEC_LENGTH (arglist)--;
-             TREE_VEC_LENGTH (TREE_PURPOSE (found)) --;
-
-             /* See if the arguments match.  If they do, then TMPL is
-                the partial instantiation we want.  */
-             success = comp_template_args (TREE_PURPOSE (found), arglist);
-
-             /* Restore the argument vectors to their full size.  */
-             TREE_VEC_LENGTH (arglist)++;
-             TREE_VEC_LENGTH (TREE_PURPOSE (found))++;
-
-             if (success)
-               {
-                 found = tmpl;
-                 break;
-               }
-           }
-
-         if (!found)
-           {
-             /* 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)--;
-             found = tsubst (template, arglist, complain, NULL_TREE);
-             TREE_VEC_LENGTH (arglist)++;
-           }
+         /* This is a full instantiation of a member template.  Find
+            the partial instantiation of which this is an instance.  */
+
+         /* Temporarily reduce by one the number of levels in the ARGLIST
+            so as to avoid comparing the last set of arguments.  */
+         TREE_VEC_LENGTH (arglist)--;
+         found = tsubst (gen_tmpl, arglist, complain, NULL_TREE);
+         TREE_VEC_LENGTH (arglist)++;
+         found = CLASSTYPE_TI_TEMPLATE (found);
        }
 
       SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
-      DECL_TEMPLATE_INSTANTIATIONS (template)
+
+      elt.spec = t;
+      slot = (spec_entry **) htab_find_slot_with_hash (type_specializations,
+                                                      &elt, hash, INSERT);
+      *slot = GGC_NEW (spec_entry);
+      **slot = elt;
+
+      /* Note this use of the partial instantiation so we can check it
+        later in maybe_process_partial_specialization.  */
+      DECL_TEMPLATE_INSTANTIATIONS (templ)
        = tree_cons (arglist, t,
-                    DECL_TEMPLATE_INSTANTIATIONS (template));
+                    DECL_TEMPLATE_INSTANTIATIONS (templ));
 
       if (TREE_CODE (t) == ENUMERAL_TYPE
          && !is_partial_instantiation)
@@ -6251,6 +6514,7 @@ uses_template_parms (tree t)
           || TREE_CODE (t) == BASELINK
           || TREE_CODE (t) == IDENTIFIER_NODE
           || TREE_CODE (t) == TRAIT_EXPR
+          || TREE_CODE (t) == CONSTRUCTOR
           || CONSTANT_CLASS_P (t))
     dependent_p = (type_dependent_expression_p (t)
                   || value_dependent_expression_p (t));
@@ -6288,7 +6552,7 @@ static int last_template_error_tick;
 static int
 push_tinst_level (tree d)
 {
-  struct tinst_level *new;
+  struct tinst_level *new_level;
 
   if (tinst_depth >= max_tinst_depth)
     {
@@ -6308,12 +6572,12 @@ push_tinst_level (tree d)
       return 0;
     }
 
-  new = GGC_NEW (struct tinst_level);
-  new->decl = d;
-  new->locus = input_location;
-  new->in_system_header_p = in_system_header;
-  new->next = current_tinst_level;
-  current_tinst_level = new;
+  new_level = GGC_NEW (struct tinst_level);
+  new_level->decl = d;
+  new_level->locus = input_location;
+  new_level->in_system_header_p = in_system_header;
+  new_level->next = current_tinst_level;
+  current_tinst_level = new_level;
 
   ++tinst_depth;
 #ifdef GATHER_STATISTICS
@@ -6334,7 +6598,6 @@ pop_tinst_level (void)
   /* Restore the filename and line number stashed away when we started
      this instantiation.  */
   input_location = current_tinst_level->locus;
-  in_system_header = current_tinst_level->in_system_header_p;
   current_tinst_level = current_tinst_level->next;
   --tinst_depth;
   ++tinst_level_tick;
@@ -6371,6 +6634,30 @@ outermost_tinst_level (void)
   return level;
 }
 
+/* Returns TRUE if PARM is a parameter of the template TEMPL.  */
+
+bool
+parameter_of_template_p (tree parm, tree templ)
+{
+  tree parms;
+  int i;
+
+  if (!parm || !templ)
+    return false;
+
+  gcc_assert (DECL_TEMPLATE_PARM_P (parm));
+  gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
+
+  parms = DECL_TEMPLATE_PARMS (templ);
+  parms = INNERMOST_TEMPLATE_PARMS (parms);
+
+  for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
+    if (parm == TREE_VALUE (TREE_VEC_ELT (parms, i)))
+      return true;
+
+  return false;
+}
+
 /* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL.  ARGS is the
    vector of template arguments, as for tsubst.
 
@@ -6400,7 +6687,7 @@ tsubst_friend_function (tree decl, tree args)
 
       /* 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.  */
+        current class with same name.  */
       push_nested_namespace (ns);
       fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
                         tf_warning_or_error, NULL_TREE,
@@ -6538,46 +6825,58 @@ tsubst_friend_function (tree decl, tree args)
            ;
          else
            {
+             tree new_template = TI_TEMPLATE (new_friend_template_info);
+             tree new_args = TI_ARGS (new_friend_template_info);
+
              /* Overwrite whatever template info was there before, if
                 any, with the new template information pertaining to
                 the declaration.  */
              DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
 
              if (TREE_CODE (old_decl) != TEMPLATE_DECL)
-               reregister_specialization (new_friend,
-                                          most_general_template (old_decl),
-                                          old_decl);
+               /* We should have called reregister_specialization in
+                  duplicate_decls.  */
+               gcc_assert (retrieve_specialization (new_template,
+                                                    new_args, 0)
+                           == old_decl);
              else
                {
                  tree t;
-                 tree new_friend_args;
 
+                 /* Indicate that the old function template is a partial
+                    instantiation.  */
                  DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (old_decl))
                    = new_friend_result_template_info;
 
-                 new_friend_args = TI_ARGS (new_friend_template_info);
-                 for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
+                 gcc_assert (new_template
+                             == most_general_template (new_template));
+                 gcc_assert (new_template != old_decl);
+
+                 /* Reassign any specializations already in the hash table
+                    to the new more general template, and add the
+                    additional template args.  */
+                 for (t = DECL_TEMPLATE_INSTANTIATIONS (old_decl);
                       t != NULL_TREE;
                       t = TREE_CHAIN (t))
                    {
                      tree spec = TREE_VALUE (t);
+                     spec_entry elt;
+
+                     elt.tmpl = old_decl;
+                     elt.args = DECL_TI_ARGS (spec);
+                     elt.spec = NULL_TREE;
+
+                     htab_remove_elt (decl_specializations, &elt);
 
                      DECL_TI_ARGS (spec)
-                       = add_outermost_template_args (new_friend_args,
+                       = add_outermost_template_args (new_args,
                                                       DECL_TI_ARGS (spec));
-                   }
 
-                 /* Now, since specializations are always supposed to
-                    hang off of the most general template, we must move
-                    them.  */
-                 t = most_general_template (old_decl);
-                 if (t != old_decl)
-                   {
-                     DECL_TEMPLATE_SPECIALIZATIONS (t)
-                       = chainon (DECL_TEMPLATE_SPECIALIZATIONS (t),
-                                  DECL_TEMPLATE_SPECIALIZATIONS (old_decl));
-                     DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
+                     register_specialization
+                       (spec, new_template, DECL_TI_ARGS (spec), true, 0);
+
                    }
+                 DECL_TEMPLATE_INSTANTIATIONS (old_decl) = NULL_TREE;
                }
            }
 
@@ -6832,10 +7131,44 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
     }
 }
 
+/* Perform (or defer) access check for typedefs that were referenced
+   from within the template TMPL code.
+   This is a subroutine of instantiate_template and instantiate_class_template.
+   TMPL is the template to consider and TARGS is the list of arguments of
+   that template.  */
+
+static void
+perform_typedefs_access_check (tree tmpl, tree targs)
+{
+  tree t;
+
+  if (!tmpl
+      || (!CLASS_TYPE_P (tmpl)
+         && TREE_CODE (tmpl) != FUNCTION_DECL))
+    return;
+
+  for (t = get_types_needing_access_check (tmpl); t; t = TREE_CHAIN (t))
+    {
+      tree type_decl = TREE_PURPOSE (t);
+      tree type_scope = TREE_VALUE (t);
+
+      if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
+       continue;
+
+      if (uses_template_parms (type_decl))
+       type_decl = tsubst (type_decl, targs, tf_error, NULL_TREE);
+      if (uses_template_parms (type_scope))
+       type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
+
+      perform_or_defer_access_check (TYPE_BINFO (type_scope),
+                                    type_decl, type_decl);
+    }
+}
+
 tree
 instantiate_class_template (tree type)
 {
-  tree template, args, pattern, t, member;
+  tree templ, args, pattern, t, member;
   tree typedecl;
   tree pbinfo;
   tree base_list;
@@ -6849,12 +7182,12 @@ instantiate_class_template (tree type)
     return type;
 
   /* Figure out which template is being instantiated.  */
-  template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
-  gcc_assert (TREE_CODE (template) == TEMPLATE_DECL);
+  templ = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
+  gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
 
   /* Determine what specialization of the original template to
      instantiate.  */
-  t = most_specialized_class (type, template);
+  t = most_specialized_class (type, templ);
   if (t == error_mark_node)
     {
       TYPE_BEING_DEFINED (type) = 1;
@@ -6877,7 +7210,7 @@ instantiate_class_template (tree type)
     }
   else
     {
-      pattern = TREE_TYPE (template);
+      pattern = TREE_TYPE (templ);
       args = CLASSTYPE_TI_ARGS (type);
     }
 
@@ -6902,11 +7235,10 @@ instantiate_class_template (tree type)
 
   SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
 
-  /* Set the input location to the template definition. This is needed
-     if tsubsting causes an error.  */
-  typedecl = TYPE_MAIN_DECL (type);
+  /* Set the input location to the most specialized template definition.
+     This is needed if tsubsting causes an error.  */
+  typedecl = TYPE_MAIN_DECL (pattern);
   input_location = DECL_SOURCE_LOCATION (typedecl);
-  in_system_header = DECL_IN_SYSTEM_HEADER (typedecl);
 
   TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern);
   TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
@@ -7104,7 +7436,7 @@ instantiate_class_template (tree type)
                {
                  tree r;
 
-                 /* The the file and line for this declaration, to
+                 /* The file and line for this declaration, to
                     assist in error message reporting.  Since we
                     called push_tinst_level above, we don't need to
                     restore these.  */
@@ -7263,7 +7595,7 @@ instantiate_class_template (tree type)
              /* Build new DECL_FRIENDLIST.  */
              tree r;
 
-             /* The the file and line for this declaration, to
+             /* The file and line for this declaration, to
                 assist in error message reporting.  Since we
                 called push_tinst_level above, we don't need to
                 restore these.  */
@@ -7299,7 +7631,7 @@ instantiate_class_template (tree type)
   /* Now that the class is complete, instantiate default arguments for
      any member functions.  We don't do this earlier because the
      default arguments may reference members of the class.  */
-  if (!PRIMARY_TEMPLATE_P (template))
+  if (!PRIMARY_TEMPLATE_P (templ))
     for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
       if (TREE_CODE (t) == FUNCTION_DECL
          /* Implicitly generated member functions will not have template
@@ -7308,6 +7640,12 @@ instantiate_class_template (tree type)
          && DECL_TEMPLATE_INFO (t))
        tsubst_default_arguments (t);
 
+  /* Some typedefs referenced from within the template code need to be access
+     checked at template instantiation time, i.e now. These types were
+     added to the template at parsing time. Let's get those and perform
+     the access checks then.  */
+  perform_typedefs_access_check (pattern, args);
+  perform_deferred_access_checks ();
   pop_nested_class ();
   pop_from_top_level ();
   pop_deferring_access_checks ();
@@ -7341,6 +7679,37 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   return r;
 }
 
+/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
+   NONTYPE_ARGUMENT_PACK.  */
+
+static tree
+make_fnparm_pack (tree spec_parm)
+{
+  /* Collect all of the extra "packed" parameters into an
+     argument pack.  */
+  tree parmvec;
+  tree parmtypevec;
+  tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
+  tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
+  int i, len = list_length (spec_parm);
+
+  /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters.  */
+  parmvec = make_tree_vec (len);
+  parmtypevec = make_tree_vec (len);
+  for (i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
+    {
+      TREE_VEC_ELT (parmvec, i) = spec_parm;
+      TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
+    }
+
+  /* Build the argument packs.  */
+  SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
+  SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
+  TREE_TYPE (argpack) = argtypepack;
+
+  return argpack;
+}        
+
 /* Substitute ARGS into T, which is an pack expansion
    (i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
    TREE_VEC with the substituted arguments, a PACK_EXPANSION_* node
@@ -7355,6 +7724,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   tree first_arg_pack; int i, len = -1;
   tree result;
   int incomplete = 0;
+  bool very_local_specializations = false;
 
   gcc_assert (PACK_EXPANSION_P (t));
   pattern = PACK_EXPANSION_PATTERN (t);
@@ -7371,7 +7741,18 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
       tree orig_arg = NULL_TREE;
 
       if (TREE_CODE (parm_pack) == PARM_DECL)
-       arg_pack = retrieve_local_specialization (parm_pack);
+       {
+         arg_pack = retrieve_local_specialization (parm_pack);
+         if (arg_pack == NULL_TREE)
+           {
+             /* This can happen for a parameter name used later in a function
+                declaration (such as in a late-specified return type).  Just
+                make a dummy decl, since it's only used for its type.  */
+             gcc_assert (cp_unevaluated_operand != 0);
+             arg_pack = tsubst_decl (parm_pack, args, complain);
+             arg_pack = make_fnparm_pack (arg_pack);
+           }
+       }
       else
         {
           int level, idx, levels;
@@ -7458,13 +7839,31 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
      and return a PACK_EXPANSION_*. The caller will need to deal with
      that.  */
   if (unsubstituted_packs)
-    return make_pack_expansion (tsubst (pattern, args, complain, 
-                                       in_decl));
+    {
+      tree new_pat;
+      if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
+       new_pat = tsubst_expr (pattern, args, complain, in_decl,
+                              /*integral_constant_expression_p=*/false);
+      else
+       new_pat = tsubst (pattern, args, complain, in_decl);
+      return make_pack_expansion (new_pat);
+    }
 
   /* We could not find any argument packs that work.  */
   if (len < 0)
     return error_mark_node;
 
+  if (!local_specializations)
+    {
+      /* We're in a late-specified return type, so we don't have a local
+        specializations table.  Create one for doing this expansion.  */
+      very_local_specializations = true;
+      local_specializations = htab_create (37,
+                                          hash_local_specialization,
+                                          eq_local_specializations,
+                                          NULL);
+    }
+
   /* For each argument in each argument pack, substitute into the
      pattern.  */
   result = make_tree_vec (len + incomplete);
@@ -7526,7 +7925,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
          break;
        }
     }
-  
+
   /* Update ARGS to restore the substitution from parameter packs to
      their argument packs.  */
   for (pack = packs; pack; pack = TREE_CHAIN (pack))
@@ -7549,6 +7948,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
         }
     }
 
+  if (very_local_specializations)
+    {
+      htab_delete (local_specializations);
+      local_specializations = NULL;
+    }
+  
   return result;
 }
 
@@ -7741,11 +8146,14 @@ tsubst_aggr_type (tree t,
          tree argvec;
          tree context;
          tree r;
-         bool saved_skip_evaluation;
+         int saved_unevaluated_operand;
+         int saved_inhibit_evaluation_warnings;
 
          /* In "sizeof(X<I>)" we need to evaluate "I".  */
-         saved_skip_evaluation = skip_evaluation;
-         skip_evaluation = false;
+         saved_unevaluated_operand = cp_unevaluated_operand;
+         cp_unevaluated_operand = 0;
+         saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+         c_inhibit_evaluation_warnings = 0;
 
          /* First, determine the context for the type we are looking
             up.  */
@@ -7780,7 +8188,8 @@ tsubst_aggr_type (tree t,
              r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
            }
 
-         skip_evaluation = saved_skip_evaluation;
+         cp_unevaluated_operand = saved_unevaluated_operand;
+         c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
 
          return r;
        }
@@ -7844,11 +8253,11 @@ tsubst_default_argument (tree fn, tree type, tree arg)
       cp_function_chain->x_current_class_ref = saved_class_ref;
     }
 
-  pop_access_scope (fn);
-
   /* Make sure the default argument is reasonable.  */
   arg = check_default_argument (type, arg);
 
+  pop_access_scope (fn);
+
   return arg;
 }
 
@@ -7886,6 +8295,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
   location_t saved_loc;
   tree r = NULL_TREE;
   tree in_decl = t;
+  hashval_t hash = 0;
 
   /* Set the filename and linenumber to improve error-reporting.  */
   saved_loc = input_location;
@@ -7896,8 +8306,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
     case TEMPLATE_DECL:
       {
        /* We can get here when processing a member function template,
-          member class template, and template template parameter of
-          a template class.  */
+          member class template, or template template parameter.  */
        tree decl = DECL_TEMPLATE_RESULT (t);
        tree spec;
        tree tmpl_args;
@@ -7914,7 +8323,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            TREE_CHAIN (r) = NULL_TREE;
            TREE_TYPE (r) = new_type;
            DECL_TEMPLATE_RESULT (r)
-             = build_decl (TYPE_DECL, DECL_NAME (decl), new_type);
+             = build_decl (DECL_SOURCE_LOCATION (decl),
+                           TYPE_DECL, DECL_NAME (decl), new_type);
            DECL_TEMPLATE_PARMS (r)
              = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
                                       complain);
@@ -7940,13 +8350,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        if (full_args == error_mark_node)
          return error_mark_node;
 
-       /* tsubst_template_args doesn't copy the vector if
-          nothing changed.  But, *something* should have
-          changed.  */
-       gcc_assert (full_args != tmpl_args);
+       /* If this is a default template template argument,
+          tsubst might not have changed anything.  */
+       if (full_args == tmpl_args)
+         return t;
 
-       spec = retrieve_specialization (t, full_args,
-                                       /*class_specializations_p=*/true);
+       hash = hash_tmpl_and_args (t, full_args);
+       spec = retrieve_specialization (t, full_args, hash);
        if (spec != NULL_TREE)
          {
            r = spec;
@@ -8013,7 +8423,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
          /* Record this non-type partial instantiation.  */
          register_specialization (r, t,
                                   DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
-                                  false);
+                                  false, hash);
       }
       break;
 
@@ -8055,8 +8465,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                                           args, complain, in_decl);
 
            /* Check to see if we already have this specialization.  */
-           spec = retrieve_specialization (gen_tmpl, argvec,
-                                           /*class_specializations_p=*/false);
+           hash = hash_tmpl_and_args (gen_tmpl, argvec);
+           spec = retrieve_specialization (gen_tmpl, argvec, hash);
 
            if (spec)
              {
@@ -8147,7 +8557,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        /* Clear out the mangled name and RTL for the instantiation.  */
        SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
        SET_DECL_RTL (r, NULL_RTX);
-       DECL_INITIAL (r) = NULL_TREE;
+       /* Leave DECL_INITIAL set on deleted instantiations.  */
+       if (!DECL_DELETED_FN (r))
+         DECL_INITIAL (r) = NULL_TREE;
        DECL_CONTEXT (r) = ctx;
 
        if (member && DECL_CONV_FN_P (r))
@@ -8171,14 +8583,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        DECL_PENDING_INLINE_INFO (r) = 0;
        DECL_PENDING_INLINE_P (r) = 0;
        DECL_SAVED_TREE (r) = NULL_TREE;
+       DECL_STRUCT_FUNCTION (r) = NULL;
        TREE_USED (r) = 0;
-       if (DECL_CLONED_FUNCTION (r))
-         {
-           DECL_CLONED_FUNCTION (r) = tsubst (DECL_CLONED_FUNCTION (t),
-                                              args, complain, t);
-           TREE_CHAIN (r) = TREE_CHAIN (DECL_CLONED_FUNCTION (r));
-           TREE_CHAIN (DECL_CLONED_FUNCTION (r)) = r;
-         }
+       /* We'll re-clone as appropriate in instantiate_template.  */
+       DECL_CLONED_FUNCTION (r) = NULL_TREE;
 
        /* Set up the DECL_TEMPLATE_INFO for R.  There's no need to do
           this in the special friend case mentioned above where
@@ -8188,7 +8596,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            DECL_TEMPLATE_INFO (r)
              = tree_cons (gen_tmpl, argvec, NULL_TREE);
            SET_DECL_IMPLICIT_INSTANTIATION (r);
-           register_specialization (r, gen_tmpl, argvec, false);
+           register_specialization (r, gen_tmpl, argvec, false, hash);
 
            /* We're not supposed to instantiate default arguments
               until they are called, for a template.  But, for a
@@ -8403,6 +8811,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
             tsubst_copy (DECL_NAME (t), args, complain, in_decl));
          if (!r)
            r = error_mark_node;
+         else
+           {
+             TREE_PROTECTED (r) = TREE_PROTECTED (t);
+             TREE_PRIVATE (r) = TREE_PRIVATE (t);
+           }
        }
       else
        {
@@ -8473,9 +8886,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                tmpl = DECL_TI_TEMPLATE (t);
                gen_tmpl = most_general_template (tmpl);
                argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
-               spec = (retrieve_specialization 
-                       (gen_tmpl, argvec,
-                        /*class_specializations_p=*/false));
+               hash = hash_tmpl_and_args (gen_tmpl, argvec);
+               spec = retrieve_specialization (gen_tmpl, argvec, hash);
              }
          }
        else
@@ -8587,7 +8999,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
               processing here.  */
            DECL_EXTERNAL (r) = 1;
 
-           register_specialization (r, gen_tmpl, argvec, false);
+           register_specialization (r, gen_tmpl, argvec, false, hash);
            DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
            SET_DECL_IMPLICIT_INSTANTIATION (r);
          }
@@ -8761,13 +9173,6 @@ tsubst_function_type (tree t,
   if (arg_types == error_mark_node)
     return error_mark_node;
 
-  if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED
-      && in_decl != NULL_TREE
-      && !TREE_NO_WARNING (in_decl)
-      && (SCALAR_TYPE_P (return_type) || VOID_TYPE_P (return_type)))
-    warning (OPT_Wignored_qualifiers,
-            "type qualifiers ignored on function return type");
-
   /* Construct a new type node and return it.  */
   if (TREE_CODE (t) == FUNCTION_TYPE)
     fntype = build_function_type (return_type, arg_types);
@@ -8884,7 +9289,7 @@ tsubst_exception_specification (tree fntype,
    This function is used for dealing with types, decls and the like;
    for expressions, use tsubst_expr or tsubst_copy.  */
 
-static tree
+tree
 tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
   tree type, r;
@@ -8900,6 +9305,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   if (DECL_P (t))
     return tsubst_decl (t, args, complain);
 
+  if (args == NULL_TREE)
+    return t;
+
   if (TREE_CODE (t) == IDENTIFIER_NODE)
     type = IDENTIFIER_TYPE_VALUE (t);
   else
@@ -8921,7 +9329,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        {
          tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
          tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
-         r = retrieve_specialization (tmpl, gen_args, false);
+         r = retrieve_specialization (tmpl, gen_args, 0);
        }
       else if (DECL_FUNCTION_SCOPE_P (decl)
               && DECL_TEMPLATE_INFO (DECL_CONTEXT (decl))
@@ -8984,10 +9392,29 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
        max = tsubst_expr (omax, args, complain, in_decl,
                           /*integral_constant_expression_p=*/false);
+
+       /* Fix up type of the magic NOP_EXPR with TREE_SIDE_EFFECTS if
+          needed.  */
+       if (TREE_CODE (max) == NOP_EXPR
+           && TREE_SIDE_EFFECTS (omax)
+           && !TREE_TYPE (max))
+         TREE_TYPE (max) = TREE_TYPE (TREE_OPERAND (max, 0));
+
        max = fold_decl_constant_value (max);
 
+       /* If we're in a partial instantiation, preserve the magic NOP_EXPR
+          with TREE_SIDE_EFFECTS that indicates this is not an integral
+          constant expression.  */
+       if (processing_template_decl
+           && TREE_SIDE_EFFECTS (omax) && TREE_CODE (omax) == NOP_EXPR)
+         {
+           gcc_assert (TREE_CODE (max) == NOP_EXPR);
+           TREE_SIDE_EFFECTS (max) = 1;
+         }
+
        if (TREE_CODE (max) != INTEGER_CST
            && !at_function_scope_p ()
+           && !TREE_SIDE_EFFECTS (max)
            && !value_dependent_expression_p (max))
          {
            if (complain & tf_error)
@@ -9423,7 +9850,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        if (e1 == error_mark_node || e2 == error_mark_node)
          return error_mark_node;
 
-       return fold_build2 (TREE_CODE (t), TREE_TYPE (t), e1, e2);
+       return fold_build2_loc (input_location,
+                           TREE_CODE (t), TREE_TYPE (t), e1, e2);
       }
 
     case NEGATE_EXPR:
@@ -9433,7 +9861,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        if (e == error_mark_node)
          return error_mark_node;
 
-       return fold_build1 (TREE_CODE (t), TREE_TYPE (t), e);
+       return fold_build1_loc (input_location, TREE_CODE (t), TREE_TYPE (t), e);
       }
 
     case TYPENAME_TYPE:
@@ -9462,7 +9890,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
               But, such constructs have already been resolved by this
               point, so here CTX really should have complete type, unless
               it's a partial instantiation.  */
-           ctx = complete_type (ctx);
+           if (!(complain & tf_no_class_instantiations))
+             ctx = complete_type (ctx);
            if (!COMPLETE_TYPE_P (ctx))
              {
                if (complain & tf_error)
@@ -9555,11 +9984,18 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
        tree type;
 
-       type = 
-          finish_decltype_type (tsubst_expr 
-                                (DECLTYPE_TYPE_EXPR (t), args,
-                                 complain, in_decl,
-                                 /*integral_constant_expression_p=*/false),
+       ++cp_unevaluated_operand;
+       ++c_inhibit_evaluation_warnings;
+
+       type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args,
+                           complain, in_decl,
+                           /*integral_constant_expression_p=*/false);
+
+       --cp_unevaluated_operand;
+       --c_inhibit_evaluation_warnings;
+
+       type =
+          finish_decltype_type (type,
                                 DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
        return cp_build_qualified_type_real (type,
                                             cp_type_quals (t)
@@ -9708,16 +10144,29 @@ tsubst_qualified_id (tree qualified_id, tree args,
     expr = name;
 
   if (dependent_type_p (scope))
-    return build_qualified_name (/*type=*/NULL_TREE,
-                                scope, expr,
-                                QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+    {
+      tree type = NULL_TREE;
+      if (DECL_P (expr) && !dependent_scope_p (scope))
+       type = TREE_TYPE (expr);
+      return build_qualified_name (type, scope, expr,
+                                  QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+    }
 
   if (!BASELINK_P (name) && !DECL_P (expr))
     {
       if (TREE_CODE (expr) == BIT_NOT_EXPR)
-       /* If this were actually a destructor call, it would have been
-          parsed as such by the parser.  */
-       expr = error_mark_node;
+       {
+         /* A BIT_NOT_EXPR is used to represent a destructor.  */
+         if (!check_dtor_name (scope, TREE_OPERAND (expr, 0)))
+           {
+             error ("qualifying type %qT does not match destructor name ~%qT",
+                    scope, TREE_OPERAND (expr, 0));
+             expr = error_mark_node;
+           }
+         else
+           expr = lookup_qualified_name (scope, complete_dtor_identifier,
+                                         /*is_type_p=*/0, false);
+       }
       else
        expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
       if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
@@ -9727,7 +10176,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
            {
              error ("dependent-name %qE is parsed as a non-type, but "
                     "instantiation yields a type", qualified_id);
-             inform ("say %<typename %E%> if a type is meant", qualified_id);
+             inform (input_location, "say %<typename %E%> if a type is meant", qualified_id);
            }
          return error_mark_node;
        }
@@ -9746,7 +10195,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
       if (complain & tf_error)
        qualified_name_lookup_error (scope,
                                     TREE_OPERAND (qualified_id, 1),
-                                    expr);
+                                    expr, input_location);
       return error_mark_node;
     }
 
@@ -9755,7 +10204,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
 
   if (expr == error_mark_node && complain & tf_error)
     qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
-                                expr);
+                                expr, input_location);
   else if (TYPE_P (scope))
     {
       expr = (adjust_result_of_qualified_name_lookup
@@ -9786,7 +10235,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   enum tree_code code;
   tree r;
 
-  if (t == NULL_TREE || t == error_mark_node)
+  if (t == NULL_TREE || t == error_mark_node || args == NULL_TREE)
     return t;
 
   code = TREE_CODE (t);
@@ -9795,7 +10244,24 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     {
     case PARM_DECL:
       r = retrieve_local_specialization (t);
-      gcc_assert (r != NULL);
+
+      if (r == NULL)
+       {
+         tree c;
+         /* This can happen for a parameter name used later in a function
+            declaration (such as in a late-specified return type).  Just
+            make a dummy decl, since it's only used for its type.  */
+         gcc_assert (cp_unevaluated_operand != 0);
+         /* We copy T because want to tsubst the PARM_DECL only,
+            not the following PARM_DECLs that are chained to T.  */
+         c = copy_node (t);
+         r = tsubst_decl (c, args, complain);
+         /* Give it the template pattern as its context; its true context
+            hasn't been instantiated yet and this is good enough for
+            mangling.  */
+         DECL_CONTEXT (r) = DECL_CONTEXT (t);
+       }
+      
       if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
        r = ARGUMENT_PACK_SELECT_ARG (r);
       mark_used (r);
@@ -10296,12 +10762,22 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
 #define RECUR(NODE)                            \
   tsubst_expr ((NODE), args, complain, in_decl,        \
               integral_constant_expression_p)
-  tree decl, init, cond, incr;
+  tree decl, init, cond, incr, auto_node;
 
   init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
   gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
   decl = RECUR (TREE_OPERAND (init, 0));
   init = TREE_OPERAND (init, 1);
+  auto_node = type_uses_auto (TREE_TYPE (decl));
+  if (auto_node && init)
+    {
+      tree init_expr = init;
+      if (TREE_CODE (init_expr) == DECL_EXPR)
+       init_expr = DECL_INITIAL (DECL_EXPR_DECL (init_expr));
+      init_expr = RECUR (init_expr);
+      TREE_TYPE (decl)
+       = do_auto_deduction (TREE_TYPE (decl), init_expr, auto_node);
+    }
   gcc_assert (!type_dependent_expression_p (decl));
 
   if (!CLASS_TYPE_P (TREE_TYPE (decl)))
@@ -10339,7 +10815,7 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
        }
       if (c == NULL)
        {
-         c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+         c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
          OMP_CLAUSE_DECL (c) = decl;
          c = finish_omp_clauses (c);
          if (c)
@@ -10487,7 +10963,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                                          /*is_type_p=*/false,
                                          /*complain=*/false);
            if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
-             qualified_name_lookup_error (scope, name, decl);
+             qualified_name_lookup_error (scope, name, decl, input_location);
            else
              do_local_using_decl (decl, scope, name);
          }
@@ -10532,13 +11008,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                             pack expansion where the parameter packs
                             used in that expansion were of length
                             zero.  */
-                         init = build_default_init (TREE_TYPE (decl),
-                                                     NULL_TREE);
+                         init = build_value_init (TREE_TYPE (decl));
                        else
                          init = t;
                      }
 
-                   finish_decl (decl, init, NULL_TREE);
+                   cp_finish_decl (decl, init, false, NULL_TREE, 0);
                  }
              }
          }
@@ -10625,12 +11100,20 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       break;
 
     case CASE_LABEL_EXPR:
-      finish_case_label (RECUR (CASE_LOW (t)),
+      finish_case_label (EXPR_LOCATION (t),
+                        RECUR (CASE_LOW (t)),
                         RECUR (CASE_HIGH (t)));
       break;
 
     case LABEL_EXPR:
-      finish_label_stmt (DECL_NAME (LABEL_EXPR_LABEL (t)));
+      {
+       tree decl = LABEL_EXPR_LABEL (t);
+       tree label;
+
+       label = finish_label_stmt (DECL_NAME (decl));
+       if (DECL_ATTRIBUTES (decl) != NULL_TREE)
+         cplus_decl_attributes (&label, DECL_ATTRIBUTES (decl), 0);
+      }
       break;
 
     case GOTO_EXPR:
@@ -10934,7 +11417,8 @@ tsubst_copy_and_build (tree t,
                                     /*done=*/true,
                                     /*address_p=*/false,
                                     /*template_arg_p=*/false,
-                                    &error_msg);
+                                    &error_msg,
+                                    input_location);
        if (error_msg)
          error (error_msg);
        if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
@@ -10945,26 +11429,26 @@ tsubst_copy_and_build (tree t,
     case TEMPLATE_ID_EXPR:
       {
        tree object;
-       tree template = RECUR (TREE_OPERAND (t, 0));
+       tree templ = RECUR (TREE_OPERAND (t, 0));
        tree targs = TREE_OPERAND (t, 1);
 
        if (targs)
          targs = tsubst_template_args (targs, args, complain, in_decl);
 
-       if (TREE_CODE (template) == COMPONENT_REF)
+       if (TREE_CODE (templ) == COMPONENT_REF)
          {
-           object = TREE_OPERAND (template, 0);
-           template = TREE_OPERAND (template, 1);
+           object = TREE_OPERAND (templ, 0);
+           templ = TREE_OPERAND (templ, 1);
          }
        else
          object = NULL_TREE;
-       template = lookup_template_function (template, targs);
+       templ = lookup_template_function (templ, targs);
 
        if (object)
-         return build3 (COMPONENT_REF, TREE_TYPE (template),
-                        object, template, NULL_TREE);
+         return build3 (COMPONENT_REF, TREE_TYPE (templ),
+                        object, templ, NULL_TREE);
        else
-         return baselink_for_fns (template);
+         return baselink_for_fns (templ);
       }
 
     case INDIRECT_REF:
@@ -11054,7 +11538,8 @@ tsubst_copy_and_build (tree t,
        op1 = tsubst_non_call_postfix_expression (op1, args, complain,
                                                  in_decl);
       if (TREE_CODE (op1) == LABEL_DECL)
-       return finish_label_address_expr (DECL_NAME (op1));
+       return finish_label_address_expr (DECL_NAME (op1),
+                                         EXPR_LOCATION (op1));
       return build_x_unary_op (ADDR_EXPR, op1, complain);
 
     case PLUS_EXPR:
@@ -11107,16 +11592,7 @@ tsubst_copy_and_build (tree t,
     case ARRAY_REF:
       op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
                                                args, complain, in_decl);
-      return build_x_binary_op (ARRAY_REF, op1,
-                               (TREE_NO_WARNING (TREE_OPERAND (t, 0))
-                                ? ERROR_MARK
-                                : TREE_CODE (TREE_OPERAND (t, 0))),
-                               RECUR (TREE_OPERAND (t, 1)),
-                               (TREE_NO_WARNING (TREE_OPERAND (t, 1))
-                                ? ERROR_MARK
-                                : TREE_CODE (TREE_OPERAND (t, 1))),
-                               /*overloaded_p=*/NULL,
-                               complain);
+      return build_x_array_ref (op1, RECUR (TREE_OPERAND (t, 1)), complain);
 
     case SIZEOF_EXPR:
       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
@@ -11135,11 +11611,13 @@ tsubst_copy_and_build (tree t,
        }
       else
        {
-         ++skip_evaluation;
+         ++cp_unevaluated_operand;
+         ++c_inhibit_evaluation_warnings;
          op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
                                       /*function_p=*/false,
                                       /*integral_constant_expression_p=*/false);
-         --skip_evaluation;
+         --cp_unevaluated_operand;
+         --c_inhibit_evaluation_warnings;
        }
       if (TYPE_P (op1))
        return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), 
@@ -11176,24 +11654,54 @@ tsubst_copy_and_build (tree t,
 
     case NEW_EXPR:
       {
+       tree placement = RECUR (TREE_OPERAND (t, 0));
        tree init = RECUR (TREE_OPERAND (t, 3));
+       VEC(tree,gc) *placement_vec;
+       VEC(tree,gc) *init_vec;
+       tree ret;
 
-       if (TREE_OPERAND (t, 3) && !init)
-         /* If there was an initializer in the the original tree, but
-            it instantiated to an empty list, then we should pass on
-            VOID_ZERO_NODE to tell build_new that it was an empty
-            initializer () rather than no initializer.  This can only
-            happen when the initializer is a pack expansion whose
-            parameter packs are of length zero.  */
-         init = void_zero_node;
+       if (placement == NULL_TREE)
+         placement_vec = NULL;
+       else
+         {
+           placement_vec = make_tree_vector ();
+           for (; placement != NULL_TREE; placement = TREE_CHAIN (placement))
+             VEC_safe_push (tree, gc, placement_vec, TREE_VALUE (placement));
+         }
 
-       return build_new
-         (RECUR (TREE_OPERAND (t, 0)),
-          RECUR (TREE_OPERAND (t, 1)),
-          RECUR (TREE_OPERAND (t, 2)),
-          init,
-          NEW_EXPR_USE_GLOBAL (t),
-           complain);
+       /* If there was an initializer in the original tree, but it
+          instantiated to an empty list, then we should pass a
+          non-NULL empty vector to tell build_new that it was an
+          empty initializer() rather than no initializer.  This can
+          only happen when the initializer is a pack expansion whose
+          parameter packs are of length zero.  */
+       if (init == NULL_TREE && TREE_OPERAND (t, 3) == NULL_TREE)
+         init_vec = NULL;
+       else
+         {
+           init_vec = make_tree_vector ();
+           if (init == void_zero_node)
+             gcc_assert (init_vec != NULL);
+           else
+             {
+               for (; init != NULL_TREE; init = TREE_CHAIN (init))
+                 VEC_safe_push (tree, gc, init_vec, TREE_VALUE (init));
+             }
+         }
+
+       ret = build_new (&placement_vec,
+                        RECUR (TREE_OPERAND (t, 1)),
+                        RECUR (TREE_OPERAND (t, 2)),
+                        &init_vec,
+                        NEW_EXPR_USE_GLOBAL (t),
+                        complain);
+
+       if (placement_vec != NULL)
+         release_tree_vector (placement_vec);
+       if (init_vec != NULL)
+         release_tree_vector (init_vec);
+
+       return ret;
       }
 
     case DELETE_EXPR:
@@ -11211,9 +11719,11 @@ tsubst_copy_and_build (tree t,
     case CALL_EXPR:
       {
        tree function;
-       tree call_args;
+       VEC(tree,gc) *call_args;
+       unsigned int nargs, i;
        bool qualified_p;
        bool koenig_p;
+       tree ret;
 
        function = CALL_EXPR_FN (t);
        /* When we parsed the expression,  we determined whether or
@@ -11248,8 +11758,40 @@ tsubst_copy_and_build (tree t,
              qualified_p = true;
          }
 
-       /* FIXME:  Rewrite this so as not to construct an arglist.  */
-       call_args = RECUR (CALL_EXPR_ARGS (t));
+       nargs = call_expr_nargs (t);
+       call_args = make_tree_vector ();
+       for (i = 0; i < nargs; ++i)
+         {
+           tree arg = CALL_EXPR_ARG (t, i);
+
+           if (!PACK_EXPANSION_P (arg))
+             VEC_safe_push (tree, gc, call_args,
+                            RECUR (CALL_EXPR_ARG (t, i)));
+           else
+             {
+               /* Expand the pack expansion and push each entry onto
+                  CALL_ARGS.  */
+               arg = tsubst_pack_expansion (arg, args, complain, in_decl);
+               if (TREE_CODE (arg) == TREE_VEC)
+                 {
+                   unsigned int len, j;
+
+                   len = TREE_VEC_LENGTH (arg);
+                   for (j = 0; j < len; ++j)
+                     {
+                       tree value = TREE_VEC_ELT (arg, j);
+                       if (value != NULL_TREE)
+                         value = convert_from_reference (value);
+                       VEC_safe_push (tree, gc, call_args, value);
+                     }
+                 }
+               else
+                 {
+                   /* A partial substitution.  Add one entry.  */
+                   VEC_safe_push (tree, gc, call_args, arg);
+                 }
+             }
+         }
 
        /* We do not perform argument-dependent lookup if normal
           lookup finds a non-function, in accordance with the
@@ -11260,12 +11802,17 @@ tsubst_copy_and_build (tree t,
                    not appropriate, even if an unqualified-name was used
                    to denote the function.  */
                 && !DECL_FUNCTION_MEMBER_P (get_first_fn (function)))
-               || TREE_CODE (function) == IDENTIFIER_NODE))
+               || TREE_CODE (function) == IDENTIFIER_NODE)
+           /* Only do this when substitution turns a dependent call
+              into a non-dependent call.  */
+           && type_dependent_expression_p_push (t)
+           && !any_type_dependent_arguments_p (call_args))
          function = perform_koenig_lookup (function, call_args);
 
        if (TREE_CODE (function) == IDENTIFIER_NODE)
          {
            unqualified_name_lookup_error (function);
+           release_tree_vector (call_args);
            return error_mark_node;
          }
 
@@ -11274,27 +11821,32 @@ tsubst_copy_and_build (tree t,
          mark_used (function);
 
        if (TREE_CODE (function) == OFFSET_REF)
-         return build_offset_ref_call_from_tree (function, call_args);
-       if (TREE_CODE (function) == COMPONENT_REF)
+         ret = build_offset_ref_call_from_tree (function, &call_args);
+       else if (TREE_CODE (function) == COMPONENT_REF)
          {
            if (!BASELINK_P (TREE_OPERAND (function, 1)))
-             return finish_call_expr (function, call_args,
+             ret = finish_call_expr (function, &call_args,
                                       /*disallow_virtual=*/false,
                                       /*koenig_p=*/false,
                                       complain);
            else
-             return (build_new_method_call
+             ret = (build_new_method_call
                      (TREE_OPERAND (function, 0),
                       TREE_OPERAND (function, 1),
-                      call_args, NULL_TREE,
+                      &call_args, NULL_TREE,
                       qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
                       /*fn_p=*/NULL,
                       complain));
          }
-       return finish_call_expr (function, call_args,
-                                /*disallow_virtual=*/qualified_p,
-                                koenig_p,
-                                complain);
+       else
+         ret = finish_call_expr (function, &call_args,
+                                 /*disallow_virtual=*/qualified_p,
+                                 koenig_p,
+                                 complain);
+
+       release_tree_vector (call_args);
+
+       return ret;
       }
 
     case COND_EXPR:
@@ -11463,7 +12015,8 @@ tsubst_copy_and_build (tree t,
              }
            else
              {
-               qualified_name_lookup_error (object_type, tmpl, member);
+               qualified_name_lookup_error (object_type, tmpl, member,
+                                            input_location);
                return error_mark_node;
              }
          }
@@ -11503,6 +12056,7 @@ tsubst_copy_and_build (tree t,
        bool process_index_p;
         int newlen;
         bool need_copy_p = false;
+       tree r;
 
        if (type == error_mark_node)
          return error_mark_node;
@@ -11567,10 +12121,13 @@ tsubst_copy_and_build (tree t,
               }
           }
 
+       r = build_constructor (init_list_type_node, n);
+       CONSTRUCTOR_IS_DIRECT_INIT (r) = CONSTRUCTOR_IS_DIRECT_INIT (t);
+
        if (TREE_HAS_CONSTRUCTOR (t))
-         return finish_compound_literal (type, n);
+         return finish_compound_literal (type, r);
 
-       return build_constructor (NULL_TREE, n);
+       return r;
       }
 
     case TYPEID_EXPR:
@@ -11658,11 +12215,48 @@ tsubst_copy_and_build (tree t,
 }
 
 /* Verify that the instantiated ARGS are valid. For type arguments,
-   make sure that the type's linkage is ok. For non-type arguments,
+   make sure that the type is not variably modified. For non-type arguments,
    make sure they are constants if they are integral or enumerations.
    Emit an error under control of COMPLAIN, and return TRUE on error.  */
 
 static bool
+check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
+{
+  if (ARGUMENT_PACK_P (t))
+    {
+      tree vec = ARGUMENT_PACK_ARGS (t);
+      int len = TREE_VEC_LENGTH (vec);
+      bool result = false;
+      int i;
+
+      for (i = 0; i < len; ++i)
+       if (check_instantiated_arg (tmpl, TREE_VEC_ELT (vec, i), complain))
+         result = true;
+      return result;
+    }
+  else if (TYPE_P (t))
+    {
+      if (variably_modified_type_p (t, NULL_TREE))
+       {
+         if (complain & tf_error)
+           error ("%qT is a variably modified type", t);
+         return true;
+       }
+    }
+  /* A non-type argument of integral or enumerated type must be a
+     constant.  */
+  else if (TREE_TYPE (t)
+          && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
+          && !TREE_CONSTANT (t))
+    {
+      if (complain & tf_error)
+       error ("integral expression %qE is not constant", t);
+      return true;
+    }
+  return false;
+}
+
+static bool
 check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
 {
   int ix, len = DECL_NTPARMS (tmpl);
@@ -11670,50 +12264,8 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
 
   for (ix = 0; ix != len; ix++)
     {
-      tree t = TREE_VEC_ELT (args, ix);
-
-      if (TYPE_P (t))
-       {
-         /* [basic.link]: A name with no linkage (notably, the name
-            of a class or enumeration declared in a local scope)
-            shall not be used to declare an entity with linkage.
-            This implies that names with no linkage cannot be used as
-            template arguments.  */
-         tree nt = no_linkage_check (t, /*relaxed_p=*/false);
-
-         if (nt)
-           {
-             /* DR 488 makes use of a type with no linkage cause
-                type deduction to fail.  */
-             if (complain & tf_error)
-               {
-                 if (TYPE_ANONYMOUS_P (nt))
-                   error ("%qT is/uses anonymous type", t);
-                 else
-                   error ("template argument for %qD uses local type %qT",
-                          tmpl, t);
-               }
-             result = true;
-           }
-         /* In order to avoid all sorts of complications, we do not
-            allow variably-modified types as template arguments.  */
-         else if (variably_modified_type_p (t, NULL_TREE))
-           {
-             if (complain & tf_error)
-               error ("%qT is a variably modified type", t);
-             result = true;
-           }
-       }
-      /* A non-type argument of integral or enumerated type must be a
-        constant.  */
-      else if (TREE_TYPE (t)
-              && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
-              && !TREE_CONSTANT (t))
-       {
-         if (complain & tf_error)
-           error ("integral expression %qE is not constant", t);
-         result = true;
-       }
+      if (check_instantiated_arg (tmpl, TREE_VEC_ELT (args, ix), complain))
+       result = true;
     }
   if (result && (complain & tf_error))
     error ("  trying to instantiate %qD", tmpl);
@@ -11724,8 +12276,9 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
    the template arguments in TARG_PTR.  */
 
 tree
-instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
+instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
 {
+  tree targ_ptr = orig_args;
   tree fndecl;
   tree gen_tmpl;
   tree spec;
@@ -11742,8 +12295,10 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
       tree spec;
       tree clone;
 
-      spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr,
-                                  complain);
+      /* Use DECL_ABSTRACT_ORIGIN because only FUNCTION_DECLs have
+        DECL_CLONED_FUNCTION.  */
+      spec = instantiate_template (DECL_ABSTRACT_ORIGIN (tmpl),
+                                  targ_ptr, complain);
       if (spec == error_mark_node)
        return error_mark_node;
 
@@ -11757,26 +12312,25 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
     }
 
   /* Check to see if we already have this specialization.  */
-  spec = retrieve_specialization (tmpl, targ_ptr,
-                                 /*class_specializations_p=*/false);
-  if (spec != NULL_TREE)
-    return spec;
-
   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);
+    /* 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);
 
-      /* Check to see if we already have this specialization.  */
-      spec = retrieve_specialization (gen_tmpl, targ_ptr,
-                                     /*class_specializations_p=*/false);
-      if (spec != NULL_TREE)
-       return spec;
-    }
+  /* It would be nice to avoid hashing here and then again in tsubst_decl,
+     but it doesn't seem to be on the hot path.  */
+  spec = retrieve_specialization (gen_tmpl, targ_ptr, 0);
+
+  gcc_assert (tmpl == gen_tmpl
+             || ((fndecl = retrieve_specialization (tmpl, orig_args, 0))
+                 == spec)
+             || fndecl == NULL_TREE);
+
+  if (spec != NULL_TREE)
+    return spec;
 
   if (check_instantiated_args (gen_tmpl, INNERMOST_TEMPLATE_ARGS (targ_ptr),
                               complain))
@@ -11807,6 +12361,12 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
   /* Now we know the specialization, compute access previously
      deferred.  */
   push_access_scope (fndecl);
+
+  /* Some typedefs referenced from within the template code need to be access
+     checked at template instantiation time, i.e now. These types were
+     added to the template at parsing time. Let's get those and perfom
+     the acces checks then.  */
+  perform_typedefs_access_check (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
   perform_deferred_access_checks ();
   pop_access_scope (fndecl);
   pop_deferring_access_checks ();
@@ -11825,9 +12385,10 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
   return fndecl;
 }
 
-/* The FN is a TEMPLATE_DECL for a function.  The ARGS are the
-   arguments that are being used when calling it.  TARGS is a vector
-   into which the deduced template arguments are placed.
+/* The FN is a TEMPLATE_DECL for a function.  ARGS is an array with
+   NARGS elements of the arguments that are being used when calling
+   it.  TARGS is a vector into which the deduced template arguments
+   are placed.
 
    Return zero for success, 2 for an incomplete match that doesn't resolve
    all the types, and 1 for complete failure.  An error message will be
@@ -11859,7 +12420,8 @@ int
 fn_type_unification (tree fn,
                     tree explicit_targs,
                     tree targs,
-                    tree args,
+                    const tree *args,
+                    unsigned int nargs,
                     tree return_type,
                     unification_kind_t strict,
                     int flags)
@@ -11976,8 +12538,14 @@ fn_type_unification (tree fn,
 
   if (return_type)
     {
+      tree *new_args;
+
       parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
-      args = tree_cons (NULL_TREE, return_type, args);
+      new_args = XALLOCAVEC (tree, nargs + 1);
+      new_args[0] = return_type;
+      memcpy (new_args + 1, args, nargs * sizeof (tree));
+      args = new_args;
+      ++nargs;
     }
 
   /* We allow incomplete unification without an error message here
@@ -11985,7 +12553,7 @@ fn_type_unification (tree fn,
      callers must be ready to deal with unification failures in any
      event.  */
   result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
-                                 targs, parms, args, /*subr=*/0,
+                                 targs, parms, args, nargs, /*subr=*/0,
                                  strict, flags);
 
   if (result == 0 && incomplete_argument_packs_p)
@@ -12040,9 +12608,27 @@ fn_type_unification (tree fn,
        the corresponding deduced argument values.  If the
        substitution results in an invalid type, as described above,
        type deduction fails.  */
-    if (tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE)
-       == error_mark_node)
-      return 1;
+    {
+      tree substed = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
+      if (substed == error_mark_node)
+       return 1;
+
+      /* If we're looking for an exact match, check that what we got
+        is indeed an exact match.  It might not be if some template
+        parameters are used in non-deduced contexts.  */
+      if (strict == DEDUCE_EXACT)
+       {
+         unsigned int i;
+
+         tree sarg
+           = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (substed));
+         if (return_type)
+           sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
+         for (i = 0; i < nargs && sarg; ++i, sarg = TREE_CHAIN (sarg))
+           if (!same_type_p (args[i], TREE_VALUE (sarg)))
+             return 1;
+       }
+    }
 
   return result;
 }
@@ -12154,7 +12740,8 @@ static int
 type_unification_real (tree tparms,
                       tree targs,
                       tree xparms,
-                      tree xargs,
+                      const tree *xargs,
+                      unsigned int xnargs,
                       int subr,
                       unification_kind_t strict,
                       int flags)
@@ -12164,11 +12751,13 @@ type_unification_real (tree tparms,
   int ntparms = TREE_VEC_LENGTH (tparms);
   int sub_strict;
   int saw_undeduced = 0;
-  tree parms, args;
+  tree parms;
+  const tree *args;
+  unsigned int nargs;
+  unsigned int ia;
 
   gcc_assert (TREE_CODE (tparms) == TREE_VEC);
   gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
-  gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
   gcc_assert (ntparms > 0);
 
   switch (strict)
@@ -12193,17 +12782,19 @@ type_unification_real (tree tparms,
  again:
   parms = xparms;
   args = xargs;
+  nargs = xnargs;
 
+  ia = 0;
   while (parms && parms != void_list_node
-        && args && args != void_list_node)
+        && ia < nargs)
     {
       if (TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
         break;
 
       parm = TREE_VALUE (parms);
       parms = TREE_CHAIN (parms);
-      arg = TREE_VALUE (args);
-      args = TREE_CHAIN (args);
+      arg = args[ia];
+      ++ia;
       arg_expr = NULL;
 
       if (arg == error_mark_node)
@@ -12267,6 +12858,8 @@ type_unification_real (tree tparms,
          arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
                                                          arg_expr);
 
+       if (arg == init_list_type_node && arg_expr)
+         arg = arg_expr;
        if (unify (tparms, targs, parm, arg, arg_strict))
          return 1;
       }
@@ -12280,20 +12873,11 @@ type_unification_real (tree tparms,
       /* Unify the remaining arguments with the pack expansion type.  */
       tree argvec;
       tree parmvec = make_tree_vec (1);
-      int len = 0;
-      tree t;
 
-      /* Count the number of arguments that remain.  */
-      for (t = args; t && t != void_list_node; t = TREE_CHAIN (t))
-        len++;
-        
       /* Allocate a TREE_VEC and copy in all of the arguments */ 
-      argvec = make_tree_vec (len);
-      for (i = 0; args && args != void_list_node; args = TREE_CHAIN (args))
-        {
-          TREE_VEC_ELT (argvec, i) = TREE_VALUE (args);
-          ++i;
-        }
+      argvec = make_tree_vec (nargs - ia);
+      for (i = 0; ia < nargs; ++ia, ++i)
+       TREE_VEC_ELT (argvec, i) = args[ia];
 
       /* Copy the parameter into parmvec.  */
       TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
@@ -12307,7 +12891,7 @@ type_unification_real (tree tparms,
 
   /* Fail if we've reached the end of the parm list, and more args
      are present, and the parm list isn't variadic.  */
-  if (args && args != void_list_node && parms == void_list_node)
+  if (ia < nargs && parms == void_list_node)
     return 1;
   /* Fail if parms are left and they don't have default values.  */
   if (parms && parms != void_list_node
@@ -12344,8 +12928,9 @@ type_unification_real (tree tparms,
             to explicitly check cxx_dialect here.  */
           if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
             {
-              tree arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)), 
-                                 targs, tf_none, NULL_TREE);
+              tree arg = tsubst_template_arg
+                               (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)),
+                                targs, tf_none, NULL_TREE);
               if (arg == error_mark_node)
                 return 1;
               else
@@ -12398,6 +12983,7 @@ resolve_overloaded_unification (tree tparms,
 {
   tree tempargs = copy_node (targs);
   int good = 0;
+  tree goodfn = NULL_TREE;
   bool addr_p;
 
   if (TREE_CODE (arg) == ADDR_EXPR)
@@ -12443,8 +13029,13 @@ resolve_overloaded_unification (tree tparms,
          if (subargs)
            {
              elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
-             good += try_one_overload (tparms, targs, tempargs, parm,
-                                       elem, strict, sub_strict, addr_p);
+             if (try_one_overload (tparms, targs, tempargs, parm,
+                                   elem, strict, sub_strict, addr_p)
+                 && (!goodfn || !decls_match (goodfn, elem)))
+               {
+                 goodfn = elem;
+                 ++good;
+               }
            }
          --processing_template_decl;
        }
@@ -12457,9 +13048,14 @@ resolve_overloaded_unification (tree tparms,
     return false;
   else
     for (; arg; arg = OVL_NEXT (arg))
-      good += try_one_overload (tparms, targs, tempargs, parm,
-                               TREE_TYPE (OVL_CURRENT (arg)),
-                               strict, sub_strict, addr_p);
+      if (try_one_overload (tparms, targs, tempargs, parm,
+                           TREE_TYPE (OVL_CURRENT (arg)),
+                           strict, sub_strict, addr_p)
+         && (!goodfn || !decls_match (goodfn, OVL_CURRENT (arg))))
+       {
+         goodfn = OVL_CURRENT (arg);
+         ++good;
+       }
 
   /* [temp.deduct.type] A template-argument can be deduced from a pointer
      to function or pointer to member function argument if the set of
@@ -12838,7 +13434,9 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
                        match.  */
 
                     if (resolve_overloaded_unification
-                        (tparms, targs, parm, arg, strict, sub_strict)
+                        (tparms, targs, parm, arg,
+                        (unification_kind_t) strict,
+                        sub_strict)
                         != 0)
                       return 1;
                     skip_arg_p = true;
@@ -12857,8 +13455,8 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
 
             if (!subr)
               arg_strict |= 
-                maybe_adjust_types_for_deduction (strict, &parm, &arg, 
-                                                 arg_expr);
+                maybe_adjust_types_for_deduction ((unification_kind_t) strict,
+                                                 &parm, &arg, arg_expr);
           }
 
         if (!skip_arg_p)
@@ -13033,7 +13631,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 
   if (arg == error_mark_node)
     return 1;
-  if (arg == unknown_type_node)
+  if (arg == unknown_type_node
+      || arg == init_list_type_node)
     /* We can't deduce anything from this, but we might get all the
        template args from other function args.  */
     return 0;
@@ -13045,6 +13644,40 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
   if (arg == parm && !uses_template_parms (parm))
     return 0;
 
+  /* Handle init lists early, so the rest of the function can assume
+     we're dealing with a type. */
+  if (BRACE_ENCLOSED_INITIALIZER_P (arg))
+    {
+      tree elt, elttype;
+      unsigned i;
+
+      if (!is_std_init_list (parm))
+       /* We can only deduce from an initializer list argument if the
+          parameter is std::initializer_list; otherwise this is a
+          non-deduced context. */
+       return 0;
+
+      elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
+
+      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
+       {
+         int elt_strict = strict;
+         if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
+           {
+             tree type = TREE_TYPE (elt);
+             /* It should only be possible to get here for a call.  */
+             gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL);
+             elt_strict |= maybe_adjust_types_for_deduction
+               (DEDUCE_CALL, &elttype, &type, elt);
+             elt = type;
+           }
+
+         if (unify (tparms, targs, elttype, elt, elt_strict))
+           return 1;
+       }
+      return 0;
+    }
+
   /* Immediately reject some pairs that won't unify because of
      cv-qualification mismatches.  */
   if (TREE_CODE (arg) == TREE_CODE (parm)
@@ -13240,6 +13873,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
             ISO C++, so we can do as we please here.  */
          if (variably_modified_type_p (arg, NULL_TREE))
            return 1;
+
+         /* Strip typedefs as in convert_template_argument.  */
+         arg = strip_typedefs (arg);
        }
 
       /* If ARG is a parameter pack or an expansion, we cannot unify
@@ -13248,6 +13884,13 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          && !template_parameter_pack_p (parm))
        return 1;
 
+      /* If the argument deduction results is a METHOD_TYPE,
+         then there is a problem.
+         METHOD_TYPE doesn't map to any real C++ type the result of
+        the deduction can not be of that type.  */
+      if (TREE_CODE (arg) == METHOD_TYPE)
+       return 1;
+
       TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
       return 0;
 
@@ -13290,7 +13933,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
        /* Convert the ARG to the type of PARM; the deduced non-type
           template argument must exactly match the types of the
           corresponding parameter.  */
-       arg = fold (build_nop (TREE_TYPE (parm), arg));
+       arg = fold (build_nop (tparm, arg));
       else if (uses_template_parms (tparm))
        /* We haven't deduced the type of this parameter yet.  Try again
           later.  */
@@ -13409,12 +14052,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          /* If only one of the bounds used a MINUS_EXPR, compensate
             by adding one to the other bound.  */
          if (parm_cst && !arg_cst)
-           parm_max = fold_build2 (PLUS_EXPR,
+           parm_max = fold_build2_loc (input_location, PLUS_EXPR,
                                    integer_type_node,
                                    parm_max,
                                    integer_one_node);
          else if (arg_cst && !parm_cst)
-           arg_max = fold_build2 (PLUS_EXPR,
+           arg_max = fold_build2_loc (input_location, PLUS_EXPR,
                                   integer_type_node,
                                   arg_max,
                                   integer_one_node);
@@ -13531,26 +14174,42 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 
     case METHOD_TYPE:
     case FUNCTION_TYPE:
-      if (TREE_CODE (arg) != TREE_CODE (parm))
-       return 1;
+      {
+       unsigned int nargs;
+       tree *args;
+       tree a;
+       unsigned int i;
 
-      /* CV qualifications for methods can never be deduced, they must
-        match exactly.  We need to check them explicitly here,
-        because type_unification_real treats them as any other
-        cvqualified parameter.  */
-      if (TREE_CODE (parm) == METHOD_TYPE
-         && (!check_cv_quals_for_unify
-             (UNIFY_ALLOW_NONE,
-              TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
-              TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
-       return 1;
+       if (TREE_CODE (arg) != TREE_CODE (parm))
+         return 1;
 
-      if (unify (tparms, targs, TREE_TYPE (parm),
-                TREE_TYPE (arg), UNIFY_ALLOW_NONE))
-       return 1;
-      return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
-                                   TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT,
-                                   LOOKUP_NORMAL);
+       /* CV qualifications for methods can never be deduced, they must
+          match exactly.  We need to check them explicitly here,
+          because type_unification_real treats them as any other
+          cv-qualified parameter.  */
+       if (TREE_CODE (parm) == METHOD_TYPE
+           && (!check_cv_quals_for_unify
+               (UNIFY_ALLOW_NONE,
+                TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
+                TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
+         return 1;
+
+       if (unify (tparms, targs, TREE_TYPE (parm),
+                  TREE_TYPE (arg), UNIFY_ALLOW_NONE))
+         return 1;
+
+       nargs = list_length (TYPE_ARG_TYPES (arg));
+       args = XALLOCAVEC (tree, nargs);
+       for (a = TYPE_ARG_TYPES (arg), i = 0;
+            a != NULL_TREE && a != void_list_node;
+            a = TREE_CHAIN (a), ++i)
+         args[i] = TREE_VALUE (a);
+       nargs = i;
+
+       return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
+                                     args, nargs, 1, DEDUCE_EXACT,
+                                     LOOKUP_NORMAL);
+      }
 
     case OFFSET_TYPE:
       /* Unify a pointer to member with a pointer to member function, which
@@ -14104,6 +14763,9 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
   tree targs = make_tree_vec (ntparms);
   tree decl_type;
   tree decl_arg_types;
+  tree *args;
+  unsigned int nargs, ix;
+  tree arg;
 
   /* Substitute the explicit template arguments into the type of DECL.
      The call to fn_type_unification will handle substitution into the
@@ -14138,8 +14800,15 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
   decl_arg_types = skip_artificial_parms_for (decl, 
                                              TYPE_ARG_TYPES (decl_type));
 
+  nargs = list_length (decl_arg_types);
+  args = XALLOCAVEC (tree, nargs);
+  for (arg = decl_arg_types, ix = 0;
+       arg != NULL_TREE && arg != void_list_node;
+       arg = TREE_CHAIN (arg), ++ix)
+    args[ix] = TREE_VALUE (arg);
+
   if (fn_type_unification (fn, explicit_args, targs,
-                          decl_arg_types,
+                          args, ix,
                           (check_rettype || DECL_CONV_FN_P (fn)
                            ? TREE_TYPE (decl_type) : NULL_TREE),
                           DEDUCE_EXACT, LOOKUP_NORMAL))
@@ -14150,7 +14819,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
 
 /* Return the innermost template arguments that, when applied to a
    template specialization whose innermost template parameters are
-   TPARMS, and whose specialization arguments are PARMS, yield the
+   TPARMS, and whose specialization arguments are SPEC_ARGS, yield the
    ARGS.
 
    For example, suppose we have:
@@ -14563,7 +15232,7 @@ do_decl_instantiation (tree decl, tree storage)
         the first instantiation was `extern' and the second is not,
         and EXTERN_P for the opposite case.  */
       if (DECL_NOT_REALLY_EXTERN (result) && !extern_p)
-       pedwarn ("duplicate explicit instantiation of %q#D", result);
+       permerror (input_location, "duplicate explicit instantiation of %q#D", result);
       /* If an "extern" explicit instantiation follows an ordinary
         explicit instantiation, the template is instantiated.  */
       if (extern_p)
@@ -14576,7 +15245,7 @@ do_decl_instantiation (tree decl, tree storage)
     }
   else if (!DECL_TEMPLATE_INFO (result))
     {
-      pedwarn ("explicit instantiation of non-template %q#D", result);
+      permerror (input_location, "explicit instantiation of non-template %q#D", result);
       return;
     }
 
@@ -14584,8 +15253,9 @@ do_decl_instantiation (tree decl, tree storage)
     ;
   else if (storage == ridpointers[(int) RID_EXTERN])
     {
-      if (pedantic && !in_system_header)
-       pedwarn ("ISO C++ forbids the use of %<extern%> on explicit "
+      if (!in_system_header && (cxx_dialect == cxx98))
+       pedwarn (input_location, OPT_pedantic, 
+                "ISO C++ 1998 forbids the use of %<extern%> on explicit "
                 "instantiations");
       extern_p = 1;
     }
@@ -14671,9 +15341,20 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
   if (storage != NULL_TREE)
     {
-      if (pedantic && !in_system_header)
-       pedwarn("ISO C++ forbids the use of %qE on explicit instantiations",
-               storage);
+      if (!in_system_header)
+       {
+         if (storage == ridpointers[(int) RID_EXTERN])
+           {
+             if (cxx_dialect == cxx98)
+               pedwarn (input_location, OPT_pedantic, 
+                        "ISO C++ 1998 forbids the use of %<extern%> on "
+                        "explicit instantiations");
+           }
+         else
+           pedwarn (input_location, OPT_pedantic, 
+                    "ISO C++ forbids the use of %qE"
+                    " on explicit instantiations", storage);
+       }
 
       if (storage == ridpointers[(int) RID_INLINE])
        nomem_p = 1;
@@ -14717,7 +15398,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
       if (!previous_instantiation_extern_p && !extern_p
          && (complain & tf_error))
-       pedwarn ("duplicate explicit instantiation of %q#T", t);
+       permerror (input_location, "duplicate explicit instantiation of %q#T", t);
 
       /* If we've already instantiated the template, just return now.  */
       if (!CLASSTYPE_INTERFACE_ONLY (t))
@@ -14884,8 +15565,6 @@ regenerate_decl_from_template (tree decl, tree tmpl)
       if (DECL_DECLARED_INLINE_P (code_pattern)
          && !DECL_DECLARED_INLINE_P (decl))
        DECL_DECLARED_INLINE_P (decl) = 1;
-      if (DECL_INLINE (code_pattern) && !DECL_INLINE (decl))
-       DECL_INLINE (decl) = 1;
     }
   else if (TREE_CODE (decl) == VAR_DECL)
     DECL_INITIAL (decl) =
@@ -14977,7 +15656,6 @@ instantiate_decl (tree d, int defer_ok,
   bool pattern_defined;
   int need_push;
   location_t saved_loc = input_location;
-  int saved_in_system_header = in_system_header;
   bool external_p;
 
   /* This function should only be used to instantiate templates for
@@ -14998,25 +15676,28 @@ instantiate_decl (tree d, int defer_ok,
   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 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.  */
+  if (DECL_TEMPLATE_INSTANTIATED (d)
+      || DECL_TEMPLATE_SPECIALIZATION (d))
+    /* D has already been instantiated or explicitly specialized, so
+       there's nothing for us to do here.
+
+       It might seem reasonable to 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.  */
     return d;
 
-  /* If we already have a specialization of this declaration, then
-     there's no reason to instantiate it.  Note that
-     retrieve_specialization gives us both instantiations and
-     specializations, so we must explicitly check
-     DECL_TEMPLATE_SPECIALIZATION.  */
   gen_tmpl = most_general_template (tmpl);
   gen_args = DECL_TI_ARGS (d);
-  spec = retrieve_specialization (gen_tmpl, gen_args,
-                                 /*class_specializations_p=*/false);
-  if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
-    return spec;
+
+  if (tmpl != gen_tmpl)
+    /* We should already have the extra args.  */
+    gcc_assert (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (gen_tmpl))
+               == TMPL_ARGS_DEPTH (gen_args));
+  /* And what's in the hash table should match D.  */
+  gcc_assert ((spec = retrieve_specialization (gen_tmpl, gen_args, 0)) == d
+             || spec == NULL_TREE);
 
   /* This needs to happen before any tsubsting.  */
   if (! push_tinst_level (d))
@@ -15060,7 +15741,6 @@ instantiate_decl (tree d, int defer_ok,
     mark_definable (d);
 
   input_location = DECL_SOURCE_LOCATION (d);
-  in_system_header = DECL_IN_SYSTEM_HEADER (d);
 
   /* If D is a member of an explicitly instantiated class template,
      and no definition is available, treat it like an implicit
@@ -15108,8 +15788,14 @@ instantiate_decl (tree d, int defer_ok,
   /* In general, we do not instantiate such templates...  */
   if (external_p
       /* ... but we instantiate inline functions so that we can inline
-        them and ... */
-      && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
+        them.  An explicit instantiation declaration prohibits implicit
+        instantiation of non-inline functions.  With high levels of
+        optimization, we would normally inline non-inline functions
+        -- but we're not allowed to do that for "extern template" functions.
+        Therefore, we check DECL_DECLARED_INLINE_P, rather than
+        possibly_inlined_p.  And ...  */
+      && ! (TREE_CODE (d) == FUNCTION_DECL
+           && DECL_DECLARED_INLINE_P (d))
       /* ... we instantiate static data members whose values are
         needed in integral constant expressions.  */
       && ! (TREE_CODE (d) == VAR_DECL
@@ -15156,7 +15842,8 @@ instantiate_decl (tree d, int defer_ok,
       input_location = saved_loc;
 
       if (at_eof && !pattern_defined
-         && DECL_EXPLICIT_INSTANTIATION (d))
+         && DECL_EXPLICIT_INSTANTIATION (d)
+         && DECL_NOT_REALLY_EXTERN (d))
        /* [temp.explicit]
 
           The definition of a non-exported function template, a
@@ -15164,8 +15851,8 @@ instantiate_decl (tree d, int defer_ok,
           member function or static data member of a class template
           shall be present in every translation unit in which it is
           explicitly instantiated.  */
-       pedwarn
-         ("explicit instantiation of %qD but no definition available", d);
+       permerror (input_location,  "explicit instantiation of %qD "
+                  "but no definition available", d);
 
       /* ??? Historically, we have instantiated inline functions, even
         when marked as "extern template".  */
@@ -15186,9 +15873,7 @@ instantiate_decl (tree d, int defer_ok,
       /* Instantiate inline functions so that the inliner can do its
         job, even though we'll not be emitting a copy of this
         function.  */
-      if (!(TREE_CODE (d) == FUNCTION_DECL
-           && flag_inline_trees
-           && DECL_DECLARED_INLINE_P (d)))
+      if (!(TREE_CODE (d) == FUNCTION_DECL && possibly_inlined_p (d)))
        goto out;
     }
 
@@ -15219,7 +15904,7 @@ instantiate_decl (tree d, int defer_ok,
 
       /* The initializer is placed in DECL_INITIAL by
         regenerate_decl_from_template.  Pull it out so that
-        finish_decl can process it.  */
+        cp_finish_decl can process it.  */
       init = DECL_INITIAL (d);
       DECL_INITIAL (d) = NULL_TREE;
       DECL_INITIALIZED_P (d) = 0;
@@ -15231,7 +15916,7 @@ instantiate_decl (tree d, int defer_ok,
 
       /* Enter the scope of D so that access-checking works correctly.  */
       push_nested_class (DECL_CONTEXT (d));
-      finish_decl (d, init, NULL_TREE);
+      cp_finish_decl (d, init, false, NULL_TREE, 0);
       pop_nested_class ();
     }
   else if (TREE_CODE (d) == FUNCTION_DECL)
@@ -15272,37 +15957,12 @@ instantiate_decl (tree d, int defer_ok,
        }
       if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
         {
-          /* Collect all of the extra "packed" parameters into an
-             argument pack.  */
-          tree parmvec;
-          tree parmtypevec;
-          tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
-          tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
-          int i, len = 0;
-          tree t;
-          
-          /* Count how many parameters remain.  */
-          for (t = spec_parm; t; t = TREE_CHAIN (t))
-            len++;
-
-          /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters.  */
-          parmvec = make_tree_vec (len);
-          parmtypevec = make_tree_vec (len);
-          for(i = 0; i < len; i++, spec_parm = TREE_CHAIN (spec_parm))
-            {
-              TREE_VEC_ELT (parmvec, i) = spec_parm;
-              TREE_VEC_ELT (parmtypevec, i) = TREE_TYPE (spec_parm);
-            }
-
-          /* Build the argument packs.  */
-          SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
-          SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
-          TREE_TYPE (argpack) = argtypepack;
-          
           /* Register the (value) argument pack as a specialization of
              TMPL_PARM, then move on.  */
+         tree argpack = make_fnparm_pack (spec_parm);
           register_local_specialization (argpack, tmpl_parm);
           tmpl_parm = TREE_CHAIN (tmpl_parm);
+         spec_parm = NULL_TREE;
         }
       gcc_assert (!spec_parm);
 
@@ -15332,7 +15992,6 @@ instantiate_decl (tree d, int defer_ok,
 
 out:
   input_location = saved_loc;
-  in_system_header = saved_in_system_header;
   pop_deferring_access_checks ();
   pop_tinst_level ();
 
@@ -15350,7 +16009,6 @@ instantiate_pending_templates (int retries)
 {
   int reconsider;
   location_t saved_loc = input_location;
-  int saved_in_system_header = in_system_header;
 
   /* Instantiating templates may trigger vtable generation.  This in turn
      may require further template instantiations.  We place a limit here
@@ -15434,7 +16092,6 @@ instantiate_pending_templates (int retries)
   while (reconsider);
 
   input_location = saved_loc;
-  in_system_header = saved_in_system_header;
 }
 
 /* Substitute ARGVEC into T, which is a list of initializers for
@@ -15703,7 +16360,7 @@ current_instantiation (void)
 static int
 invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
 {
-  if (INTEGRAL_TYPE_P (type))
+  if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
     return 0;
   else if (POINTER_TYPE_P (type))
     return 0;
@@ -15781,9 +16438,9 @@ dependent_type_p_r (tree type)
           && !TREE_CONSTANT (TYPE_MAX_VALUE (type)))
     {
       /* If this is the TYPE_DOMAIN of an array type, consider it
-        dependent.  */
-      return (value_dependent_expression_p (TYPE_MAX_VALUE (type))
-             || type_dependent_expression_p (TYPE_MAX_VALUE (type)));
+        dependent.  We already checked for value-dependence in
+        compute_array_index_type.  */
+      return type_dependent_expression_p (TYPE_MAX_VALUE (type));
     }
 
   /* -- a template-id in which either the template name is a template
@@ -15854,7 +16511,7 @@ dependent_type_p (tree type)
       /* If we are not processing a template, then nobody should be
         providing us with a dependent type.  */
       gcc_assert (type);
-      gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM);
+      gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto (type));
       return false;
     }
 
@@ -15878,6 +16535,17 @@ dependent_type_p (tree type)
   return TYPE_DEPENDENT_P (type);
 }
 
+/* Returns TRUE if SCOPE is a dependent scope, in which we can't do any
+   lookup.  In other words, a dependent type that is not the current
+   instantiation.  */
+
+bool
+dependent_scope_p (tree scope)
+{
+  return (scope && TYPE_P (scope) && dependent_type_p (scope)
+         && !currently_open_class (scope));
+}
+
 /* Returns TRUE if EXPRESSION is dependent, according to CRITERION.  */
 
 static bool
@@ -15899,7 +16567,7 @@ dependent_scope_ref_p (tree expression, bool criterion (tree))
      An id-expression is type-dependent if it contains a
      nested-name-specifier that contains a class-name that names a
      dependent type.  */
-  /* The suggested resolution to Core Issue 2 implies that if the
+  /* The suggested resolution to Core Issue 224 implies that if the
      qualifying type is the current class, then we must peek
      inside it.  */
   if (DECL_P (name)
@@ -16149,6 +16817,19 @@ type_dependent_expression_p (tree expression)
   if (TREE_CODE (expression) == STMT_EXPR)
     expression = stmt_expr_value_expr (expression);
 
+  if (BRACE_ENCLOSED_INITIALIZER_P (expression))
+    {
+      tree elt;
+      unsigned i;
+
+      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expression), i, elt)
+       {
+         if (type_dependent_expression_p (elt))
+           return true;
+       }
+      return false;
+    }
+
   if (TREE_TYPE (expression) == unknown_type_node)
     {
       if (TREE_CODE (expression) == ADDR_EXPR)
@@ -16193,19 +16874,31 @@ type_dependent_expression_p (tree expression)
   return (dependent_type_p (TREE_TYPE (expression)));
 }
 
-/* Returns TRUE if ARGS (a TREE_LIST of arguments to a function call)
-   contains a type-dependent expression.  */
+/* Like type_dependent_expression_p, but it also works while not processing
+   a template definition, i.e. during substitution or mangling.  */
 
 bool
-any_type_dependent_arguments_p (const_tree args)
+type_dependent_expression_p_push (tree expr)
 {
-  while (args)
-    {
-      tree arg = TREE_VALUE (args);
+  bool b;
+  ++processing_template_decl;
+  b = type_dependent_expression_p (expr);
+  --processing_template_decl;
+  return b;
+}
+
+/* Returns TRUE if ARGS contains a type-dependent expression.  */
 
+bool
+any_type_dependent_arguments_p (const VEC(tree,gc) *args)
+{
+  unsigned int i;
+  tree arg;
+
+  for (i = 0; VEC_iterate (tree, args, i, arg); ++i)
+    {
       if (type_dependent_expression_p (arg))
        return true;
-      args = TREE_CHAIN (args);
     }
   return false;
 }
@@ -16447,7 +17140,15 @@ resolve_typename_type (tree type, bool only_current_p)
   gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
 
   scope = TYPE_CONTEXT (type);
-  name = TYPE_IDENTIFIER (type);
+  /* Usually the non-qualified identifier of a TYPENAME_TYPE is
+     TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
+     a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
+     the typedef. In that case TYPE_IDENTIFIER (type) is not the non-qualified
+     identifier  of the TYPENAME_TYPE anymore.
+     So by getting the TYPE_IDENTIFIER of the _main declaration_ of the
+     TYPENAME_TYPE instead, we avoid messing up with a possible
+     typedef variant case.  */
+  name = TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
 
   /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
      it first before we can figure out what NAME refers to.  */
@@ -16617,22 +17318,292 @@ build_non_dependent_expr (tree expr)
   return build1 (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)), expr);
 }
 
-/* ARGS is a TREE_LIST of expressions as arguments to a function call.
-   Return a new TREE_LIST with the various arguments replaced with
-   equivalent non-dependent expressions.  */
+/* ARGS is a vector of expressions as arguments to a function call.
+   Replace the arguments with equivalent non-dependent expressions.
+   This modifies ARGS in place.  */
+
+void
+make_args_non_dependent (VEC(tree,gc) *args)
+{
+  unsigned int ix;
+  tree arg;
+
+  for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+    {
+      tree newarg = build_non_dependent_expr (arg);
+      if (newarg != arg)
+       VEC_replace (tree, args, ix, newarg);
+    }
+}
+
+/* Returns a type which represents 'auto'.  We use a TEMPLATE_TYPE_PARM
+   with a level one deeper than the actual template parms.  */
 
 tree
-build_non_dependent_args (tree args)
+make_auto (void)
 {
-  tree a;
-  tree new_args;
+  tree au;
+
+  /* ??? Is it worth caching this for multiple autos at the same level?  */
+  au = cxx_make_type (TEMPLATE_TYPE_PARM);
+  TYPE_NAME (au) = build_decl (BUILTINS_LOCATION,
+                              TYPE_DECL, get_identifier ("auto"), au);
+  TYPE_STUB_DECL (au) = TYPE_NAME (au);
+  TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
+    (0, processing_template_decl + 1, processing_template_decl + 1,
+     TYPE_NAME (au), NULL_TREE);
+  TYPE_CANONICAL (au) = canonical_type_parameter (au);
+  DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
+  SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
+
+  return au;
+}
+
+/* Replace auto in TYPE with std::initializer_list<auto>.  */
 
-  new_args = NULL_TREE;
-  for (a = args; a; a = TREE_CHAIN (a))
-    new_args = tree_cons (NULL_TREE,
-                         build_non_dependent_expr (TREE_VALUE (a)),
-                         new_args);
-  return nreverse (new_args);
+static tree
+listify_autos (tree type, tree auto_node)
+{
+  tree std_init_list = namespace_binding
+    (get_identifier ("initializer_list"), std_node);
+  tree argvec;
+  tree init_auto;
+  if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
+    {    
+      error ("deducing auto from brace-enclosed initializer list requires "
+            "#include <initializer_list>");
+      return error_mark_node;
+    }
+  argvec = make_tree_vec (1);
+  TREE_VEC_ELT (argvec, 0) = auto_node;
+  init_auto = lookup_template_class (std_init_list, argvec, NULL_TREE,
+                                    NULL_TREE, 0, tf_warning_or_error);
+
+  TREE_VEC_ELT (argvec, 0) = init_auto;
+  if (processing_template_decl)
+    argvec = add_to_template_args (current_template_args (), argvec);
+  return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
+}
+
+/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
+   from INIT.  AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE.  */
+
+tree
+do_auto_deduction (tree type, tree init, tree auto_node)
+{
+  tree parms, tparms, targs;
+  tree args[1];
+  int val;
+
+  /* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
+     with either a new invented type template parameter U or, if the
+     initializer is a braced-init-list (8.5.4), with
+     std::initializer_list<U>.  */
+  if (BRACE_ENCLOSED_INITIALIZER_P (init))
+    type = listify_autos (type, auto_node);
+
+  parms = build_tree_list (NULL_TREE, type);
+  args[0] = init;
+  tparms = make_tree_vec (1);
+  targs = make_tree_vec (1);
+  TREE_VEC_ELT (tparms, 0)
+    = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
+  val = type_unification_real (tparms, targs, parms, args, 1, 0,
+                              DEDUCE_CALL, LOOKUP_NORMAL);
+  if (val > 0)
+    {
+      error ("unable to deduce %qT from %qE", type, init);
+      return error_mark_node;
+    }
+
+  if (processing_template_decl)
+    targs = add_to_template_args (current_template_args (), targs);
+  return tsubst (type, targs, tf_warning_or_error, NULL_TREE);
+}
+
+/* Substitutes LATE_RETURN_TYPE for 'auto' in TYPE and returns the
+   result.  */
+
+tree
+splice_late_return_type (tree type, tree late_return_type)
+{
+  tree argvec;
+
+  if (late_return_type == NULL_TREE)
+    return type;
+  argvec = make_tree_vec (1);
+  TREE_VEC_ELT (argvec, 0) = late_return_type;
+  if (processing_template_decl)
+    argvec = add_to_template_args (current_template_args (), argvec);
+  return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
+}
+
+/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto'.  */
+
+bool
+is_auto (const_tree type)
+{
+  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+      && TYPE_IDENTIFIER (type) == get_identifier ("auto"))
+    return true;
+  else
+    return false;
+}
+
+/* Returns true iff TYPE contains a use of 'auto'.  Since auto can only
+   appear as a type-specifier for the declaration in question, we don't
+   have to look through the whole type.  */
+
+tree
+type_uses_auto (tree type)
+{
+  enum tree_code code;
+  if (is_auto (type))
+    return type;
+
+  code = TREE_CODE (type);
+
+  if (code == POINTER_TYPE || code == REFERENCE_TYPE
+      || code == OFFSET_TYPE || code == FUNCTION_TYPE
+      || code == METHOD_TYPE || code == ARRAY_TYPE)
+    return type_uses_auto (TREE_TYPE (type));
+
+  if (TYPE_PTRMEMFUNC_P (type))
+    return type_uses_auto (TREE_TYPE (TREE_TYPE
+                                  (TYPE_PTRMEMFUNC_FN_TYPE (type))));
+
+  return NULL_TREE;
+}
+
+/* For a given template T, return the list of typedefs referenced
+   in T for which access check is needed at T instantiation time.
+   T is either  a FUNCTION_DECL or a RECORD_TYPE.
+   Those typedefs were added to T by the function
+   append_type_to_template_for_access_check.  */
+
+tree
+get_types_needing_access_check (tree t)
+{
+  tree ti, result = NULL_TREE;
+
+  if (!t || t == error_mark_node)
+    return t;
+
+  if (!(ti = get_template_info (t)))
+    return NULL_TREE;
+
+  if (CLASS_TYPE_P (t)
+      || TREE_CODE (t) == FUNCTION_DECL)
+    {
+      if (!TI_TEMPLATE (ti))
+       return NULL_TREE;
+
+      result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
+    }
+
+  return result;
+}
+
+/* Append the typedef TYPE_DECL used in template T to a list of typedefs
+   tied to T. That list of typedefs will be access checked at
+   T instantiation time.
+   T is either a FUNCTION_DECL or a RECORD_TYPE.
+   TYPE_DECL is a TYPE_DECL node representing a typedef.
+   SCOPE is the scope through which TYPE_DECL is accessed.
+
+   This function is a subroutine of
+   append_type_to_template_for_access_check.  */
+
+static void
+append_type_to_template_for_access_check_1 (tree t,
+                                           tree type_decl,
+                                           tree scope)
+{
+  tree ti;
+
+  if (!t || t == error_mark_node)
+    return;
+
+  gcc_assert ((TREE_CODE (t) == FUNCTION_DECL
+              || CLASS_TYPE_P (t))
+             && type_decl
+             && TREE_CODE (type_decl) == TYPE_DECL
+             && scope);
+
+  if (!(ti = get_template_info (t)))
+    return;
+
+  gcc_assert (TI_TEMPLATE (ti));
+
+  TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti) =
+    tree_cons (type_decl, scope, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti));
+}
+
+/* Append TYPE_DECL to the template TEMPL.
+   TEMPL is either a class type, a FUNCTION_DECL or a a TEMPLATE_DECL.
+   At TEMPL instanciation time, TYPE_DECL will be checked to see
+   if it can be accessed through SCOPE.
+
+   e.g. consider the following code snippet:
+
+     class C
+     {
+       typedef int myint;
+     };
+
+     template<class U> struct S
+     {
+       C::myint mi;
+     };
+
+     S<char> s;
+
+   At S<char> instantiation time, we need to check the access of C::myint
+   In other words, we need to check the access of the myint typedef through
+   the C scope. For that purpose, this function will add the myint typedef
+   and the scope C through which its being accessed to a list of typedefs
+   tied to the template S. That list will be walked at template instantiation
+   time and access check performed on each typedefs it contains.
+   Note that this particular code snippet should yield an error because
+   myint is private to C.  */
+
+void
+append_type_to_template_for_access_check (tree templ,
+                                          tree type_decl,
+                                         tree scope)
+{
+  tree node;
+
+  gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
+
+  /* Make sure we don't append the type to the template twice.  */
+  for (node = get_types_needing_access_check (templ);
+       node;
+       node = TREE_CHAIN (node))
+    {
+      tree decl = TREE_PURPOSE (node);
+      tree type_scope = TREE_VALUE (node);
+
+      if (decl == type_decl && type_scope == scope)
+       return;
+    }
+
+  append_type_to_template_for_access_check_1 (templ, type_decl, scope);
+}
+
+/* Set up the hash tables for template instantiations.  */
+
+void
+init_template_processing (void)
+{
+  decl_specializations = htab_create_ggc (37,
+                                         hash_specialization,
+                                         eq_specializations,
+                                         ggc_free);
+  type_specializations = htab_create_ggc (37,
+                                         hash_specialization,
+                                         eq_specializations,
+                                         ggc_free);
 }
 
 #include "gt-cp-pt.h"