Commit f9a7ae04 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment.

	* cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment.
	(INNERMOST_TEMPLATE_ARGS): New macro.
	(innermost_args): Remove.
	(get_innermost_template_args): New function.
	* decl2.c (arg_assoc_class): Use INNERMOST_TEMPLATE_ARGS.
	* error.c (dump_function_decl): Be caution when using
	most_general_template.
	* method.c (build_template_parm_names):  Use
	INNERMOST_TEMPLATE_ARGS.
	* pt.c (add_to_template_args): Tidy comment
	(get_innermost_template_args): New function.
	(check_explicit_specialization): Clear DECL_INITIAL for a new
	specialization.
	(process_partial_specialization): Use INNERMOST_TEMPLATE_ARGS.
	Tidy.
	(push_template_decl): Always register specializations of the most
	general template.
	(convert_template_argument): Use INNERMOST_TEMPLATE_ARGS.
	(coerce_template_parms): Likewise.
	(lookup_template_class): Likewise.
	(innermost_args): Remove.
	(tsubst_decl): Use INNERMOST_TEMPLATE_ARGS.
	(tsubst_decl): Handle tricky specializations.  Use
	get_innermost_template_args.
	(instantiate_template): Simplify handling of partial
	instantiations.
	(get_class_bindings): Use INNERMOST_TEMPLATE_ARGS.
	(most_general_template): Reimplement, in a more straightforward
	manner.
	(regenerate_decl_from_template): Tweak formatting.  Use
	TMPL_ARGS_DEPTH for clarity.
	(set_mangled_name_for_template_decl): Use INNERMOST_ARGS.

	* dump.c (dequeue_and_dump): Dump information about thunks.

