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
;
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;
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;
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
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);
}
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.
/* 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. */
= 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);
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();
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. */
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 ()
{