Commit e4a84209 by Mark Mitchell Committed by Mark Mitchell

decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it uses template parameters.

	* decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
	uses template parameters.
	* method.c (build_template_parm_names): Use the full set of
	template arguments for tsubst'ing.
	(build_overload_identifier): Pass the full set of template
	arguments to build_template_parm_names, not just the
	innermost_args.
	* pt.c (TMPL_ARGS_DEPTH): Define using
	TMPL_ARGS_HAVE_MULTIPLE_LEVELS, for clarity.
	(NUM_TMPL_ARGS): New macro.
	(add_outermost_template_args): Deal with the case where the outer
	args will be completely discarded.
	(coerce_template_parms): Use the full set of template arguments
	for tsubst'ing.  Simplify.  Add some asserts.  Improve
	error messages.
	(lookup_template_class): Pass the full set of template arguments
	to coerce_template_parms.
	(tsubst): Add assertion.
	(do_type_instantiation): Don't instantiate member template
	classes.
	* init.c (build_offset_ref): Deal with a TEMPLATE_ID_EXPR whose
	name is a LOOKUP_EXPR, rather than an IDENTIFIER_NODE.

From-SVN: r21609
parent be5ceb72
1998-08-04 Mark Mitchell <mark@markmitchell.com>
* decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
uses template parameters.
* method.c (build_template_parm_names): Use the full set of
template arguments for tsubst'ing.
(build_overload_identifier): Pass the full set of template
arguments to build_template_parm_names, not just the
innermost_args.
* pt.c (TMPL_ARGS_DEPTH): Define using
TMPL_ARGS_HAVE_MULTIPLE_LEVELS, for clarity.
(NUM_TMPL_ARGS): New macro.
(add_outermost_template_args): Deal with the case where the outer
args will be completely discarded.
(coerce_template_parms): Use the full set of template arguments
for tsubst'ing. Simplify. Add some asserts. Improve
error messages.
(lookup_template_class): Pass the full set of template arguments
to coerce_template_parms.
(tsubst): Add assertion.
(do_type_instantiation): Don't instantiate member template
classes.
* init.c (build_offset_ref): Deal with a TEMPLATE_ID_EXPR whose
name is a LOOKUP_EXPR, rather than an IDENTIFIER_NODE.
1998-08-03 Jason Merrill <jason@yorick.cygnus.com>
* method.c (set_mangled_name_for_decl): Change return type to void.
......
......@@ -2396,8 +2396,9 @@ pushtag (name, type, globalize)
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
DECL_ASSEMBLER_NAME (d)
= get_identifier (build_overload_name (type, 1, 1));
if (!uses_template_parms (type))
DECL_ASSEMBLER_NAME (d)
= get_identifier (build_overload_name (type, 1, 1));
}
}
if (b->parm_flag == 2)
......
......@@ -1547,6 +1547,11 @@ build_offset_ref (type, name)
part, we treat this just like a.f. We do remember, however,
the template-id that was used. */
name = TREE_OPERAND (orig_name, 0);
if (TREE_CODE (name) == LOOKUP_EXPR)
/* This can happen during tsubst'ing. */
name = TREE_OPERAND (name, 0);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
}
......
......@@ -862,13 +862,14 @@ build_template_parm_names (parmlist, arglist)
tree arglist;
{
int i, nparms;
tree inner_args = innermost_args (arglist);
nparms = TREE_VEC_LENGTH (parmlist);
icat (nparms);
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i);
tree arg = TREE_VEC_ELT (inner_args, i);
if (TREE_CODE (parm) == TYPE_DECL)
{
/* This parameter is a type. */
......@@ -919,9 +920,8 @@ build_overload_identifier (name)
{
/* NAME is the TYPE_DECL for a template specialization. */
tree template, parmlist, arglist, tname;
template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
arglist = innermost_args (TREE_VALUE (template));
template = TREE_PURPOSE (template);
template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name));
arglist = CLASSTYPE_TI_ARGS (TREE_TYPE (name));
tname = DECL_NAME (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
OB_PUTC ('t');
......
......@@ -135,19 +135,6 @@ static int template_class_depth_real PROTO((tree, int));
only one level of arguments, but which is a TREE_VEC containing as
its only entry the TREE_VEC for that level. */
/* The depth of a template argument vector. When called directly by
the parser, we use a TREE_LIST rather than a TREE_VEC to represent
template arguments. In fact, we may even see NULL_TREE if there
are no template arguments. In both of those cases, there is only
one level of template arguments. */
#define TMPL_ARGS_DEPTH(NODE) \
((NODE != NULL_TREE \
&& TREE_CODE (NODE) == TREE_VEC \
&& TREE_VEC_LENGTH (NODE) > 0 \
&& TREE_VEC_ELT (NODE, 0) != NULL_TREE \
&& TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC) ? \
TREE_VEC_LENGTH (NODE) : 1)
/* Non-zero if the template arguments is actually a vector of vectors,
rather than just a vector. */
#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
......@@ -157,6 +144,14 @@ static int template_class_depth_real PROTO((tree, int));
&& TREE_VEC_ELT (NODE, 0) != NULL_TREE \
&& TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
/* The depth of a template argument vector. When called directly by
the parser, we use a TREE_LIST rather than a TREE_VEC to represent
template arguments. In fact, we may even see NULL_TREE if there
are no template arguments. In both of those cases, there is only
one level of template arguments. */
#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. */
#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \
......@@ -177,6 +172,13 @@ static int template_class_depth_real PROTO((tree, int));
#define SET_TMPL_ARG(ARGS, LEVEL, IDX, VAL) \
(TREE_VEC_ELT (TREE_VEC_ELT ((ARGS), (LEVEL) - 1), (IDX)) = (VAL))
/* Given a single level of template arguments in NODE, return the
number of arguments. */
#define NUM_TMPL_ARGS(NODE) \
((NODE) == NULL_TREE ? 0 \
: (TREE_CODE (NODE) == TREE_VEC \
? TREE_VEC_LENGTH (NODE) : list_length (NODE)))
/* The number of levels of template parameters given by NODE. */
#define TMPL_PARMS_DEPTH(NODE) \
(TREE_INT_CST_HIGH (TREE_PURPOSE (NODE)))
......@@ -506,6 +508,16 @@ add_outermost_template_args (args, extra_args)
{
tree new_args;
/* If there are more levels of EXTRA_ARGS than there are ARGS,
something very fishy is going on. */
my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
0);
/* If *all* the new arguments will be the EXTRA_ARGS, just return
them. */
if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args))
return extra_args;
/* For the moment, we make ARGS look like it contains fewer levels. */
TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);
......@@ -2545,15 +2557,11 @@ coerce_template_parms (parms, arglist, in_decl,
int require_all_arguments;
{
int nparms, nargs, i, lost = 0;
tree vec = NULL_TREE;
if (arglist == NULL_TREE)
nargs = 0;
else if (TREE_CODE (arglist) == TREE_VEC)
nargs = TREE_VEC_LENGTH (arglist);
else
nargs = list_length (arglist);
tree inner_args;
tree vec;
inner_args = innermost_args (arglist);
nargs = NUM_TMPL_ARGS (inner_args);
nparms = TREE_VEC_LENGTH (parms);
if (nargs > nparms
......@@ -2563,22 +2571,42 @@ coerce_template_parms (parms, arglist, in_decl,
{
if (complain)
{
error ("incorrect number of parameters (%d, should be %d)",
nargs, nparms);
cp_error ("wrong number of template arguments (%d, should be %d)",
nargs, nparms);
if (in_decl)
cp_error_at ("in template expansion for decl `%D'",
in_decl);
cp_error_at ("provided for `%D'", in_decl);
}
return error_mark_node;
}
if (arglist && TREE_CODE (arglist) == TREE_VEC && nargs == nparms)
vec = copy_node (arglist);
/* Create in VEC the appropriate innermost arguments, and reset
ARGLIST to contain the complete set of arguments. */
if (inner_args && TREE_CODE (inner_args) == TREE_VEC && nargs == nparms)
{
/* If we already have all the arguments, we can just use them.
This is an optimization over the code in the `else' branch
below, and should be functionally identicial. */
vec = copy_node (inner_args);
arglist = add_outermost_template_args (arglist, vec);
}
else
{
/* If we don't already have all the arguments we must get what
we can from default template arguments. The tricky bit is
that previous arguments can influence the default values,
e.g.:
template <class T, class U = T> void foo();
If we see `foo<int>' we have to come up with an {int, int}
vector. */
tree new_arglist;
vec = make_tree_vec (nparms);
new_arglist = add_outermost_template_args (arglist, vec);
for (i = 0; i < nparms; i++)
{
......@@ -2597,23 +2625,33 @@ coerce_template_parms (parms, arglist, in_decl,
}
else if (i < nargs)
{
arg = TREE_VEC_ELT (arglist, i);
arg = TREE_VEC_ELT (inner_args, i);
if (arg == error_mark_node)
lost++;
}
/* If no template argument was supplied, look for a default
value. */
else if (TREE_PURPOSE (parm) == NULL_TREE)
{
/* There was no default value. */
my_friendly_assert (!require_all_arguments, 0);
break;
}
else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
arg = tsubst (TREE_PURPOSE (parm), vec, in_decl);
arg = tsubst (TREE_PURPOSE (parm), new_arglist, in_decl);
else
arg = tsubst_expr (TREE_PURPOSE (parm), vec, in_decl);
arg = tsubst_expr (TREE_PURPOSE (parm), new_arglist, in_decl);
TREE_VEC_ELT (vec, i) = arg;
}
/* We've left ARGLIST intact up to this point, in order to allow
iteration through it in the case that it was a TREE_LIST, but
from here on it should contain the full set of template
arguments. */
arglist = new_arglist;
}
for (i = 0; i < nparms; i++)
{
tree arg = TREE_VEC_ELT (vec, i);
......@@ -2772,7 +2810,7 @@ coerce_template_parms (parms, arglist, in_decl,
}
else
{
tree t = tsubst (TREE_TYPE (parm), vec, in_decl);
tree t = tsubst (TREE_TYPE (parm), arglist, in_decl);
if (processing_template_decl)
arg = maybe_fold_nontype_arg (arg);
......@@ -3205,17 +3243,29 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
{
/* We have multiple levels of arguments to coerce, at once. */
int i;
int saved_depth = TMPL_ARGS_DEPTH (arglist);
tree bound_args = make_tree_vec (parm_depth);
for (i = TREE_VEC_LENGTH (arglist) - 1,
for (i = saved_depth,
t = DECL_TEMPLATE_PARMS (template);
i >= 0 && t != NULL_TREE;
i > 0 && t != NULL_TREE;
--i, t = TREE_CHAIN (t))
TREE_VEC_ELT (bound_args, i) =
coerce_template_parms (TREE_VALUE (t),
TREE_VEC_ELT (arglist, i),
template, 1, 1);
{
tree a = coerce_template_parms (TREE_VALUE (t),
arglist, template, 1, 1);
SET_TMPL_ARGS_LEVEL (bound_args, i, a);
/* We temporarily reduce the length of the ARGLIST so
that coerce_template_parms will see only the arguments
corresponding to the template parameters it is
examining. */
TREE_VEC_LENGTH (arglist)--;
}
/* Restore the ARGLIST to its full size. */
TREE_VEC_LENGTH (arglist) = saved_depth;
arglist = bound_args;
}
else
......@@ -4647,9 +4697,13 @@ tsubst (t, args, in_decl)
if (arg != NULL_TREE)
{
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
return cp_build_type_variant
(arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
{
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
== 't', 0);
return cp_build_type_variant
(arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
}
else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
if (CLASSTYPE_TEMPLATE_INFO (t))
......@@ -7392,8 +7446,22 @@ do_type_instantiation (t, storage)
instantiate_decl (tmp);
}
/* In contrast to implicit instantiation, where only the
declarations, and not the definitions, of members are
instantiated, we have here:
[temp.explicit]
The explicit instantiation of a class template specialization
implies the instantiation of all of its members not
previously explicitly specialized in the translation unit
containing the explicit instantiation.
Of course, we can't instantiate member template classes, since
we don't have any arguments for them. */
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
if (IS_AGGR_TYPE (TREE_VALUE (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);
}
}
......
// Build don't run:
template<class T>
class foo {
T deft;
template<class U> int priv (U u, T t) { return u - t; }
public:
foo (T t) : deft (t) {}
template<class U> int pub (U u) {
int (foo::*fn) (U, T);
fn = &foo<T>::template priv<U>;
return (this->*fn) (u, deft);
}
};
int
main ()
{
foo<long> fff (5);
return fff.pub (3);
}
// Build don't link:
template <class Q>
class A {
public:
typedef enum { X, Y } B;
template <B c> class Traits{ };
};
template class A<int>;
template class A<double>::Traits<A<double>::X>;
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