Commit 73b0fce8 by Kriang Lerdsuwanakij Committed by Jason Merrill

pt.c (coerce_template_parms): Don't access elements of ARGLIST that is not really present.

Wed Jan 21 10:29:57 1998  Kriang Lerdsuwanakij  <lerdsuwa@scf.usc.edu>
	* pt.c (coerce_template_parms): Don't access elements of ARGLIST
	that is not really present.  Substitute default arguments in
	template template arguments.  Correctly convert TEMPLATE_DECL to
	TEMPLATE_TEMPLATE_PARM.
	(comp_template_args): TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM
	are no longer treated specially here.
	* parse.y (template_template_parm): Fix copy error.
	* decl.c (grokdeclarator): Warn about missing `typename' for nested
	type created from template template parameters.
	* parse.y (bad_parm): Likewise
	* class.c (finish_struct): Handle TEMPLATE_TEMPLATE_PARM.
	(push_nested_class): Likewise.
	* cp-tree.def (TEMPLATE_TEMPLATE_PARM): New tree code.
	* cp-tree.h (DECL_TEMPLATE_TEMPLATE_PARM_P): New macro.
	(copy_template_template_parm): Declare.
	* decl.c (arg_looking_for_template): New variable.
	(lookup_name_real): Handle TEMPLATE_TEMPLATE_PARM.
	Try to return TEMPLATE_DECL or TEMPLATE_TEMPLATE_PARM
	node if arg_looking_for_template is nonzero.
	(pushdecl): Handle TEMPLATE_TEMPLATE_PARM.
	(grok_op_properties, xref_tag, xref_basetypes): Likewise.
	(grokdeclarator): Handle TEMPLATE_DECL.
	* decl2.c (constructor_name_full): Handle TEMPLATE_TEMPLATE_PARM.
	* error.c (dump_type): Add TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM.
	(dump_type_prefix, dump_type_suffix) Handle TEMPLATE_TEMPLATE_PARM.
	(dump_decl): Handle unnamed template type parameters.
	Handle template template parameters.
	(dump_function_name): Handle template template parameters.
	* init.c (is_aggr_typedef, is_aggr_type, get_aggr_from_typedef):
	Handle TEMPLATE_TEMPLATE_PARM.
	* method.c (build_template_template_parm_names): New function.
	(build_template_parm_names): Handle TEMPLATE_DECL.
	(build_overload_nested_name, build_overload_name):
	Handle TEMPLATE_TEMPLATE_PARM.
	* parse.y (maybe_identifier): New nonterminal.
	(template_type_parm): Use it.
	(template_template_parm, template_arg1): New nonterminal.
	(template_parm): Add template_template_parm rules.
	(template_arg): Set processing_template_arg.
	(template_arg1): Rules moved from template_arg.
	(primary, nonnested_type): Set arg_looking_for_template if we are
	processing template arguments.
	* pt.c (begin_member_template_processing): Handle TEMPLATE_DECL.
	(process_template_parm): Handle template template parameters.
	(coerce_template_parms, comp_template_args): Likewise.
	(mangle_class_name_for_template, lookup_template_class): Likewise.
	(uses_template_parms): Handle TEMPLATE_DECL and
	TEMPLATE_TEMPLATE_PARM.
	(current_template_args): Handle TEMPLATE_DECL.
	(tsubst, tsubst_copy, unify): Handle TEMPLATE_TEMPLATE_PARM.
	* search.c (dfs_walk, dfs_record_inheritance):
	Handle TEMPLATE_TEMPLATE_PARM.
	* tree.c (copy_template_template_parm): New function.
	(mapcar): Handle TEMPLATE_TEMPLATE_PARM.
	* typeck.c (comptypes): Handle TEMPLATE_TEMPLATE_PARM.

From-SVN: r17441
parent 84303d9a
Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* pt.c (coerce_template_parms): Don't access elements of ARGLIST
that is not really present. Substitute default arguments in
template template arguments. Correctly convert TEMPLATE_DECL to
TEMPLATE_TEMPLATE_PARM.
(comp_template_args): TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM
are no longer treated specially here.
* parse.y (template_template_parm): Fix copy error.
* decl.c (grokdeclarator): Warn about missing `typename' for nested
type created from template template parameters.
* parse.y (bad_parm): Likewise
* class.c (finish_struct): Handle TEMPLATE_TEMPLATE_PARM.
(push_nested_class): Likewise.
* cp-tree.def (TEMPLATE_TEMPLATE_PARM): New tree code.
* cp-tree.h (DECL_TEMPLATE_TEMPLATE_PARM_P): New macro.
(copy_template_template_parm): Declare.
* decl.c (arg_looking_for_template): New variable.
(lookup_name_real): Handle TEMPLATE_TEMPLATE_PARM.
Try to return TEMPLATE_DECL or TEMPLATE_TEMPLATE_PARM
node if arg_looking_for_template is nonzero.
(pushdecl): Handle TEMPLATE_TEMPLATE_PARM.
(grok_op_properties, xref_tag, xref_basetypes): Likewise.
(grokdeclarator): Handle TEMPLATE_DECL.
* decl2.c (constructor_name_full): Handle TEMPLATE_TEMPLATE_PARM.
* error.c (dump_type): Add TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM.
(dump_type_prefix, dump_type_suffix) Handle TEMPLATE_TEMPLATE_PARM.
(dump_decl): Handle unnamed template type parameters.
Handle template template parameters.
(dump_function_name): Handle template template parameters.
* init.c (is_aggr_typedef, is_aggr_type, get_aggr_from_typedef):
Handle TEMPLATE_TEMPLATE_PARM.
* method.c (build_template_template_parm_names): New function.
(build_template_parm_names): Handle TEMPLATE_DECL.
(build_overload_nested_name, build_overload_name):
Handle TEMPLATE_TEMPLATE_PARM.
* parse.y (maybe_identifier): New nonterminal.
(template_type_parm): Use it.
(template_template_parm, template_arg1): New nonterminal.
(template_parm): Add template_template_parm rules.
(template_arg): Set processing_template_arg.
(template_arg1): Rules moved from template_arg.
(primary, nonnested_type): Set arg_looking_for_template if we are
processing template arguments.
* pt.c (begin_member_template_processing): Handle TEMPLATE_DECL.
(process_template_parm): Handle template template parameters.
(coerce_template_parms, comp_template_args): Likewise.
(mangle_class_name_for_template, lookup_template_class): Likewise.
(uses_template_parms): Handle TEMPLATE_DECL and
TEMPLATE_TEMPLATE_PARM.
(current_template_args): Handle TEMPLATE_DECL.
(tsubst, tsubst_copy, unify): Handle TEMPLATE_TEMPLATE_PARM.
* search.c (dfs_walk, dfs_record_inheritance):
Handle TEMPLATE_TEMPLATE_PARM.
* tree.c (copy_template_template_parm): New function.
(mapcar): Handle TEMPLATE_TEMPLATE_PARM.
* typeck.c (comptypes): Handle TEMPLATE_TEMPLATE_PARM.
Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
* decl.c (start_decl): Don't allow duplicate definitions of static
......
......@@ -4479,7 +4479,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
parms, we've seen all the injected decls. */
if ((TREE_CODE (d) == TYPE_DECL
&& (TREE_TYPE (d) == t
|| TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM))
|| TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM
|| TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TEMPLATE_PARM))
|| TREE_CODE (d) == CONST_DECL)
break;
/* Don't inject cache decls. */
......@@ -4883,7 +4884,8 @@ push_nested_class (type, modify)
tree context;
if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
return;
context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
......
......@@ -91,6 +91,12 @@ DEFTREECODE (TEMPLATE_DECL, "template_decl", 'd', 0)
Use TYPE_FIELDS to find parmlist and index. */
DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0)
/* Index into a template parameter list. This parameter must be a type.
If it is used in signature of a template, TEMPLATE_INFO is NULL_TREE.
Otherwise it is used to declare a type like TT<int>.
Use TYPE_FIELDS to find parmlist and index. */
DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
/* A type designated by 'typename T::t'. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
......
......@@ -1350,6 +1350,12 @@ extern int flag_new_for_scope;
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE)
/* Nonzero for TEMPLATE_DECL nodes that represents template template
parameters */
#define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \
(TREE_CODE (NODE) == TEMPLATE_DECL && TREE_TYPE (NODE) \
&& TREE_CODE (TREE_TYPE (NODE)) == TEMPLATE_TEMPLATE_PARM)
#define DECL_FUNCTION_TEMPLATE_P(NODE) \
(TREE_CODE (NODE) == TEMPLATE_DECL \
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
......@@ -1920,11 +1926,13 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
/* These macros are for accessing the fields of TEMPLATE...PARM nodes. */
/* These macros are for accessing the fields of TEMPLATE_TYPE_PARM
and TEMPLATE_TEMPLATE_PARM nodes. */
#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TYPE_FIELDS (NODE))
#define TEMPLATE_TYPE_LEVEL(NODE) TREE_INT_CST_HIGH (TYPE_FIELDS (NODE))
#define TEMPLATE_TYPE_SET_INFO(NODE,I,L) \
(TYPE_FIELDS (NODE) = build_int_2 (I, L))
/* These macros are for accessing the fields of TEMPLATE_CONST_PARM nodes. */
#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_LOW(NODE))
#define TEMPLATE_CONST_LEVEL(NODE) (TREE_INT_CST_HIGH(NODE))
#define TEMPLATE_CONST_SET_INFO(NODE,I,L) \
......@@ -2463,6 +2471,7 @@ extern int promotes_to_aggr_type PROTO((tree, enum tree_code));
extern int is_aggr_type_2 PROTO((tree, tree));
extern char *lang_printable_name PROTO((tree, int));
extern tree build_exception_variant PROTO((tree, tree));
extern tree copy_template_template_parm PROTO((tree));
extern tree copy_to_permanent PROTO((tree));
extern void print_lang_statistics PROTO((void));
extern void __eprintf
......
......@@ -397,6 +397,9 @@ static struct named_label_list *named_label_uses = NULL;
in the TREE_PURPOSE slot. */
tree static_aggregates;
/* Nonzero if we lookup name inside template argument. */
int arg_looking_for_template;
/* -- end of C++ */
/* Two expressions that are constants with value zero.
......@@ -3104,7 +3107,8 @@ pushdecl (x)
/* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
|| TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM)
|| TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM
|| TREE_CODE (x) == TEMPLATE_TEMPLATE_PARM)
name = DECL_NAME (x);
if (name)
......@@ -4534,6 +4538,7 @@ lookup_name_real (name, prefer_type, nonclass)
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (type) == TYPENAME_TYPE)
/* Someone else will give an error about this if needed. */
val = NULL_TREE;
......@@ -4667,7 +4672,13 @@ lookup_name_real (name, prefer_type, nonclass)
val = from_obj;
}
if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
if (TREE_CODE (val) == TEMPLATE_DECL && arg_looking_for_template)
{
/* TEMPLATE_TEMPLATE_PARM node is preferred over TEMPLATE_DECL. */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
val = TREE_TYPE (val);
}
else if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
|| TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
;
else if (IDENTIFIER_HAS_TYPE_VALUE (name))
......@@ -7996,7 +8007,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else if (TREE_OPERAND (decl, 1)
&& TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
ctype = cname;
else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM)
else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
|| TREE_CODE (cname) == TEMPLATE_TEMPLATE_PARM)
{
cp_error ("`%T::%D' is not a valid declarator", cname,
TREE_OPERAND (decl, 1));
......@@ -8205,7 +8217,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
/* C++ aggregate types. */
else if (TREE_CODE (id) == TYPE_DECL)
else if (TREE_CODE (id) == TYPE_DECL || TREE_CODE (id) == TEMPLATE_DECL)
{
if (type)
cp_error ("multiple declarations `%T' and `%T'", type,
......@@ -10592,7 +10604,8 @@ grok_op_properties (decl, virtualp, friendp)
/* This lets bad template code slip through. */
if (IS_AGGR_TYPE (arg)
|| TREE_CODE (arg) == ENUMERAL_TYPE
|| TREE_CODE (arg) == TEMPLATE_TYPE_PARM)
|| TREE_CODE (arg) == TEMPLATE_TYPE_PARM
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
goto foundaggr;
}
cp_error
......@@ -10821,12 +10834,14 @@ xref_tag (code_type_node, name, binfo, globalize)
}
else
t = IDENTIFIER_TYPE_VALUE (name);
if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM)
if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
&& TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM)
t = NULL_TREE;
if (! globalize)
{
if (pedantic && t && TREE_CODE (t) == TEMPLATE_TYPE_PARM)
if (pedantic && t && (TREE_CODE (t) == TEMPLATE_TYPE_PARM
|| TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM))
{
cp_pedwarn ("redeclaration of template type-parameter `%T'", name);
cp_pedwarn_at (" previously declared here", t);
......@@ -11023,7 +11038,8 @@ xref_basetypes (code_type_node, name, ref, binfo)
if (!basetype
|| (TREE_CODE (basetype) != RECORD_TYPE
&& TREE_CODE (basetype) != TYPENAME_TYPE
&& TREE_CODE (basetype) != TEMPLATE_TYPE_PARM))
&& TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
&& TREE_CODE (basetype) != TEMPLATE_TEMPLATE_PARM))
{
cp_error ("base type `%T' fails to be a struct or class type",
TREE_VALUE (binfo));
......
......@@ -1997,7 +1997,8 @@ tree
constructor_name_full (thing)
tree thing;
{
if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM)
if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM
|| TREE_CODE (thing) == TEMPLATE_TEMPLATE_PARM)
thing = TYPE_NAME (thing);
else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
{
......
......@@ -229,6 +229,86 @@ dump_type (t, v)
OB_PUTID (TYPE_IDENTIFIER (t));
break;
/* A substituted template template parameter. Default template
argument handling are different from dump_decl. */
case TEMPLATE_DECL:
{
tree orig_args = DECL_TEMPLATE_PARMS (t);
tree args;
int i;
for (args = orig_args = nreverse (orig_args);
args;
args = TREE_CHAIN (args))
{
int len = TREE_VEC_LENGTH (TREE_VALUE (args));
OB_PUTS ("template <");
for (i = 0; i < len; i++)
{
tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
tree defval = TREE_PURPOSE (arg);
arg = TREE_VALUE (arg);
if (TREE_CODE (arg) == TYPE_DECL)
{
OB_PUTS ("class ");
if (DECL_NAME (arg))
OB_PUTID (DECL_NAME (arg));
else
OB_PUTS ("{anon}");
}
else
dump_decl (arg, 1);
if (defval)
{
OB_PUTS (" = ");
if (TREE_CODE (arg) == TYPE_DECL)
dump_type (defval, 1);
else
dump_expr (defval, 1);
}
OB_PUTC2 (',', ' ');
}
if (len != 0)
OB_UNPUT (2);
OB_PUTC2 ('>', ' ');
}
nreverse(orig_args);
dump_type (TREE_TYPE (t), v);
}
break;
case TEMPLATE_TEMPLATE_PARM:
if (!CLASSTYPE_TEMPLATE_INFO (t))
{
/* For parameters inside template signature. */
if (TYPE_IDENTIFIER (t))
OB_PUTID (TYPE_IDENTIFIER (t));
else
OB_PUTS ("{anonymous template template parm}");
}
else
{
int i;
tree args = CLASSTYPE_TI_ARGS (t);
OB_PUTID (TYPE_IDENTIFIER (t));
OB_PUTC ('<');
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{
tree arg = TREE_VEC_ELT (args, i);
if (TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
|| TREE_CODE (arg) == TEMPLATE_DECL)
dump_type (arg, 0);
else
dump_expr (arg, 0);
if (i < TREE_VEC_LENGTH (args)-1)
OB_PUTC2 (',', ' ');
}
OB_PUTC ('>');
}
break;
case TEMPLATE_TYPE_PARM:
dump_readonly_or_volatile (t, after);
if (TYPE_IDENTIFIER (t))
......@@ -447,6 +527,7 @@ dump_type_prefix (t, v)
case REAL_TYPE:
case RECORD_TYPE:
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
case TREE_LIST:
case TYPE_DECL:
case TREE_VEC:
......@@ -529,6 +610,7 @@ dump_type_suffix (t, v)
case REAL_TYPE:
case RECORD_TYPE:
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
case TREE_LIST:
case TYPE_DECL:
case TREE_VEC:
......@@ -740,7 +822,10 @@ dump_decl (t, v)
if (TREE_CODE (arg) == TYPE_DECL)
{
OB_PUTS ("class ");
OB_PUTID (DECL_NAME (arg));
if (DECL_NAME (arg))
OB_PUTID (DECL_NAME (arg));
else
OB_PUTS ("{anon}");
}
else
dump_decl (arg, 1);
......@@ -786,7 +871,8 @@ dump_decl (t, v)
OB_PUTC ('<');
for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args))
{
if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (args))) == 't')
if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (args))) == 't'
|| TREE_CODE (TREE_VALUE (args)) == TEMPLATE_DECL)
dump_type (TREE_VALUE (args), 0);
else
dump_expr (TREE_VALUE (args), 0);
......@@ -995,7 +1081,8 @@ dump_function_name (t)
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't')
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
......@@ -1023,7 +1110,8 @@ dump_function_name (t)
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't')
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
......
......@@ -1606,7 +1606,8 @@ is_aggr_typedef (name, or_else)
}
if (! IS_AGGR_TYPE (type)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
{
if (or_else)
cp_error ("`%T' is not an aggregate type", type);
......@@ -1627,7 +1628,8 @@ is_aggr_type (type, or_else)
return 0;
if (! IS_AGGR_TYPE (type)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
{
if (or_else)
cp_error ("`%T' is not an aggregate type", type);
......@@ -1658,7 +1660,8 @@ get_aggr_from_typedef (name, or_else)
}
if (! IS_AGGR_TYPE (type)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
{
if (or_else)
cp_error ("type `%T' is of non-aggregate type", type);
......
......@@ -73,6 +73,7 @@ static void do_build_copy_constructor PROTO((tree));
static tree largest_union_member PROTO((tree));
static tree build_decl_overload_real PROTO((tree, tree, tree, tree,
tree, int));
static void build_template_template_parm_names PROTO((tree));
static void build_template_parm_names PROTO((tree, tree));
static void build_underscore_int PROTO((int));
......@@ -388,8 +389,11 @@ build_overload_nested_name (decl)
{
tree context = DECL_CONTEXT (decl);
/* For a template type parameter, we want to output an 'Xn'
rather than 'T' or some such. */
if (TREE_CODE (context) == TEMPLATE_TYPE_PARM)
rather than 'T' or some such. For a template template
parameter, we also want an extra prefix 'z' and the
parameter list. */
if (TREE_CODE (context) == TEMPLATE_TYPE_PARM
|| TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM)
build_overload_name (context, 0, 0);
else
{
......@@ -661,6 +665,41 @@ build_overload_value (type, value, in_template)
}
/* Add encodings for the declaration of template template parameters.
PARMLIST must be a TREE_VEC */
static void
build_template_template_parm_names (parmlist)
tree parmlist;
{
int i, nparms;
my_friendly_assert (TREE_CODE (parmlist) == TREE_VEC, 246.5);
nparms = TREE_VEC_LENGTH (parmlist);
icat (nparms);
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
if (TREE_CODE (parm) == TYPE_DECL)
{
/* This parameter is a type. */
OB_PUTC ('Z');
}
else if (TREE_CODE (parm) == TEMPLATE_DECL)
{
/* This parameter is a template. */
OB_PUTC ('z');
build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
}
else
{
/* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0);
}
}
}
/* Add encodings for the vector of template parameters in PARMLIST,
given the vector of arguments to be substituted in ARGLIST. */
......@@ -683,6 +722,23 @@ build_template_parm_names (parmlist, arglist)
OB_PUTC ('Z');
build_overload_name (arg, 0, 0);
}
else if (TREE_CODE (parm) == TEMPLATE_DECL)
{
/* This parameter is a template. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
/* Output parameter declaration, argument index and level */
build_overload_name (arg, 0, 0);
else
{
/* A TEMPLATE_DECL node, output the parameter declaration
and template name */
OB_PUTC ('z');
build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
icat (IDENTIFIER_LENGTH (DECL_NAME (arg)));
OB_PUTID (DECL_NAME (arg));
}
}
else
{
parm = tsubst (parm, arglist,
......@@ -1053,6 +1109,34 @@ build_overload_name (parmtypes, begin, end)
OB_PUTC ('v');
break;
case TEMPLATE_TEMPLATE_PARM:
/* Find and output the original template parameter
declaration. */
if (CLASSTYPE_TEMPLATE_INFO (parmtype))
{
OB_PUTC ('t');
OB_PUTC ('z');
OB_PUTC ('X');
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
build_template_parm_names (
DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
CLASSTYPE_TI_ARGS (parmtype));
}
else
{
OB_PUTC ('Z');
OB_PUTC ('z');
OB_PUTC ('X');
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
build_template_template_parm_names (
DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype)));
}
break;
case TEMPLATE_TYPE_PARM:
OB_PUTC ('X');
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -71,6 +71,12 @@ extern tree strip_attrs PROTO((tree));
error message if the user supplies an empty conditional expression. */
static char *cond_stmt_keyword;
/* If nonzero, we try to treat TEMPLATE_DECL as argument in template
template parameter. */
static int processing_template_arg;
extern int arg_looking_for_template;
static tree empty_parms PROTO((void));
static tree finish_member_template_decl PROTO((tree, tree));
......@@ -222,7 +228,7 @@ finish_member_template_decl (template_arguments, decl)
%type <code> unop
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist
%type <ttype> PFUNCNAME
%type <ttype> PFUNCNAME maybe_identifier
%type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
%type <ttype> reserved_declspecs boolean.literal
......@@ -284,9 +290,10 @@ finish_member_template_decl (template_arguments, decl)
%type <ttype> nonmomentary_expr maybe_parmlist
%type <itype> initdcl0 notype_initdcl0 member_init_list
%type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type_parm
%type <ttype> template_type_parm template_template_parm
%type <code> template_close_bracket
%type <ttype> template_type template_arg_list template_arg_list_opt template_arg
%type <ttype> template_type template_arg_list template_arg_list_opt
%type <ttype> template_arg template_arg1
%type <ttype> condition xcond paren_cond_or_null
%type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
%type <ttype> complete_type_name notype_identifier nonnested_type
......@@ -473,11 +480,16 @@ template_parm_list:
{ $$ = process_template_parm ($1, $3); }
;
maybe_identifier:
identifier
{ $$ = $1; }
| /* empty */
{ $$ = NULL_TREE; }
template_type_parm:
aggr
aggr maybe_identifier
{
$$ = build_tree_list ($1, NULL_TREE);
ttpa:
$$ = build_tree_list ($1, $2);
if (TREE_PURPOSE ($$) == signature_type_node)
sorry ("signature as template type parameter");
else if (TREE_PURPOSE ($$) != class_type_node)
......@@ -486,14 +498,28 @@ template_type_parm:
TREE_PURPOSE ($$) = class_type_node;
}
}
| aggr identifier
{ $$ = build_tree_list ($1, $2); goto ttpa; }
| TYPENAME_KEYWORD
{ $$ = build_tree_list (class_type_node, NULL_TREE); }
| TYPENAME_KEYWORD identifier
| TYPENAME_KEYWORD maybe_identifier
{ $$ = build_tree_list (class_type_node, $2); }
;
template_template_parm:
template_header aggr maybe_identifier
{
tree decl = build_decl (TYPE_DECL, $3, NULL_TREE);
tree tmpl = build_lang_decl (TEMPLATE_DECL, $3, NULL_TREE);
DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
DECL_TEMPLATE_RESULT (tmpl) = decl;
SET_DECL_ARTIFICIAL (decl);
end_template_decl ();
if ($2 == signature_type_node)
sorry ("signature as template template parameter");
else if ($2 != class_type_node)
pedwarn ("template template parameters must use the keyword `class'");
$$ = build_tree_list (class_type_node, tmpl);
}
;
template_parm:
/* The following rules introduce a new reduce/reduce
conflict on the ',' and '>' input tokens: they are valid
......@@ -510,6 +536,21 @@ template_parm:
{ $$ = build_tree_list (NULL_TREE, $1.t); }
| parm '=' expr_no_commas %prec ARITHCOMPARE
{ $$ = build_tree_list ($3, $1.t); }
| template_template_parm
{ $$ = build_tree_list (NULL_TREE, $1); }
| template_template_parm '=' PTYPENAME
{
tree defarg;
arg_looking_for_template = 1;
defarg = lookup_name ($3, 0);
arg_looking_for_template = 0;
if (!defarg || defarg == error_mark_node
|| (TREE_CODE (defarg) != TEMPLATE_DECL
&& TREE_CODE (defarg) != TEMPLATE_TEMPLATE_PARM))
defarg = do_identifier ($3, 1);
$$ = build_tree_list (defarg, $1);
}
;
template_def:
......@@ -945,6 +986,12 @@ template_arg_list:
;
template_arg:
{ processing_template_arg = 1; }
template_arg1
{ $$ = $2;
processing_template_arg = 0; }
template_arg1:
type_id
{ $$ = groktypename ($1.t); }
| expr_no_commas %prec ARITHCOMPARE
......@@ -1360,7 +1407,21 @@ primary:
if (TREE_CODE ($$) == BIT_NOT_EXPR)
$$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0));
else if (TREE_CODE ($$) != TEMPLATE_ID_EXPR)
$$ = do_identifier ($$, 1);
if (processing_template_arg)
{
tree id;
arg_looking_for_template = processing_template_arg;
id = lookup_name ($$, 0);
arg_looking_for_template = 0;
if (!id || id == error_mark_node
|| (TREE_CODE (id) != TEMPLATE_DECL
&& TREE_CODE (id) != TEMPLATE_TEMPLATE_PARM))
id = do_identifier ($$, 1);
$$ = id;
}
else
$$ = do_identifier ($$, 1);
}
| CONSTANT
| boolean.literal
......@@ -3014,7 +3075,10 @@ nonnested_type:
{
if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
arg_looking_for_template = processing_template_arg;
$$ = lookup_name ($1, 1);
arg_looking_for_template = 0;
if (current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& ! IDENTIFIER_CLASS_VALUE ($1))
......@@ -4247,7 +4311,8 @@ bad_parm:
{
error ("type specifier omitted for parameter");
if (TREE_CODE ($$) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TYPE_PARM)
&& (TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TYPE_PARM
|| TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TEMPLATE_PARM))
cp_error (" perhaps you want `typename %E' to make it a type", $$);
$$ = build_tree_list (integer_type_node, $$);
}
......
......@@ -2471,7 +2471,8 @@ dfs_walk (binfo, fn, qfn)
if (qfn == 0 || (*qfn)(base_binfo))
{
if (TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TYPE_PARM)
if (TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TYPE_PARM
|| TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TEMPLATE_PARM)
/* Pass */;
else if (fn == dfs_init_vbase_pointers)
{
......@@ -3134,7 +3135,8 @@ dfs_record_inheritance (binfo)
tree baseclass = BINFO_TYPE (base_binfo);
mi_boolean *base_row = BINFO_DERIVES_FROM_STAR (base_binfo);
if (TREE_CODE (baseclass) == TEMPLATE_TYPE_PARM)
if (TREE_CODE (baseclass) == TEMPLATE_TYPE_PARM
|| TREE_CODE (baseclass) == TEMPLATE_TEMPLATE_PARM)
continue;
my_friendly_assert (CLASSTYPE_CID (baseclass) != 0, 2365);
......
......@@ -1438,6 +1438,27 @@ build_exception_variant (type, raises)
return v;
}
/* Given a TEMPLATE_TEMPLATE_PARM node T, create a new one together with its
lang_specific field and its corresponding TEMPLATE_DECL node */
tree
copy_template_template_parm (t)
tree t;
{
tree template = TYPE_NAME (t);
tree t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
template = copy_node (template);
copy_lang_decl (template);
TREE_TYPE (template) = t2;
TYPE_NAME (t2) = template;
TYPE_STUB_DECL (t2) = template;
/* No need to copy these */
TYPE_FIELDS (t2) = TYPE_FIELDS (t);
CLASSTYPE_TEMPLATE_INFO (t2) = CLASSTYPE_TEMPLATE_INFO (t);
return t2;
}
/* Subroutine of copy_to_permanent
Assuming T is a node build bottom-up, make it all exist on
......@@ -1629,6 +1650,9 @@ mapcar (t, func)
CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func);
return t;
case TEMPLATE_TEMPLATE_PARM:
return copy_template_template_parm (t);
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
......
......@@ -836,6 +836,37 @@ comptypes (type1, type2, strict)
val = comp_array_types (comptypes, t1, t2, strict);
break;
case TEMPLATE_TEMPLATE_PARM:
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2))
return 0;
if (CLASSTYPE_TEMPLATE_INFO (t1) && CLASSTYPE_TEMPLATE_INFO (t2))
{
int i = TREE_VEC_LENGTH (CLASSTYPE_TI_ARGS (t1));
tree *p1 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t1), 0);
tree *p2 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t2), 0);
while (i--)
{
if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
{
if (! comptypes (p1[i], p2[i], 1))
return 0;
}
else
{
if (simple_cst_equal (p1[i], p2[i]) <= 0)
return 0;
}
}
return 1;
}
else if (CLASSTYPE_TEMPLATE_INFO (t1) || CLASSTYPE_TEMPLATE_INFO (t2))
return 0;
else
return 1;
case TEMPLATE_TYPE_PARM:
return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2)
&& TEMPLATE_TYPE_LEVEL (t1) == TEMPLATE_TYPE_LEVEL (t2);
......
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