This patch attempts resolve the mentioned PR by fixing two underlying issues:
1. When a template is first declared we currently take care to set the DECL_CONTEXT of each of its template template parms to point to it (line 5119 in pt.c:push_template_decl_real). However, we currently don't do this for subsequent redeclarations of the template (push_template_decl_real is only called for the first declaration). If a DECL_CONTEXT of a template template parm is not set, lookup_template_class_1 gets confused when it attempts to instantiate the template template parm. This patch makes the function redeclare_class_template to also set the DECL_CONTEXTs of a template template parm. 2. When the DECL_CONTEXT of a template template parm is not set, lookup_template_class_1 instead uses current_template_args to synthesize an argument list instead of using the TI_ARGS of the DECL_CONTEXT. Using current_template_args is not 100% right, however, since we may not currently be in the same parameter level that the template template parm was defined in. We may be in a deeper parameter level if 1) a nested template has been defined in the meantime or 2) if a nested parameter list has been started in the meantime. Parameter levels that are greater than the level of the given template template parm are irrelevant. This patch peels off these irrelevant parameter levels from current_template_parms before augmenting the argument list in lookup_template_class_1. OK to commit after bootstrap + regtest? gcc/cp/ChangeLog: PR c++/66850 * pt.c (redeclare_class_template): Set the DECL_CONTEXTs of each template template parm in the redeclaration. (lookup_template_class_1): Peel off irrelevant template levels from current_template_parms before augmenting the argument list. gcc/testsuite/ChangeLog: PR c++/66850 * g++.dg/template/pr66850.C: New test. --- gcc/cp/pt.c | 25 ++++++++++++++++--- gcc/testsuite/g++.dg/template/pr66850.C | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/pr66850.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2097963..6bdfd33 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5297,6 +5297,14 @@ redeclare_class_template (tree type, tree parms) /* Update the new parameters, too; they'll be used as the parameters for any members. */ TREE_PURPOSE (TREE_VEC_ELT (parms, i)) = tmpl_default; + + /* Give each template template parm in this redeclaration a + DECL_CONTEXT of the template for which they are a parameter. */ + if (TREE_CODE (parm) == TEMPLATE_DECL) + { + gcc_assert (DECL_CONTEXT (parm) == NULL_TREE); + DECL_CONTEXT (parm) = tmpl; + } } return true; @@ -7749,9 +7757,20 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, if (outer) outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer))); else if (current_template_parms) - /* This is an argument of the current template, so we haven't set - DECL_CONTEXT yet. */ - outer = current_template_args (); + { + /* This is an argument of the current template, so we haven't set + DECL_CONTEXT yet. */ + tree relevant_template_parms; + + /* Parameter levels that are greater than the level of the given + template template parm are irrelevant. */ + relevant_template_parms = current_template_parms; + while (TMPL_PARMS_DEPTH (relevant_template_parms) + != TEMPLATE_TYPE_LEVEL (TREE_TYPE (templ))) + relevant_template_parms = TREE_CHAIN (relevant_template_parms); + + outer = template_parms_to_args (relevant_template_parms); + } if (outer) arglist = add_to_template_args (outer, arglist); diff --git a/gcc/testsuite/g++.dg/template/pr66850.C b/gcc/testsuite/g++.dg/template/pr66850.C new file mode 100644 index 0000000..31c1290 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr66850.C @@ -0,0 +1,44 @@ +// PR c++/66850 +// Each namespace contains an otherwise standalone test case, none of which +// should cause an ICE. + +namespace X { + template <template <typename U, U> class> struct Sort; + + template <template <typename U, U> class Comparator> + struct Sort + { + template <int I> + struct less_than + { + Comparator<int, I> a; + }; + }; +} + +namespace Y { + template <typename C, C> struct integral_constant {}; + + template <typename T, template <typename U, U> class> struct Sort; + + template <template <typename U, U> class Comparator> + struct Sort<int, Comparator> + { + template <int I> struct less_than: + integral_constant<bool, Comparator<int, I>::value> {}; + }; +} + +namespace Z { + template <typename T, template <typename U, U> class> struct Sort; + + template <template <typename U, U> class Comparator> + struct Sort<int, Comparator> + { + template <int I> + struct less_than + { + Comparator<int, I> a; + }; + }; +} -- 2.5.0.rc1.40.ge088f2b.dirty