From-SVN: r34384
parent 22ad5966
2000-06-03 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment.
(INNERMOST_TEMPLATE_ARGS): New macro.
(innermost_args): Remove.
(get_innermost_template_args): New function.
* decl2.c (arg_assoc_class): Use INNERMOST_TEMPLATE_ARGS.
* error.c (dump_function_decl): Be caution when using
most_general_template.
* method.c (build_template_parm_names): Use
INNERMOST_TEMPLATE_ARGS.
* pt.c (add_to_template_args): Tidy comment
(get_innermost_template_args): New function.
(check_explicit_specialization): Clear DECL_INITIAL for a new
specialization.
(process_partial_specialization): Use INNERMOST_TEMPLATE_ARGS.
Tidy.
(push_template_decl): Always register specializations of the most
general template.
(convert_template_argument): Use INNERMOST_TEMPLATE_ARGS.
(coerce_template_parms): Likewise.
(lookup_template_class): Likewise.
(innermost_args): Remove.
(tsubst_decl): Use INNERMOST_TEMPLATE_ARGS.
(tsubst_decl): Handle tricky specializations. Use
get_innermost_template_args.
(instantiate_template): Simplify handling of partial
instantiations.
(get_class_bindings): Use INNERMOST_TEMPLATE_ARGS.
(most_general_template): Reimplement, in a more straightforward
manner.
(regenerate_decl_from_template): Tweak formatting. Use
TMPL_ARGS_DEPTH for clarity.
(set_mangled_name_for_template_decl): Use INNERMOST_ARGS.
* dump.c (dequeue_and_dump): Dump information about thunks.
2000-06-02 Jason Merrill <jason@casey.soma.redhat.com>
* exception.cc (__cp_pop_exception): If we aren't popping or
......
......@@ -2325,8 +2325,8 @@ struct lang_decl
#define TMPL_ARGS_DEPTH(NODE) \
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)
/* The LEVELth level of the template ARGS. Note that template
parameter levels are indexed from 1, not from 0. */
/* The LEVELth level of the template ARGS. The outermost level of of
args is level 1, not level 0. */
#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \
? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS)
......@@ -2352,6 +2352,10 @@ struct lang_decl
: (TREE_CODE (NODE) == TREE_VEC \
? TREE_VEC_LENGTH (NODE) : list_length (NODE)))
/* Returns the innermost level of template arguments in ARGS. */
#define INNERMOST_TEMPLATE_ARGS(NODE) \
(get_innermost_template_args ((NODE), 1))
/* The number of levels of template parameters given by NODE. */
#define TMPL_PARMS_DEPTH(NODE) \
(TREE_INT_CST_HIGH (TREE_PURPOSE (NODE)))
......@@ -4298,7 +4302,7 @@ extern int maybe_clone_body PARAMS ((tree));
/* in pt.c */
extern void init_pt PARAMS ((void));
extern void check_template_shadow PARAMS ((tree));
extern tree innermost_args PARAMS ((tree));
extern tree get_innermost_template_args PARAMS ((tree, int));
extern tree tsubst PARAMS ((tree, tree, int, tree));
extern tree tsubst_expr PARAMS ((tree, tree, int, tree));
extern tree tsubst_copy PARAMS ((tree, tree, int, tree));
......
......@@ -4798,7 +4798,7 @@ arg_assoc_class (k, type)
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
{
list = innermost_args (CLASSTYPE_TI_ARGS (type));
list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
}
......
......@@ -578,6 +578,13 @@ dequeue_and_dump (di)
dump_string (di, "operator");
if (DECL_CONV_FN_P (t))
dump_string (di, "conversion");
if (DECL_THUNK_P (t))
{
dump_string (di, "thunk");
dump_int (di, "dlta", THUNK_DELTA (t));
dump_int (di, "vcll", THUNK_VCALL_OFFSET (t));
dump_child ("fn", DECL_INITIAL (t));
}
if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
{
if (DECL_GLOBAL_CTOR_P (t))
......
......@@ -1111,10 +1111,15 @@ dump_function_decl (t, flags)
/* Pretty print template instantiations only. */
if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
{
tree tmpl;
template_args = DECL_TI_ARGS (t);
t = most_general_template (t);
if (TREE_CODE (t) == TEMPLATE_DECL)
template_parms = DECL_TEMPLATE_PARMS (t);
tmpl = most_general_template (t);
if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL)
{
template_parms = DECL_TEMPLATE_PARMS (tmpl);
t = tmpl;
}
}
fntype = TREE_TYPE (t);
......
......@@ -945,7 +945,7 @@ build_template_parm_names (parmlist, arglist)
tree arglist;
{
int i, nparms;
tree inner_args = innermost_args (arglist);
tree inner_args = INNERMOST_TEMPLATE_ARGS (arglist);
nparms = TREE_VEC_LENGTH (parmlist);
icat (nparms);
......
......@@ -474,9 +474,7 @@ is_member_template_class (t)
#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)
......@@ -535,6 +533,39 @@ add_outermost_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. */
......@@ -1484,13 +1515,13 @@ check_explicit_specialization (declarator, decl, template_count, flags)
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;
}
......@@ -2025,7 +2056,7 @@ process_partial_specialization (decl)
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);
......@@ -2082,7 +2113,7 @@ process_partial_specialization (decl)
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:");
......@@ -2097,9 +2128,10 @@ process_partial_specialization (decl)
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]
......@@ -2502,7 +2534,9 @@ push_template_decl_real (decl, is_friend)
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;
}
......@@ -3124,7 +3158,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
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
......@@ -3322,7 +3356,7 @@ coerce_template_parms (parms, args, in_decl,
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);
......@@ -3469,7 +3503,7 @@ mangle_class_name_for_template (name, parms, arglist)
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++)
{
......@@ -3824,7 +3858,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
else
arglist
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
innermost_args (arglist),
INNERMOST_TEMPLATE_ARGS (arglist),
template, 1, 1);
if (arglist == error_mark_node)
......@@ -5143,17 +5177,6 @@ maybe_fold_nontype_arg (arg)
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
......@@ -5548,7 +5571,7 @@ tsubst_decl (t, args, type, in_decl)
spec_args, /*complain=*/1, in_decl);
DECL_TI_TEMPLATE (new_fn) = fn;
register_specialization (new_fn, r,
innermost_args (spec_args));
INNERMOST_TEMPLATE_ARGS (spec_args));
}
/* Record this partial instantiation. */
......@@ -5593,7 +5616,19 @@ tsubst_decl (t, args, type, in_decl)
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 subtituting 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();
......@@ -5618,21 +5653,7 @@ tsubst_decl (t, args, type, in_decl)
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
{
......@@ -7440,25 +7461,23 @@ instantiate_template (tmpl, targ_ptr)
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--)
{
......@@ -8885,7 +8904,7 @@ get_class_bindings (tparms, parms, args)
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_tree_vec (ntparms);
args = innermost_args (args);
args = INNERMOST_TEMPLATE_ARGS (args);
if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE))
return NULL_TREE;
......@@ -8970,7 +8989,9 @@ most_specialized (fns, decl, explicit_args)
}
/* 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); };
......@@ -8987,14 +9008,37 @@ tree
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;
}
......@@ -9345,10 +9389,13 @@ regenerate_decl_from_template (decl, tmpl)
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);
......@@ -9474,32 +9521,30 @@ instantiate_decl (d, defer_ok)
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
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))))
{
/* The present template, TD, should not be a definition. If it
were a definition, we should be using it! Note that we
......@@ -9941,7 +9986,7 @@ set_mangled_name_for_template_decl (decl)
/* 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));
partial_args = make_tree_vec (TMPL_ARGS_DEPTH (targs));
for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
SET_TMPL_ARGS_LEVEL (partial_args, i,
TMPL_ARGS_LEVEL (targs, i));
......@@ -9966,7 +10011,7 @@ set_mangled_name_for_template_decl (decl)
/* 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);
......
// Build don't link:
// Origin: Jason Merrill <jason@cygnus.com>
template <class T> struct A {
template <class U> void f(U);
};
template <>
template <class U>
void A<int>::f(U);
A<int> a;
void g ()
{
a.f (3);
}
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T> struct A {
template <class U> int f(U) { return 1; }
};
template <>
template <class U>
int A<int>::f(U) { return 0; }
A<int> a;
int main ()
{
return a.f (3);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment