OSDN Git Service

gcc/cp/ChangeLog:
[pf3gnuchains/gcc-fork.git] / gcc / cp / pt.c
index 8b2d8c3..de70e53 100644 (file)
@@ -710,8 +710,8 @@ check_specialization_namespace (tree tmpl)
     return true;
   else
     {
-      permerror ("specialization of %qD in different namespace", tmpl);
-      permerror ("  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,7 +728,7 @@ check_explicit_instantiation_namespace (tree spec)
      namespace of its template.  */
   ns = decl_namespace_context (spec);
   if (!is_ancestor (current_namespace, ns))
-    permerror ("explicit instantiation of %qD in namespace %qD "
+    permerror (input_location, "explicit instantiation of %qD in namespace %qD "
               "(which does not enclose namespace %qD)",
               spec, current_namespace, ns);
 }
@@ -811,8 +811,8 @@ maybe_process_partial_specialization (tree type)
          if (current_namespace
              != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
            {
-             permerror ("specializing %q#T in different namespace", type);
-             permerror ("  from definition of %q+#D",
+             permerror (input_location, "specializing %q#T in different namespace", type);
+             permerror (input_location, "  from definition of %q+#D",
                         CLASSTYPE_TI_TEMPLATE (type));
            }
 
@@ -1289,12 +1289,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;
@@ -2006,8 +2002,8 @@ check_explicit_specialization (tree declarator,
       for (; t; t = TREE_CHAIN (t))
        if (TREE_PURPOSE (t))
          {
-           permerror
-             ("default argument specified in explicit specialization");
+           permerror (input_location, 
+                      "default argument specified in explicit specialization");
            break;
          }
     }
@@ -2745,9 +2741,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);
         }
@@ -2813,12 +2809,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;
@@ -2826,7 +2825,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)
@@ -2836,24 +2835,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,
@@ -3292,15 +3292,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:
@@ -3585,7 +3590,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
@@ -3596,6 +3602,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)))
@@ -3749,8 +3758,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)
@@ -4020,7 +4029,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;
@@ -4141,7 +4150,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;
     }
@@ -4187,7 +4196,7 @@ 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);
+         inform (input_location, "%Joriginal definition appeared here", tmpl_parm);
          return false;
        }
 
@@ -4241,7 +4250,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
@@ -4570,7 +4579,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;
        }
 
@@ -4608,7 +4617,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;
        }
     }
@@ -4683,7 +4692,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)))
@@ -4942,7 +4951,7 @@ convert_template_argument (tree parm,
   if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
       && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
     {
-      permerror ("to refer to a type member of a template parameter, "
+      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),
@@ -5055,7 +5064,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
@@ -5228,10 +5249,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.  */
@@ -5239,13 +5256,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
@@ -5292,42 +5318,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;
@@ -5384,6 +5416,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))
@@ -5400,9 +5451,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;
 
@@ -5580,6 +5628,7 @@ lookup_template_class (tree d1,
       d1 = DECL_NAME (templ);
     }
   else if (TREE_CODE (d1) == TEMPLATE_DECL
+           && DECL_TEMPLATE_RESULT (d1)
           && TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
     {
       templ = d1;
@@ -5836,14 +5885,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
        {
@@ -5888,8 +5943,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 (templ);
       if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
        {
          DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
@@ -6338,7 +6391,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;
@@ -6375,6 +6427,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.
 
@@ -6404,7 +6480,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,
@@ -6910,7 +6986,6 @@ instantiate_class_template (tree type)
      if tsubsting causes an error.  */
   typedecl = TYPE_MAIN_DECL (type);
   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);
@@ -7108,7 +7183,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.  */
@@ -7267,7 +7342,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.  */
@@ -8151,7 +8226,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))
@@ -8175,6 +8252,7 @@ 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))
          {
@@ -9552,11 +9630,16 @@ 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),
+       ++skip_evaluation;
+
+       type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args,
+                           complain, in_decl,
+                           /*integral_constant_expression_p=*/false);
+
+       --skip_evaluation;
+
+       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)
@@ -9724,7 +9807,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;
        }
@@ -9792,7 +9875,22 @@ 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)
+       {
+         /* This can happen for a parameter name used later in a function
+            declaration (such as in a late-specified return type).
+            Replace it with an arbitrary expression with the same type
+            (*(T*)0).  This should only occur in an unevaluated context
+            (i.e. decltype).  */
+         gcc_assert (skip_evaluation);
+         r = non_reference (TREE_TYPE (t));
+         r = tsubst (r, args, complain, in_decl);
+         r = build_pointer_type (r);
+         r = build_c_cast (r, null_node);
+         return cp_build_indirect_ref (r, NULL, tf_warning_or_error);
+       }
+      
       if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
        r = ARGUMENT_PACK_SELECT_ARG (r);
       mark_used (r);
@@ -10293,12 +10391,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)))
@@ -10529,8 +10637,7 @@ 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;
                      }
