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]

C++ PATCH for c++/60241 (ICE with specialization of member class template)


We already have the code to reassign instances to the appropriate template when we see a specialization of a partial instantiation of a member template, but it wasn't firing properly in this case, for two reasons:

1) We were attaching the instances to the most general template and then looking for them on the partial instantiation.
2) We were only reassigning explicit specializations.

Tested x86_64-pc-linux-gnu, applying to trunk. It should be appropriate for backporting later if it doesn't cause trouble.
commit 667bae7d1bfeea4e881cf6236d8679fc0c11c49e
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Feb 21 13:51:18 2014 -0500

    	PR c++/60241
    	* pt.c (lookup_template_class_1): Update DECL_TEMPLATE_INSTANTIATIONS
    	of the partial instantiation, not the most general template.
    	(maybe_process_partial_specialization): Reassign everything on
    	that list.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a394441..91a8840 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -914,11 +914,13 @@ maybe_process_partial_specialization (tree type)
 	       t; t = TREE_CHAIN (t))
 	    {
 	      tree inst = TREE_VALUE (t);
-	      if (CLASSTYPE_TEMPLATE_SPECIALIZATION (inst))
+	      if (CLASSTYPE_TEMPLATE_SPECIALIZATION (inst)
+		  || !COMPLETE_OR_OPEN_TYPE_P (inst))
 		{
 		  /* We already have a full specialization of this partial
-		     instantiation.  Reassign it to the new member
-		     specialization template.  */
+		     instantiation, or a full specialization has been
+		     looked up but not instantiated.  Reassign it to the
+		     new member specialization template.  */
 		  spec_entry elt;
 		  spec_entry *entry;
 		  void **slot;
@@ -937,7 +939,7 @@ maybe_process_partial_specialization (tree type)
 		  *entry = elt;
 		  *slot = entry;
 		}
-	      else if (COMPLETE_OR_OPEN_TYPE_P (inst))
+	      else
 		/* But if we've had an implicit instantiation, that's a
 		   problem ([temp.expl.spec]/6).  */
 		error ("specialization %qT after instantiation %qT",
@@ -7596,7 +7598,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 	}
 
       /* Let's consider the explicit specialization of a member
-         of a class template specialization that is implicitely instantiated,
+         of a class template specialization that is implicitly instantiated,
 	 e.g.:
 	     template<class T>
 	     struct S
@@ -7694,9 +7696,9 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 
       /* Note this use of the partial instantiation so we can check it
 	 later in maybe_process_partial_specialization.  */
-      DECL_TEMPLATE_INSTANTIATIONS (templ)
+      DECL_TEMPLATE_INSTANTIATIONS (found)
 	= tree_cons (arglist, t,
-		     DECL_TEMPLATE_INSTANTIATIONS (templ));
+		     DECL_TEMPLATE_INSTANTIATIONS (found));
 
       if (TREE_CODE (template_type) == ENUMERAL_TYPE && !is_dependent_type
 	  && !DECL_ALIAS_TEMPLATE_P (gen_tmpl))
diff --git a/gcc/testsuite/g++.dg/template/memclass5.C b/gcc/testsuite/g++.dg/template/memclass5.C
new file mode 100644
index 0000000..eb32f13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/memclass5.C
@@ -0,0 +1,26 @@
+// PR c++/60241
+
+template <typename T>
+struct x
+{
+    template <typename U>
+    struct y
+    {
+        typedef T result2;
+    };
+
+    typedef y<int> zy;
+};
+
+template<>
+template<class T>
+struct x<int>::y
+{
+    typedef double result2;
+};
+
+int main()
+{
+    x<int>::zy::result2 xxx;
+    x<int>::y<int>::result2 xxx2;
+}

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