[C++ PATCH] Fix PR6440, a regression

Kriang Lerdsuwanakij lerdsuwa@users.sourceforge.net
Wed Mar 5 13:47:00 GMT 2003


Hi

This patch is a revised fix for PR6440 which is a regression from 2.95 
that present in 3.2, 3.3 branches and trunk.  Currently GCC ICE on
the explicit specialization:

	   template <> template <class U> class C<int>::D;

due to problem in 'most_general_template' logic.  It still thinks
'C<T>::D<U>' is the most general one rather than the 

The patch fixes this ICE by applying SET_CLASSTYPE_TEMPLATE_SPECIALIZATION 
to 'C<int>::D' in 'maybe_process_partial_specialization' and make 
'most_general_template' terminate on this specialization.  The rest 
of the patch just adds some more checks to reject invalid code.

Bootstrapped and tested on i686-pc-linux-gnu.  OK for 3.3 and trunk?

--Kriang


2003-03-05  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/6440
	* pt.c (maybe_process_partial_specialization): Handle
	member class template when enclosing class template is
	explicit specialized.
	(most_general_template): Stop looking when DECL is already
	specialized.

2003-03-05  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/6440
	* g++.dg/template/spec7.C: New test.
	* g++.dg/template/spec8.C: Likewise.


diff -cprN gcc-33-save/gcc/cp/pt.c gcc-33-new/gcc/cp/pt.c
*** gcc-33-save/gcc/cp/pt.c	Tue Mar  4 21:11:48 2003
--- gcc-33-new/gcc/cp/pt.c	Wed Mar  5 19:09:13 2003
*************** void 
*** 767,774 ****
  maybe_process_partial_specialization (type)
       tree type;
  {
!   if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
      {
        if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
  	  && !COMPLETE_TYPE_P (type))
  	{
--- 767,788 ----
  maybe_process_partial_specialization (type)
       tree type;
  {
!   /* TYPE maybe an ERROR_MARK_NODE.  */
!   tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE;
! 
!   if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
      {
+       /* This is for ordinary explicit specialization and partial
+ 	 specialization of a template class such as:
+ 
+ 	   template <> class C<int>;
+ 
+ 	 or:
+ 
+ 	   template <class T> class C<T*>;
+ 
+ 	 Make sure that `C<int>' and `C<T*>' are implicit instantiations.  */
+ 
        if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
  	  && !COMPLETE_TYPE_P (type))
  	{
*************** maybe_process_partial_specialization (ty
*** 786,791 ****
--- 800,861 ----
        else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
  	error ("specialization of `%T' after instantiation", type);
      }
+   else if (CLASS_TYPE_P (type)
+ 	   && !CLASSTYPE_USE_TEMPLATE (type)
+ 	   && CLASSTYPE_TEMPLATE_INFO (type)
+ 	   && context && CLASS_TYPE_P (context)
+ 	   && CLASSTYPE_TEMPLATE_INFO (context))
+     {
+       /* This is for an explicit specialization of member class
+ 	 template according to [temp.expl.spec/18]:
+ 
+ 	   template <> template <class U> class C<int>::D;
+ 
+ 	 The context `C<int>' must be an implicit instantiation.
+ 	 Otherwise this is just a member class template declared
+ 	 earlier like:
+ 
+ 	   template <> class C<int> { template <class U> class D; };
+ 	   template <> template <class U> class C<int>::D;
+ 
+ 	 In the first case, `C<int>::D' is a specialization of `C<T>::D'
+ 	 while in the second case, `C<int>::D' is a primary template
+ 	 and `C<T>::D' may not exist.  */
+ 
+       if (CLASSTYPE_IMPLICIT_INSTANTIATION (context)
+ 	  && !COMPLETE_TYPE_P (type))
+ 	{
+ 	  tree t;
+ 
+ 	  if (current_namespace
+ 	      != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+ 	    {
+ 	      pedwarn ("specializing `%#T' in different namespace", type);
+ 	      cp_pedwarn_at ("  from definition of `%#D'",
+ 			     CLASSTYPE_TI_TEMPLATE (type));
+ 	    }
+ 
+ 	  /* Check for invalid specialization after instantiation:
+ 
+ 	       template <> template <> class C<int>::D<int>;
+ 	       template <> template <class U> class C<int>::D;  */
+ 
+ 	  for (t = DECL_TEMPLATE_INSTANTIATIONS
+ 		 (most_general_template (CLASSTYPE_TI_TEMPLATE (type)));
+ 	       t; t = TREE_CHAIN (t))
+ 	    if (TREE_VALUE (t) != type
+ 		&& TYPE_CONTEXT (TREE_VALUE (t)) == context)
+ 	      error ("specialization `%T' after instantiation `%T'",
+ 		     type, TREE_VALUE (t));
+ 
+ 	  /* Mark TYPE as a specialization.  And as a result, we only
+ 	     have one level of template argument for the innermost
+ 	     class template.  */
+ 	  SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ 	  CLASSTYPE_TI_ARGS (type)
+ 	    = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
+ 	}
+     }
    else if (processing_specialization)
      error ("explicit specialization of non-template `%T'", type);
  }
*************** most_general_template (decl)
*** 9603,9608 ****
--- 9673,9682 ----
        if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
  	break;
  
+       if (CLASS_TYPE_P (TREE_TYPE (decl))
+ 	  && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ 	break;
+ 
        /* Stop if we run into an explicitly specialized class template.  */
        if (!DECL_NAMESPACE_SCOPE_P (decl)
  	  && DECL_CONTEXT (decl)
diff -cprN gcc-33-save/gcc/testsuite/g++.dg/template/spec7.C gcc-33-new/gcc/testsuite/g++.dg/template/spec7.C
*** gcc-33-save/gcc/testsuite/g++.dg/template/spec7.C	Thu Jan  1 07:00:00 1970
--- gcc-33-new/gcc/testsuite/g++.dg/template/spec7.C	Wed Mar  5 19:21:46 2003
***************
*** 0 ****
--- 1,27 ----
+ // { dg-do compile }
+ 
+ // PR c++/6440: Specialization of member class template.
+ 
+ template<class T> struct A
+ {
+   template<class U> struct B {};
+ }; 
+ 
+ template<> template<class U>
+ struct A<int>::B
+ {
+   void f();
+   template <class V> void g(V);
+ };
+ 
+ template<> template<> template <class V> void A<int>::B<char>::g(V)
+ {
+ }
+ 
+ A<int>::B<char> b;
+ 
+ int h()
+ {
+   b.f();
+   b.g(0);
+ }
diff -cprN gcc-33-save/gcc/testsuite/g++.dg/template/spec8.C gcc-33-new/gcc/testsuite/g++.dg/template/spec8.C
*** gcc-33-save/gcc/testsuite/g++.dg/template/spec8.C	Thu Jan  1 07:00:00 1970
--- gcc-33-new/gcc/testsuite/g++.dg/template/spec8.C	Tue Mar  4 21:24:14 2003
***************
*** 0 ****
--- 1,11 ----
+ // { dg-do compile }
+ 
+ // Specialization of member class template.
+ 
+ template<class T1> struct A
+ {
+   template<class T2> struct B {};
+ }; 
+ 
+ template <> template <> struct A<int>::B<int> {};
+ template <> template <class U> struct A<int>::B {}; // { dg-error "specialization" }



More information about the Gcc-patches mailing list