This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c++/66850 (Adding a forward declaration causes ICE on valid code)
- From: Patrick Palka <patrick at parcs dot ath dot cx>
- To: gcc-patches at gcc dot gnu dot org
- Cc: jason at redhat dot com, Patrick Palka <patrick at parcs dot ath dot cx>
- Date: Sun, 12 Jul 2015 19:31:37 -0400
- Subject: [PATCH] Fix PR c++/66850 (Adding a forward declaration causes ICE on valid code)
- Authentication-results: sourceware.org; auth=none
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