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
This commit is contained in:
parent
be5ceb725b
commit
e4a8420974
7 changed files with 184 additions and 48 deletions
|
@ -1,3 +1,29 @@
|
|||
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');
|
||||
|
|
150
gcc/cp/pt.c
150
gcc/cp/pt.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
23
gcc/testsuite/g++.old-deja/g++.pt/crash18.C
Normal file
23
gcc/testsuite/g++.old-deja/g++.pt/crash18.C
Normal file
|
@ -0,0 +1,23 @@
|
|||
// 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);
|
||||
}
|
13
gcc/testsuite/g++.old-deja/g++.pt/memclass16.C
Normal file
13
gcc/testsuite/g++.old-deja/g++.pt/memclass16.C
Normal file
|
@ -0,0 +1,13 @@
|
|||
// 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>;
|
Loading…
Add table
Reference in a new issue