This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix PR15664, 18276 (tsubst template template parm)
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 13 Nov 2004 00:06:48 +0700
- Subject: [C++ PATCH] Fix PR15664, 18276 (tsubst template template parm)
Hi
This patch fixes PR15664 and PR18276. It turned out that
tsubsting TEMPLATE_DECL that is a template template parameter
produces broken tree node. A total of 3 problems found:
- DECL_TEMPLATE_RESULT should point to a TYPE_DECL (not a
TEMPLATE_DECL).
- The substituted TEMPLATE_TEMPLATE_PARM should have TYPE_NAME
point back to the new TEMPLATE_DECL (not the old TEMPLATE_DECL).
- DECL_TEMPLATE_PARMS is not reduced.
I reorganize the case TEMPLATE_DECL in tsubst_decl to group
the codes related to template template parameter together
(making it not fragile to surrounding code changes) and add the fix.
Tested on i686-pc-linux-gnu. OK for mainline?
--Kriang
2004-11-12 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/15664, c++/18276
* pt.c (tsubst_decl) <TEMPLATE_DECL case>: Reorganize. Correctly
tsubst TEMPLATE_DECL that is a TEMPLATE_TEMPLATE_PARM.
2004-11-12 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/15664, c++/18276
* g++.dg/template/ttp13.C: New test.
* g++.dg/template/ttp14.C: Likewise.
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c Sun Nov 7 22:40:15 2004
--- gcc-main-new/gcc/cp/pt.c Fri Nov 12 19:13:26 2004
*************** tsubst_decl (tree t, tree args, tree typ
*** 6152,6189 ****
{
case TEMPLATE_DECL:
{
! /* We can get here when processing a member template function
! of a template class. */
tree decl = DECL_TEMPLATE_RESULT (t);
tree spec;
! int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
! if (!is_template_template_parm)
{
! /* We might already have an instance of this template.
! The ARGS are for the surrounding class type, so the
! full args contain the tsubst'd args for the context,
! plus the innermost args from the template decl. */
! tree tmpl_args = DECL_CLASS_TEMPLATE_P (t)
! ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))
! : DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
! tree full_args;
!
! full_args = tsubst_template_args (tmpl_args, args,
! complain, in_decl);
!
! /* tsubst_template_args doesn't copy the vector if
! nothing changed. But, *something* should have
! changed. */
! gcc_assert (full_args != tmpl_args);
!
! spec = retrieve_specialization (t, full_args,
! /*class_specializations_p=*/true);
! if (spec != NULL_TREE)
! {
! r = spec;
! break;
! }
}
/* Make a new template decl. It will be similar to the
--- 6152,6205 ----
{
case TEMPLATE_DECL:
{
! /* We can get here when processing a member function template,
! member class template, and template template parameter of
! a template class. */
tree decl = DECL_TEMPLATE_RESULT (t);
tree spec;
! tree tmpl_args;
! tree full_args;
! if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
{
! /* Template template parameter is treated here. */
! tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
! if (new_type == error_mark_node)
! return error_mark_node;
!
! r = copy_decl (t);
! TREE_CHAIN (r) = NULL_TREE;
! TREE_TYPE (r) = new_type;
! DECL_TEMPLATE_RESULT (r)
! = build_decl (TYPE_DECL, DECL_NAME (decl), new_type);
! DECL_TEMPLATE_PARMS (r)
! = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
! complain);
! TYPE_NAME (new_type) = r;
! break;
! }
!
! /* We might already have an instance of this template.
! The ARGS are for the surrounding class type, so the
! full args contain the tsubst'd args for the context,
! plus the innermost args from the template decl. */
! tmpl_args = DECL_CLASS_TEMPLATE_P (t)
! ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))
! : DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
! full_args = tsubst_template_args (tmpl_args, args,
! complain, in_decl);
!
! /* tsubst_template_args doesn't copy the vector if
! nothing changed. But, *something* should have
! changed. */
! gcc_assert (full_args != tmpl_args);
!
! spec = retrieve_specialization (t, full_args,
! /*class_specializations_p=*/true);
! if (spec != NULL_TREE)
! {
! r = spec;
! break;
}
/* Make a new template decl. It will be similar to the
*************** tsubst_decl (tree t, tree args, tree typ
*** 6195,6208 ****
gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
TREE_CHAIN (r) = NULL_TREE;
- if (is_template_template_parm)
- {
- tree new_decl = tsubst (decl, args, complain, in_decl);
- DECL_TEMPLATE_RESULT (r) = new_decl;
- TREE_TYPE (r) = TREE_TYPE (new_decl);
- break;
- }
-
DECL_CONTEXT (r)
= tsubst_aggr_type (DECL_CONTEXT (t), args,
complain, in_decl,
--- 6211,6216 ----
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/ttp13.C gcc-main-new/gcc/testsuite/g++.dg/template/ttp13.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/ttp13.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/ttp13.C Thu Nov 11 22:23:53 2004
***************
*** 0 ****
--- 1,20 ----
+ // { dg-do compile }
+
+ // Origin: Wolfgang Bangerth <bangerth@dealii.org>
+
+ // PR c++/15664: Template substitution of template template parameter
+
+ template <int N> struct S {
+ template<template<typename> class A>
+ friend void foo();
+ };
+
+ template<template<typename> class A>
+ void foo();
+
+ template <typename> struct X {};
+
+ int main () {
+ S<1> s;
+ foo<X>();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/ttp14.C gcc-main-new/gcc/testsuite/g++.dg/template/ttp14.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/ttp14.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/ttp14.C Thu Nov 11 22:27:07 2004
***************
*** 0 ****
--- 1,15 ----
+ // { dg-do compile }
+
+ // Origin: akim@epita.fr
+ // Volker Reichelt <reichelt@gcc.gnu.org>
+
+ // PR c++/18276: Template substitution of template template parameter
+
+ template<template<int> class> struct A;
+
+ template<int> struct B
+ {
+ template<template<int> class> friend class A;
+ };
+
+ B<0> b;