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++/24791


Another of our most-reported bugs: This is a bug where we were crashing when people try to do an explicit specialization with the same template header as the template rather than just "template<>". Now we give a more helpful error message.

Yes, I've just been complaining about giving too high priority to ice-on-invalid bugs, but this one seems higher priority because of the number of duplicate reports.

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

2007-10-26  Jason Merrill  <jason@redhat.com>

	PR c++/24791
	* pt.c (get_template_info): New fn.
	(template_class_depth): Use it.
	(push_template_decl_real): Check that the template args of the 
	definition match the args of the previous declaration.

Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h	(revision 129643)
--- cp/cp-tree.h	(working copy)
*************** extern bool uses_parameter_packs        
*** 4440,4445 ****
--- 4440,4446 ----
  extern bool template_parameter_pack_p           (const_tree);
  extern tree make_pack_expansion                 (tree);
  extern bool check_for_bare_parameter_packs      (tree);
+ extern tree get_template_info			(tree);
  extern int template_class_depth			(tree);
  extern int is_specialization_of			(tree, tree);
  extern bool is_specialization_of_friend		(tree, tree);
Index: cp/pt.c
===================================================================
*** cp/pt.c	(revision 129643)
--- cp/pt.c	(working copy)
*************** finish_member_template_decl (tree decl)
*** 263,268 ****
--- 263,287 ----
    return error_mark_node;
  }
  
+ /* Return the template info node corresponding to T, whatever T is.  */
+ 
+ tree
+ get_template_info (tree t)
+ {
+   tree tinfo = NULL_TREE;
+ 
+   if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+     tinfo = DECL_TEMPLATE_INFO (t);
+ 
+   if (!tinfo && TREE_CODE (t) == TYPE_DECL)
+     t = TREE_TYPE (t);
+ 
+   if (TAGGED_TYPE_P (t))
+     tinfo = TYPE_TEMPLATE_INFO (t);
+ 
+   return tinfo;
+ }
+ 
  /* Returns the template nesting level of the indicated class TYPE.
  
     For example, in:
*************** template_class_depth (tree type)
*** 291,310 ****
         type = (TREE_CODE (type) == FUNCTION_DECL)
  	 ? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type))
      {
!       if (TREE_CODE (type) != FUNCTION_DECL)
! 	{
! 	  if (CLASSTYPE_TEMPLATE_INFO (type)
! 	      && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
! 	      && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
! 	    ++depth;
! 	}
!       else
! 	{
! 	  if (DECL_TEMPLATE_INFO (type)
! 	      && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type))
! 	      && uses_template_parms (DECL_TI_ARGS (type)))
! 	    ++depth;
! 	}
      }
  
    return depth;
--- 310,320 ----
         type = (TREE_CODE (type) == FUNCTION_DECL)
  	 ? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type))
      {
!       tree tinfo = get_template_info (type);
! 
!       if (tinfo && PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo))
! 	  && uses_template_parms (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo))))
! 	++depth;
      }
  
    return depth;
*************** push_template_decl_real (tree decl, bool
*** 3866,3892 ****
      {
        tree a, t, current, parms;
        int i;
  
!       if (TREE_CODE (decl) == TYPE_DECL)
! 	{
! 	  if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
! 	       || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
! 	      && TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
! 	      && TYPE_TI_TEMPLATE (TREE_TYPE (decl)))
! 	    tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
! 	  else
! 	    {
! 	      error ("%qD does not declare a template type", decl);
! 	      return decl;
! 	    }
! 	}
!       else if (!DECL_LANG_SPECIFIC (decl) || !DECL_TEMPLATE_INFO (decl))
  	{
  	  error ("template definition of non-template %q#D", decl);
  	  return decl;
  	}
!       else
! 	tmpl = DECL_TI_TEMPLATE (decl);
  
        if (DECL_FUNCTION_TEMPLATE_P (tmpl)
  	  && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
--- 3876,3890 ----
      {
        tree a, t, current, parms;
        int i;
+       tree tinfo = get_template_info (decl);
  
!       if (!tinfo)
  	{
  	  error ("template definition of non-template %q#D", decl);
  	  return decl;
  	}
! 
!       tmpl = TI_TEMPLATE (tinfo);
  
        if (DECL_FUNCTION_TEMPLATE_P (tmpl)
  	  && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
*************** push_template_decl_real (tree decl, bool
*** 3946,3954 ****
  		return error_mark_node;
  	      }
  
- 	    /* Perhaps we should also check that the parms are used in the
- 	       appropriate qualifying scopes in the declarator?  */
- 
  	    if (current == decl)
  	      current = ctx;
  	    else
--- 3944,3949 ----
*************** push_template_decl_real (tree decl, bool
*** 3956,3961 ****
--- 3951,3972 ----
  			 ? TYPE_CONTEXT (current)
  			 : DECL_CONTEXT (current));
  	  }
+ 
+       /* Check that the parms are used in the appropriate qualifying scopes
+ 	 in the declarator.  */
+       if (!comp_template_args
+ 	  (TI_ARGS (tinfo),
+ 	   TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl)))))
+ 	{
+ 	  error ("\
+ template arguments to %qD do not match original template %qD",
+ 		 decl, DECL_TEMPLATE_RESULT (tmpl));
+ 	  if (!uses_template_parms (TI_ARGS (tinfo)))
+ 	    inform ("use template<> for an explicit specialization");
+ 	  /* Avoid crash in import_export_decl.  */
+ 	  DECL_INTERFACE_KNOWN (decl) = 1;
+ 	  return error_mark_node;
+ 	}
      }
  
    DECL_TEMPLATE_RESULT (tmpl) = decl;
Index: testsuite/g++.old-deja/g++.pt/crash11.C
===================================================================
*** testsuite/g++.old-deja/g++.pt/crash11.C	(revision 129643)
--- testsuite/g++.old-deja/g++.pt/crash11.C	(working copy)
*************** class A
*** 8,13 ****
  };
  
  
! template <class j> class A::A_impl // { dg-error "does not declare a template" }
  {
  };
--- 8,13 ----
  };
  
  
! template <class j> class A::A_impl // { dg-error "non-template" }
  {
  };
Index: testsuite/g++.dg/template/error33.C
===================================================================
*** testsuite/g++.dg/template/error33.C	(revision 0)
--- testsuite/g++.dg/template/error33.C	(revision 0)
***************
*** 0 ****
--- 1,11 ----
+ // PR c++/24791
+ 
+ template<int> struct A
+ {
+     static int i;
+     A() { ++i; }
+ };
+ 
+ template<int> int A<0>::i(0);	// { dg-error "template" }
+ 
+ A<0> a;

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