cp-tree.h (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Move here from pt.c.
* cp-tree.h (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Move here from pt.c. (TMPL_ARGS_DEPTH, TMPL_ARGS_LEVEL, SET_TMPL_ARGS_LEVEL): Likewise. (TMPL_ARG, SET_TMPL_ARG, NUM_TMPL_ARGS, TMPL_PARMS_DEPTH): Likewise. * error.c (dump_template_bindings): Remove unused parameter. Handle multiple levels of template parameters. (dump_template_decl): Use `parms', not `args', for template parameters. Fix thinko. (dump_function_decl): Use DECL_TEMPLATE_INSTANTIATION. Don't pass flags to dump_template_bindings. * pt.c (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Move to cp-tree.h. (TMPL_ARGS_DEPTH, TMPL_ARGS_LEVEL, SET_TMPL_ARGS_LEVEL): Likewise. (TMPL_ARG, SET_TMPL_ARG, NUM_TMPL_ARGS, TMPL_PARMS_DEPTH): Likewise. (tsubst_copy): Clarify variable name. (most_general_template): Robustify. From-SVN: r29708
This commit is contained in:
parent
0acbb8d94d
commit
b5ac18ea8c
|
@ -1,3 +1,20 @@
|
|||
1999-09-29 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Move here from pt.c.
|
||||
(TMPL_ARGS_DEPTH, TMPL_ARGS_LEVEL, SET_TMPL_ARGS_LEVEL): Likewise.
|
||||
(TMPL_ARG, SET_TMPL_ARG, NUM_TMPL_ARGS, TMPL_PARMS_DEPTH): Likewise.
|
||||
* error.c (dump_template_bindings): Remove unused parameter.
|
||||
Handle multiple levels of template parameters.
|
||||
(dump_template_decl): Use `parms', not `args', for template
|
||||
parameters. Fix thinko.
|
||||
(dump_function_decl): Use DECL_TEMPLATE_INSTANTIATION. Don't pass
|
||||
flags to dump_template_bindings.
|
||||
* pt.c (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Move to cp-tree.h.
|
||||
(TMPL_ARGS_DEPTH, TMPL_ARGS_LEVEL, SET_TMPL_ARGS_LEVEL): Likewise.
|
||||
(TMPL_ARG, SET_TMPL_ARG, NUM_TMPL_ARGS, TMPL_PARMS_DEPTH): Likewise.
|
||||
(tsubst_copy): Clarify variable name.
|
||||
(most_general_template): Robustify.
|
||||
|
||||
1999-09-29 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* error.c (dump_template_parms): Don't use TS_PEDANTIC_NAME
|
||||
|
|
|
@ -1852,6 +1852,66 @@ struct lang_decl
|
|||
#define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE))
|
||||
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
|
||||
|
||||
/* We use TREE_VECs to hold template arguments. If there is only one
|
||||
level of template arguments, then the TREE_VEC contains the
|
||||
arguments directly. If there is more than one level of template
|
||||
arguments, then each entry in the TREE_VEC is itself a TREE_VEC,
|
||||
containing the template arguments for a single level. The first
|
||||
entry in the outer TREE_VEC is the outermost level of template
|
||||
parameters; the last is the innermost.
|
||||
|
||||
It is incorrect to ever form a template argument vector containing
|
||||
only one level of arguments, but which is a TREE_VEC containing as
|
||||
its only entry the TREE_VEC for that level. */
|
||||
|
||||
/* Non-zero if the template arguments is actually a vector of vectors,
|
||||
rather than just a vector. */
|
||||
#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(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)
|
||||
|
||||
/* 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) \
|
||||
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \
|
||||
? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS)
|
||||
|
||||
/* Set the LEVELth level of the template ARGS to VAL. This macro does
|
||||
not work with single-level argument vectors. */
|
||||
#define SET_TMPL_ARGS_LEVEL(ARGS, LEVEL, VAL) \
|
||||
(TREE_VEC_ELT ((ARGS), (LEVEL) - 1) = (VAL))
|
||||
|
||||
/* Accesses the IDXth parameter in the LEVELth level of the ARGS. */
|
||||
#define TMPL_ARG(ARGS, LEVEL, IDX) \
|
||||
(TREE_VEC_ELT (TMPL_ARGS_LEVEL (ARGS, LEVEL), IDX))
|
||||
|
||||
/* Set the IDXth element in the LEVELth level of ARGS to VAL. This
|
||||
macro does not work with single-level argument vectors. */
|
||||
#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)))
|
||||
|
||||
/* The TEMPLATE_DECL instantiated or specialized by NODE. This
|
||||
TEMPLATE_DECL will be the immediate parent, not the most general
|
||||
template. For example, in:
|
||||
|
|
|
@ -92,7 +92,7 @@ static tree ident_fndecl PROTO((tree));
|
|||
static void dump_template_argument PROTO((tree, enum tree_string_flags));
|
||||
static void dump_template_argument_list PROTO((tree, enum tree_string_flags));
|
||||
static void dump_template_parameter PROTO((tree, enum tree_string_flags));
|
||||
static void dump_template_bindings PROTO((tree, tree, enum tree_string_flags));
|
||||
static void dump_template_bindings PROTO((tree, tree));
|
||||
static void dump_scope PROTO((tree, enum tree_string_flags));
|
||||
static void dump_template_parms PROTO((tree, int, enum tree_string_flags));
|
||||
|
||||
|
@ -293,41 +293,39 @@ dump_template_parameter (parm, flags)
|
|||
TREE_VEC. */
|
||||
|
||||
static void
|
||||
dump_template_bindings (parms, args, flags)
|
||||
dump_template_bindings (parms, args)
|
||||
tree parms, args;
|
||||
enum tree_string_flags flags;
|
||||
{
|
||||
int arg_idx = 0;
|
||||
int need_comma = 0;
|
||||
|
||||
while (parms)
|
||||
{
|
||||
tree p = TREE_VALUE (parms);
|
||||
int lvl = TMPL_PARMS_DEPTH (parms);
|
||||
int arg_idx = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TREE_VEC_LENGTH (p); ++i)
|
||||
{
|
||||
tree arg = TREE_VEC_ELT (args, arg_idx);
|
||||
{
|
||||
tree arg = TMPL_ARG (args, lvl, arg_idx);
|
||||
|
||||
if (need_comma)
|
||||
OB_PUTS (", ");
|
||||
dump_template_parameter (TREE_VEC_ELT (p, i), TS_PLAIN);
|
||||
OB_PUTS (" = ");
|
||||
if (arg)
|
||||
dump_template_argument (arg, TS_PLAIN);
|
||||
else
|
||||
OB_PUTS ("{missing}");
|
||||
if (need_comma)
|
||||
OB_PUTS (", ");
|
||||
dump_template_parameter (TREE_VEC_ELT (p, i), TS_PLAIN);
|
||||
OB_PUTS (" = ");
|
||||
if (arg)
|
||||
dump_template_argument (arg, TS_PLAIN);
|
||||
else
|
||||
OB_PUTS ("{missing}");
|
||||
|
||||
++arg_idx;
|
||||
need_comma = 1;
|
||||
}
|
||||
++arg_idx;
|
||||
need_comma = 1;
|
||||
}
|
||||
|
||||
parms = TREE_CHAIN (parms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Dump into the obstack a human-readable equivalent of TYPE. FLAGS
|
||||
controls the format. */
|
||||
|
||||
|
@ -1042,31 +1040,32 @@ dump_template_decl (t, flags)
|
|||
tree t;
|
||||
enum tree_string_flags flags;
|
||||
{
|
||||
tree orig_args = DECL_TEMPLATE_PARMS (t);
|
||||
tree args;
|
||||
tree orig_parms = DECL_TEMPLATE_PARMS (t);
|
||||
tree parms;
|
||||
int i;
|
||||
|
||||
if (flags & TS_TEMPLATE_PREFIX)
|
||||
{
|
||||
for (args = orig_args = nreverse (orig_args);
|
||||
args;
|
||||
args = TREE_CHAIN (args))
|
||||
for (parms = orig_parms = nreverse (orig_parms);
|
||||
parms;
|
||||
parms = TREE_CHAIN (parms))
|
||||
{
|
||||
int len = TREE_VEC_LENGTH (TREE_VALUE (args));
|
||||
tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
|
||||
int len = TREE_VEC_LENGTH (inner_parms);
|
||||
|
||||
OB_PUTS ("template <");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (i)
|
||||
OB_PUTS (", ");
|
||||
dump_template_parameter (TREE_VEC_ELT (args, i), flags);
|
||||
dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags);
|
||||
}
|
||||
OB_END_TEMPLATE_ID ();
|
||||
OB_PUTC (' ');
|
||||
}
|
||||
nreverse(orig_args);
|
||||
nreverse(orig_parms);
|
||||
/* If we've shown the template<args> prefix, we'd better show the
|
||||
* decl's type too. */
|
||||
decl's type too. */
|
||||
flags |= TS_DECL_TYPE;
|
||||
}
|
||||
if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
|
||||
|
@ -1113,11 +1112,12 @@ dump_function_decl (t, flags)
|
|||
t = DECL_TEMPLATE_RESULT (t);
|
||||
|
||||
/* Pretty print template instantiations only. */
|
||||
if (DECL_USE_TEMPLATE (t) == 1 || DECL_USE_TEMPLATE (t) == 3)
|
||||
if (DECL_TEMPLATE_INSTANTIATION (t))
|
||||
{
|
||||
template_args = DECL_TI_ARGS (t);
|
||||
t = most_general_template (t);
|
||||
template_parms = DECL_TEMPLATE_PARMS (t);
|
||||
if (TREE_CODE (t) == TEMPLATE_DECL)
|
||||
template_parms = DECL_TEMPLATE_PARMS (t);
|
||||
}
|
||||
|
||||
fntype = TREE_TYPE (t);
|
||||
|
@ -1184,7 +1184,7 @@ dump_function_decl (t, flags)
|
|||
if (template_parms != NULL_TREE && template_args != NULL_TREE)
|
||||
{
|
||||
OB_PUTS (" [with ");
|
||||
dump_template_bindings (template_parms, template_args, flags);
|
||||
dump_template_bindings (template_parms, template_args);
|
||||
OB_PUTC (']');
|
||||
}
|
||||
}
|
||||
|
|
70
gcc/cp/pt.c
70
gcc/cp/pt.c
|
@ -158,66 +158,6 @@ static int template_args_equal PROTO((tree, tree));
|
|||
static void print_template_context PROTO((int));
|
||||
static void tsubst_default_arguments PROTO((tree));
|
||||
|
||||
/* We use TREE_VECs to hold template arguments. If there is only one
|
||||
level of template arguments, then the TREE_VEC contains the
|
||||
arguments directly. If there is more than one level of template
|
||||
arguments, then each entry in the TREE_VEC is itself a TREE_VEC,
|
||||
containing the template arguments for a single level. The first
|
||||
entry in the outer TREE_VEC is the outermost level of template
|
||||
parameters; the last is the innermost.
|
||||
|
||||
It is incorrect to ever form a template argument vector containing
|
||||
only one level of arguments, but which is a TREE_VEC containing as
|
||||
its only entry the TREE_VEC for that level. */
|
||||
|
||||
/* Non-zero if the template arguments is actually a vector of vectors,
|
||||
rather than just a vector. */
|
||||
#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(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)
|
||||
|
||||
/* 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) \
|
||||
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \
|
||||
? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS)
|
||||
|
||||
/* Set the LEVELth level of the template ARGS to VAL. This macro does
|
||||
not work with single-level argument vectors. */
|
||||
#define SET_TMPL_ARGS_LEVEL(ARGS, LEVEL, VAL) \
|
||||
(TREE_VEC_ELT ((ARGS), (LEVEL) - 1) = (VAL))
|
||||
|
||||
/* Accesses the IDXth parameter in the LEVELth level of the ARGS. */
|
||||
#define TMPL_ARG(ARGS, LEVEL, IDX) \
|
||||
(TREE_VEC_ELT (TMPL_ARGS_LEVEL (ARGS, LEVEL), IDX))
|
||||
|
||||
/* Set the IDXth element in the LEVELth level of ARGS to VAL. This
|
||||
macro does not work with single-level argument vectors. */
|
||||
#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)))
|
||||
|
||||
/* Called once to initialize pt.c. */
|
||||
|
||||
void
|
||||
|
@ -7081,10 +7021,10 @@ tsubst_copy (t, args, complain, in_decl)
|
|||
to expand the STMT_EXPR here. */
|
||||
if (!processing_template_decl)
|
||||
{
|
||||
tree rtl_expr = begin_stmt_expr ();
|
||||
tree stmt_expr = begin_stmt_expr ();
|
||||
tsubst_expr (STMT_EXPR_STMT (t), args,
|
||||
complain, in_decl);
|
||||
return finish_stmt_expr (rtl_expr);
|
||||
return finish_stmt_expr (stmt_expr);
|
||||
}
|
||||
|
||||
return t;
|
||||
|
@ -9092,7 +9032,11 @@ tree
|
|||
most_general_template (decl)
|
||||
tree decl;
|
||||
{
|
||||
while (DECL_TEMPLATE_INFO (decl))
|
||||
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.) */
|
||||
&& TREE_CODE (DECL_TI_TEMPLATE (decl)) == TEMPLATE_DECL)
|
||||
decl = DECL_TI_TEMPLATE (decl);
|
||||
|
||||
return decl;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// Build don't link:
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
template <class T>
|
||||
struct S
|
||||
{
|
||||
template <class U>
|
||||
void f ();
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class U>
|
||||
void S<T>::f ()
|
||||
{
|
||||
U& u; // ERROR - uninitialized reference
|
||||
}
|
||||
|
||||
template void S<int>::f<double>(); // ERROR - instantiated from here
|
Loading…
Reference in New Issue