Template as template parameter patch
Kriang Lerdsuwanakij
lerdsuwa@scf-fs.usc.edu
Tue Feb 10 03:34:00 GMT 1998
Hi,
The included patch is my implementation of template template parameter
together with test cases. The patch is against egcs-971225. It passes
the regression test. Only 2 new test cases (ttp22.C and ttp23.C) fails.
I will post a fix to these 2 cases as a separate patch since it has
nothing to do with template template parameter. (The failure is due to
deriving a template class, the base class name D should not be introduced
to the derived class scope to mean D<int>.)
Implementation details:
The design involves a new TEMPLATE_TEMPLATE_PARM node. It is similar to
TEMPLATE_TYPE_PARM except that its TYPE_NAME is a TEMPLATE_DECL and its
template arguments, if present, are kept inside the template_info field.
Most of the changes are TEMPLATE_TEMPLATE_PARM and TEMPLATE_DECL handling.
In tsubst(), a TEMPLATE_TEMPLATE_PARM with template arguments (which is a
type using template template parameter like TT<int>) is turned into a
RECORD_TYPE while the one without template arguments (template template
paramter that is part of template signature like int f<TT>() ) is turned
into a TEMPLATE_DECL.
For name mangling, a special character 'z' is used in signatures that
contain template template parameters. If used as a type, template name is
encoded as zX??. As a comparison, ordinary template uses <length of
template name>+<template name> .
If used as template argument in signature, the argument is encoded as
z + <number of arguments> + <argument list>
+ <length of substituted template name> + <subst. template name>
(Ordinary type parameter is encoded as Z + <substituded type> .)
Enjoy!
Kriang
===============================================================
Changelog entry for gcc/ and libiberty/
Tue Jan 13 17:33:34 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* cplus-dem.c (demangle_template_template_parm): New function.
(demangle_template): Handle template template parameters.
Changelog entry for gcc/cp/
Tue Jan 13 17:33:34 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* 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.
============== Diff for cplus-dem.c in gcc/ and libiberty/ ================
diff -rNpu3 gcc-old/cplus-dem.c gcc/cplus-dem.c
--- gcc-old/cplus-dem.c Sat Jan 10 02:25:42 1998
+++ gcc/cplus-dem.c Tue Jan 13 17:33:34 1998
@@ -223,6 +223,10 @@ demangle_method_args PARAMS ((struct wor
#endif
static int
+demangle_template_template_parm PARAMS ((struct work_stuff *work,
+ const char **, string *));
+
+static int
demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
string *, int));
@@ -923,6 +927,70 @@ demangle_method_args (work, mangled, dec
#endif
static int
+demangle_template_template_parm (work, mangled, tname)
+ struct work_stuff *work;
+ const char **mangled;
+ string *tname;
+{
+ int i;
+ int r;
+ int need_comma = 0;
+ int success = 1;
+ string temp;
+
+ string_append (tname, "template <");
+ /* get size of template parameter list */
+ if (get_count (mangled, &r))
+ {
+ for (i = 0; i < r; i++)
+ {
+ if (need_comma)
+ {
+ string_append (tname, ", ");
+ }
+
+ /* Z for type parameters */
+ if (**mangled == 'Z')
+ {
+ (*mangled)++;
+ string_append (tname, "class");
+ }
+ /* z for template parameters */
+ else if (**mangled == 'z')
+ {
+ (*mangled)++;
+ success =
+ demangle_template_template_parm (work, mangled, tname);
+ if (!success)
+ {
+ break;
+ }
+ }
+ else
+ {
+ /* temp is initialized in do_type */
+ success = do_type (work, mangled, &temp);
+ if (success)
+ {
+ string_appends (tname, &temp);
+ }
+ string_delete(&temp);
+ if (!success)
+ {
+ break;
+ }
+ }
+ need_comma = 1;
+ }
+
+ }
+ if (tname->p[-1] == '>')
+ string_append (tname, " ");
+ string_append (tname, "> class");
+ return (success);
+}
+
+static int
demangle_template (work, mangled, tname, trawname, is_type)
struct work_stuff *work;
const char **mangled;
@@ -951,19 +1019,50 @@ demangle_template (work, mangled, tname,
{
start = *mangled;
/* get template name */
- if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
+ if (**mangled == 'z')
{
- return (0);
+ int idx;
+ (*mangled)++;
+ (*mangled)++;
+
+ idx = consume_count_with_underscores (mangled);
+ if (idx == -1
+ || (work->tmpl_argvec && idx >= work->ntmpl_args)
+ || consume_count_with_underscores (mangled) == -1)
+ {
+ return (0);
+ }
+ if (work->tmpl_argvec)
+ {
+ string_append (tname, work->tmpl_argvec[idx]);
+ if (trawname)
+ string_append (trawname, work->tmpl_argvec[idx]);
+ }
+ else
+ {
+ char buf[10];
+ sprintf(buf, "T%d", idx);
+ string_append (tname, buf);
+ if (trawname)
+ string_append (trawname, work->tmpl_argvec[idx]);
+ }
}
- if (trawname)
- string_appendn (trawname, *mangled, r);
- is_java_array = (work -> options & DMGL_JAVA)
- && strncmp (*mangled, "JArray1Z", 8) == 0;
- if (! is_java_array)
+ else
{
- string_appendn (tname, *mangled, r);
+ if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
+ {
+ return (0);
+ }
+ if (trawname)
+ string_appendn (trawname, *mangled, r);
+ is_java_array = (work -> options & DMGL_JAVA)
+ && strncmp (*mangled, "JArray1Z", 8) == 0;
+ if (! is_java_array)
+ {
+ string_appendn (tname, *mangled, r);
+ }
+ *mangled += r;
}
- *mangled += r;
}
if (!is_java_array)
string_append (tname, "<");
@@ -1006,6 +1105,33 @@ demangle_template (work, mangled, tname,
}
}
string_delete(&temp);
+ if (!success)
+ {
+ break;
+ }
+ }
+ /* z for template parameters */
+ else if (**mangled == 'z')
+ {
+ int r2;
+ (*mangled)++;
+ success = demangle_template_template_parm (work, mangled, tname);
+
+ if (success
+ && (r2 = consume_count (mangled)) > 0 && strlen (*mangled) >= r2)
+ {
+ string_append (tname, " ");
+ string_appendn (tname, *mangled, r2);
+ if (!is_type)
+ {
+ /* Save the template argument. */
+ int len = r2;
+ work->tmpl_argvec[i] = xmalloc (len + 1);
+ memcpy (work->tmpl_argvec[i], *mangled, len);
+ work->tmpl_argvec[i][len] = '\0';
+ }
+ *mangled += r2;
+ }
if (!success)
{
break;
============== Diff for files in gcc/cp/ and gcc/testsuite/ ================
diff -rNpu3 gcc-old/cp/class.c gcc/cp/class.c
--- gcc-old/cp/class.c Sat Jan 10 02:27:52 1998
+++ gcc/cp/class.c Sat Jan 10 02:27:33 1998
@@ -4506,7 +4506,8 @@ finish_struct (t, list_of_fieldlists, at
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. */
@@ -4870,7 +4871,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));
diff -rNpu3 gcc-old/cp/cp-tree.def gcc/cp/cp-tree.def
--- gcc-old/cp/cp-tree.def Sat Jan 10 02:27:52 1998
+++ gcc/cp/cp-tree.def Sat Jan 10 02:27:33 1998
@@ -91,6 +91,12 @@ DEFTREECODE (TEMPLATE_DECL, "template_de
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)
diff -rNpu3 gcc-old/cp/cp-tree.h gcc/cp/cp-tree.h
--- gcc-old/cp/cp-tree.h Sat Jan 10 02:27:52 1998
+++ gcc/cp/cp-tree.h Sat Jan 10 02:27:33 1998
@@ -1348,6 +1348,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)
@@ -1917,11 +1923,13 @@ extern tree current_class_type; /* _TYPE
#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) \
@@ -2450,6 +2458,7 @@ extern int promotes_to_aggr_type PROTO(
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
diff -rNpu3 gcc-old/cp/decl.c gcc/cp/decl.c
--- gcc-old/cp/decl.c Sat Jan 10 02:27:52 1998
+++ gcc/cp/decl.c Sat Jan 10 02:27:33 1998
@@ -397,6 +397,9 @@ static struct named_label_list *named_la
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.
@@ -3038,7 +3041,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)
@@ -4468,6 +4472,7 @@ lookup_name_real (name, prefer_type, non
}
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;
@@ -4601,7 +4606,13 @@ lookup_name_real (name, prefer_type, non
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))
@@ -8100,7 +8111,7 @@ grokdeclarator (declarator, declspecs, d
}
}
/* 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,
@@ -10486,7 +10497,8 @@ grok_op_properties (decl, virtualp, frie
/* 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
@@ -10715,12 +10727,14 @@ xref_tag (code_type_node, name, binfo, g
}
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);
@@ -10917,7 +10931,8 @@ xref_basetypes (code_type_node, name, re
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));
diff -rNpu3 gcc-old/cp/decl2.c gcc/cp/decl2.c
--- gcc-old/cp/decl2.c Sat Jan 10 02:27:52 1998
+++ gcc/cp/decl2.c Sat Jan 10 02:27:33 1998
@@ -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)))
{
diff -rNpu3 gcc-old/cp/error.c gcc/cp/error.c
--- gcc-old/cp/error.c Sat Jan 10 02:27:52 1998
+++ gcc/cp/error.c Sat Jan 10 02:27:33 1998
@@ -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);
@@ -977,7 +1063,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);
@@ -1004,7 +1091,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);
diff -rNpu3 gcc-old/cp/init.c gcc/cp/init.c
--- gcc-old/cp/init.c Sat Jan 10 02:27:52 1998
+++ gcc/cp/init.c Sat Jan 10 02:27:33 1998
@@ -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);
diff -rNpu3 gcc-old/cp/method.c gcc/cp/method.c
--- gcc-old/cp/method.c Sat Jan 10 02:27:53 1998
+++ gcc/cp/method.c Sat Jan 10 02:40:59 1998
@@ -73,6 +73,7 @@ static void do_build_copy_constructor PR
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_te
}
+/* 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, arg
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,
@@ -1049,6 +1105,34 @@ build_overload_name (parmtypes, begin, e
case UNKNOWN_TYPE:
/* This will take some work. */
OB_PUTC ('?');
+ 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:
diff -rNpu3 gcc-old/cp/parse.y gcc/cp/parse.y
--- gcc-old/cp/parse.y Sat Jan 10 02:27:53 1998
+++ gcc/cp/parse.y Sat Jan 10 02:27:34 1998
@@ -72,6 +72,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));
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
@@ -196,7 +202,7 @@ empty_parms ()
%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
@@ -258,9 +264,9 @@ empty_parms ()
%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
+%type <ttype> template_type template_arg_list 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
@@ -447,11 +453,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)
@@ -460,14 +471,31 @@ 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'");
+ TREE_PURPOSE ($$) = class_type_node;
+ }
+ $$ = 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
@@ -484,6 +512,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:
@@ -935,6 +978,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
@@ -1353,7 +1402,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
@@ -3018,7 +3081,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))
diff -rNpu3 gcc-old/cp/pt.c gcc/cp/pt.c
--- gcc-old/cp/pt.c Sat Jan 10 02:27:53 1998
+++ gcc/cp/pt.c Tue Jan 13 17:10:23 1998
@@ -108,6 +108,7 @@ begin_member_template_processing (decl)
switch (TREE_CODE (parm))
{
case TYPE_DECL:
+ case TEMPLATE_DECL:
pushdecl (parm);
break;
@@ -665,6 +666,8 @@ process_template_parm (list, next)
if (TREE_CODE (p) == TYPE_DECL)
idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
+ else if (TREE_CODE (p) == TEMPLATE_DECL)
+ idx = TEMPLATE_TYPE_IDX (TREE_TYPE (DECL_TEMPLATE_RESULT (p)));
else
idx = TEMPLATE_CONST_IDX (DECL_INITIAL (p));
++idx;
@@ -710,9 +713,26 @@ process_template_parm (list, next)
}
else
{
- tree t = make_lang_type (TEMPLATE_TYPE_PARM);
+ tree t;
+ parm = TREE_VALUE (parm);
+
+ if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ t = make_lang_type (TEMPLATE_TEMPLATE_PARM);
+ /* This is for distinguishing between real templates and template
+ template parameters */
+ TREE_TYPE (parm) = t;
+ TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t;
+ decl = parm;
+ }
+ else
+ {
+ t = make_lang_type (TEMPLATE_TYPE_PARM);
+ /* parm is either IDENTIFIER_NODE or NULL_TREE */
+ decl = build_decl (TYPE_DECL, parm, t);
+ }
+
CLASSTYPE_GOT_SEMICOLON (t) = 1;
- decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t);
TYPE_NAME (t) = decl;
TYPE_STUB_DECL (t) = decl;
parm = decl;
@@ -791,7 +811,8 @@ current_template_args ()
{
t = TREE_VALUE (t);
- if (TREE_CODE (t) == TYPE_DECL)
+ if (TREE_CODE (t) == TYPE_DECL
+ || TREE_CODE (t) == TEMPLATE_DECL)
t = TREE_TYPE (t);
else
t = DECL_INITIAL (t);
@@ -970,6 +991,7 @@ coerce_template_parms (parms, arglist, i
tree in_decl;
{
int nparms, nargs, i, lost = 0;
+ int is_tmpl_parm = 0;
tree vec;
if (arglist == NULL_TREE)
@@ -993,7 +1015,23 @@ coerce_template_parms (parms, arglist, i
}
if (arglist && TREE_CODE (arglist) == TREE_VEC)
- vec = copy_node (arglist);
+ if (nargs == nparms)
+ vec = copy_node (arglist);
+ else
+ {
+ /* We arrive here when a template is used in template template
+ parameter with some default arguments */
+ is_tmpl_parm = 1;
+ vec = make_tree_vec (nparms);
+ for (i = 0; i < nparms; i++)
+ {
+ tree arg = TREE_VEC_ELT (arglist, i);
+ if (arg)
+ TREE_VEC_ELT (vec, i) = arg;
+ else
+ TREE_VEC_ELT (vec, i) = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+ }
+ }
else
{
vec = make_tree_vec (nparms);
@@ -1027,10 +1065,32 @@ coerce_template_parms (parms, arglist, i
tree arg = TREE_VEC_ELT (vec, i);
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
tree val = 0;
- int is_type, requires_type;
- is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
- requires_type = TREE_CODE (parm) == TYPE_DECL;
+ int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
+
+ /* In case we are checking arguments inside a template template
+ parameter, ARG that does not come from default argument is
+ also a TREE_LIST node */
+ if (TREE_CODE (arg) == TREE_LIST)
+ {
+ is_tmpl_parm = 1;
+ arg = TREE_VALUE (arg);
+ }
+
+ /* Check if it is a class template. */
+ is_tmpl_type = (TREE_CODE (arg) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
+ || (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ && !CLASSTYPE_TEMPLATE_INFO (arg));
+ if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_STUB_DECL (arg);
+
+ requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
+ is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
+ || is_tmpl_type
+ || (is_tmpl_parm && TREE_CODE (arg) == TYPE_DECL);
+ requires_type = TREE_CODE (parm) == TYPE_DECL
+ || requires_tmpl_type;
if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
@@ -1049,7 +1109,8 @@ coerce_template_parms (parms, arglist, i
i, in_decl);
if (is_type)
cp_error (" expected a constant of type `%T', got `%T'",
- TREE_TYPE (parm), arg);
+ TREE_TYPE (parm),
+ (is_tmpl_type ? DECL_NAME (arg) : arg));
else
cp_error (" expected a type, got `%E'", arg);
}
@@ -1057,18 +1118,77 @@ coerce_template_parms (parms, arglist, i
TREE_VEC_ELT (vec, i) = error_mark_node;
continue;
}
+ if (is_tmpl_type ^ requires_tmpl_type)
+ {
+ if (in_decl)
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i, in_decl);
+ if (is_tmpl_type)
+ cp_error (" expected a type, got `%T'", DECL_NAME (arg));
+ else
+ cp_error (" expected a class template, got `%T'", arg);
+ }
+ lost++;
+ TREE_VEC_ELT (vec, i) = error_mark_node;
+ continue;
+ }
+ if (is_tmpl_parm)
+ {
+ if (requires_tmpl_type)
+ {
+ cp_error ("nested template template parameter not implemented");
+ lost++;
+ TREE_VEC_ELT (vec, i) = error_mark_node;
+ }
+ continue;
+ }
+
if (is_type)
{
- val = groktypename (arg);
- if (! processing_template_decl)
+ if (requires_tmpl_type)
+ {
+ if (!CLASSTYPE_TEMPLATE_INFO (parm))
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ /* The parameter and argument roles have to be switched
+ here in order to handle default arguments properly.
+ For example,
+ template<template <class> class TT> void f(TT<int>)
+ should be able to accept vector<int> which comes from
+ template <class T, class Allcator = allocator>
+ class vector. */
+
+ val = coerce_template_parms (argparm, parmparm, in_decl);
+ if (val != error_mark_node)
+ val = arg;
+
+ /* TEMPLATE_TEMPLATE_PARM node is preferred over
+ TEMPLATE_DECL. */
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
+ val = TREE_TYPE (val);
+ }
+ else
+ /* The parameter has been substituted with arguments.
+ We have already checked this */
+ val = arg;
+ }
+ else
{
- tree t = target_type (val);
- if (TREE_CODE (t) != TYPENAME_TYPE
- && IS_AGGR_TYPE (t)
- && decl_function_context (TYPE_MAIN_DECL (t)))
+ val = groktypename (arg);
+ if (! processing_template_decl)
{
- cp_error ("type `%T' composed from a local class is not a valid template-argument", val);
- return error_mark_node;
+ tree t = target_type (val);
+ if (TREE_CODE (t) != TYPENAME_TYPE
+ && IS_AGGR_TYPE (t)
+ && decl_function_context (TYPE_MAIN_DECL (t)))
+ {
+ cp_error ("type `%T' composed from a local class is not a valid template-argument",
+ val);
+ return error_mark_node;
+ }
}
}
}
@@ -1166,6 +1286,14 @@ comp_template_args (oldargs, newargs)
tree nt = TREE_VEC_ELT (newargs, i);
tree ot = TREE_VEC_ELT (oldargs, i);
+ /* It's messy because we introduce template template parameters
+ as TEMPLATE_DECL nodes in the class scope but store them in
+ TEMPLATE_INFO as a TEMPLATE_TEMPLATE_PARM nodes */
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (nt))
+ nt = TREE_TYPE (nt);
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (ot))
+ ot = TREE_TYPE (ot);
+
if (nt == ot)
continue;
if (TREE_CODE (nt) != TREE_CODE (ot))
@@ -1236,6 +1364,17 @@ mangle_class_name_for_template (name, pa
cat (type_as_string (arg, 0));
continue;
}
+ else if (TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ if (TREE_CODE (arg) == TEMPLATE_DECL)
+ /* Already substituted with real template. Just output
+ the template name here */
+ cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
+ else
+ /* Output the parameter declaration */
+ cat (type_as_string (arg, 0));
+ continue;
+ }
else
my_friendly_assert (TREE_CODE (parm) == PARM_DECL, 269);
@@ -1359,9 +1498,15 @@ lookup_template_class (d1, arglist, in_d
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
- template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
- if (! template)
- template = IDENTIFIER_CLASS_VALUE (d1);
+ if (IDENTIFIER_LOCAL_VALUE (d1)
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_LOCAL_VALUE (d1)))
+ template = IDENTIFIER_LOCAL_VALUE (d1);
+ else
+ {
+ template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
+ if (! template)
+ template = IDENTIFIER_CLASS_VALUE (d1);
+ }
}
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
{
@@ -1390,7 +1535,29 @@ lookup_template_class (d1, arglist, in_d
return error_mark_node;
}
- if (PRIMARY_TEMPLATE_P (template))
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+ {
+ /* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
+ template arguments */
+
+ tree parm = copy_template_template_parm (TREE_TYPE (template));
+ tree template2 = TYPE_STUB_DECL (parm);
+ tree arglist2;
+
+ CLASSTYPE_GOT_SEMICOLON (parm) = 1;
+ parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+
+ arglist2 = coerce_template_parms (parmlist, arglist, template);
+ if (arglist2 == error_mark_node)
+ return error_mark_node;
+
+ arglist2 = copy_to_permanent (arglist2);
+ CLASSTYPE_TEMPLATE_INFO (parm)
+ = perm_tree_cons (template2, arglist2, NULL_TREE);
+ TYPE_SIZE (parm) = 0;
+ return parm;
+ }
+ else if (PRIMARY_TEMPLATE_P (template))
{
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
@@ -1556,6 +1723,15 @@ uses_template_parms (t)
case TYPE_DECL:
return uses_template_parms (TREE_TYPE (t));
+ case TEMPLATE_DECL:
+ /* A template template parameter is encountered */
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
+ /* We are parsing a template declaration */
+ return 1;
+ /* We are instantiating templates with template template
+ parameter */
+ return 0;
+
case FUNCTION_DECL:
case VAR_DECL:
/* ??? What about FIELD_DECLs? */
@@ -1578,6 +1754,7 @@ uses_template_parms (t)
/* template parm nodes */
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_CONST_PARM:
return 1;
@@ -2168,12 +2345,14 @@ tsubst (t, args, nargs, in_decl)
}
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_CONST_PARM:
{
int idx;
int level;
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
idx = TEMPLATE_TYPE_IDX (t);
level = TEMPLATE_TYPE_LEVEL (t);
@@ -2203,6 +2382,29 @@ tsubst (t, args, nargs, in_decl)
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))
+ {
+ /* We are processing a data member constructed
+ from template template parameter */
+ tree argvec = tsubst (
+ TREE_VALUE (CLASSTYPE_TEMPLATE_INFO (t)),
+ args, nargs, in_decl);
+ tree r;
+
+ /* ARG is the real template to be instantiated. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_NAME (arg);
+ r = lookup_template_class (DECL_NAME (arg),
+ argvec, in_decl);
+ return cp_build_type_variant (r, TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
+ }
+ else
+ /* We are processing a template argument list. */
+ return arg;
+ }
else
return arg;
}
@@ -2213,6 +2415,8 @@ tsubst (t, args, nargs, in_decl)
my_friendly_assert((TREE_CODE (t) == TEMPLATE_CONST_PARM
&& TEMPLATE_CONST_LEVEL (t) > 1)
|| (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ && TEMPLATE_TYPE_LEVEL (t) > 1)
+ || (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
&& TEMPLATE_TYPE_LEVEL (t) > 1),
0);
return t;
@@ -3125,6 +3329,7 @@ tsubst_copy (t, args, nargs, in_decl)
case ENUMERAL_TYPE:
case INTEGER_TYPE:
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_CONST_PARM:
case POINTER_TYPE:
case REFERENCE_TYPE:
@@ -3850,6 +4055,79 @@ unify (tparms, targs, ntparms, parm, arg
return 1;
targs[idx] = arg;
return 0;
+
+ case TEMPLATE_TEMPLATE_PARM:
+ (*nsubsts)++;
+ idx = TEMPLATE_TYPE_IDX (parm);
+ /* Check for mixed types and values. */
+ if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TEMPLATE_DECL)
+ return 1;
+
+ if (!strict && targs[idx] != NULL_TREE &&
+ TREE_CODE (targs[idx]) == NOP_EXPR)
+ /* An explicit template argument. Don't even try to match
+ here; the overload resolution code will manage check to
+ see whether the call is legal. */
+ return 0;
+
+ if (CLASSTYPE_TEMPLATE_INFO (parm))
+ {
+ /* We arrive here when PARM does not involve template
+ specialization. */
+
+ /* ARG must be constructed from a template class. */
+ if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
+ return 1;
+
+ {
+ tree parmtmpl = CLASSTYPE_TI_TEMPLATE (parm);
+ tree parmvec = CLASSTYPE_TI_ARGS (parm);
+ tree argvec = CLASSTYPE_TI_ARGS (arg);
+ tree argtmplvec
+ = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
+ int i, j;
+
+ /* The parameter and argument roles have to be switched here
+ in order to handle default arguments properly. For example,
+ template<template <class> class TT> void f(TT<int>)
+ should be able to accept vector<int> which comes from
+ template <class T, class Allcator = allocator>
+ class vector. */
+
+ if (coerce_template_parms (argtmplvec, parmvec, parmtmpl)
+ == error_mark_node)
+ return 1;
+
+ /* Deduce arguments T, i from TT<T> or TT<i>. */
+ for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
+ {
+ tree t = TREE_VEC_ELT (parmvec, i);
+ if (TREE_CODE (t) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
+ && TREE_CODE (t) != TEMPLATE_CONST_PARM)
+ continue;
+
+ /* This argument can be deduced. */
+
+ if (unify (tparms, targs, ntparms, t,
+ TREE_VEC_ELT (argvec, i), nsubsts, strict))
+ return 1;
+ }
+ }
+ arg = CLASSTYPE_TI_TEMPLATE (arg);
+ }
+
+ /* Simple cases: Value already set, does match or doesn't. */
+ if (targs[idx] == arg
+ || (targs[idx]
+ && TREE_CODE (targs[idx]) == NOP_EXPR
+ && TREE_OPERAND (targs[idx], 0) == arg))
+ return 0;
+ else if (targs[idx])
+ return 1;
+ targs[idx] = arg;
+ return 0;
+
case TEMPLATE_CONST_PARM:
(*nsubsts)++;
idx = TEMPLATE_CONST_IDX (parm);
diff -rNpu3 gcc-old/cp/search.c gcc/cp/search.c
--- gcc-old/cp/search.c Sat Jan 10 02:27:53 1998
+++ gcc/cp/search.c Sat Jan 10 02:27:34 1998
@@ -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);
diff -rNpu3 gcc-old/cp/tree.c gcc/cp/tree.c
--- gcc-old/cp/tree.c Sat Jan 10 02:27:53 1998
+++ gcc/cp/tree.c Sat Jan 10 02:27:34 1998
@@ -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
@@ -1624,6 +1645,9 @@ mapcar (t, func)
t = copy_node (t);
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))
diff -rNpu3 gcc-old/cp/typeck.c gcc/cp/typeck.c
--- gcc-old/cp/typeck.c Sat Jan 10 02:27:54 1998
+++ gcc/cp/typeck.c Tue Jan 13 17:10:31 1998
@@ -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);
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp1.C gcc/testsuite/g++.old-deja/g++.pt/ttp1.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp1.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp1.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,14 @@
+// Build don't link:
+
+template<class E> class D
+{
+};
+
+template<template<class> class D,class E> class C
+{
+};
+
+int main()
+{
+ C<int,D> c; // ERROR - args not match
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp10.C gcc/testsuite/g++.old-deja/g++.pt/ttp10.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp10.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp10.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,30 @@
+// Build don't link:
+
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D d; // ERROR - D is a template
+ public:
+ int f();
+};
+
+template<template<class> class D,class E> int C<D,E>::f()
+{
+ return d.f(); // ERROR - d not properly declared
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp11.C gcc/testsuite/g++.old-deja/g++.pt/ttp11.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp11.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp11.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,25 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { return d.f(); }
+};
+
+int main()
+{
+ C<D,int> c;
+ C<D,char> d;
+ c.f();
+ d.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp12.C gcc/testsuite/g++.old-deja/g++.pt/ttp12.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp12.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp12.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,28 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class E,class D> class C
+{
+ E<D> d;
+ public:
+ int f();
+};
+
+template<template<class> class E,class D> int C<E,D>::f()
+{
+ return d.f();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp13.C gcc/testsuite/g++.old-deja/g++.pt/ttp13.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp13.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp13.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,28 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f();
+};
+
+template<template<class> class D,class E> int C<D,E>::f()
+{
+ return d.f();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp14.C gcc/testsuite/g++.old-deja/g++.pt/ttp14.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp14.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp14.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,30 @@
+template<class T> class D
+{
+ T a;
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<class E,template<class> class DD = D> class C
+{
+ DD<E> d;
+ public:
+ int f();
+};
+
+template<class E,template<class> class DD = D> int C<E,DD>::f()
+{
+ DD<E> d2;
+ return d2.f();
+}
+
+int main()
+{
+ C<int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp15.C gcc/testsuite/g++.old-deja/g++.pt/ttp15.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp15.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp15.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,29 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f();
+};
+
+template<template<class> class D,class E> int C<D,E>::f()
+{
+ D<E> d2;
+ return d2.f();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp16.C gcc/testsuite/g++.old-deja/g++.pt/ttp16.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp16.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp16.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,30 @@
+template<class T> class D
+{
+ T a;
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f();
+};
+
+template<template<class> class D,class E> int C<D,E>::f()
+{
+ D<E> d2;
+ return d2.f();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp17.C gcc/testsuite/g++.old-deja/g++.pt/ttp17.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp17.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp17.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,30 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f();
+ int g() { return 0; }
+};
+
+template<template<class> class D,class E> int C<D,E>::f()
+{
+ C<D,E> d2;
+ return d2.g();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp18.C gcc/testsuite/g++.old-deja/g++.pt/ttp18.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp18.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp18.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,30 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f();
+ int g() { return 0; }
+};
+
+template<template<class> class D,class E> int C<D,E>::f()
+{
+ C<D,char> d2;
+ return d2.g();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp19.C gcc/testsuite/g++.old-deja/g++.pt/ttp19.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp19.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp19.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,24 @@
+#include <vector>
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int size() { return d.size(); }
+};
+
+template<template<class> class D,class E> int size(D<E> &d1)
+{
+ d1.size();
+ C<D,E> d2;
+ d2.size();
+ return 0;
+}
+
+int main()
+{
+ std::vector<int> c1;
+ std::vector<char> c2;
+ size(c1);
+ size(c2);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp2.C gcc/testsuite/g++.old-deja/g++.pt/ttp2.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp2.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp2.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,14 @@
+// Build don't link:
+
+template<class E> class D
+{
+};
+
+template<template<class> class D,int> class C
+{
+};
+
+int main()
+{
+ C<1,D> c; // ERROR - args not match
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp20.C gcc/testsuite/g++.old-deja/g++.pt/ttp20.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp20.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp20.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,27 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C : D<E>
+{
+ public:
+ int g();
+};
+
+template<template<class> class D,class E> int C<D,E>::g()
+{
+ return f();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.g();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp21.C gcc/testsuite/g++.old-deja/g++.pt/ttp21.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp21.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp21.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,33 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C : D<E>
+{
+ public:
+ int g();
+};
+
+template<template<class> class D,class E> int C<D,E>::g()
+{
+ return f();
+}
+
+class E : C<D,int>
+{
+ public:
+ int h() { return g(); }
+};
+
+int main()
+{
+ E c;
+ c.h();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp22.C gcc/testsuite/g++.old-deja/g++.pt/ttp22.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp22.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp22.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,33 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class DD,class EE> class C : DD<EE>
+{
+ public:
+ int f();
+};
+
+template<template<class> class DD,class EE> int C<DD,EE>::f()
+{
+ return DD<EE>::f();
+}
+
+class E : C<D,int>
+{
+ public:
+ int f() { return C<D,int>::f(); }
+};
+
+int main()
+{
+ E c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp23.C gcc/testsuite/g++.old-deja/g++.pt/ttp23.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp23.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp23.C Tue Jan 13 17:13:16 1998
@@ -0,0 +1,33 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class E,class D> class C : E<D>
+{
+ public:
+ int f();
+};
+
+template<template<class> class E,class D> int C<E,D>::f()
+{
+ return E<D>::f();
+}
+
+class E : C<D,int>
+{
+ public:
+ int f() { return C<D,int>::f(); }
+};
+
+int main()
+{
+ E c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp24.C gcc/testsuite/g++.old-deja/g++.pt/ttp24.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp24.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp24.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,22 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> int f()
+{
+ D<E> d;
+ return d.f();
+};
+
+int main()
+{
+ f<D,int>();
+ f<D,char>();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp25.C gcc/testsuite/g++.old-deja/g++.pt/ttp25.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp25.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp25.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,33 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { return d.f(); }
+};
+
+template<template<class> class D,class E> int f(D<E> &d1)
+{
+ d1.f();
+ C<D,E> d2;
+ d2.f();
+ return 0;
+}
+
+int main()
+{
+ D<int> c1;
+ D<char> c2;
+ f(c1);
+ f(c2);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp26.C gcc/testsuite/g++.old-deja/g++.pt/ttp26.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp26.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp26.C Sat Jan 10 02:29:46 1998
@@ -0,0 +1,33 @@
+template<class T, class U = int> class D
+{
+ public:
+ int f();
+};
+
+template<class T, class U> int D<T,U>::f()
+{
+ return sizeof(T)+sizeof(U);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { return d.f(); }
+};
+
+template<template<class> class D,class E> int f(D<E> &d1)
+{
+ d1.f();
+ C<D,E> d2;
+ d2.f();
+ return 0;
+}
+
+int main()
+{
+ D<int> c1;
+ D<char> c2;
+ f(c1);
+ f(c2);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp27.C gcc/testsuite/g++.old-deja/g++.pt/ttp27.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp27.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp27.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,35 @@
+template<class T> class D
+{
+ public:
+ int f() const;
+};
+
+template<class T> int D<T>::f() const
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() const { return d.f(); }
+};
+
+template<template<class> class D,class E> int f(const D<E> &d1)
+{
+ d1.f();
+ C<D,E> d2;
+ d2.f();
+ return 0;
+}
+
+int main()
+{
+ D<const int> c1;
+ D<char> c2;
+ const D<char> c3(c2);
+ f(c1);
+ f(c2);
+ f(c3);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp28.C gcc/testsuite/g++.old-deja/g++.pt/ttp28.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp28.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp28.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,39 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { return d.f(); }
+};
+
+template<template<class> class D,class E> int f(D<E> &d1)
+{
+ d1.f();
+ C<D,E> d2;
+ d2.f();
+ return 0;
+}
+
+template<> int f<>(D<char> &d1)
+{
+ d1.f();
+ return 0;
+}
+
+int main()
+{
+ D<int> c1;
+ D<char> c2;
+ f(c1);
+ f(c2);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp29.C gcc/testsuite/g++.old-deja/g++.pt/ttp29.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp29.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp29.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,32 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+extern "C" void abort();
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { abort(); return 0; }
+};
+
+template<class E> class C<D,E>
+{
+ D<E> d;
+ public:
+ int f() { return d.f(); }
+};
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp3.C gcc/testsuite/g++.old-deja/g++.pt/ttp3.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp3.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp3.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,14 @@
+// Build don't link:
+
+template<class E,class F> class D
+{
+};
+
+template<template<class> class D,class E> class C
+{ // ERROR - ref below
+};
+
+int main()
+{
+ C<D,int> c; // ERROR - param list not match
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp30.C gcc/testsuite/g++.old-deja/g++.pt/ttp30.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp30.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp30.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,37 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+extern "C" void abort();
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { abort(); return 0; }
+};
+
+template<class E> class C<D,E>
+{
+ D<E> d;
+ public:
+ int f();
+};
+
+template<class E> int C<D,E>::f()
+{
+ return d.f();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp31.C gcc/testsuite/g++.old-deja/g++.pt/ttp31.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp31.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp31.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,32 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+extern "C" void abort();
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { abort(); return 0; }
+};
+
+template<template <class> class F> class C<F,int>
+{
+ F<int> d;
+ public:
+ int f() { return d.f(); }
+};
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp32.C gcc/testsuite/g++.old-deja/g++.pt/ttp32.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp32.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp32.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,37 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+extern "C" void abort();
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { abort(); return 0; }
+};
+
+template<template <class> class F> class C<F,int>
+{
+ F<int> d;
+ public:
+ int f();
+};
+
+template<template<class>class F> int C<F,int>::f()
+{
+ return d.f();
+}
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp33.C gcc/testsuite/g++.old-deja/g++.pt/ttp33.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp33.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp33.C Sat Jan 10 03:40:49 1998
@@ -0,0 +1,31 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ template<template<class> class F> int f(F<int>);
+};
+
+template<template<class> class D,class E>
+template<template<class> class F> int C<D,E>::f(F<int>)
+{
+ F<E> d2;
+ return d2.f();
+}
+
+int main()
+{
+ C<D,int> c;
+ D<int> d;
+ c.f(d);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp34.C gcc/testsuite/g++.old-deja/g++.pt/ttp34.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp34.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp34.C Sat Jan 10 04:01:11 1998
@@ -0,0 +1,31 @@
+template<class T> class D
+{
+ public:
+ int f();
+};
+
+template<class T> int D<T>::f()
+{
+ return sizeof(T);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f();
+};
+
+template<template<class> class D,class E> int C<D,E>::f()
+{
+ D<E> d2;
+ return d2.f();
+}
+
+template class C<D,int>;
+
+int main()
+{
+ C<D,int> c;
+ c.f();
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp35.C gcc/testsuite/g++.old-deja/g++.pt/ttp35.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp35.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp35.C Tue Jan 13 17:02:26 1998
@@ -0,0 +1,35 @@
+template<int T, class U = int> class D
+{
+ public:
+ int f();
+};
+
+template<int T, class U> int D<T,U>::f()
+{
+ return T+sizeof(U);
+}
+
+template<template<int> class D,class E> class C
+{
+ D<1> d;
+ public:
+ int f() { return d.f(); }
+};
+
+template<template<int> class D> int f(D<2> &d1)
+{
+ d1.f();
+ return 0;
+}
+
+template<template<int> class D> int f(D<1> &d1)
+{
+ d1.f();
+ return 0;
+}
+
+int main()
+{
+ D<1> c1;
+ f(c1);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp36.C gcc/testsuite/g++.old-deja/g++.pt/ttp36.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp36.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp36.C Tue Jan 13 17:02:20 1998
@@ -0,0 +1,29 @@
+template<int T, class U = int> class D
+{
+ public:
+ int f();
+};
+
+template<int T, class U> int D<T,U>::f()
+{
+ return T+sizeof(U);
+}
+
+template<template<int> class D,class E> class C
+{
+ D<1> d;
+ public:
+ int f() { return d.f(); }
+};
+
+template<template<int> class D> int f(D<1> &d1)
+{
+ d1.f();
+ return 0;
+}
+
+int main()
+{
+ D<1> c1;
+ f(c1);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp37.C gcc/testsuite/g++.old-deja/g++.pt/ttp37.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp37.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp37.C Tue Jan 13 17:02:10 1998
@@ -0,0 +1,29 @@
+template<int T, class U = int> class D
+{
+ public:
+ int f();
+};
+
+template<int T, class U> int D<T,U>::f()
+{
+ return T+sizeof(U);
+}
+
+template<template<int> class D,class E> class C
+{
+ D<1> d;
+ public:
+ int f() { return d.f(); }
+};
+
+template<template<int> class D, int T> int f(D<T> &d1)
+{
+ d1.f();
+ return T;
+}
+
+int main()
+{
+ D<1> c1;
+ f(c1);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp38.C gcc/testsuite/g++.old-deja/g++.pt/ttp38.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp38.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp38.C Tue Jan 13 17:02:04 1998
@@ -0,0 +1,29 @@
+template<class T, class U = int> class D
+{
+ public:
+ int f();
+};
+
+template<class T, class U> int D<T,U>::f()
+{
+ return sizeof(T)+sizeof(U);
+}
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+ public:
+ int f() { return d.f(); }
+};
+
+template<template<class> class D> int f(D<int> &d1)
+{
+ d1.f();
+ return 0;
+}
+
+int main()
+{
+ D<int> c1;
+ f(c1);
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp4.C gcc/testsuite/g++.old-deja/g++.pt/ttp4.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp4.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp4.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,15 @@
+// Build don't link:
+
+template<class E> class D
+{
+};
+
+template<template<class> class D,class E> class C
+{
+ D<1> d; // ERROR - arg not match
+};
+
+int main()
+{
+ C<D,int> c;
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp5.C gcc/testsuite/g++.old-deja/g++.pt/ttp5.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp5.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp5.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,15 @@
+// Build don't link:
+
+template<int> class D
+{
+};
+
+template<template<int> class D,class E> class C
+{
+ D<int> d; // ERROR - arg not match
+};
+
+int main()
+{
+ C<D,int> c;
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp6.C gcc/testsuite/g++.old-deja/g++.pt/ttp6.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp6.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp6.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,13 @@
+template<int> class F
+{
+};
+
+template<template<int> class D,class E> class C
+{
+ D<1> d;
+};
+
+int main()
+{
+ C<F,int> c;
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp7.C gcc/testsuite/g++.old-deja/g++.pt/ttp7.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp7.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp7.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,15 @@
+// Build don't link:
+
+template<class E> class D
+{
+};
+
+template<template<class> class D,class E> class C // ERROR - ref below
+{
+ D<int,int> d; // ERROR - arg not match
+};
+
+int main()
+{
+ C<D,int> c;
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp8.C gcc/testsuite/g++.old-deja/g++.pt/ttp8.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp8.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp8.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,17 @@
+template<class E> class DD
+{
+};
+
+template<int> class D
+{
+};
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+};
+
+int main()
+{
+ C<DD,int> c;
+}
diff -rNpu3 gcc-old/testsuite/g++.old-deja/g++.pt/ttp9.C gcc/testsuite/g++.old-deja/g++.pt/ttp9.C
--- gcc-old/testsuite/g++.old-deja/g++.pt/ttp9.C Wed Dec 31 16:00:00 1969
+++ gcc/testsuite/g++.old-deja/g++.pt/ttp9.C Sat Jan 10 02:29:47 1998
@@ -0,0 +1,13 @@
+template<class E,class F=int> class D
+{
+};
+
+template<template<class> class D,class E> class C
+{
+ D<E> d;
+};
+
+int main()
+{
+ C<D,int> c;
+}
More information about the Gcc
mailing list