#include "rtl.h"
#include "defaults.h"
#include "ggc.h"
-#include "hashtab.h"
+#include "timevar.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
extern struct obstack permanent_obstack;
-extern int lineno;
-extern char *input_filename;
-
/* The PENDING_TEMPLATES is a TREE_LIST of templates whose
instantiations have been deferred, either because their definitions
were not yet available, or because we were putting off doing the
static varray_type inline_parm_levels;
static size_t inline_parm_levels_used;
+static tree current_tinst_level;
+
/* A map from local variable declarations in the body of the template
presently being instantiated to the corresponding instantiated
local variables. */
static int unify PARAMS ((tree, tree, tree, tree, int));
static void add_pending_template PARAMS ((tree));
static int push_tinst_level PARAMS ((tree));
+static void reopen_tinst_level PARAMS ((tree));
static tree classtype_mangled_name PARAMS ((tree));
-static char *mangle_class_name_for_template PARAMS ((char *, tree, tree));
-static tree tsubst_expr_values PARAMS ((tree, tree));
+static char *mangle_class_name_for_template PARAMS ((const char *, tree, tree));
+static tree tsubst_initializer_list PARAMS ((tree, tree));
static int list_eq PARAMS ((tree, tree));
static tree get_class_bindings PARAMS ((tree, tree, tree));
static tree coerce_template_parms PARAMS ((tree, tree, tree, int, int));
static tree get_template_base_recursive PARAMS ((tree, tree,
tree, tree, tree, int));
static tree get_template_base PARAMS ((tree, tree, tree, tree));
+static int verify_class_unification PARAMS ((tree, tree, tree));
static tree try_class_unification PARAMS ((tree, tree, tree, tree));
static int coerce_template_template_parms PARAMS ((tree, tree, int,
tree, tree));
static tree determine_specialization PARAMS ((tree, tree, tree *, int));
static int template_args_equal PARAMS ((tree, tree));
-static void print_template_context PARAMS ((int));
static void tsubst_default_arguments PARAMS ((tree));
static tree for_each_template_parm_r PARAMS ((tree *, int *, void *));
static tree instantiate_clone PARAMS ((tree, tree));
ggc_add_tree_root (&pending_templates, 1);
ggc_add_tree_root (&maybe_templates, 1);
ggc_add_tree_root (&saved_trees, 1);
+ ggc_add_tree_root (¤t_tinst_level, 1);
}
/* Do any processing required when DECL (a member template declaration
available. */
tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
TREE_TYPE (parm));
- SET_DECL_ARTIFICIAL (decl);
+ DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = DECL_INITIAL (parm);
SET_DECL_TEMPLATE_PARM_P (decl);
pushdecl (decl);
#endif
/* Return a new template argument vector which contains all of ARGS,
- but has as its innermost set of arguments the EXTRA_ARGS. The
- resulting vector will be built on a temporary obstack, and so must
- be explicitly copied to the permanent obstack, if required. */
+ but has as its innermost set of arguments the EXTRA_ARGS. */
static tree
add_to_template_args (args, extra_args)
return new_args;
}
+/* Return the N levels of innermost template arguments from the ARGS. */
+
+tree
+get_innermost_template_args (args, n)
+ tree args;
+ int n;
+{
+ tree new_args;
+ int extra_levels;
+ int i;
+
+ my_friendly_assert (n >= 0, 20000603);
+
+ /* If N is 1, just return the innermost set of template arguments. */
+ if (n == 1)
+ return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
+
+ /* If we're not removing anything, just return the arguments we were
+ given. */
+ extra_levels = TMPL_ARGS_DEPTH (args) - n;
+ my_friendly_assert (extra_levels >= 0, 20000603);
+ if (extra_levels == 0)
+ return args;
+
+ /* Make a new set of arguments, not containing the outer arguments. */
+ new_args = make_tree_vec (n);
+ for (i = 1; i <= n; ++i)
+ SET_TMPL_ARGS_LEVEL (new_args, i,
+ TMPL_ARGS_LEVEL (args, i + extra_levels));
+
+ return new_args;
+}
+
/* We've got a template header coming up; push to a new level for storing
the parms. */
check_specialization_scope ();
}
-/* Called at then end of processing a declaration preceeded by
+/* Called at then end of processing a declaration preceded by
template<>. */
void
return NULL_TREE;
}
-/* Like retrieve_speciailization, but for local declarations. */
+/* Like retrieve_specialization, but for local declarations. */
static tree
retrieve_local_specialization (tmpl)
t != NULL_TREE;
t = CLASSTYPE_USE_TEMPLATE (t)
? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE)
- if (same_type_p (TYPE_MAIN_VARIANT (t),
- TYPE_MAIN_VARIANT (TREE_TYPE (tmpl))))
+ if (same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (tmpl)))
return 1;
}
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
- cp_error ("template-id `%D' in declaration of primary template",
- declarator);
+ if (uses_template_parms (declarator))
+ cp_error ("partial specialization `%D' of function template",
+ declarator);
+ else
+ cp_error ("template-id `%D' in declaration of primary template",
+ declarator);
return decl;
}
name = is_constructor ? ctor_identifier : dtor_identifier;
}
- if (!IDENTIFIER_TYPENAME_P (name))
+ if (!DECL_CONV_FN_P (decl))
{
idx = lookup_fnfields_1 (ctype, name);
if (idx >= 0)
/* If TMPL is not the most general template (for
example, if TMPL is a friend template that is
injected into namespace scope), then there will
- be too many levels fo TARGS. Remove some of them
+ be too many levels of TARGS. Remove some of them
here. */
int i;
tree new_targs;
return instantiate_template (tmpl, targs);
}
- /* If this is both a template specialization, then it's a
- specialization of a member template of a template class.
- In that case we want to return the TEMPLATE_DECL, not the
- specialization of it. */
+ /* If this is a specialization of a member template of a
+ template class. In we want to return the TEMPLATE_DECL,
+ not the specialization of it. */
if (tsk == tsk_template)
{
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
+ DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE;
return tmpl;
}
{
tree p = TREE_VALUE (tree_last (list));
- if (TREE_CODE (p) == TYPE_DECL)
+ if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
- else if (TREE_CODE (p) == TEMPLATE_DECL)
- idx = TEMPLATE_TYPE_IDX (TREE_TYPE (DECL_TEMPLATE_RESULT (p)));
else
idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
++idx;
processing_template_decl,
decl, TREE_TYPE (parm));
}
- SET_DECL_ARTIFICIAL (decl);
+ DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
pushdecl (decl);
parm = build_tree_list (defval, parm);
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
if (DECL_LANG_SPECIFIC (decl))
{
- DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
+ if (CAN_HAVE_FULL_LANG_DECL_P (decl))
+ DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
+ DECL_ASSIGNMENT_OPERATOR_P (tmpl) = DECL_ASSIGNMENT_OPERATOR_P (decl);
+ if (DECL_OVERLOADED_OPERATOR_P (decl))
+ SET_OVERLOADED_OPERATOR_CODE (tmpl,
+ DECL_OVERLOADED_OPERATOR_P (decl));
}
return tmpl;
tree type = TREE_TYPE (decl);
tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
tree specargs = CLASSTYPE_TI_ARGS (type);
- tree inner_args = innermost_args (specargs);
+ tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
int nargs = TREE_VEC_LENGTH (inner_args);
or some such would have been OK. */
tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
tpd.parms = alloca (sizeof (int) * ntparms);
- bzero ((PTR) tpd.parms, sizeof (int) * ntparms);
+ memset ((PTR) tpd.parms, 0, sizeof (int) * ntparms);
tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs);
- bzero ((PTR) tpd.arg_uses_template_parms, sizeof (int) * nargs);
+ memset ((PTR) tpd.arg_uses_template_parms, 0, sizeof (int) * nargs);
for (i = 0; i < nargs; ++i)
{
tpd.current_arg = i;
if (tpd.parms[i] == 0)
{
/* One of the template parms was not used in the
- specialization. */
+ specialization. */
if (!did_error_intro)
{
cp_error ("template parameters not used in partial specialization:");
The argument list of the specialization shall not be identical to
the implicit argument list of the primary template. */
- if (comp_template_args (inner_args,
- innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE
- (maintmpl)))))
+ if (comp_template_args
+ (inner_args,
+ INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE
+ (maintmpl)))))
cp_error ("partial specialization `%T' does not specialize any template arguments", type);
/* [temp.class.spec]
template, not in the specialization. */
tpd2.current_arg = i;
tpd2.arg_uses_template_parms[i] = 0;
- bzero ((PTR) tpd2.parms, sizeof (int) * nargs);
+ memset ((PTR) tpd2.parms, 0, sizeof (int) * nargs);
for_each_template_parm (type,
&mark_template_parm,
&tpd2);
it is defined. */
ctx = CP_DECL_CONTEXT (decl);
else
- /* Otherwise, if we're currently definining some class, the DECL
+ /* Otherwise, if we're currently defining some class, the DECL
is assumed to be a member of the class. */
ctx = current_scope ();
DECL_TEMPLATE_INFO (new_tmpl)
= tree_cons (tmpl, args, NULL_TREE);
- register_specialization (new_tmpl, tmpl, args);
+ register_specialization (new_tmpl,
+ most_general_template (tmpl),
+ args);
return decl;
}
/* Attempt to convert the non-type template parameter EXPR to the
indicated TYPE. If the conversion is successful, return the
- converted value. If the conversion is unsuccesful, return
+ converted value. If the conversion is unsuccessful, return
NULL_TREE if we issued an error message, or error_mark_node if we
did not. We issue error messages for out-and-out bad template
parameters, but not simply because the conversion failed, since we
tree e = expr;
STRIP_NOPS (e);
- if (TREE_CODE (type) == REFERENCE_TYPE
- || TREE_CODE (expr_type) == ARRAY_TYPE)
+ if (TREE_CODE (expr_type) == ARRAY_TYPE
+ || (TREE_CODE (type) == REFERENCE_TYPE
+ && TREE_CODE (e) != ADDR_EXPR))
referent = e;
else
{
;
else if (TREE_CODE (referent) != VAR_DECL)
goto bad_argument;
- else if (!TREE_PUBLIC (referent))
+ else if (!DECL_EXTERNAL_LINKAGE_P (referent))
{
cp_error ("address of non-extern `%E' cannot be used as template argument", referent);
return error_mark_node;
else
fns = expr;
- fn = instantiate_type (type_pointed_to, fns, 0);
+ fn = instantiate_type (type_pointed_to, fns, itf_none);
if (fn == error_mark_node)
return error_mark_node;
- if (!TREE_PUBLIC (fn))
+ if (!DECL_EXTERNAL_LINKAGE_P (fn))
{
if (really_overloaded_fn (fns))
return error_mark_node;
{
tree type_referred_to = TREE_TYPE (type);
+ /* If this expression already has reference type, get the
+ underling object. */
+ if (TREE_CODE (expr_type) == REFERENCE_TYPE)
+ {
+ my_friendly_assert (TREE_CODE (expr) == ADDR_EXPR, 20000604);
+ expr = TREE_OPERAND (expr, 0);
+ expr_type = TREE_TYPE (expr);
+ }
+
if (TREE_CODE (type_referred_to) == FUNCTION_TYPE)
{
/* For a non-type template-parameter of type reference to
template-argument represents a set of overloaded
functions, the matching function is selected from the
set (_over.over_). */
- tree fns = expr;
tree fn;
- fn = instantiate_type (type_referred_to, fns, 0);
+ fn = instantiate_type (type_referred_to, expr, itf_none);
if (fn == error_mark_node)
return error_mark_node;
- if (!TREE_PUBLIC (fn))
+ if (!DECL_EXTERNAL_LINKAGE_P (fn))
{
- if (really_overloaded_fn (fns))
+ if (really_overloaded_fn (expr))
/* Don't issue an error here; we might get a different
function if the overloading had worked out
differently. */
TREE_TYPE (fn)),
0);
- return fn;
+ expr = fn;
}
else
{
identical) type of the template-argument. The
template-parameter is bound directly to the
template-argument, which must be an lvalue. */
- if ((TYPE_MAIN_VARIANT (expr_type)
- != TYPE_MAIN_VARIANT (type_referred_to))
+ if (!same_type_p (TYPE_MAIN_VARIANT (expr_type),
+ TYPE_MAIN_VARIANT (type_referred_to))
|| !at_least_as_qualified_p (type_referred_to,
expr_type)
|| !real_lvalue_p (expr))
return error_mark_node;
- else
- return expr;
}
+
+ mark_addressable (expr);
+ return build1 (ADDR_EXPR, type, expr);
}
break;
if (TREE_CODE (expr) != ADDR_EXPR)
return error_mark_node;
- expr = instantiate_type (type, expr, 0);
+ expr = instantiate_type (type, expr, itf_none);
if (expr == error_mark_node)
return error_mark_node;
tree inner_args;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
- inner_args = innermost_args (args);
+ inner_args = INNERMOST_TEMPLATE_ARGS (args);
if (TREE_CODE (arg) == TREE_LIST
&& TREE_TYPE (arg) != NULL_TREE
is_tmpl_type
= ((TREE_CODE (arg) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
- || (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
- && !TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (arg))
+ || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| (TREE_CODE (arg) == RECORD_TYPE
&& CLASSTYPE_TEMPLATE_INFO (arg)
&& TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
the standard. Accepting this is not merely an
extension, since deciding whether or not these
conversions can occur is part of determining which
- function template to call, or whether a given epxlicit
+ function template to call, or whether a given explicit
argument specification is legal. */
val = convert_nontype_argument (t, arg);
else
tree new_args;
tree new_inner_args;
- inner_args = innermost_args (args);
+ inner_args = INNERMOST_TEMPLATE_ARGS (args);
nargs = NUM_TMPL_ARGS (inner_args);
nparms = TREE_VEC_LENGTH (parms);
{
if (nt == ot)
return 1;
- if (TREE_CODE (nt) != TREE_CODE (ot))
- return 0;
+
if (TREE_CODE (nt) == TREE_VEC)
/* For member templates */
- return comp_template_args (ot, nt);
- else if (TYPE_P (ot))
- return same_type_p (ot, nt);
+ return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
+ else if (TYPE_P (nt))
+ return TYPE_P (ot) && same_type_p (ot, nt);
+ else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
+ return 0;
else
return (cp_tree_equal (ot, nt) > 0);
}
static char *
mangle_class_name_for_template (name, parms, arglist)
- char *name;
+ const char *name;
tree parms, arglist;
{
static struct obstack scratch_obstack;
cat (name);
ccat ('<');
nparms = TREE_VEC_LENGTH (parms);
- arglist = innermost_args (arglist);
+ arglist = INNERMOST_TEMPLATE_ARGS (arglist);
my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
for (i = 0; i < nparms; i++)
{
if (TREE_CODE (parm) == TYPE_DECL)
{
- cat (type_as_string (arg, TS_CHASE_TYPEDEFS));
+ cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
continue;
}
else if (TREE_CODE (parm) == TEMPLATE_DECL)
my_friendly_assert (TREE_CODE (context) == NAMESPACE_DECL
|| CLASS_TYPE_P (context),
980422);
- cat(decl_as_string (DECL_CONTEXT (arg), 0));
+ cat(decl_as_string (DECL_CONTEXT (arg), TFF_PLAIN_IDENTIFIER));
cat("::");
}
cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
}
else
/* Output the parameter declaration */
- cat (type_as_string (arg, TS_CHASE_TYPEDEFS));
+ cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
continue;
}
else
}
/* No need to check arglist against parmlist here; we did that
in coerce_template_parms, called from lookup_template_class. */
- cat (expr_as_string (arg, 0));
+ cat (expr_as_string (arg, TFF_PLAIN_IDENTIFIER));
}
{
char *bufp = obstack_next_free (&scratch_obstack);
add_pending_template (d)
tree d;
{
- tree ti = (TYPE_P (d)) ? CLASSTYPE_TEMPLATE_INFO (d) : DECL_TEMPLATE_INFO (d);
+ tree ti = (TYPE_P (d)
+ ? CLASSTYPE_TEMPLATE_INFO (d)
+ : DECL_TEMPLATE_INFO (d));
+ int level;
if (TI_PENDING_TEMPLATE_FLAG (ti))
return;
- *template_tail = tree_cons (build_srcloc_here (), d, NULL_TREE);
+ /* We are called both from instantiate_decl, where we've already had a
+ tinst_level pushed, and instantiate_template, where we haven't.
+ Compensate. */
+ level = !(current_tinst_level && TINST_DECL (current_tinst_level) == d);
+
+ if (level)
+ push_tinst_level (d);
+
+ *template_tail = tree_cons (current_tinst_level, d, NULL_TREE);
template_tail = &TREE_CHAIN (*template_tail);
TI_PENDING_TEMPLATE_FLAG (ti) = 1;
+
+ if (level)
+ pop_tinst_level ();
}
D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
(Actually ARGLIST may be either a TREE_LIST or a TREE_VEC. It will
be a TREE_LIST if called directly from the parser, and a TREE_VEC
- otherwise.) Since ARGLIST is build on the temp_decl_obstack, we must
- copy it here to keep it from being reclaimed when the decl storage
- is reclaimed.
+ otherwise.)
IN_DECL, if non-NULL, is the template declaration we are trying to
instantiate.
d1 = DECL_NAME (template);
context = DECL_CONTEXT (template);
}
- else
- my_friendly_abort (272);
/* With something like `template <class T> class X class X { ... };'
we could end up with D1 having nothing but an IDENTIFIER_VALUE.
We don't want to do that, but we have to deal with the situation,
so let's give them some syntax errors to chew on instead of a
- crash. */
+ crash. Alternatively D1 might not be a template type at all. */
if (! template)
{
cp_error ("`%T' is not a template", d1);
return error_mark_node;
}
- if (context == NULL_TREE)
- context = global_namespace;
-
if (TREE_CODE (template) != TEMPLATE_DECL)
{
cp_error ("non-template type `%T' used as a template", d1);
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
template arguments */
- tree parm = copy_template_template_parm (TREE_TYPE (template));
- tree template2 = TYPE_STUB_DECL (parm);
+ tree parm;
tree arglist2;
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
if (arglist2 == error_mark_node)
return error_mark_node;
- TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm)
- = tree_cons (template2, arglist2, NULL_TREE);
+ parm = copy_template_template_parm (TREE_TYPE (template), arglist2);
TYPE_SIZE (parm) = 0;
return parm;
}
else
arglist
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
- innermost_args (arglist),
+ INNERMOST_TEMPLATE_ARGS (arglist),
template, 1, 1);
if (arglist == error_mark_node)
/* Note that we use DECL_CONTEXT, rather than
CP_DECL_CONTEXT, so that the termination test is
- always just `ctx'. We're not interested in namepace
+ always just `ctx'. We're not interested in namespace
scopes. */
for (ctx = current_class_type;
ctx;
found = NULL_TREE;
}
}
-
- if (!found)
- {
- for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
- found; found = TREE_CHAIN (found))
- if (comp_template_args (TREE_PURPOSE (found), arglist))
- break;
-
- if (found)
- found = TREE_VALUE (found);
- }
-
if (found)
- return found;
+ return found;
+
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ found; found = TREE_CHAIN (found))
+ if (comp_template_args (TREE_PURPOSE (found), arglist))
+ return TREE_VALUE (found);
/* This type is a "partial instantiation" if any of the template
- arguments still inolve template parameters. Note that we set
+ arguments still involve template parameters. Note that we set
IS_PARTIAL_INSTANTIATION for partial specializations as
well. */
is_partial_instantiation = uses_template_parms (arglist);
return found;
}
+ context = tsubst (DECL_CONTEXT (template), arglist,
+ /*complain=*/0, in_decl);
+ if (!context)
+ context = global_namespace;
+
/* Create the type. */
if (TREE_CODE (template_type) == ENUMERAL_TYPE)
{
if (!is_partial_instantiation)
- t = start_enum (TYPE_IDENTIFIER (template_type));
+ {
+ set_current_access_from_decl (TYPE_NAME (template_type));
+ t = start_enum (TYPE_IDENTIFIER (template_type));
+ }
else
/* We don't want to call start_enum for this type, since
the values for the enumeration constants may involve
found = template;
else
{
- /* This is a full instantiation of a member template. There
- should be some partial instantiation of which this is an
- instance. */
+ /* This is a full instantiation of a member template. Look
+ for a partial instantiation of which this is an instance. */
for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
found; found = TREE_CHAIN (found))
}
if (!found)
- my_friendly_abort (0);
+ {
+ /* There was no partial instantiation. This happens
+ where C<T> is a member template of A<T> and it's used
+ in something like
+
+ template <typename T> struct B { A<T>::C<int> m; };
+ B<float>;
+
+ Create the partial instantiation.
+ */
+ TREE_VEC_LENGTH (arglist)--;
+ template = tsubst (template, arglist, /*complain=*/0, NULL_TREE);
+ TREE_VEC_LENGTH (arglist)++;
+ found = template;
+ }
}
- SET_TYPE_TEMPLATE_INFO (t,
- tree_cons (found, arglist, NULL_TREE));
+ SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
DECL_TEMPLATE_INSTANTIATIONS (template)
= tree_cons (arglist, t,
DECL_TEMPLATE_INSTANTIATIONS (template));
DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
if (!is_partial_instantiation)
{
- DECL_ASSEMBLER_NAME (type_decl)
- = get_identifier (build_overload_name (t, 1, 1));
+ if (flag_new_abi)
+ DECL_ASSEMBLER_NAME (type_decl) = mangle_decl (type_decl);
+ else
+ DECL_ASSEMBLER_NAME (type_decl)
+ = get_identifier (build_overload_name (t, 1, 1));
/* For backwards compatibility; code that uses
-fexternal-templates expects looking up a template to
switch (TREE_CODE (t))
{
case RECORD_TYPE:
- if (TYPE_PTRMEMFUNC_FLAG (t))
+ if (TYPE_PTRMEMFUNC_P (t))
break;
/* Fall through. */
return error_mark_node;
break;
- case TEMPLATE_TEMPLATE_PARM:
+ case BOUND_TEMPLATE_TEMPLATE_PARM:
/* Record template parameters such as `T' inside `TT<T>'. */
- if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t)
- && for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
+ if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
return error_mark_node;
/* Fall through. */
+ case TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_TYPE_PARM:
case TEMPLATE_PARM_INDEX:
if (fn && (*fn)(t, data))
return NULL_TREE;
}
-/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or
- TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA.
+/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
+ BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T,
+ call FN with the parameter and the DATA.
If FN returns non-zero, the iteration is terminated, and
for_each_template_parm returns 1. Otherwise, the iteration
continues. If FN never returns a non-zero value, the value
pfd.data = data;
/* Walk the tree. */
- return walk_tree (&t, for_each_template_parm_r, &pfd) != NULL_TREE;
+ return walk_tree_without_duplicates (&t,
+ for_each_template_parm_r,
+ &pfd) != NULL_TREE;
}
int
return for_each_template_parm (t, 0, 0);
}
-static struct tinst_level *current_tinst_level;
-static struct tinst_level *free_tinst_level;
static int tinst_depth;
extern int max_tinst_depth;
#ifdef GATHER_STATISTICS
static int tinst_level_tick;
static int last_template_error_tick;
-/* Print out all the template instantiations that we are currently
- working on. If ERR, we are being called from cp_thing, so do
- the right thing for an error message. */
-
-static void
-print_template_context (err)
- int err;
-{
- struct tinst_level *p = current_tinst_level;
- int line = lineno;
- char *file = input_filename;
-
- if (err && p)
- {
- if (current_function_decl != p->decl
- && current_function_decl != NULL_TREE)
- /* We can get here during the processing of some synthesized
- method. Then, p->decl will be the function that's causing
- the synthesis. */
- ;
- else
- {
- if (current_function_decl == p->decl)
- /* Avoid redundancy with the the "In function" line. */;
- else
- fprintf (stderr, "%s: In instantiation of `%s':\n",
- file, decl_as_string (p->decl, TS_DECL_TYPE | TS_FUNC_NORETURN));
-
- line = p->line;
- file = p->file;
- p = p->next;
- }
- }
-
- for (; p; p = p->next)
- {
- fprintf (stderr, "%s:%d: instantiated from `%s'\n", file, line,
- decl_as_string (p->decl, TS_DECL_TYPE | TS_FUNC_NORETURN));
- line = p->line;
- file = p->file;
- }
- fprintf (stderr, "%s:%d: instantiated from here\n", file, line);
-}
-
-/* Called from cp_thing to print the template context for an error. */
-
-void
-maybe_print_template_context ()
-{
- if (last_template_error_tick == tinst_level_tick
- || current_tinst_level == 0)
- return;
-
- last_template_error_tick = tinst_level_tick;
- print_template_context (1);
-}
+/* We're starting to instantiate D; record the template instantiation context
+ for diagnostics and to restore it later. */
static int
push_tinst_level (d)
tree d;
{
- struct tinst_level *new;
+ tree new;
if (tinst_depth >= max_tinst_depth)
{
cp_error ("template instantiation depth exceeds maximum of %d (use -ftemplate-depth-NN to increase the maximum) instantiating `%D'",
max_tinst_depth, d);
- print_template_context (0);
+ print_instantiation_context ();
return 0;
}
- if (free_tinst_level)
- {
- new = free_tinst_level;
- free_tinst_level = new->next;
- }
- else
- new = (struct tinst_level *) xmalloc (sizeof (struct tinst_level));
-
- new->decl = d;
- new->line = lineno;
- new->file = input_filename;
- new->next = current_tinst_level;
+ new = build_expr_wfl (d, input_filename, lineno, 0);
+ TREE_CHAIN (new) = current_tinst_level;
current_tinst_level = new;
++tinst_depth;
return 1;
}
+/* We're done instantiating this template; return to the instantiation
+ context. */
+
void
pop_tinst_level ()
{
- struct tinst_level *old = current_tinst_level;
+ tree old = current_tinst_level;
/* Restore the filename and line number stashed away when we started
this instantiation. */
- lineno = old->line;
- input_filename = old->file;
+ lineno = TINST_LINE (old);
+ input_filename = TINST_FILE (old);
extract_interface_info ();
- current_tinst_level = old->next;
- old->next = free_tinst_level;
- free_tinst_level = old;
+ current_tinst_level = TREE_CHAIN (old);
--tinst_depth;
++tinst_level_tick;
}
-struct tinst_level *
+/* We're instantiating a deferred template; restore the template
+ instantiation context in which the instantiation was requested, which
+ is one step out from LEVEL. */
+
+static void
+reopen_tinst_level (level)
+ tree level;
+{
+ tree t;
+
+ tinst_depth = 0;
+ for (t = level; t; t = TREE_CHAIN (t))
+ ++tinst_depth;
+
+ current_tinst_level = level;
+ pop_tinst_level ();
+}
+
+/* Return the outermost template instantiation context, for use with
+ -falt-external-templates. */
+
+tree
tinst_for_decl ()
{
- struct tinst_level *p = current_tinst_level;
+ tree p = current_tinst_level;
if (p)
- for (; p->next ; p = p->next )
+ for (; TREE_CHAIN (p) ; p = TREE_CHAIN (p))
;
return p;
}
/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the
vector of template arguments, as for tsubst.
- Returns an appropriate tsbust'd friend declaration. */
+ Returns an appropriate tsubst'd friend declaration. */
static tree
tsubst_friend_function (decl, args)
{
tree new_friend;
int line = lineno;
- char *file = input_filename;
+ const char *file = input_filename;
lineno = DECL_SOURCE_LINE (decl);
input_filename = DECL_SOURCE_FILE (decl);
function declaration. Now, we have to figure out what
instantiation of what template. */
{
- tree template_id;
+ tree template_id, arglist, fns;
tree new_args;
tree tmpl;
-
- template_id
- = lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
- args, /*complain=*/1,
- NULL_TREE),
- tsubst (DECL_TI_ARGS (decl),
- args, /*complain=*/1,
- NULL_TREE));
+ tree ns = CP_DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));
+
+ /* Friend functions are looked up in the containing namespace scope.
+ We must enter that scope, to avoid finding member functions of the
+ current cless with same name. */
+ push_nested_namespace (ns);
+ fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
+ /*complain=*/1, NULL_TREE);
+ pop_nested_namespace (ns);
+ arglist = tsubst (DECL_TI_ARGS (decl), args,
+ /*complain=*/1, NULL_TREE);
+ template_id = lookup_template_function (fns, arglist);
+
new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
tmpl = determine_specialization (template_id, new_friend,
&new_args,
instantiation of anything. */
DECL_USE_TEMPLATE (new_friend) = 0;
if (TREE_CODE (decl) == TEMPLATE_DECL)
- DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
+ {
+ DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
+ DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
+ = DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
+ }
/* The mangled name for the NEW_FRIEND is incorrect. The call to
tsubst will have resulted in a call to
/* FRIEND_TMPL is a friend TEMPLATE_DECL. ARGS is the vector of
template arguments, as for tsubst.
- Returns an appropriate tsbust'd friend type. */
+ Returns an appropriate tsubst'd friend type or error_mark_node on
+ failure. */
static tree
tsubst_friend_class (friend_tmpl, args)
tree parms
= tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
args, /*complain=*/1);
+ if (!parms)
+ return error_mark_node;
redeclare_class_template (TREE_TYPE (tmpl), parms);
friend_type = TREE_TYPE (tmpl);
}
TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
TYPE_METHODS (type) = TYPE_METHODS (pattern);
CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
+ CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
+
/* Pretend that the type is complete, so that we will look
inside it during name lookup and such. */
TYPE_SIZE (type) = bitsize_zero_node;
= TYPE_USES_VIRTUAL_BASECLASSES (pattern);
TYPE_PACKED (type) = TYPE_PACKED (pattern);
TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
+ TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (pattern);
TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
if (ANON_AGGR_TYPE_P (pattern))
SET_ANON_AGGR_TYPE_P (type);
pbase = TREE_VEC_ELT (pbases, i);
- /* Substitue to figure out the base class. */
+ /* Substitute to figure out the base class. */
base = tsubst (BINFO_TYPE (pbase), args,
/*complain=*/1, NULL_TREE);
if (base == error_mark_node)
/* Now that our base classes are set up, enter the scope of the
class, so that name lookups into base classes, etc. will work
- corectly. This is precisely analagous to what we do in
+ correctly. This is precisely analogous to what we do in
begin_class_definition when defining an ordinary non-template
class. */
pushclass (type, 1);
information. */
++processing_template_decl;
- make_friend_class (type, new_friend_type);
+ if (new_friend_type != error_mark_node)
+ make_friend_class (type, new_friend_type);
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
--processing_template_decl;
if (!PRIMARY_TEMPLATE_P (template))
for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) == FUNCTION_DECL
- /* Implicitly generated member functions will not have tmplate
+ /* Implicitly generated member functions will not have template
information; they are not instantiations, but instead are
created "fresh" for each instantiation. */
&& DECL_TEMPLATE_INFO (t))
return arg;
}
-/* Return the TREE_VEC with the arguments for the innermost template header,
- where ARGS is either that or the VEC of VECs for all the
- arguments. */
-
-tree
-innermost_args (args)
- tree args;
-{
- return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
-}
-
/* Substitute ARGS into the vector of template arguments T. */
static tree
int len = TREE_VEC_LENGTH (t), need_new = 0, i;
tree *elts = (tree *) alloca (len * sizeof (tree));
- bzero ((char *) elts, len * sizeof (tree));
+ memset ((char *) elts, 0, len * sizeof (tree));
for (i = 0; i < len; i++)
{
(tsubst_expr (TREE_VEC_ELT (t, i), args, complain,
NULL_TREE));
+ if (elts[i] == error_mark_node)
+ return error_mark_node;
+
if (elts[i] != TREE_VEC_ELT (t, i))
need_new = 1;
}
type T. If T is not an aggregate or enumeration type, it is
handled as if by tsubst. IN_DECL is as for tsubst. If
ENTERING_SCOPE is non-zero, T is the context for a template which
- we are presently tsubst'ing. Return the subsituted value. */
+ we are presently tsubst'ing. Return the substituted value. */
static tree
tsubst_aggr_type (t, args, complain, in_decl, entering_scope)
S we only want {double}. */
argvec = tsubst_template_arg_vector (TYPE_TI_ARGS (t), args,
complain);
+ if (argvec == error_mark_node)
+ return error_mark_node;
r = lookup_template_class (t, argvec, in_decl, context,
entering_scope);
tree in_decl;
{
int saved_lineno;
- char* saved_filename;
+ const char *saved_filename;
tree r = NULL_TREE;
/* Set the filename and linenumber to improve error-reporting. */
if (TREE_CODE (decl) == TYPE_DECL)
break;
- for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
- spec != NULL_TREE;
- spec = TREE_CHAIN (spec))
- {
- /* It helps to consider example here. Consider:
-
- template <class T>
- struct S {
- template <class U>
- void f(U u);
-
- template <>
- void f(T* t) {}
- };
-
- Now, for example, we are instantiating S<int>::f(U u).
- We want to make a template:
-
- template <class U>
- void S<int>::f(U);
-
- It will have a specialization, for the case U = int*, of
- the form:
-
- template <>
- void S<int>::f<int*>(int*);
-
- This specialization will be an instantiation of
- the specialization given in the declaration of S, with
- argument list int*. */
-
- tree fn = TREE_VALUE (spec);
- tree spec_args;
- tree new_fn;
-
- if (!DECL_TEMPLATE_SPECIALIZATION (fn))
- /* Instantiations are on the same list, but they're of
- no concern to us. */
- continue;
-
- if (TREE_CODE (fn) != TEMPLATE_DECL)
- /* A full specialization. There's no need to record
- that here. */
- continue;
-
- spec_args = tsubst (DECL_TI_ARGS (fn), args,
- /*complain=*/1, in_decl);
- new_fn
- = tsubst (DECL_TEMPLATE_RESULT (most_general_template (fn)),
- spec_args, /*complain=*/1, in_decl);
- DECL_TI_TEMPLATE (new_fn) = fn;
- register_specialization (new_fn, r,
- innermost_args (spec_args));
- }
-
/* Record this partial instantiation. */
register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)));
break;
}
- /* Here, we deal with the peculiar case:
+ /* We can see more levels of arguments than parameters if
+ there was a specialization of a member template, like
+ this:
+
+ template <class T> struct S { template <class U> void f(); }
+ template <> template <class U> void S<int>::f(U);
+
+ Here, we'll be substituting into the specialization,
+ because that's where we can find the code we actually
+ want to generate, but we'll have enough arguments for
+ the most general template.
+
+ We also deal with the peculiar case:
template <class T> struct S {
template <class U> friend void f();
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));
if (args_depth > parms_depth
&& !DECL_TEMPLATE_SPECIALIZATION (t))
- {
- my_friendly_assert (DECL_FRIEND_P (t), 0);
-
- if (parms_depth > 1)
- {
- int i;
-
- args = make_tree_vec (parms_depth);
- for (i = 0; i < parms_depth; ++i)
- TREE_VEC_ELT (args, i) =
- TREE_VEC_ELT (args, i + (args_depth - parms_depth));
- }
- else
- args = TREE_VEC_ELT (args, args_depth - parms_depth);
- }
+ args = get_innermost_template_args (args, parms_depth);
}
else
{
/* We do NOT check for matching decls pushed separately at this
point, as they may not represent instantiations of this
template, and in any case are considered separate under the
- discrete model. Instead, see add_maybe_template. */
+ discrete model. */
r = copy_decl (t);
DECL_USE_TEMPLATE (r) = 0;
TREE_TYPE (r) = type;
/*complain=*/1, t,
/*entering_scope=*/1);
- if (member && IDENTIFIER_TYPENAME_P (DECL_NAME (r)))
- /* Type-conversion operator. Reconstruct the name, in
- case it's the name of one of the template's parameters. */
- DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
+ if (member && DECL_CONV_FN_P (r))
+ {
+ /* Type-conversion operator. Reconstruct the name, in
+ case it's the name of one of the template's parameters. */
+ if (flag_new_abi)
+ DECL_NAME (r) = mangle_conv_op_name_for_type (TREE_TYPE (type));
+ else
+ DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
+ }
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,
/*complain=*/1, t);
TREE_CHAIN (r) = NULL_TREE;
DECL_PENDING_INLINE_INFO (r) = 0;
DECL_PENDING_INLINE_P (r) = 0;
+ DECL_SAVED_TREE (r) = NULL_TREE;
TREE_USED (r) = 0;
if (DECL_CLONED_FUNCTION (r))
{
register_specialization (r, gen_tmpl, argvec);
/* Set the mangled name for R. */
- if (DECL_DESTRUCTOR_P (t))
- DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+ if (DECL_DESTRUCTOR_P (t))
+ {
+ if (flag_new_abi)
+ set_mangled_name_for_decl (r);
+ else
+ DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+ }
else
{
/* Instantiations of template functions must be mangled
in_decl);
}
- if (DECL_CONSTRUCTOR_P (r))
+ if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))
{
maybe_retrofit_in_chrg (r);
- grok_ctor_properties (ctx, r);
+ if (DECL_CONSTRUCTOR_P (r))
+ grok_ctor_properties (ctx, r);
+ if (PRIMARY_TEMPLATE_P (gen_tmpl))
+ clone_function_decl(r, /*update_method_vec_p=*/0);
}
- else if (DECL_OVERLOADED_OPERATOR_P (r))
+ else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
}
break;
break;
case TYPE_DECL:
- if (DECL_IMPLICIT_TYPEDEF_P (t))
+ if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+ || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
{
- /* For an implicit typedef, we just want the implicit
- typedef for the tsubst'd type. We've already got the
- tsubst'd type, as TYPE, so we just need it's associated
- declaration. */
- r = TYPE_NAME (type);
- break;
- }
- else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
- || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
- {
- /* For a template type parameter, we don't have to do
- anything special. */
+ /* If this is the canonical decl, we don't have to mess with
+ instantiations, and often we can't (for typename, template
+ type parms and such). Note that TYPE_NAME is not correct for
+ the above test if we've copied the type for a typedef. */
r = TYPE_NAME (type);
break;
}
case VAR_DECL:
{
- tree argvec;
- tree gen_tmpl;
+ tree argvec = NULL_TREE;
+ tree gen_tmpl = NULL_TREE;
tree spec;
- tree tmpl;
+ tree tmpl = NULL_TREE;
tree ctx;
int local_p;
case VOID_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
+ case VECTOR_TYPE:
case BOOLEAN_TYPE:
case INTEGER_CST:
case REAL_CST:
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
+ case BOUND_TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_PARM_INDEX:
{
int idx;
r = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
idx = TEMPLATE_TYPE_IDX (t);
level = TEMPLATE_TYPE_LEVEL (t);
(arg, CP_TYPE_QUALS (arg) | CP_TYPE_QUALS (t),
complain);
}
- else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
- if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
- {
- /* We are processing a type constructed from
- a template template parameter */
- tree argvec = tsubst (TYPE_TI_ARGS (t),
- args, complain, in_decl);
- if (argvec == error_mark_node)
- return error_mark_node;
+ /* We are processing a type constructed from
+ a template template parameter */
+ tree argvec = tsubst (TYPE_TI_ARGS (t),
+ args, complain, in_decl);
+ if (argvec == error_mark_node)
+ return error_mark_node;
- /* We can get a TEMPLATE_TEMPLATE_PARM here when
- we are resolving nested-types in the signature of
- a member function templates.
- Otherwise ARG is a TEMPLATE_DECL and is the real
- template to be instantiated. */
- if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- arg = TYPE_NAME (arg);
-
- r = lookup_template_class (DECL_NAME (arg),
- argvec, in_decl,
- DECL_CONTEXT (arg),
- /*entering_scope=*/0);
- return cp_build_qualified_type_real (r,
- TYPE_QUALS (t),
- complain);
- }
- else
- /* We are processing a template argument list. */
- return arg;
+ /* We can get a TEMPLATE_TEMPLATE_PARM here when
+ we are resolving nested-types in the signature of
+ a member function templates.
+ Otherwise ARG is a TEMPLATE_DECL and is the real
+ template to be instantiated. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_NAME (arg);
+
+ r = lookup_template_class (arg,
+ argvec, in_decl,
+ DECL_CONTEXT (arg),
+ /*entering_scope=*/0);
+ return cp_build_qualified_type_real (r,
+ TYPE_QUALS (t),
+ complain);
}
else
+ /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
return arg;
}
}
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
- r = copy_node (t);
- TEMPLATE_TYPE_PARM_INDEX (r)
- = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
- r, levels);
- TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
- TYPE_MAIN_VARIANT (r) = r;
- TYPE_POINTER_TO (r) = NULL_TREE;
- TYPE_REFERENCE_TO (r) = NULL_TREE;
-
- if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
- && TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
+ case BOUND_TEMPLATE_TEMPLATE_PARM:
+ if (CP_TYPE_QUALS (t))
{
- tree argvec = tsubst (TYPE_TI_ARGS (t), args,
- complain, in_decl);
- if (argvec == error_mark_node)
- return error_mark_node;
+ r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
+ r = cp_build_qualified_type_real (r, CP_TYPE_QUALS (t),
+ complain);
+ }
+ else
+ {
+ r = copy_node (t);
+ TEMPLATE_TYPE_PARM_INDEX (r)
+ = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+ r, levels);
+ TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
+ TYPE_MAIN_VARIANT (r) = r;
+ TYPE_POINTER_TO (r) = NULL_TREE;
+ TYPE_REFERENCE_TO (r) = NULL_TREE;
+
+ if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ {
+ tree argvec = tsubst (TYPE_TI_ARGS (t), args,
+ complain, in_decl);
+ if (argvec == error_mark_node)
+ return error_mark_node;
- TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
- = tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
+ = tree_cons (TYPE_TI_TEMPLATE (t), argvec, NULL_TREE);
+ }
}
break;
|| (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
{
static int last_line = 0;
- static char* last_file = 0;
+ static const char* last_file = 0;
/* We keep track of the last time we issued this error
message to avoid spewing a ton of messages during a
r = build_reference_type (type);
r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
- /* Will this ever be needed for TYPE_..._TO values? */
- layout_type (r);
+ if (r != error_mark_node)
+ /* Will this ever be needed for TYPE_..._TO values? */
+ layout_type (r);
+
return r;
}
case OFFSET_TYPE:
case INTEGER_TYPE:
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
+ case BOUND_TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_PARM_INDEX:
case POINTER_TYPE:
case REFERENCE_TYPE:
return tsubst (t, args, complain, in_decl);
case IDENTIFIER_NODE:
- if (IDENTIFIER_TYPENAME_P (t)
- /* Make sure it's not just a variable named `__opr', for instance,
- which can occur in some existing code. */
- && TREE_TYPE (t))
- return build_typename_overload
- (tsubst (TREE_TYPE (t), args, complain, in_decl));
+ if (IDENTIFIER_TYPENAME_P (t))
+ {
+ tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (flag_new_abi)
+ return mangle_conv_op_name_for_type (new_type);
+ else
+ return (build_typename_overload (new_type));
+ }
else
return t;
}
case VA_ARG_EXPR:
- return build_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
+ return build_x_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
in_decl),
tsubst (TREE_TYPE (t), args, complain, in_decl));
break;
case CTOR_INITIALIZER:
- prep_stmt (t);
- current_member_init_list
- = tsubst_expr_values (TREE_OPERAND (t, 0), args);
- current_base_init_list
- = tsubst_expr_values (TREE_OPERAND (t, 1), args);
- setup_vtbl_ptr ();
- tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
- break;
+ {
+ tree member_init_list;
+ tree base_init_list;
+
+ prep_stmt (t);
+ member_init_list
+ = tsubst_initializer_list (TREE_OPERAND (t, 0), args);
+ base_init_list
+ = tsubst_initializer_list (TREE_OPERAND (t, 1), args);
+ setup_vtbl_ptr (member_init_list, base_init_list);
+ tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
+ break;
+ }
case RETURN_STMT:
prep_stmt (t);
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl);
- if (init)
- DECL_INITIAL (decl) = error_mark_node;
- /* By marking the declaration as instantiated, we avoid
- trying to instantiate it. Since instantiate_decl can't
- handle local variables, and since we've already done
- all that needs to be done, that's the right thing to
- do. */
- if (TREE_CODE (decl) == VAR_DECL)
- DECL_TEMPLATE_INSTANTIATED (decl) = 1;
- maybe_push_decl (decl);
- cp_finish_decl (decl, init, NULL_TREE, 0);
+ if (decl != error_mark_node)
+ {
+ if (TREE_CODE (decl) != TYPE_DECL)
+ /* Make sure the type is instantiated now. */
+ complete_type (TREE_TYPE (decl));
+ if (init)
+ DECL_INITIAL (decl) = error_mark_node;
+ /* By marking the declaration as instantiated, we avoid
+ trying to instantiate it. Since instantiate_decl can't
+ handle local variables, and since we've already done
+ all that needs to be done, that's the right thing to
+ do. */
+ if (TREE_CODE (decl) == VAR_DECL)
+ DECL_TEMPLATE_INSTANTIATED (decl) = 1;
+ maybe_push_decl (decl);
+ cp_finish_decl (decl, init, NULL_TREE, 0);
+ }
}
return decl;
}
tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
finish_for_expr (tmp, stmt);
tsubst_expr (FOR_BODY (t), args, complain, in_decl);
- finish_for_stmt (tmp, stmt);
+ finish_for_stmt (stmt);
}
break;
val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
finish_switch_cond (val, stmt);
tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
- finish_switch_stmt (val, stmt);
+ finish_switch_stmt (stmt);
}
break;
case CASE_LABEL:
prep_stmt (t);
finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl),
- tsubst_expr (CASE_HIGH (t), args, complain, in_decl));
+ tsubst_expr (CASE_HIGH (t), args, complain,
+ in_decl));
break;
case LABEL_STMT:
instantiate_template (tmpl, targ_ptr)
tree tmpl, targ_ptr;
{
+ tree clone;
tree fndecl;
tree gen_tmpl;
tree spec;
if (spec != NULL_TREE)
return spec;
- if (DECL_TEMPLATE_INFO (tmpl) && !DECL_TEMPLATE_SPECIALIZATION (tmpl))
+ gen_tmpl = most_general_template (tmpl);
+ if (tmpl != gen_tmpl)
{
/* The TMPL is a partial instantiation. To get a full set of
arguments we must add the arguments used to perform the
partial instantiation. */
targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
targ_ptr);
- gen_tmpl = most_general_template (tmpl);
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, targ_ptr);
if (spec != NULL_TREE)
return spec;
}
- else
- gen_tmpl = tmpl;
len = DECL_NTPARMS (gen_tmpl);
- inner_args = innermost_args (targ_ptr);
+ inner_args = INNERMOST_TEMPLATE_ARGS (targ_ptr);
i = len;
while (i--)
{
if (flag_external_templates)
add_pending_template (fndecl);
+ /* If we've just instantiated the main entry point for a function,
+ instantiate all the alternate entry points as well. */
+ for (clone = TREE_CHAIN (gen_tmpl);
+ clone && DECL_CLONED_FUNCTION_P (clone);
+ clone = TREE_CHAIN (clone))
+ instantiate_template (clone, targ_ptr);
+
return fndecl;
}
return;
decl = build_decl (TYPE_DECL, id, type);
- SET_DECL_ARTIFICIAL (decl);
+ DECL_ARTIFICIAL (decl) = 1;
pushdecl_class_level (decl);
}
sections are symmetric. PARM is the type of a function parameter
or the return type of the conversion function. ARG is the type of
the argument passed to the call, or the type of the value
- intialized with the result of the conversion function. */
+ initialized with the result of the conversion function. */
static void
maybe_adjust_types_for_deduction (strict, parm, arg)
*parm = TREE_TYPE (*parm);
}
-/* Like type_unfication.
+/* Like type_unification.
If SUBR is 1, we're being called recursively (to unify the
arguments of a function or method parameter of a function
if (!subr)
maybe_adjust_types_for_deduction (strict, &parm, &arg);
- switch (unify (tparms, targs, parm, arg, sub_strict))
- {
- case 0:
- break;
- case 1:
- return 1;
- }
+ if (unify (tparms, targs, parm, arg, sub_strict))
+ return 1;
}
/* Fail if we've reached the end of the parm list, and more args
are present, and the parm list isn't variadic. */
return 1;
}
+/* Verify that nondeduce template argument agrees with the type
+ obtained from argument deduction. Return nonzero if the
+ verification fails.
+
+ For example:
+
+ struct A { typedef int X; };
+ template <class T, class U> struct C {};
+ template <class T> struct C<T, typename T::X> {};
+
+ Then with the instantiation `C<A, int>', we can deduce that
+ `T' is `A' but unify () does not check whether `typename T::X'
+ is `int'. This function ensure that they agree.
+
+ TARGS, PARMS are the same as the arguments of unify.
+ ARGS contains template arguments from all levels. */
+
+static int
+verify_class_unification (targs, parms, args)
+ tree targs, parms, args;
+{
+ int i;
+ int nparms = TREE_VEC_LENGTH (parms);
+ tree new_parms = tsubst (parms, add_outermost_template_args (args, targs),
+ /*complain=*/0, NULL_TREE);
+ if (new_parms == error_mark_node)
+ return 1;
+
+ args = INNERMOST_TEMPLATE_ARGS (args);
+
+ for (i = 0; i < nparms; i++)
+ {
+ tree parm = TREE_VEC_ELT (new_parms, i);
+ tree arg = TREE_VEC_ELT (args, i);
+
+ /* In case we are deducing from a function argument of a function
+ templates, some parameters may not be deduced yet. So we
+ make sure that only fully substituted elements of PARM are
+ compared below. */
+
+ if (!uses_template_parms (parm) && !template_args_equal (parm, arg))
+ return 1;
+ }
+ return 0;
+}
+
/* PARM is a template class (perhaps with unbound template
parameters). ARG is a fully instantiated type. If ARG can be
bound to PARM, return ARG, otherwise return NULL_TREE. TPARMS and
tree parm;
tree arg;
{
- int i;
tree copy_of_targs;
if (!CLASSTYPE_TEMPLATE_INFO (arg)
with S<I, I, I>. If we kept the already deduced knowledge, we
would reject the possibility I=1. */
copy_of_targs = make_tree_vec (TREE_VEC_LENGTH (targs));
- i = unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE);
/* If unification failed, we're done. */
- if (i != 0)
+ if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
+ CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
return NULL_TREE;
- else
- return arg;
+
+ return arg;
}
/* Subroutine of get_template_base. RVAL, if non-NULL, is a base we
- have alreay discovered to be satisfactory. ARG_BINFO is the binfo
+ have already discovered to be satisfactory. ARG_BINFO is the binfo
for the base class of ARG that we are currently examining. */
static tree
}
/* Takes parameters as for type_unification. Returns 0 if the
- type deduction suceeds, 1 otherwise. The parameter STRICT is a
+ type deduction succeeds, 1 otherwise. The parameter STRICT is a
bitwise or of the following flags:
UNIFY_ALLOW_NONE:
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
+ case BOUND_TEMPLATE_TEMPLATE_PARM:
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
if (TEMPLATE_TYPE_LEVEL (parm)
&& TREE_CODE (tparm) != TEMPLATE_DECL))
return 1;
- if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
+ if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
- if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm))
- {
- /* We arrive here when PARM does not involve template
- specialization. */
+ /* ARG must be constructed from a template class. */
+ if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
+ return 1;
- /* ARG must be constructed from a template class. */
- if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
- return 1;
+ {
+ tree parmtmpl = TYPE_TI_TEMPLATE (parm);
+ tree parmvec = TYPE_TI_ARGS (parm);
+ tree argvec = CLASSTYPE_TI_ARGS (arg);
+ tree argtmplvec
+ = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
+ int i;
- {
- tree parmtmpl = TYPE_TI_TEMPLATE (parm);
- tree parmvec = TYPE_TI_ARGS (parm);
- tree argvec = CLASSTYPE_TI_ARGS (arg);
- tree argtmplvec
- = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
- int i;
-
- /* The parameter and argument roles have to be switched here
- in order to handle default arguments properly. For example,
- template<template <class> class TT> void f(TT<int>)
- should be able to accept vector<int> which comes from
- template <class T, class Allocator = allocator>
- class vector. */
-
- if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
- == error_mark_node)
- return 1;
+ /* The parameter and argument roles have to be switched here
+ in order to handle default arguments properly. For example,
+ template<template <class> class TT> void f(TT<int>)
+ should be able to accept vector<int> which comes from
+ template <class T, class Allocator = allocator>
+ class vector. */
+
+ if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
+ == error_mark_node)
+ return 1;
- /* Deduce arguments T, i from TT<T> or TT<i>.
- We check each element of PARMVEC and ARGVEC individually
- rather than the whole TREE_VEC since they can have
- different number of elements. */
+ /* Deduce arguments T, i from TT<T> or TT<i>.
+ We check each element of PARMVEC and ARGVEC individually
+ rather than the whole TREE_VEC since they can have
+ different number of elements. */
- for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
- {
- tree t = TREE_VEC_ELT (parmvec, i);
+ for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
+ {
+ tree t = TREE_VEC_ELT (parmvec, i);
- if (unify (tparms, targs, t,
- TREE_VEC_ELT (argvec, i),
- UNIFY_ALLOW_NONE))
- return 1;
- }
+ if (unify (tparms, targs, t,
+ TREE_VEC_ELT (argvec, i),
+ UNIFY_ALLOW_NONE))
+ return 1;
}
- arg = CLASSTYPE_TI_TEMPLATE (arg);
- }
+ }
+ arg = CLASSTYPE_TI_TEMPLATE (arg);
+
+ /* Fall through to deduce template name. */
+ }
+
+ if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ {
+ /* Deduce template name TT from TT, TT<>, TT<T> and TT<i>. */
+
+ /* Simple cases: Value already set, does match or doesn't. */
+ if (targ != NULL_TREE && template_args_equal (targ, arg))
+ return 0;
+ else if (targ)
+ return 1;
}
else
{
/*complain=*/0);
if (arg == error_mark_node)
return 1;
- }
- /* Simple cases: Value already set, does match or doesn't. */
- if (targ != NULL_TREE && same_type_p (targ, arg))
- return 0;
- else if (targ)
- return 1;
+ /* Simple cases: Value already set, does match or doesn't. */
+ if (targ != NULL_TREE && same_type_p (targ, arg))
+ return 0;
+ else if (targ)
+ return 1;
+ }
/* Make sure that ARG is not a variable-sized array. (Note that
were talking about variable-sized arrays (like `int[n]'),
parameter-list and, if the corresponding template-argument is
deduced, the template-argument type shall match the type of the
template-parameter exactly, except that a template-argument
- deduced from an array bound may be of any integral type. */
- if (same_type_p (TREE_TYPE (arg), TREE_TYPE (parm)))
+ deduced from an array bound may be of any integral type.
+ The non-type parameter might use already deduced type parameters. */
+ if (same_type_p (TREE_TYPE (arg),
+ tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE)))
/* OK */;
else if ((strict & UNIFY_ALLOW_INTEGER)
&& (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
case REAL_TYPE:
case COMPLEX_TYPE:
+ case VECTOR_TYPE:
case INTEGER_TYPE:
case BOOLEAN_TYPE:
case VOID_TYPE:
TYPE_MAX_VALUE (arg), UNIFY_ALLOW_INTEGER))
return 1;
}
- /* We use the TYPE_MAIN_VARIANT since we have already
- checked cv-qualification at the top of the
+ /* We have already checked cv-qualification at the top of the
function. */
- else if (!same_type_p (TYPE_MAIN_VARIANT (arg),
- TYPE_MAIN_VARIANT (parm)))
+ else if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
return 1;
/* As far as unification is concerned, this wins. Later checks
return 1;
if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
return 1;
- for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
+ for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
if (unify (tparms, targs,
TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
UNIFY_ALLOW_NONE))
Then, we should unify `int' and `U'. */
t = arg;
else
- /* There's no chance of unication succeeding. */
+ /* There's no chance of unification succeeding. */
return 1;
return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
}
- else if (!same_type_p (TYPE_MAIN_VARIANT (parm),
- TYPE_MAIN_VARIANT (arg)))
+ else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
return 1;
return 0;
default:
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
- /* We're looking at an expression. This can happen with
- something like:
+ {
+
+ /* We're looking at an expression. This can happen with
+ something like:
- template <int I>
- void foo(S<I>, S<I + 2>);
+ template <int I>
+ void foo(S<I>, S<I + 2>);
- This is a "nondeduced context":
+ This is a "nondeduced context":
- [deduct.type]
+ [deduct.type]
- The nondeduced contexts are:
+ The nondeduced contexts are:
- --A type that is a template-id in which one or more of
- the template-arguments is an expression that references
- a template-parameter.
+ --A type that is a template-id in which one or more of
+ the template-arguments is an expression that references
+ a template-parameter.
- In these cases, we assume deduction succeeded, but don't
- actually infer any unifications. */
- return 0;
+ In these cases, we assume deduction succeeded, but don't
+ actually infer any unifications. */
+
+ if (!uses_template_parms (parm)
+ && !template_args_equal (parm, arg))
+ return 1;
+ else
+ return 0;
+ }
else
sorry ("use of `%s' in template type unification",
tree_code_name [(int) TREE_CODE (parm)]);
set correctly by tsubst. */
TREE_PUBLIC (result) = 1;
+ /* We used to set this unconditionally; we moved that to
+ do_decl_instantiation so it wouldn't get set on members of
+ explicit class template instantiations. But we still need to set
+ it here for the 'extern template' case in order to suppress
+ implicit instantiations. */
+ if (extern_p)
+ SET_DECL_EXPLICIT_INSTANTIATION (result);
+
if (! extern_p)
{
DECL_INTERFACE_KNOWN (result) = 1;
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_tree_vec (ntparms);
- args = innermost_args (args);
-
- if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE))
+ if (unify (tparms, vec, parms, INNERMOST_TEMPLATE_ARGS (args),
+ UNIFY_ALLOW_NONE))
return NULL_TREE;
for (i = 0; i < ntparms; ++i)
if (! TREE_VEC_ELT (vec, i))
return NULL_TREE;
+ if (verify_class_unification (vec, parms, args))
+ return NULL_TREE;
+
return vec;
}
/* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
Pick the most specialized template, and return the corresponding
instantiation, or if there is no corresponding instantiation, the
- template itself. EXPLICIT_ARGS is any template arguments explicity
+ template itself. EXPLICIT_ARGS is any template arguments explicitly
mentioned in a template-id. If there is no most specialized
template, error_mark_node is returned. If there are no templates
at all, NULL_TREE is returned. */
}
/* If DECL is a specialization of some template, return the most
- general such template. For example, given:
+ general such template. Otherwise, returns NULL_TREE.
+
+ For example, given:
template <class T> struct S { template <class U> void f(U); };
most_general_template (decl)
tree decl;
{
- while (DECL_TEMPLATE_INFO (decl)
- && !(TREE_CODE (decl) == TEMPLATE_DECL
- && DECL_TEMPLATE_SPECIALIZATION (decl))
- /* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or
- IDENTIFIER_NODE in some cases. (See cp-tree.h for
- details.) */
- && TREE_CODE (DECL_TI_TEMPLATE (decl)) == TEMPLATE_DECL)
- decl = DECL_TI_TEMPLATE (decl);
+ /* If DECL is a FUNCTION_DECL, find the TEMPLATE_DECL of which it is
+ an immediate specialization. */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (DECL_TEMPLATE_INFO (decl)) {
+ decl = DECL_TI_TEMPLATE (decl);
+
+ /* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE for a
+ template friend. */
+ if (TREE_CODE (decl) != TEMPLATE_DECL)
+ return NULL_TREE;
+ } else
+ return NULL_TREE;
+ }
+
+ /* Look for more and more general templates. */
+ while (DECL_TEMPLATE_INFO (decl))
+ {
+ /* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or IDENTIFIER_NODE
+ in some cases. (See cp-tree.h for details.) */
+ if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
+ break;
+
+ /* Stop if we run into an explicitly specialized class template. */
+ if (!DECL_NAMESPACE_SCOPE_P (decl)
+ && DECL_CONTEXT (decl)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (DECL_CONTEXT (decl)))
+ break;
+
+ decl = DECL_TI_TEMPLATE (decl);
+ }
return decl;
}
= get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
if (spec_args)
{
- list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
+ list = tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
TREE_TYPE (list) = TREE_TYPE (t);
}
}
int extern_p = 0;
if (!decl)
- /* An error ocurred, for which grokdeclarator has already issued
+ /* An error occurred, for which grokdeclarator has already issued
an appropriate message. */
return;
else if (! DECL_LANG_SPECIFIC (decl))
We check DECL_INTERFACE_KNOWN so as not to complain when the first
instantiation was `extern' and the second is not, and EXTERN_P for
the opposite case. If -frepo, chances are we already got marked
- as an explicit instantion because of the repo file. */
+ as an explicit instantiation because of the repo file. */
if (DECL_INTERFACE_KNOWN (result) && !extern_p && !flag_use_repository)
cp_pedwarn ("duplicate explicit instantiation of `%#D'", result);
}
}
+/* Perform an explicit instantiation of template class T. STORAGE, if
+ non-null, is the RID for extern, inline or static. COMPLAIN is
+ non-zero if this is called from the parser, zero if called recursively,
+ since the standard is unclear (as detailed below). */
+
void
-do_type_instantiation (t, storage)
+do_type_instantiation (t, storage, complain)
tree t, storage;
+ int complain;
{
int extern_p = 0;
int nomem_p = 0;
if (!COMPLETE_TYPE_P (t))
{
- cp_error ("explicit instantiation of `%#T' before definition of template",
- t);
+ if (complain)
+ cp_error ("explicit instantiation of `%#T' before definition of template",
+ t);
return;
}
No program shall both explicitly instantiate and explicitly
specialize a template. */
- cp_error ("explicit instantiation of `%#T' after", t);
- cp_error_at ("explicit specialization here", t);
+ if (complain)
+ {
+ cp_error ("explicit instantiation of `%#T' after", t);
+ cp_error_at ("explicit specialization here", t);
+ }
return;
}
else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t))
was `extern'. If EXTERN_P then the second is. If -frepo, chances
are we already got marked as an explicit instantion because of the
repo file. All these cases are OK. */
- if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository)
+ if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository
+ && complain)
cp_pedwarn ("duplicate explicit instantiation of `%#T'", t);
/* If we've already instantiated the template, just return now. */
Of course, we can't instantiate member template classes, since
we don't have any arguments for them. Note that the standard
- is unclear on whether the instatiation of the members are
+ is unclear on whether the instantiation of the members are
*explicit* instantiations or not. We choose to be generous,
and not set DECL_EXPLICIT_INSTANTIATION. Therefore, we allow
the explicit instantiation of a class where some of the members
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
if (IS_AGGR_TYPE (TREE_VALUE (tmp))
&& !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
- do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
+ do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage, 0);
}
}
tree decl;
tree tmpl;
{
+ /* The most general version of TMPL. */
+ tree gen_tmpl;
+ /* The arguments used to instantiate DECL, from the most general
+ template. */
tree args;
tree code_pattern;
tree new_decl;
- tree gen_tmpl;
int unregistered;
args = DECL_TI_ARGS (decl);
DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
DECL_ASSEMBLER_NAME (new_decl) = DECL_ASSEMBLER_NAME (decl);
DECL_RTL (new_decl) = DECL_RTL (decl);
+ DECL_USE_TEMPLATE (new_decl) = DECL_USE_TEMPLATE (decl);
/* Call duplicate decls to merge the old and new declarations. */
duplicate_decls (new_decl, decl);
tree gen_tmpl;
int pattern_defined;
int line = lineno;
- char *file = input_filename;
+ const char *file = input_filename;
/* This function should only be used to instantiate templates for
functions and static member variables. */
if (DECL_TEMPLATE_INSTANTIATED (d))
/* D has already been instantiated. It might seem reasonable to
- check whether or not D is an explict instantiation, and, if so,
+ check whether or not D is an explicit instantiation, and, if so,
stop here. But when an explicit instantiation is deferred
until the end of the compilation, DECL_EXPLICIT_INSTANTIATION
is set, even though we still need to do the instantiation. */
if (! push_tinst_level (d))
return d;
+ timevar_push (TV_PARSE);
+
/* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
for the instantiation. This is not always the most general
template. Consider, for example:
and an instantiation of S<double>::f<int>. We want TD to be the
specialization S<T>::f<int>, not the more general S<T>::f<U>. */
td = tmpl;
- for (td = tmpl;
- /* An instantiation cannot have a definition, so we need a
- more general template. */
- DECL_TEMPLATE_INSTANTIATION (td)
- /* We must also deal with friend templates. Given:
-
- template <class T> struct S {
- template <class U> friend void f() {};
- };
-
- S<int>::f<U> say, is not an instantiation of S<T>::f<U>,
- so far as the language is concerned, but that's still
- where we get the pattern for the instantiation from. On
- ther hand, if the definition comes outside the class, say:
-
- template <class T> struct S {
- template <class U> friend void f();
- };
- template <class U> friend void f() {}
-
- we don't need to look any further. That's what the check for
- DECL_INITIAL is for. */
- || (TREE_CODE (d) == FUNCTION_DECL
- && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td)
- && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td)));
- )
+ while (/* An instantiation cannot have a definition, so we need a
+ more general template. */
+ DECL_TEMPLATE_INSTANTIATION (td)
+ /* We must also deal with friend templates. Given:
+
+ template <class T> struct S {
+ template <class U> friend void f() {};
+ };
+
+ S<int>::f<U> say, is not an instantiation of S<T>::f<U>,
+ so far as the language is concerned, but that's still
+ where we get the pattern for the instantiation from. On
+ other hand, if the definition comes outside the class, say:
+
+ template <class T> struct S {
+ template <class U> friend void f();
+ };
+ template <class U> friend void f() {}
+
+ we don't need to look any further. That's what the check for
+ DECL_INITIAL is for. */
+ || (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td)
+ && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td))))
{
/* The present template, TD, should not be a definition. If it
were a definition, we should be using it! Note that we
import_export_decl (d);
}
- /* Reject all external templates except inline functions. */
- if (DECL_INTERFACE_KNOWN (d)
- && ! DECL_NOT_REALLY_EXTERN (d)
- && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
- goto out;
-
/* We need to set up DECL_INITIAL regardless of pattern_defined if
the variable is a static const initialized in the class body. */
if (TREE_CODE (d) == VAR_DECL
&& DECL_INITIAL (d) == NULL_TREE
&& DECL_INITIAL (code_pattern) != NULL_TREE)
;
+ /* Reject all external templates except inline functions. */
+ else if (DECL_INTERFACE_KNOWN (d)
+ && ! DECL_NOT_REALLY_EXTERN (d)
+ && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
+ goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. We restore the source position here
because it's used by add_pending_template. */
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
+ htab_t saved_local_specializations;
+
+ /* Save away the current list, in case we are instantiating one
+ template from within the body of another. */
+ saved_local_specializations = local_specializations;
+
/* Set up the list of local specializations. */
- my_friendly_assert (local_specializations == NULL, 20000422);
local_specializations = htab_create (37,
htab_hash_pointer,
htab_eq_pointer,
/* Set up context. */
start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
- store_parm_decls ();
/* We already set up __FUNCTION__, etc., so we don't want to do
it again now. */
- current_function_name_declared = 1;
+ function_name_declared_p = 1;
/* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
/* We don't need the local specializations any more. */
htab_delete (local_specializations);
- local_specializations = NULL;
+ local_specializations = saved_local_specializations;
/* Finish the function. */
expand_body (finish_function (0));
pop_from_top_level ();
pop_tinst_level ();
+ timevar_pop (TV_PARSE);
+
return d;
}
t = &pending_templates;
while (*t)
{
- tree srcloc = TREE_PURPOSE (*t);
tree instantiation = TREE_VALUE (*t);
- input_filename = SRCLOC_FILE (srcloc);
- lineno = SRCLOC_LINE (srcloc);
+ reopen_tinst_level (TREE_PURPOSE (*t));
if (TYPE_P (instantiation))
{
else
t = &TREE_CHAIN (*t);
}
+ tinst_depth = 0;
+ current_tinst_level = NULL_TREE;
}
template_tail = t;
return instantiated_something;
}
-/* Substitute ARGVEC into T, which is a TREE_LIST. In particular, it
- is an initializer list: the TREE_PURPOSEs are DECLs, and the
- TREE_VALUEs are initializer values. Used by instantiate_decl. */
+/* Substitute ARGVEC into T, which is a list of initializers for
+ either base class or a non-static data member. The TREE_PURPOSEs
+ are DECLs, and the TREE_VALUEs are the initializer values. Used by
+ instantiate_decl. */
static tree
-tsubst_expr_values (t, argvec)
+tsubst_initializer_list (t, argvec)
tree t, argvec;
{
tree first = NULL_TREE;
for (; t; t = TREE_CHAIN (t))
{
- tree pur = tsubst_copy (TREE_PURPOSE (t), argvec,
- /*complain=*/1, NULL_TREE);
- tree val = tsubst_expr (TREE_VALUE (t), argvec, /*complain=*/1,
- NULL_TREE);
- *p = build_tree_list (pur, val);
- p = &TREE_CHAIN (*p);
- }
- return first;
-}
+ tree decl;
+ tree init;
+ tree val;
-/* D is an undefined function declaration in the presence of templates with
- the same name, listed in FNS. If one of them can produce D as an
- instantiation, remember this so we can instantiate it at EOF if D has
- not been defined by that time. */
-
-void
-add_maybe_template (d, fns)
- tree d, fns;
-{
- tree t;
+ decl = tsubst_copy (TREE_PURPOSE (t), argvec, /*complain=*/1,
+ NULL_TREE);
+ init = tsubst_expr (TREE_VALUE (t), argvec, /*complain=*/1,
+ NULL_TREE);
- if (DECL_MAYBE_TEMPLATE (d))
- return;
+ if (!init)
+ ;
+ else if (TREE_CODE (init) == TREE_LIST)
+ for (val = init; val; val = TREE_CHAIN (val))
+ TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val));
+ else
+ init = convert_from_reference (init);
- t = most_specialized (fns, d, NULL_TREE);
- if (! t)
- return;
- if (t == error_mark_node)
- {
- cp_error ("ambiguous template instantiation for `%D'", d);
- return;
+ *p = build_tree_list (decl, init);
+ p = &TREE_CHAIN (*p);
}
-
- *maybe_template_tail = tree_cons (t, d, NULL_TREE);
- maybe_template_tail = &TREE_CHAIN (*maybe_template_tail);
- DECL_MAYBE_TEMPLATE (d) = 1;
+ return first;
}
/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
}
finish_enum (newtag);
+ DECL_SOURCE_LINE (TYPE_NAME (newtag)) = DECL_SOURCE_LINE (TYPE_NAME (tag));
+ DECL_SOURCE_FILE (TYPE_NAME (newtag)) = DECL_SOURCE_FILE (TYPE_NAME (tag));
+}
+
+/* DECL is a FUNCTION_DECL that is a template specialization. Return
+ its type -- but without substituting the innermost set of template
+ arguments. So, innermost set of template parameters will appear in
+ the type. If CONTEXTP is non-NULL, then the partially substituted
+ DECL_CONTEXT (if any) will also be filled in. Similarly, TPARMSP
+ will be filled in with the substituted template parameters, if it
+ is non-NULL. */
+
+tree
+get_mostly_instantiated_function_type (decl, contextp, tparmsp)
+ tree decl;
+ tree *contextp;
+ tree *tparmsp;
+{
+ tree context = NULL_TREE;
+ tree fn_type;
+ tree tmpl;
+ tree targs;
+ tree tparms;
+ int parm_depth;
+
+ tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+ targs = DECL_TI_ARGS (decl);
+ tparms = DECL_TEMPLATE_PARMS (tmpl);
+ parm_depth = TMPL_PARMS_DEPTH (tparms);
+
+ /* There should be as many levels of arguments as there are levels
+ of parameters. */
+ my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
+
+ fn_type = TREE_TYPE (tmpl);
+ if (DECL_STATIC_FUNCTION_P (decl))
+ context = DECL_CONTEXT (decl);
+
+ if (parm_depth == 1)
+ /* No substitution is necessary. */
+ ;
+ else
+ {
+ int i;
+ tree partial_args;
+
+ /* Replace the innermost level of the TARGS with NULL_TREEs to
+ let tsubst know not to substitute for those parameters. */
+ partial_args = make_tree_vec (TREE_VEC_LENGTH (targs));
+ for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
+ SET_TMPL_ARGS_LEVEL (partial_args, i,
+ TMPL_ARGS_LEVEL (targs, i));
+ SET_TMPL_ARGS_LEVEL (partial_args,
+ TMPL_ARGS_DEPTH (targs),
+ make_tree_vec (DECL_NTPARMS (tmpl)));
+
+ /* Now, do the (partial) substitution to figure out the
+ appropriate function type. */
+ fn_type = tsubst (fn_type, partial_args, /*complain=*/1, NULL_TREE);
+ if (DECL_STATIC_FUNCTION_P (decl))
+ context = tsubst (context, partial_args, /*complain=*/1, NULL_TREE);
+
+ /* Substitute into the template parameters to obtain the real
+ innermost set of parameters. This step is important if the
+ innermost set of template parameters contains value
+ parameters whose types depend on outer template parameters. */
+ TREE_VEC_LENGTH (partial_args)--;
+ tparms = tsubst_template_parms (tparms, partial_args, /*complain=*/1);
+ }
+
+ if (contextp)
+ *contextp = context;
+ if (tparmsp)
+ *tparmsp = tparms;
+
+ return fn_type;
}
/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
set_mangled_name_for_template_decl (decl)
tree decl;
{
- tree saved_namespace;
tree context = NULL_TREE;
tree fn_type;
tree ret_type;
tree parm_types;
tree tparms;
tree targs;
- tree tmpl;
- int parm_depth;
my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL, 0);
my_friendly_assert (DECL_TEMPLATE_INFO (decl) != NULL_TREE, 0);
+ /* Under the new ABI, we don't need special machinery. */
+ if (flag_new_abi)
+ {
+ set_mangled_name_for_decl (decl);
+ return;
+ }
+
/* The names of template functions must be mangled so as to indicate
what template is being specialized with what template arguments.
For example, each of the following three functions must get
mangle the name of such an entity. */
return;
- tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
- tparms = DECL_TEMPLATE_PARMS (tmpl);
- parm_depth = TMPL_PARMS_DEPTH (tparms);
-
- /* There should be as many levels of arguments as there are levels
- of parameters. */
- my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
-
/* We now compute the PARMS and RET_TYPE to give to
build_decl_overload_real. The PARMS and RET_TYPE are the
parameter and return types of the template, after all but the
{int, U}. Thus, the args that we want to subsitute into the
return and parameter type for the function are those in TARGS,
with the innermost level omitted. */
- fn_type = TREE_TYPE (tmpl);
- if (DECL_STATIC_FUNCTION_P (decl))
- context = DECL_CONTEXT (decl);
-
- if (parm_depth == 1)
- /* No substitution is necessary. */
- ;
- else
- {
- int i;
- tree partial_args;
-
- /* Replace the innermost level of the TARGS with NULL_TREEs to
- let tsubst know not to subsitute for those parameters. */
- partial_args = make_tree_vec (TREE_VEC_LENGTH (targs));
- for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
- SET_TMPL_ARGS_LEVEL (partial_args, i,
- TMPL_ARGS_LEVEL (targs, i));
- SET_TMPL_ARGS_LEVEL (partial_args,
- TMPL_ARGS_DEPTH (targs),
- make_tree_vec (DECL_NTPARMS (tmpl)));
-
- /* Now, do the (partial) substitution to figure out the
- appropriate function type. */
- fn_type = tsubst (fn_type, partial_args, /*complain=*/1, NULL_TREE);
- if (DECL_STATIC_FUNCTION_P (decl))
- context = tsubst (context, partial_args, /*complain=*/1, NULL_TREE);
-
- /* Substitute into the template parameters to obtain the real
- innermost set of parameters. This step is important if the
- innermost set of template parameters contains value
- parameters whose types depend on outer template parameters. */
- TREE_VEC_LENGTH (partial_args)--;
- tparms = tsubst_template_parms (tparms, partial_args, /*complain=*/1);
- }
+ fn_type = get_mostly_instantiated_function_type (decl, &context, &tparms);
/* Now, get the innermost parameters and arguments, and figure out
the parameter and return types. */
tparms = INNERMOST_TEMPLATE_PARMS (tparms);
- targs = innermost_args (targs);
+ targs = INNERMOST_TEMPLATE_ARGS (targs);
ret_type = TREE_TYPE (fn_type);
parm_types = TYPE_ARG_TYPES (fn_type);
my_friendly_assert (TREE_VEC_LENGTH (tparms) == TREE_VEC_LENGTH (targs),
0);
- /* If the template is in a namespace, we need to put that into the
- mangled name. Unfortunately, build_decl_overload_real does not
- get the decl to mangle, so it relies on the current
- namespace. Therefore, we set that here temporarily. */
- my_friendly_assert (DECL_P (decl), 980702);
- saved_namespace = current_namespace;
- current_namespace = CP_DECL_CONTEXT (decl);
-
- /* Actually set the DCL_ASSEMBLER_NAME. */
+ /* Actually set the DECL_ASSEMBLER_NAME. */
DECL_ASSEMBLER_NAME (decl)
- = build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type,
+ = build_decl_overload_real (decl, parm_types, ret_type,
tparms, targs,
DECL_FUNCTION_MEMBER_P (decl)
- + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
+ + DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl));
+}
+
+/* Return truthvalue if we're processing a template different from
+ the last one involved in diagnostics. */
+int
+problematic_instantiation_changed ()
+{
+ return last_template_error_tick != tinst_level_tick;
+}
+
+/* Remember current template involved in diagnostics. */
+void
+record_last_problematic_instantiation ()
+{
+ last_template_error_tick = tinst_level_tick;
+}
- /* Restore the previously active namespace. */
- current_namespace = saved_namespace;
+tree
+current_instantiation ()
+{
+ return current_tinst_level;
}