This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR c++/66850 (Adding a forward declaration causes ICE on valid code)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]