Patch for template template parameter
Kriang Lerdsuwanakij
lerdsuwa@scf-fs.usc.edu
Mon Jan 19 23:51:00 GMT 1998
Hi,
This is a fix for various bugs in I found in the earlier patch. I also
add missing 'typename' warning in code like
template <template <class> class TT> class C {
TT<int>::size_type k; // Error
};
Kriang
==============================================================
* 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
* pt.c (tsubst): Update comments.
diff -rNpu3 gcc-ttp980113/cp/decl.c gcc-ttp-new/cp/decl.c
--- gcc-ttp980113/cp/decl.c Sat Jan 10 02:27:33 1998
+++ gcc-ttp-new/cp/decl.c Fri Jan 16 09:52:37 1998
@@ -7902,7 +7902,8 @@ grokdeclarator (declarator, declspecs, d
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));
diff -rNpu3 gcc-ttp980113/cp/parse.y gcc-ttp-new/cp/parse.y
--- gcc-ttp980113/cp/parse.y Sat Jan 10 02:27:34 1998
+++ gcc-ttp-new/cp/parse.y Fri Jan 16 09:45:23 1998
@@ -488,10 +488,7 @@ template_template_parm:
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;
- }
+ pedwarn ("template template parameters must use the keyword
`class'");
$$ = build_tree_list (class_type_node, tmpl);
}
;
@@ -4317,7 +4314,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, $$);
}
diff -rNpu3 gcc-ttp980113/cp/pt.c gcc-ttp-new/cp/pt.c
--- gcc-ttp980113/cp/pt.c Tue Jan 13 17:10:23 1998
+++ gcc-ttp-new/cp/pt.c Sun Jan 18 21:38:20 1998
@@ -1019,17 +1019,25 @@ coerce_template_parms (parms, arglist, i
vec = copy_node (arglist);
else
{
- /* We arrive here when a template is used in template template
- parameter with some default arguments */
+ /* We arrive here when a template with some default arguments
+ is used as template template argument. */
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;
+ tree arg;
+
+ if (i < nargs)
+ arg = TREE_VEC_ELT (arglist, i);
+ else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i)))
+ == TYPE_DECL)
+ arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
+ vec, i, in_decl);
else
- TREE_VEC_ELT (vec, i) = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+ arg = tsubst_expr (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
+ vec, i, in_decl);
+
+ TREE_VEC_ELT (vec, i) = arg;
}
}
else
@@ -1148,32 +1156,26 @@ coerce_template_parms (parms, arglist, i
{
if (requires_tmpl_type)
{
- if (!CLASSTYPE_TEMPLATE_INFO (parm))
- {
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+ 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 */
+ /* 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 (val != error_mark_node
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
+ val = TREE_TYPE (val);
}
else
{
@@ -1286,14 +1288,6 @@ 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))
@@ -2386,16 +2380,21 @@ tsubst (t, args, nargs, in_decl)
{
if (CLASSTYPE_TEMPLATE_INFO (t))
{
- /* We are processing a data member constructed
- from template template parameter */
+ /* We are processing a type constructed from
+ a 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. */
+ /* We can get a TEMPLATE_TEMPLATE_PARM here when
+ we are resolving nested-types in the signature of
+ a member function templates.
+ Otherwise ARG is a TEMPLATE_DECL and 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),
diff -rNpu3 gcc-ttp980113/testsuite/g++.old-deja/g++.pt/ttp39.C
gcc-ttp-new/testsuite/g++.old-deja/g++.pt/ttp39.C
--- gcc-ttp980113/testsuite/g++.old-deja/g++.pt/ttp39.C Wed Dec 31
16:00:00 1969
+++ gcc-ttp-new/testsuite/g++.old-deja/g++.pt/ttp39.C Sun Jan 18
21:38:54 1998
@@ -0,0 +1,29 @@
+template<class T, class U = T> 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);
+}
More information about the Gcc
mailing list