Patch for empty template argument bug

Kriang Lerdsuwanakij lerdsuwa@scf-fs.usc.edu
Thu Feb 19 00:25:00 GMT 1998


Hi

There were a couple report about the internal compiler error caused by
empty template argument like X<>.  The code that trigger the seg fault
is template template param code in coerce_template_parm -- it tries to
determine whether is_tmpl_parm should be set.  The patch below changes
the design by passing the is_tmpl_parm to coerce_template_parm
directly.  I also clean up the condition inside if's a bit.  The is_type
code should be more readable now. :)

Kriang

============================================================================

	* pt.c (coerce_template_parms) Add a new parameter, is_tmpl_parm,
	all callers changed.  Rely on the new parameter instead of arg 
	being a TREE_LIST when determine whether we are working inside
	template template parameter.  Clean up is_type test.


diff -rNpc gcc-old/cp/pt.c gcc/cp/pt.c
*** gcc-old/cp/pt.c	Wed Feb 18 16:24:03 1998
--- gcc/cp/pt.c	Wed Feb 18 22:54:58 1998
*************** static tree tsubst_expr_values PROTO((tr
*** 78,84 ****
  static int comp_template_args PROTO((tree, tree));
  static int list_eq PROTO((tree, tree));
  static tree get_class_bindings PROTO((tree, tree, tree));
! static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
  static tree tsubst_enum	PROTO((tree, tree, int, tree *));
  static tree add_to_template_args PROTO((tree, tree));
  static int  type_unification_real PROTO((tree, tree *, tree, tree,
int*,
--- 78,84 ----
  static int comp_template_args PROTO((tree, tree));
  static int list_eq PROTO((tree, tree));
  static tree get_class_bindings PROTO((tree, tree, tree));
! static tree coerce_template_parms PROTO((tree, tree, tree, int, int,
int));
  static tree tsubst_enum	PROTO((tree, tree, int, tree *));
  static tree add_to_template_args PROTO((tree, tree));
  static int  type_unification_real PROTO((tree, tree *, tree, tree,
int*,
*************** convert_nontype_argument (type, expr)
*** 1726,1744 ****
     If REQUIRE_ALL_ARGUMENTS is non-zero, all arguments must be
     provided in ARGLIST, or else trailing parameters must have default
     values.  If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
!    deduction for any unspecified trailing arguments.  */
  
  static tree
  coerce_template_parms (parms, arglist, in_decl,
  		       complain,
! 		       require_all_arguments)
       tree parms, arglist;
       tree in_decl;
       int complain;
       int require_all_arguments;
  {
    int nparms, nargs, i, lost = 0;
-   int is_tmpl_parm = 0;
    tree vec = NULL_TREE;
  
    if (arglist == NULL_TREE)
--- 1726,1749 ----
     If REQUIRE_ALL_ARGUMENTS is non-zero, all arguments must be
     provided in ARGLIST, or else trailing parameters must have default
     values.  If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
!    deduction for any unspecified trailing arguments.
!    
!    If IS_TMPL_PARM is non-zero,  we will coercing parameters of
template 
!    template arguments.  In this case, ARGLIST is a chain of TREE_LIST
!    nodes containing TYPE_DECL, TEMPLATE_DECL or PARM_DECL.  */
  
  static tree
  coerce_template_parms (parms, arglist, in_decl,
  		       complain,
! 		       require_all_arguments,
! 		       is_tmpl_parm)
       tree parms, arglist;
       tree in_decl;
       int complain;
       int require_all_arguments;
+      int is_tmpl_parm;
  {
    int nparms, nargs, i, lost = 0;
    tree vec = NULL_TREE;
  
    if (arglist == NULL_TREE)
*************** coerce_template_parms (parms, arglist, i
*** 1772,1781 ****
      vec = copy_node (arglist);
    else
      {
-       /* We can arrive here with arglist being a TREE_VEC when a 
- 	 template with some default arguments is used as template 
- 	 template argument.  */
-       is_tmpl_parm = TREE_CODE (arglist) == TREE_VEC;
        vec = make_tree_vec (nparms);
  
        for (i = 0; i < nparms; i++)
--- 1777,1782 ----
*************** coerce_template_parms (parms, arglist, i
*** 1819,1824 ****
--- 1820,1835 ----
        tree val = 0;
        int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
  
+       if (is_tmpl_parm && i < nargs)
+ 	{
+ 	  /* In case we are checking arguments inside a template template
+ 	     parameter, ARG that does not come from default argument is 
+ 	     also a TREE_LIST node.  Note that ARG can also be a TREE_LIST
+ 	     in other cases such as overloaded functions.  */
+ 	  if (arg != NULL_TREE && arg != error_mark_node)
+ 	    arg = TREE_VALUE (arg);
+ 	}
+ 
        if (arg == NULL_TREE)
  	/* We're out of arguments.  */
  	{
*************** coerce_template_parms (parms, arglist, i
*** 1845,1858 ****
  	  arg = TREE_VALUE (arg);
  	  TREE_TYPE (arg) = unknown_type_node;
  	}
-       else if (TREE_CODE (arg) == TREE_LIST && ! is_overloaded_fn
(arg))
- 	{
- 	  /* In case we are checking arguments inside a template template
- 	     parameter, ARG that does not come from default argument is 
- 	     also a TREE_LIST node */
-           is_tmpl_parm = 1;
- 	  arg = TREE_VALUE (arg);
- 	}
  
        requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
        requires_type = TREE_CODE (parm) == TYPE_DECL
--- 1856,1861 ----
*************** coerce_template_parms (parms, arglist, i
*** 1873,1882 ****
  	arg = TYPE_STUB_DECL (arg);
        else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
  	arg = CLASSTYPE_TI_TEMPLATE (arg);
!       
!       is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
! 		|| is_tmpl_type
! 		|| (is_tmpl_parm && TREE_CODE (arg) == TYPE_DECL);
  
        if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
  	  && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
--- 1876,1886 ----
  	arg = TYPE_STUB_DECL (arg);
        else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
  	arg = CLASSTYPE_TI_TEMPLATE (arg);
! 
!       if (is_tmpl_parm && i < nargs)
! 	is_type = TREE_CODE (arg) == TYPE_DECL || is_tmpl_type;
!       else
! 	is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't' || is_tmpl_type;
  
        if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
  	  && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
*************** coerce_template_parms (parms, arglist, i
*** 1949,1955 ****
  		   template <class T, class Allcator = allocator> 
  		   class vector.  */
  
! 	      val = coerce_template_parms (argparm, parmparm, in_decl, 1, 1);
  	      if (val != error_mark_node)
  		val = arg;
  		    
--- 1953,1959 ----
  		   template <class T, class Allcator = allocator> 
  		   class vector.  */
  
! 	      val = coerce_template_parms (argparm, parmparm, in_decl, 1, 1,
1);
  	      if (val != error_mark_node)
  		val = arg;
  		    
*************** lookup_template_class (d1, arglist, in_d
*** 2304,2310 ****
        CLASSTYPE_GOT_SEMICOLON (parm) = 1;
        parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
  
!       arglist2 = coerce_template_parms (parmlist, arglist, template,
1, 1);
        if (arglist2 == error_mark_node)
  	return error_mark_node;
  
--- 2308,2314 ----
        CLASSTYPE_GOT_SEMICOLON (parm) = 1;
        parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
  
!       arglist2 = coerce_template_parms (parmlist, arglist, template,
1, 1, 0);
        if (arglist2 == error_mark_node)
  	return error_mark_node;
  
*************** lookup_template_class (d1, arglist, in_d
*** 2321,2327 ****
        parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
  
        arglist = coerce_template_parms (parmlist, arglist, template,
! 				       1, 1);
        if (arglist == error_mark_node)
  	return error_mark_node;
        if (uses_template_parms (arglist))
--- 2325,2331 ----
        parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
  
        arglist = coerce_template_parms (parmlist, arglist, template,
! 				       1, 1, 0);
        if (arglist == error_mark_node)
  	return error_mark_node;
        if (uses_template_parms (arglist))
*************** type_unification (tparms, targs, parms, 
*** 4732,4738 ****
      {
        tree arg_vec;
        arg_vec = coerce_template_parms (tparms, targs_in, NULL_TREE, 0,
! 				       0);
  
        if (arg_vec == error_mark_node)
  	return 1;
--- 4736,4742 ----
      {
        tree arg_vec;
        arg_vec = coerce_template_parms (tparms, targs_in, NULL_TREE, 0,
! 				       0, 0);
  
        if (arg_vec == error_mark_node)
  	return 1;
*************** unify (tparms, targs, ntparms, parm, arg
*** 5016,5022 ****
  		 template <class T, class Allcator = allocator> 
  		   class vector.  */
  
! 	    if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1)
  		== error_mark_node)
  	      return 1;
  	  
--- 5020,5026 ----
  		 template <class T, class Allcator = allocator> 
  		   class vector.  */
  
! 	    if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1,
0)
  		== error_mark_node)
  	      return 1;
  	  
diff -rNpc gcc-old/testsuite/g++.old-deja/g++.pt/defarg2.C
gcc/testsuite/g++.old-deja/g++.pt/defarg2.C
*** gcc-old/testsuite/g++.old-deja/g++.pt/defarg2.C	Wed Dec 31 16:00:00
1969
--- gcc/testsuite/g++.old-deja/g++.pt/defarg2.C	Wed Feb 18 23:43:13 1998
***************
*** 0 ****
--- 1,17 ----
+ template <int S=0, class T=int>
+ struct X
+ {};
+ 
+ template <>
+ struct X<0,int>
+ {};
+ 
+ template <int S>
+ struct X<S,int>
+ : X<>
+ {};
+ 
+ int main()
+ {
+   X<1,int> x;
+ }



More information about the Gcc-bugs mailing list