This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Implement template template arg that is template parm dependent
- To: gcc-patches at gcc dot gnu dot org
- Subject: [C++ PATCH] Implement template template arg that is template parm dependent
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- Date: Mon, 17 Sep 2001 21:17:49 +0700
- Reply-To: lerdsuwa at users dot sourceforge dot net
Hi,
The appended patch implement a template template parameter feature
currently missing in GCC. The template template argument of the form
T::template C
where T is template parameter dependent and C is a member class template
is not accepted.
This patch introduce a new tree node TEMPLATE_QUALIFIED_ID.
The rest are changes to handle this tree node and a bunch of testcases.
Although it's for the current old parser, transition to the new C++ parser
should be straightforward. The changes to parse.y is small and the real
work is in the new function, make_template_qualified_id.
Bootstrapped and tested with no regressions. Ok to commit to the main
trunk?
--Kriang
2001-09-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* cp-tree.def (TEMPLATE_QUALIFIED_ID): New tree node.
* cp-tree.h (make_template_qualified_id): Prototype new function.
* decl.c (make_template_qualified_id): New function.
* decl2.c (arg_assoc_template_arg): Handle TEMPLATE_QUALIFIED_ID.
* error.c (dump_type): Likewise.
* mangle.c (write_type): Likewise.
* parse.y (template_parm): Likewise.
(template_argument): Use make_template_qualified_id.
* pt.c (convert_template_argument): Handle TEMPLATE_QUALIFIED_ID.
(tsubst): Likewise.
(tsubst_copy): Likewise.
(unify): Likewise.
* tree.c (walk_tree): Likewise.
* typeck.c (comptypes): Likewise.
diff -cprN gcc-main-save/gcc/cp/cp-tree.def gcc-main-new/gcc/cp/cp-tree.def
*** gcc-main-save/gcc/cp/cp-tree.def Fri Jul 6 19:21:49 2001
--- gcc-main-new/gcc/cp/cp-tree.def Sun Sep 9 16:01:07 2001
*************** DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PAR
*** 163,168 ****
--- 163,173 ----
of `T'. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
+ /* For template template argument of the form `T::template C'.
+ TYPE_CONTEXT is `T', the template parameter dependent object.
+ TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template. */
+ DEFTREECODE (TEMPLATE_QUALIFIED_ID, "template_qualified_id", 't', 0)
+
/* A type designated by `__typeof (expr)'. TYPE_FIELDS is the
expression in question. */
DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
diff -cprN gcc-main-save/gcc/cp/cp-tree.h gcc-main-new/gcc/cp/cp-tree.h
*** gcc-main-save/gcc/cp/cp-tree.h Mon Aug 27 21:26:05 2001
--- gcc-main-new/gcc/cp/cp-tree.h Sun Sep 9 16:26:39 2001
*************** extern void set_namespace_binding
*** 3631,3636 ****
--- 3631,3637 ----
extern tree lookup_namespace_name PARAMS ((tree, tree));
extern tree build_typename_type PARAMS ((tree, tree, tree, tree));
extern tree make_typename_type PARAMS ((tree, tree, int));
+ extern tree make_template_qualified_id PARAMS ((tree, tree, int));
extern tree lookup_name_nonclass PARAMS ((tree));
extern tree lookup_function_nonclass PARAMS ((tree, tree));
extern tree lookup_name PARAMS ((tree, int));
diff -cprN gcc-main-save/gcc/cp/decl.c gcc-main-new/gcc/cp/decl.c
*** gcc-main-save/gcc/cp/decl.c Mon Aug 27 21:26:06 2001
--- gcc-main-new/gcc/cp/decl.c Sun Sep 9 16:35:16 2001
*************** make_typename_type (context, name, compl
*** 5663,5668 ****
--- 5663,5723 ----
return build_typename_type (context, name, fullname, NULL_TREE);
}
+ /* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
+ unless an error occurs, in which case error_mark_node is returned.
+ If COMPLAIN zero, don't complain about any errors that occur. */
+
+ tree
+ make_template_qualified_id (context, name, complain)
+ tree context, name;
+ int complain;
+ {
+ tree t;
+ tree d;
+
+ if (TYPE_P (name))
+ name = TYPE_IDENTIFIER (name);
+ else if (DECL_P (name))
+ name = DECL_NAME (name);
+ if (TREE_CODE (name) != IDENTIFIER_NODE)
+ my_friendly_abort (20010902);
+
+ if (!uses_template_parms (context)
+ || currently_open_class (context))
+ {
+ tree tmpl = NULL_TREE;
+
+ if (IS_AGGR_TYPE (context))
+ tmpl = lookup_field (context, name, 0, 0);
+
+ if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
+ {
+ if (complain)
+ cp_error ("no class template named `%#T' in `%#T'", name, context);
+ return error_mark_node;
+ }
+
+ if (!enforce_access (context, tmpl))
+ return error_mark_node;
+
+ return tmpl;
+ }
+
+ /* Build the TEMPLATE_QUALIFIED_ID. */
+ t = make_aggr_type (TEMPLATE_QUALIFIED_ID);
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+ TREE_TYPE (t) = NULL_TREE;
+
+ /* Build the corresponding TEMPLATE_DECL. */
+ d = build_decl (TEMPLATE_DECL, name, t);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ DECL_ARTIFICIAL (d) = 1;
+
+ return t;
+ }
+
/* Select the right _DECL from multiple choices. */
static tree
diff -cprN gcc-main-save/gcc/cp/decl2.c gcc-main-new/gcc/cp/decl2.c
*** gcc-main-save/gcc/cp/decl2.c Mon Aug 27 21:26:06 2001
--- gcc-main-new/gcc/cp/decl2.c Sun Sep 9 16:01:18 2001
*************** arg_assoc_template_arg (k, arg)
*** 4575,4581 ****
contribute to the set of associated namespaces. ] */
/* Consider first template template arguments. */
! if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
return 0;
else if (TREE_CODE (arg) == TEMPLATE_DECL)
{
--- 4575,4582 ----
contribute to the set of associated namespaces. ] */
/* Consider first template template arguments. */
! if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
! || TREE_CODE (arg) == TEMPLATE_QUALIFIED_ID)
return 0;
else if (TREE_CODE (arg) == TEMPLATE_DECL)
{
diff -cprN gcc-main-save/gcc/cp/error.c gcc-main-new/gcc/cp/error.c
*** gcc-main-save/gcc/cp/error.c Sat Sep 1 00:55:26 2001
--- gcc-main-new/gcc/cp/error.c Sun Sep 9 16:00:49 2001
*************** dump_type (t, flags)
*** 524,529 ****
--- 524,536 ----
dump_typename (t, flags);
break;
+ case TEMPLATE_QUALIFIED_ID:
+ dump_type (TYPE_CONTEXT (t), flags);
+ print_scope_operator (scratch_buffer);
+ print_identifier (scratch_buffer, "template ");
+ dump_type (DECL_NAME (TYPE_NAME (t)), flags);
+ break;
+
case TYPEOF_TYPE:
output_add_string (scratch_buffer, "__typeof (");
dump_expr (TYPE_FIELDS (t), flags & ~TFF_EXPR_IN_PARENS);
diff -cprN gcc-main-save/gcc/cp/mangle.c gcc-main-new/gcc/cp/mangle.c
*** gcc-main-save/gcc/cp/mangle.c Wed Jul 25 22:04:30 2001
--- gcc-main-new/gcc/cp/mangle.c Mon Sep 10 21:22:24 2001
*************** write_type (type)
*** 1393,1399 ****
break;
case TYPENAME_TYPE:
! /* We handle TYPENAME_TYPEs like ordinary nested names. */
write_nested_name (TYPE_STUB_DECL (type));
break;
--- 1393,1401 ----
break;
case TYPENAME_TYPE:
! case TEMPLATE_QUALIFIED_ID:
! /* We handle TYPENAME_TYPEs and TEMPLATE_QUALIFIED_IDs like
! ordinary nested names. */
write_nested_name (TYPE_STUB_DECL (type));
break;
diff -cprN gcc-main-save/gcc/cp/parse.y gcc-main-new/gcc/cp/parse.y
*** gcc-main-save/gcc/cp/parse.y Mon Aug 27 21:26:06 2001
--- gcc-main-new/gcc/cp/parse.y Fri Sep 14 23:55:11 2001
*************** template_parm:
*** 669,675 ****
{
if (TREE_CODE ($3) != TEMPLATE_DECL
&& TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM
! && TREE_CODE ($3) != TYPE_DECL)
{
error ("invalid default template argument");
$3 = error_mark_node;
--- 669,676 ----
{
if (TREE_CODE ($3) != TEMPLATE_DECL
&& TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM
! && TREE_CODE ($3) != TYPE_DECL
! && TREE_CODE ($3) != TEMPLATE_QUALIFIED_ID)
{
error ("invalid default template argument");
$3 = error_mark_node;
*************** template_arg:
*** 1098,1103 ****
--- 1099,1114 ----
$$ = TREE_TYPE ($$);
}
| expr_no_comma_rangle
+ | nested_name_specifier TEMPLATE identifier
+ {
+ if (!processing_template_decl)
+ {
+ cp_error ("use of template qualifier outside template");
+ $$ = error_mark_node;
+ }
+ else
+ $$ = make_template_qualified_id ($1, $3, 1);
+ }
;
unop:
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c Mon Aug 27 21:26:07 2001
--- gcc-main-new/gcc/cp/pt.c Sun Sep 9 16:26:40 2001
*************** convert_template_argument (parm, arg, ar
*** 3294,3306 ****
= ((TREE_CODE (arg) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| (TREE_CODE (arg) == RECORD_TYPE
&& CLASSTYPE_TEMPLATE_INFO (arg)
&& TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
&& DECL_ARTIFICIAL (TYPE_NAME (arg))
&& requires_tmpl_type
&& is_base_of_enclosing_class (arg, current_class_type)));
! if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
arg = TYPE_STUB_DECL (arg);
else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
arg = CLASSTYPE_TI_TEMPLATE (arg);
--- 3294,3309 ----
= ((TREE_CODE (arg) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == TEMPLATE_QUALIFIED_ID
|| (TREE_CODE (arg) == RECORD_TYPE
&& CLASSTYPE_TEMPLATE_INFO (arg)
&& TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
&& DECL_ARTIFICIAL (TYPE_NAME (arg))
&& requires_tmpl_type
&& is_base_of_enclosing_class (arg, current_class_type)));
! if (is_tmpl_type
! && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
! || TREE_CODE (arg) == TEMPLATE_QUALIFIED_ID))
arg = TYPE_STUB_DECL (arg);
else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
arg = CLASSTYPE_TI_TEMPLATE (arg);
*************** convert_template_argument (parm, arg, ar
*** 3353,3382 ****
{
if (requires_tmpl_type)
{
! tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
! tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
!
! if (coerce_template_template_parms (parmparm, argparm, complain,
! in_decl, inner_args))
! {
! 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
{
! if (in_decl && complain)
{
! cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
! i + 1, in_decl);
! cp_error (" expected a template of type `%D', got `%D'", parm, arg);
}
! val = error_mark_node;
}
}
else
--- 3356,3393 ----
{
if (requires_tmpl_type)
{
! if (TREE_CODE (TREE_TYPE (arg)) == TEMPLATE_QUALIFIED_ID)
! /* The number of argument required is not known yet.
! Just accept it for now. */
! val = TREE_TYPE (arg);
else
{
! tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
! tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
!
! if (coerce_template_template_parms (parmparm, argparm,
! complain, in_decl,
! inner_args))
{
! 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
+ {
+ if (in_decl && complain)
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ cp_error (" expected a template of type `%D', got `%D'", parm, arg);
+ }
! val = error_mark_node;
! }
}
}
else
*************** tsubst (t, args, complain, in_decl)
*** 6731,6736 ****
--- 6742,6759 ----
complain);
}
+ case TEMPLATE_QUALIFIED_ID:
+ {
+ tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
+ in_decl, /*entering_scope=*/1);
+ tree name = TYPE_IDENTIFIER (t);
+
+ if (ctx == error_mark_node || name == error_mark_node)
+ return error_mark_node;
+
+ return make_template_qualified_id (ctx, name, complain);
+ }
+
case INDIRECT_REF:
{
tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
*************** tsubst_copy (t, args, complain, in_decl)
*** 7131,7136 ****
--- 7154,7160 ----
case METHOD_TYPE:
case ARRAY_TYPE:
case TYPENAME_TYPE:
+ case TEMPLATE_QUALIFIED_ID:
case TYPE_DECL:
return tsubst (t, args, complain, in_decl);
*************** unify (tparms, targs, parm, arg, strict)
*** 8515,8520 ****
--- 8539,8545 ----
switch (TREE_CODE (parm))
{
case TYPENAME_TYPE:
+ case TEMPLATE_QUALIFIED_ID:
/* In a type which contains a nested-name-specifier, template
argument values cannot be deduced for template parameters used
within the nested-name-specifier. */
diff -cprN gcc-main-save/gcc/cp/tree.c gcc-main-new/gcc/cp/tree.c
*** gcc-main-save/gcc/cp/tree.c Mon Aug 27 21:26:07 2001
--- gcc-main-new/gcc/cp/tree.c Sun Sep 9 16:01:13 2001
*************** walk_tree (tp, func, data, htab)
*** 1276,1281 ****
--- 1276,1282 ----
case DEFAULT_ARG:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_QUALIFIED_ID:
case TEMPLATE_PARM_INDEX:
case TEMPLATE_TYPE_PARM:
case REAL_TYPE:
diff -cprN gcc-main-save/gcc/cp/typeck.c gcc-main-new/gcc/cp/typeck.c
*** gcc-main-save/gcc/cp/typeck.c Mon Aug 27 21:26:07 2001
--- gcc-main-new/gcc/cp/typeck.c Sun Sep 9 16:00:35 2001
*************** comptypes (t1, t2, strict)
*** 1097,1102 ****
--- 1097,1108 ----
return 0;
return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
+ case TEMPLATE_QUALIFIED_ID:
+ if (cp_tree_equal (TYPE_IDENTIFIER (t1),
+ TYPE_IDENTIFIER (t2)) < 1)
+ return 0;
+ return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
+
case COMPLEX_TYPE:
return same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp1.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp1.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp1.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp1.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,22 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <class T> struct X
+ {
+ };
+
+ template <class T> struct C
+ {
+ X<T::template B> x; // { dg-error "type" }
+ };
+
+ int main()
+ {
+ C<A> c;
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp10.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp10.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp10.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp10.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,13 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ template <template <class> class TT> class C {
+ };
+
+ template <class T> struct D {
+ template <class U> class B {};
+ C<D<T>::template B> c;
+ };
+
+ D<int> d;
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp11.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp11.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp11.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp11.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,23 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do link }
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <template <class> class TT> struct X
+ {
+ TT<int> y;
+ };
+
+ template <class T> struct C
+ {
+ X<T::template B> x;
+ };
+
+ int main()
+ {
+ C<A> c;
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp12.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp12.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp12.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp12.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,24 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do link }
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <template <class> class TT> void f()
+ {
+ TT<int> y;
+ }
+
+ template <class T> struct C
+ {
+ void g() { f<T::template B>(); }
+ };
+
+ int main()
+ {
+ C<A> c;
+ c.g();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp13.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp13.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp13.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp13.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,27 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ template <class U> struct A
+ {
+ template <class V> struct AA {
+ template <class T> struct B {
+ int i;
+ B() : i(1) {}
+ };
+ };
+ };
+
+ template <template <class> class TT> struct X
+ {
+ TT<int> y;
+ };
+
+ template <class T, class U> struct C
+ {
+ X<T::template AA<U>::template B> x;
+ };
+
+ int main()
+ {
+ C<A<char>, int> c;
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp14.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp14.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp14.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp14.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,30 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do link }
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <template <class> class TT, class T> struct X
+ {
+ TT<int> y;
+ T z;
+ };
+
+ template <class T> struct X<T::template B, T>
+ {
+ typename T::template B<int> y;
+ T z;
+ };
+
+ template <class T> struct C
+ {
+ X<T::template B, A> x;
+ };
+
+ int main()
+ {
+ C<A> c;
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp15.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp15.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp15.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp15.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,33 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <template <class> class TT> struct X
+ {
+ TT<int> y;
+ };
+
+ template <class T> struct X<T::template B>
+ { // { dg-error "previous" }
+ T z;
+ };
+
+ template <class T> struct X<T::template B>
+ { // { dg-error "redefinition" }
+ T z;
+ };
+
+ template <class T> struct C
+ {
+ X<T::template B> x;
+ };
+
+ int main()
+ {
+ C<A> c;
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp16.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp16.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp16.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp16.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,40 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do run }
+
+ extern "C" void abort();
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <template <class> class TT, class T> struct X
+ {
+ TT<int> y;
+ T z;
+ int f() { return 0; }
+ };
+
+ template <class T> struct X<T::template B, T>
+ {
+ typename T::template B<int> y;
+ T z;
+ int f() { return 1; }
+ };
+
+ template <class T> struct C
+ {
+ X<T::template B, A> x;
+ };
+
+ int main()
+ {
+ C<A> c;
+ X<A::B, A> x1;
+ X<A::B, int> x2;
+ if (x1.f() != 1)
+ abort();
+ if (x2.f() != 0)
+ abort();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp17.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp17.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp17.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp17.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,25 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+ // { dg-options "-fno-inline" }
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <template <class> class TT> struct X
+ {
+ };
+
+ template <class T> void f(X<T::template B>)
+ {
+ }
+
+ int main()
+ {
+ X<A::B> x;
+ f<A>(x);
+ }
+
+ // { dg-final { scan-assembler "\n_?_Z1fI1AEv1XIN1T1BEE\[: \t\n\]" } }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp18.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp18.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp18.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp18.C Fri Sep 14 23:56:47 2001
***************
*** 0 ****
--- 1,23 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <template <class> class TT> struct X
+ {
+ TT<int> y;
+ };
+
+ struct C
+ {
+ X<A::template B> x; // { dg-error "template|forbid" }
+ };
+
+ int main()
+ {
+ C c;
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp2.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp2.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp2.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp2.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,22 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ struct A
+ {
+ template <class T> class B {};
+ };
+
+ template <int i> struct X
+ {
+ };
+
+ template <class T> struct C
+ {
+ X<T::template B> x; // { dg-error "type" }
+ };
+
+ int main()
+ {
+ C<A> c;
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp3.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp3.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp3.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp3.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,23 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ struct A
+ {
+ template <class T, class U> class B {};
+ };
+
+ template <template <class> class TT> struct X
+ {
+ TT<int> y;
+ };
+
+ template <class T> struct C
+ {
+ X<T::template B> x; // { dg-error "type" "" }
+ };
+
+ int main()
+ {
+ C<A> c; // { dg-error "instantiated" }
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp4.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp4.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp4.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp4.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,24 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ struct A
+ {
+ template <class T> struct B {};
+ };
+
+ template <template <class, class> class TT> // { dg-error "provided" }
+ struct X
+ {
+ TT<int> y; // { dg-error "number|type" }
+ };
+
+ template <class T> struct C
+ {
+ X<T::template B> x; // { dg-error "type" }
+ };
+
+ int main()
+ {
+ C<A> c; // { dg-error "instantiated" }
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp5.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp5.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp5.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp5.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,25 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ template <class U> struct A
+ {
+ template <class T> class B {}; // { dg-error "candidates" }
+ };
+
+ template <template <class> class TT> void f()
+ {
+ TT<int> y;
+ y = 0; // { dg-error "no match" }
+ }
+
+ template <class T> struct C
+ {
+ void g() { f<A<T>::template B>(); } // { dg-error "instantiated" }
+ };
+
+ int main()
+ {
+ C<int> c;
+ c.g(); // { dg-error "instantiated" }
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp6.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp6.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp6.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp6.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,15 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ template <template <class> class TT> class C {
+ };
+
+ template <class T> struct D {
+ C<T::template B> c; // { dg-error "no class template" }
+ };
+
+ struct E {
+ };
+
+ D<E> d; // { dg-error "instantiated" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp7.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp7.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp7.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp7.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,12 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ template <template <class> class TT> class C {
+ };
+
+ template <class T> struct D {
+ C<T::template B> c; // { dg-error "no class template" }
+ };
+
+ D<int> d; // { dg-error "instantiated" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp8.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp8.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp8.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp8.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,17 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ template <template <class> class TT> class C {
+ };
+
+ template <class T> struct D {
+ C<T::template B> c; // { dg-error "context" }
+ };
+
+ struct E {
+ private:
+ template <class T> class B {}; // { dg-error "private" }
+ };
+
+ D<E> d; // { dg-error "instantiated" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/qualttp9.C gcc-main-new/gcc/testsuite/g++.dg/template/qualttp9.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/qualttp9.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/qualttp9.C Mon Sep 10 21:37:37 2001
***************
*** 0 ****
--- 1,17 ----
+ // Copyright (C) 2001 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ template <template <class> class TT> class C {
+ };
+
+ template <class T> struct D : T {
+ C<T::template B> c;
+ };
+
+ struct E {
+ protected:
+ template <class T> class B {};
+ };
+
+ D<E> d;