OSDN Git Service

PR c++/38392
[pf3gnuchains/gcc-fork.git] / gcc / cp / pt.c
index 8b19e2c..1c0e13e 100644 (file)
@@ -119,8 +119,6 @@ static int try_one_overload (tree, tree, tree, tree, tree,
                             unification_kind_t, int, bool);
 static int unify (tree, tree, tree, tree, int);
 static void add_pending_template (tree);
-static int push_tinst_level (tree);
-static void pop_tinst_level (void);
 static tree reopen_tinst_level (struct tinst_level *);
 static tree tsubst_initializer_list (tree, tree);
 static tree get_class_bindings (tree, tree, tree);
@@ -495,6 +493,9 @@ add_to_template_args (tree args, tree extra_args)
   int i;
   int j;
 
+  if (args == NULL_TREE)
+    return extra_args;
+
   extra_depth = TMPL_ARGS_DEPTH (extra_args);
   new_args = make_tree_vec (TMPL_ARGS_DEPTH (args) + extra_depth);
 
@@ -2841,6 +2842,25 @@ get_primary_template_innermost_parameters (const_tree t)
   return parms;
 }
 
+/* Return the template parameters of the LEVELth level from the full list
+   of template parameters PARMS.  */
+
+tree
+get_template_parms_at_level (tree parms, int level)
+{
+  tree p;
+  if (!parms
+      || TREE_CODE (parms) != TREE_LIST
+      || level > TMPL_PARMS_DEPTH (parms))
+    return NULL_TREE;
+
+  for (p = parms; p; p = TREE_CHAIN (p))
+    if (TMPL_PARMS_DEPTH (p) == level)
+      return p;
+
+  return NULL_TREE;
+}
+
 /* Returns the template arguments of T if T is a template instantiation,
    NULL otherwise.  */
 
@@ -3551,6 +3571,9 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
+      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
+       TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
+             current_template_parms;
     }
 
   --processing_template_parmlist;
@@ -3697,15 +3720,17 @@ maybe_update_decl_type (tree orig_type, tree scope)
         TYPENAME_TYPEs and SCOPE_REFs that were previously dependent.  */
       tree args = current_template_args ();
       tree auto_node = type_uses_auto (type);
+      tree pushed;
       if (auto_node)
        {
          tree auto_vec = make_tree_vec (1);
          TREE_VEC_ELT (auto_vec, 0) = auto_node;
          args = add_to_template_args (args, auto_vec);
        }
-      push_scope (scope);
+      pushed = push_scope (scope);
       type = tsubst (type, args, tf_warning_or_error, NULL_TREE);
-      pop_scope (scope);
+      if (pushed)
+       pop_scope (scope);
     }
 
   if (type == error_mark_node)
@@ -3989,16 +4014,19 @@ process_partial_specialization (tree decl)
                          If they are fully specialized in the
                          specialization, that's OK.  */
                       int j;
+                      int count = 0;
                       for (j = 0; j < nargs; ++j)
                         if (tpd2.parms[j] != 0
                             && tpd.arg_uses_template_parms [j])
-                          {
-                            error ("type %qT of template argument %qE depends "
-                                   "on template parameter(s)", 
-                                   type,
-                                   arg);
-                            break;
-                          }
+                          ++count;
+                      if (count != 0)
+                        error_n (input_location, count,
+                                 "type %qT of template argument %qE depends "
+                                 "on a template parameter",
+                                 "type %qT of template argument %qE depends "
+                                 "on template parameters",
+                                 type,
+                                 arg);
                     }
                 }
             }
@@ -4525,6 +4553,9 @@ push_template_decl_real (tree decl, bool is_friend)
 
            if (current == decl)
              current = ctx;
+           else if (current == NULL_TREE)
+             /* Can happen in erroneous input.  */
+             break;
            else
              current = (TYPE_P (current)
                         ? TYPE_CONTEXT (current)
@@ -4596,9 +4627,6 @@ template arguments to %qD do not match original template %qD",
          tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
          if (TREE_CODE (parm) == TEMPLATE_DECL)
            DECL_CONTEXT (parm) = tmpl;
-
-         if (TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM)
-           DECL_CONTEXT (TYPE_NAME (TREE_TYPE (parm))) = tmpl;
        }
     }
 