@@ -11052,7 +11159,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:
@@ -11177,7 +11285,7 @@ tsubst_copy_and_build (tree t,
        tree init = RECUR (TREE_OPERAND (t, 3));
 
        if (TREE_OPERAND (t, 3) && !init)
-         /* If there was an initializer in the the original tree, but
+         /* If there was an initializer in 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
@@ -11568,6 +11676,7 @@ 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, r);
@@ -11665,58 +11774,76 @@ tsubst_copy_and_build (tree t,
    Emit an error under control of COMPLAIN, and return TRUE on error.  */
 
 static bool
-check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
+check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
 {
-  int ix, len = DECL_NTPARMS (tmpl);
-  bool result = false;
-
-  for (ix = 0; ix != len; ix++)
+  if (ARGUMENT_PACK_P (t))
     {
-      tree t = TREE_VEC_ELT (args, ix);
+      tree vec = ARGUMENT_PACK_ARGS (t);
+      int len = TREE_VEC_LENGTH (vec);
+      bool result = false;
+      int i;
 
-      if (TYPE_P (t))
+      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))
+    {
+      /* [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)
        {
-         /* [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))
+         /* DR 488 makes use of a type with no linkage cause
+            type deduction to fail.  */
+         if (complain & tf_error)
            {
-             if (complain & tf_error)
-               error ("%qT is a variably modified type", t);
-             result = true;
+             if (TYPE_ANONYMOUS_P (nt))
+               error ("%qT is/uses anonymous type", t);
+             else
+               error ("template argument for %qD uses local type %qT",
+                      tmpl, 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))
+      /* 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 ("integral expression %qE is not constant", t);
-         result = true;
+           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);
+  bool result = false;
+
+  for (ix = 0; ix != len; ix++)
+    {
+      if (check_instantiated_arg (tmpl, TREE_VEC_ELT (args, ix), complain))
+       result = true;
+    }
   if (result && (complain & tf_error))
     error ("  trying to instantiate %qD", tmpl);
   return result;
@@ -13567,7 +13694,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
       /* 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.  */
+        cv-qualified parameter.  */
       if (TREE_CODE (parm) == METHOD_TYPE
          && (!check_cv_quals_for_unify
              (UNIFY_ALLOW_NONE,
@@ -14593,7 +14720,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)
-       permerror ("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)
@@ -14606,7 +14733,7 @@ do_decl_instantiation (tree decl, tree storage)
     }
   else if (!DECL_TEMPLATE_INFO (result))
     {
-      permerror ("explicit instantiation of non-template %q#D", result);
+      permerror (input_location, "explicit instantiation of non-template %q#D", result);
       return;
     }
 
@@ -14614,8 +14741,9 @@ do_decl_instantiation (tree decl, tree storage)
     ;
   else if (storage == ridpointers[(int) RID_EXTERN])
     {
-      if (pedantic && !in_system_header && (cxx_dialect == cxx98))
-       pedwarn ("ISO C++ 1998 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;
     }
@@ -14701,17 +14829,19 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
   if (storage != NULL_TREE)
     {
-      if (pedantic && !in_system_header)
+      if (!in_system_header)
        {
          if (storage == ridpointers[(int) RID_EXTERN])
            {
              if (cxx_dialect == cxx98)
-               pedwarn("ISO C++ 1998 forbids the use of %<extern%> on "
-                       "explicit instantiations");
+               pedwarn (input_location, OPT_pedantic, 
+                        "ISO C++ 1998 forbids the use of %<extern%> on "
+                        "explicit instantiations");
            }
          else
-           pedwarn("ISO C++ forbids the use of %qE on explicit "
-                   "instantiations", storage);
+           pedwarn (input_location, OPT_pedantic, 
+                    "ISO C++ forbids the use of %qE"
+                    " on explicit instantiations", storage);
        }
 
       if (storage == ridpointers[(int) RID_INLINE])
@@ -14756,7 +14886,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
       if (!previous_instantiation_extern_p && !extern_p
          && (complain & tf_error))
-       permerror ("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))
@@ -14923,8 +15053,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) =
@@ -15016,7 +15144,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
@@ -15099,7 +15226,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
@@ -15148,7 +15274,8 @@ instantiate_decl (tree d, int defer_ok,
   if (external_p
       /* ... but we instantiate inline functions so that we can inline
         them and ... */
-      && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
+      && ! (TREE_CODE (d) == FUNCTION_DECL
+           && possibly_inlined_p (d))
       /* ... we instantiate static data members whose values are
         needed in integral constant expressions.  */
       && ! (TREE_CODE (d) == VAR_DECL
@@ -15195,7 +15322,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
@@ -15203,8 +15331,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.  */
-       permerror
-         ("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".  */
@@ -15225,9 +15353,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;
     }
 
@@ -15371,7 +15497,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 ();
 
@@ -15389,7 +15514,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
@@ -15473,7 +15597,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
@@ -15893,7 +16016,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;
     }
 
@@ -16188,6 +16311,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)
@@ -16674,4 +16810,141 @@ build_non_dependent_args (tree args)
   return nreverse (new_args);
 }
 
+/* Returns a type which represents 'auto'.  We use a TEMPLATE_TYPE_PARM
+   with a level one deeper than the actual template parms.  */
+
+tree
+make_auto (void)
+{
+  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 (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>.  */
+
+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, args, tparms, targs;
+  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 = build_tree_list (NULL_TREE, 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, 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;
+}
+
 #include "gt-cp-pt.h"