#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. */
static varray_type inline_parm_levels;
static size_t inline_parm_levels_used;
-tree current_tinst_level;
+static tree current_tinst_level;
/* A map from local variable declarations in the body of the template
presently being instantiated to the corresponding instantiated
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));
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);
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)
/* 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;
}
/* 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;
{
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);
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;
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 ();
/* 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
;
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;
set (_over.over_). */
tree fn;
- fn = instantiate_type (type_referred_to, expr, 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 (expr))
/* Don't issue an error here; we might get a different
|| !at_least_as_qualified_p (type_referred_to,
expr_type)
|| !real_lvalue_p (expr))
- expr = error_mark_node;
+ return error_mark_node;
}
mark_addressable (expr);
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;
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
{
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;
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);
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;
}
/* 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));
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
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;
-{
- tree p = current_tinst_level;
- int line = lineno;
- const char *file = input_filename;
-
- if (err && p)
- {
- if (current_function_decl != TINST_DECL (p)
- && current_function_decl != NULL_TREE)
- /* We can get here during the processing of some synthesized
- method. Then, TINST_DECL (p) will be the function that's causing
- the synthesis. */
- ;
- else
- {
- if (current_function_decl == TINST_DECL (p))
- /* Avoid redundancy with the the "In function" line. */;
- else
- fprintf (stderr, "%s: In instantiation of `%s':\n",
- file, decl_as_string (TINST_DECL (p),
- TS_DECL_TYPE | TS_FUNC_NORETURN));
-
- line = TINST_LINE (p);
- file = TINST_FILE (p);
- p = TREE_CHAIN (p);
- }
- }
-
- for (; p; p = TREE_CHAIN (p))
- {
- fprintf (stderr, "%s:%d: instantiated from `%s'\n", file, line,
- decl_as_string (TINST_DECL (p),
- TS_DECL_TYPE | TS_FUNC_NORETURN));
- line = TINST_LINE (p);
- file = TINST_FILE (p);
- }
- 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. */
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;
}
/* 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)
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;
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))
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);
template <class T> struct S { template <class U> void f(); }
template <> template <class U> void S<int>::f(U);
- Here, we'll be subtituting into the specialization,
+ 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 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;
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))
{
maybe_retrofit_in_chrg (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 (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
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 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;
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:
}
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 (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:
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),
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)]);
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_tree_vec (ntparms);
- args = INNERMOST_TEMPLATE_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. */
= 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);
}
}
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:
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:
+ other hand, if the definition comes outside the class, say:
template <class T> struct S {
template <class U> friend void f();
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. */
/* 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,
pop_from_top_level ();
pop_tinst_level ();
+ timevar_pop (TV_PARSE);
+
return d;
}
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;
-}
-
-/* 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. */
+ tree decl;
+ tree init;
+ tree val;
-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
tree partial_args;
/* Replace the innermost level of the TARGS with NULL_TREEs to
- let tsubst know not to subsitute for those parameters. */
+ 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,
DECL_FUNCTION_MEMBER_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;
+}
+
+tree
+current_instantiation ()
+{
+ return current_tinst_level;
+}