@@ -4663,10 +4691,14 @@ redeclare_class_template (tree type, tree parms)
 
   if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
     {
-      error ("redeclared with %d template parameter(s)", 
-             TREE_VEC_LENGTH (parms));
-      inform (input_location, "previous declaration %q+D used %d template parameter(s)", 
-             tmpl, TREE_VEC_LENGTH (tmpl_parms));
+      error_n (input_location, TREE_VEC_LENGTH (parms),
+               "redeclared with %d template parameter",
+               "redeclared with %d template parameters",
+               TREE_VEC_LENGTH (parms));
+      inform_n (input_location, TREE_VEC_LENGTH (tmpl_parms),
+                "previous declaration %q+D used %d template parameter",
+                "previous declaration %q+D used %d template parameters",
+                tmpl, TREE_VEC_LENGTH (tmpl_parms));
       return false;
     }
 
@@ -4682,22 +4714,24 @@ redeclare_class_template (tree type, tree parms)
         continue;
 
       tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i));
+      if (tmpl_parm == error_mark_node)
+       return false;
+
       parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
       tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i));
       parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
 
       /* TMPL_PARM and PARM can be either TYPE_DECL, PARM_DECL, or
         TEMPLATE_DECL.  */
-      if (tmpl_parm != error_mark_node
-         && (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
-             || (TREE_CODE (tmpl_parm) != TYPE_DECL
-                 && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))
-             || (TREE_CODE (tmpl_parm) != PARM_DECL
-                 && (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (tmpl_parm))
-                     != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))))
-             || (TREE_CODE (tmpl_parm) == PARM_DECL
-                 && (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (tmpl_parm))
-                     != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))))))
+      if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)
+         || (TREE_CODE (tmpl_parm) != TYPE_DECL
+             && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))
+         || (TREE_CODE (tmpl_parm) != PARM_DECL
+             && (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (tmpl_parm))
+                 != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))))
+         || (TREE_CODE (tmpl_parm) == PARM_DECL
+             && (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (tmpl_parm))
+                 != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))))
        {
          error ("template parameter %q+#D", tmpl_parm);
          error ("redeclared here as %q#D", parm);
@@ -7011,7 +7045,7 @@ static int last_template_error_tick;
 /* We're starting to instantiate D; record the template instantiation context
    for diagnostics and to restore it later.  */
 
-static int
+int
 push_tinst_level (tree d)
 {
   struct tinst_level *new_level;
@@ -7026,7 +7060,7 @@ push_tinst_level (tree d)
 
       last_template_error_tick = tinst_level_tick;
       error ("template instantiation depth exceeds maximum of %d (use "
-            "-ftemplate-depth-NN to increase the maximum) instantiating %qD",
+            "-ftemplate-depth= to increase the maximum) instantiating %qD",
             max_tinst_depth, d);
 
       print_instantiation_context ();
@@ -7054,7 +7088,7 @@ push_tinst_level (tree d)
 /* We're done instantiating this template; return to the instantiation
    context.  */
 
-static void
+void
 pop_tinst_level (void)
 {
   /* Restore the filename and line number stashed away when we started
@@ -7296,11 +7330,18 @@ tsubst_friend_function (tree decl, tree args)
              DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
 
              if (TREE_CODE (old_decl) != TEMPLATE_DECL)
-               /* We should have called reregister_specialization in
-                  duplicate_decls.  */
-               gcc_assert (retrieve_specialization (new_template,
-                                                    new_args, 0)
-                           == old_decl);
+               {
+                 /* We should have called reregister_specialization in
+                    duplicate_decls.  */
+                 gcc_assert (retrieve_specialization (new_template,
+                                                      new_args, 0)
+                             == old_decl);
+
+                 /* Instantiate it if the global has already been used.  */
+                 if (DECL_ODR_USED (old_decl))
+                   instantiate_decl (old_decl, /*defer_ok=*/true,
+                                     /*expl_inst_class_mem_p=*/false);
+               }
              else
                {
                  tree t;
@@ -8986,7 +9027,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
               specialize R.  */
            gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
            argvec = tsubst_template_args (DECL_TI_ARGS
-                                          (DECL_TEMPLATE_RESULT (gen_tmpl)),
+                                          (DECL_TEMPLATE_RESULT
+                                                 (DECL_TI_TEMPLATE (t))),
                                           args, complain, in_decl);
 
            /* Check to see if we already have this specialization.  */
@@ -9914,6 +9956,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
   if (type
       && TREE_CODE (t) != TYPENAME_TYPE
+      && TREE_CODE (t) != TEMPLATE_TYPE_PARM
       && TREE_CODE (t) != IDENTIFIER_NODE
       && TREE_CODE (t) != FUNCTION_TYPE
       && TREE_CODE (t) != METHOD_TYPE)
@@ -15028,6 +15071,13 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
       /* Matched cases are handled by the ARG == PARM test above.  */
       return 1;
 
+    case VAR_DECL:
+      /* A non-type template parameter that is a variable should be a
+        an integral constant, in which case, it whould have been
+        folded into its (constant) value. So we should not be getting
+        a variable here.  */
+      gcc_unreachable ();
+
     case TYPE_ARGUMENT_PACK:
     case NONTYPE_ARGUMENT_PACK:
       {
@@ -15437,13 +15487,10 @@ more_specialized_fn (tree pat1, tree pat2, int len)
         than the type from the parameter template (as described above)
         that type is considered to be more specialized than the other. If
         neither type is more cv-qualified than the other then neither type
-        is more specialized than the other."
+        is more specialized than the other."  */
 
-         We check same_type_p explicitly because deduction can also succeed
-         in both directions when there is a nondeduced context.  */
       if (deduce1 && deduce2
-         && quals1 != quals2 && quals1 >= 0 && quals2 >= 0
-         && same_type_p (arg1, arg2))
+         && quals1 != quals2 && quals1 >= 0 && quals2 >= 0)
        {
          if ((quals1 & quals2) == quals2)
            lose2 = true;
@@ -15910,6 +15957,18 @@ most_specialized_class (tree type, tree tmpl)
 
          --processing_template_decl;
        }
+
+      partial_spec_args =
+         coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+                                add_to_template_args (outer_args,
+                                                      partial_spec_args),
+                                tmpl, tf_none,
+                                /*require_all_args=*/true,
+                                /*use_default_args=*/true);
+
+      if (partial_spec_args == error_mark_node)
+       return error_mark_node;
+
       spec_args = get_class_bindings (parms,
                                      partial_spec_args,
                                      args);
@@ -16860,7 +16919,7 @@ instantiate_pending_templates (int retries)
 
       error ("template instantiation depth exceeds maximum of %d"
             " instantiating %q+D, possibly from virtual table generation"
-            " (use -ftemplate-depth-NN to increase the maximum)",
+            " (use -ftemplate-depth= to increase the maximum)",
             max_tinst_depth, decl);
       if (TREE_CODE (decl) == FUNCTION_DECL)
        /* Pretend that we defined it.  */
@@ -18233,6 +18292,20 @@ listify_autos (tree type, tree auto_node)
   return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
 }
 
+/* walk_tree helper for do_auto_deduction.  */
+
+static tree
+contains_auto_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+                void *type)
+{
+  /* Is this a variable with the type we're looking for?  */
+  if (DECL_P (*tp)
+      && TREE_TYPE (*tp) == type)
+    return *tp;
+  else
+    return 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.  */
 
@@ -18241,8 +18314,19 @@ do_auto_deduction (tree type, tree init, tree auto_node)
 {
   tree parms, tparms, targs;
   tree args[1];
+  tree decl;
   int val;
 
+  /* The name of the object being declared shall not appear in the
+     initializer expression.  */
+  decl = cp_walk_tree_without_duplicates (&init, contains_auto_r, type);
+  if (decl)
+    {
+      error ("variable %q#D with %<auto%> type used in its own "
+            "initializer", decl);
+      return error_mark_node;
+    }
+
   /* [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
@@ -18477,4 +18561,19 @@ init_template_processing (void)
                                          ggc_free);
 }
 
+/* Print stats about the template hash tables for -fstats.  */
+
+void
+print_template_statistics (void)
+{
+  fprintf (stderr, "decl_specializations: size %ld, %ld elements, "
+          "%f collisions\n", (long) htab_size (decl_specializations),
+          (long) htab_elements (decl_specializations),
+          htab_collisions (decl_specializations));
+  fprintf (stderr, "type_specializations: size %ld, %ld elements, "
+          "%f collisions\n", (long) htab_size (type_specializations),
+          (long) htab_elements (type_specializations),
+          htab_collisions (type_specializations));
+}
+
 #include "gt-cp-pt.h"