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);
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);
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. */
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;
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)
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);
}
}
}
if (current == decl)
current = ctx;
+ else if (current == NULL_TREE)
+ /* Can happen in erroneous input. */
+ break;
else
current = (TYPE_P (current)
? TYPE_CONTEXT (current)
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;
}
}
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;
}
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);
/* 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;
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 ();
/* 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
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;
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. */
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)
/* 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:
{
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;
--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);
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. */
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. */
{
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
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"