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));
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)
/* 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;
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
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);
}
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.
/* 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);
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 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,
/* FRIEND_TMPL is a friend TEMPLATE_DECL. ARGS is the vector of
template arguments, as for tsubst.
- Returns an appropriate tsbust'd friend type or error_mark_node on
+ Returns an appropriate tsubst'd friend type or error_mark_node on
failure. */
static tree
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);
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++)
{
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)
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;
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));
case VOID_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
+ case VECTOR_TYPE:
case BOOLEAN_TYPE:
case INTEGER_CST:
case REAL_CST:
init = tsubst_expr (init, args, complain, in_decl);
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
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
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 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. */
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);
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
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. */
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();
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. */
-
-void
-add_maybe_template (d, fns)
- tree d, fns;
-{
- tree t;
-
- if (DECL_MAYBE_TEMPLATE (d))
- return;
-
- t = most_specialized (fns, d, NULL_TREE);
- if (! t)
- return;
- if (t == error_mark_node)
- {
- cp_error ("ambiguous template instantiation for `%D'", d);
- return;
- }
-
- *maybe_template_tail = tree_cons (t, d, NULL_TREE);
- maybe_template_tail = &TREE_CHAIN (*maybe_template_tail);
- DECL_MAYBE_TEMPLATE (d) = 1;
-}
-
/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
static void
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,
}
/* Return truthvalue if we're processing a template different from
- the last one involved in diagnotics. */
+ the last one involved in diagnostics. */
int
problematic_instantiation_changed ()
{