Patchwork C++ PATCH for c++/54416 (ICE after error on bogus specialization)

login
register
mail settings
Submitter Jason Merrill
Date Dec. 11, 2012, 6:16 p.m.
Message ID <50C77873.8090808@redhat.com>
Download mbox | patch
Permalink /patch/205280/
State New
Headers show

Comments

Jason Merrill - Dec. 11, 2012, 6:16 p.m.
In this testcase we get confused by a specialization nested inside a 
class template; the members of the specialization end up having 
dependent template arguments, and then we get confused when we try to 
define one of them in a context that has no template headers.

Fixed by rejecting the definition of the specialization, and therefore 
the definition of the member of the specialization.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 9bcbafc418c3f7aff48c8e98f362e7f44849051e
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Dec 11 10:59:36 2012 -0500

    	* pt.c (maybe_process_partial_specialization): Handle aliases first.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1bc9e1b..f30a1e1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -812,13 +812,17 @@  maybe_process_partial_specialization (tree type)
 
   context = TYPE_CONTEXT (type);
 
-  if ((CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
-      /* Consider non-class instantiations of alias templates as
-	 well.  */
-      || (TYPE_P (type)
-	  && TYPE_TEMPLATE_INFO (type)
-	  && DECL_LANG_SPECIFIC (TYPE_NAME (type))
-	  && DECL_USE_TEMPLATE (TYPE_NAME (type))))
+  if (TYPE_ALIAS_P (type))
+    {
+      if (TYPE_TEMPLATE_INFO (type)
+	  && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
+	error ("specialization of alias template %qD",
+	       TYPE_TI_TEMPLATE (type));
+      else
+	error ("explicit specialization of non-template %qT", type);
+      return error_mark_node;
+    }
+  else if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
     {
       /* This is for ordinary explicit specialization and partial
 	 specialization of a template class such as:
@@ -831,8 +835,7 @@  maybe_process_partial_specialization (tree type)
 
 	 Make sure that `C<int>' and `C<T*>' are implicit instantiations.  */
 
-      if (CLASS_TYPE_P (type)
-	  && CLASSTYPE_IMPLICIT_INSTANTIATION (type)
+      if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
 	  && !COMPLETE_TYPE_P (type))
 	{
 	  check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
@@ -845,16 +848,9 @@  maybe_process_partial_specialization (tree type)
 		return error_mark_node;
 	    }
 	}
-      else if (CLASS_TYPE_P (type)
-	       && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+      else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
 	error ("specialization of %qT after instantiation", type);
 
-      if (DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
-	{
-	  error ("partial specialization of alias template %qD",
-		 TYPE_TI_TEMPLATE (type));
-	  return error_mark_node;
-	}
     }
   else if (CLASS_TYPE_P (type)
 	   && !CLASSTYPE_USE_TEMPLATE (type)
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
index d0eda5f..cbba90f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
@@ -5,10 +5,10 @@ 
 
 template<class T, class U> struct A0 {};
 template<class T, class U> using AA0 = A0<T, U>;
-template<class T> struct AA0<int, T> {}; // { dg-error "partial specialization" }
+template<class T> struct AA0<int, T> {}; // { dg-error "specialization" }
 
 template <class U> using Ptr = U*;
-template<class U> struct Ptr<U*> {}; // { dg-error "partial specialization" }
+template<class U> struct Ptr<U*> {}; // { dg-error "specialization" }
 
 struct A {
     using A = int;//{ dg-error "nested|has|same name as|class|in which|declared" }

commit e575667938e576ceeede4bdb00361d2b52540a48
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Dec 8 20:16:30 2012 -0500

    	PR c++/54416
    	* pt.c (maybe_process_partial_specialization): Don't accept
    	definition of a specialization without the appropriate header.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f30a1e1..91450d8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -850,7 +850,13 @@  maybe_process_partial_specialization (tree type)
 	}
       else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
 	error ("specialization of %qT after instantiation", type);
-
+      else if (errorcount && !processing_specialization
+	        && CLASSTYPE_TEMPLATE_SPECIALIZATION (type)
+	       && !uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+	/* Trying to define a specialization either without a template<> header
+	   or in an inappropriate place.  We've already given an error, so just
+	   bail now so we don't actually define the specialization.  */
+	return error_mark_node;
     }
   else if (CLASS_TYPE_P (type)
 	   && !CLASSTYPE_USE_TEMPLATE (type)
diff --git a/gcc/testsuite/g++.dg/template/crash105.C b/gcc/testsuite/g++.dg/template/crash105.C
index 649bf8b..8cfff6a 100644
--- a/gcc/testsuite/g++.dg/template/crash105.C
+++ b/gcc/testsuite/g++.dg/template/crash105.C
@@ -10,5 +10,8 @@  template < typename > struct S < int >
 void
 f ()
 {
-  S < int >::f (); // { dg-error "cannot call" }
+  S < int >::f ();
 }
+
+// Don't be picky about error-recovery.
+// { dg-prune-output "." }
diff --git a/gcc/testsuite/g++.dg/template/error48.C b/gcc/testsuite/g++.dg/template/error48.C
new file mode 100644
index 0000000..483f7b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error48.C
@@ -0,0 +1,15 @@ 
+// PR c++/54416
+
+template < typename T > struct foo;
+template <> struct foo < int >;
+template < typename T > struct bar
+{
+  template <> struct foo < int > // { dg-error "non-namespace scope" }
+  {
+    void baz ();
+  };
+};
+void foo < int >::baz () { }
+
+// Don't be picky about error-recovery.
+// { dg-prune-output "." }