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 PR c++/15664, c++/18276 * pt.c (tsubst_decl) : Reorganize. Correctly tsubst TEMPLATE_DECL that is a TEMPLATE_TEMPLATE_PARM. 2004-11-12 Kriang Lerdsuwanakij 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 + + // PR c++/15664: Template substitution of template template parameter + + template struct S { + template class A> + friend void foo(); + }; + + template class A> + void foo(); + + template struct X {}; + + int main () { + S<1> s; + foo(); + } 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 + + // PR c++/18276: Template substitution of template template parameter + + template class> struct A; + + template struct B + { + template class> friend class A; + }; + + B<0> b;