PATCH for partial specialization crash

Mark Mitchell mmitchell@usa.net
Sat Mar 21 18:37:00 GMT 1998


Jason --

  Here's a revised (and hopefully improved) version of the 
partial-specialization patch I submitted, and then retracted, earlier.
Is this OK?

-- 
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available

Sat Mar 21 18:28:47 1998  Mark Mitchell  <mmitchell@usa.net>

	* error.c (dump_expr): Remove unused variable `l'.

	* cp-tree.h (tree_fn_t): New typedef.
	* pt.c (for_each_template_parm): New function, created by
	converting uses_template_parms.
	(uses_template_parms): Use it.
	(mark_template_parm): New function.
	(push_template_decl): Check that the argument list of a partial
	specialization uses all the template parameters.

Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.43
diff -c -p -r1.43 cp-tree.h
*** cp-tree.h	1998/03/18 10:51:54	1.43
--- cp-tree.h	1998/03/22 02:23:06
*************** typedef struct 
*** 58,63 ****
--- 58,67 ----
    tree decl;
  } template_parm_index;
  
+ /* The type of functions taking a tree, and some additional data, and
+    returning an int.  */
+ typedef int (*tree_fn_t) PROTO((tree, void*));
+ 
  #define BINDING_SCOPE(NODE)	(((struct tree_binding*)NODE)->scope)
  #define BINDING_VALUE(NODE)	(((struct tree_binding*)NODE)->value)
  #define NAMESPACE_BINDING(ID,NS) BINDING_VALUE (binding_for_name (ID, NS))
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.29
diff -c -p -r1.29 error.c
*** error.c	1998/02/25 00:49:45	1.29
--- error.c	1998/03/22 02:23:11
*************** dump_expr (t, nop)
*** 1533,1544 ****
        }
  
      case TEMPLATE_PARM_INDEX:
!       {
! 	int l = current_template_parms ? 
! 	  list_length (current_template_parms) : 0;
! 
! 	dump_decl (TEMPLATE_PARM_DECL (t), -1);
!       }
        break;
  
      case IDENTIFIER_NODE:
--- 1533,1539 ----
        }
  
      case TEMPLATE_PARM_INDEX:
!       dump_decl (TEMPLATE_PARM_DECL (t), -1);
        break;
  
      case IDENTIFIER_NODE:
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.101
diff -c -p -r1.101 pt.c
*** pt.c	1998/03/20 10:44:05	1.101
--- pt.c	1998/03/22 02:23:26
*************** static void note_template_header PROTO((
*** 88,93 ****
--- 88,94 ----
  static tree maybe_fold_nontype_arg PROTO((tree));
  static tree convert_nontype_argument PROTO((tree, tree));
  static tree get_bindings_overload PROTO((tree, tree, tree));
+ static int for_each_template_parm PROTO((tree, tree_fn_t, void*));
  
  /* Do any processing required when DECL (a member template declaration
     using TEMPLATE_PARAMETERS as its innermost parameter list) is
*************** build_template_decl (decl, parms)
*** 1465,1471 ****
    return tmpl;
  }
  
!   
  /* Creates a TEMPLATE_DECL for the indicated DECL using the template
     parameters given by current_template_args, or reuses a
     previously existing one, if appropriate.  Returns the DECL, or an
--- 1466,1509 ----
    return tmpl;
  }
  
! struct template_parm_data
! {
!   int level;
!   int* parms;
! };
! 
! /* Subroutine of push_template_decl used to see if each template
!    parameter in a partial specialization is used in the explicit
!    argument list.  If T is of the LEVEL given in DATA (which is
!    treated as a template_parm_data*), then DATA->PARMS is marked
!    appropriately.  */
! 
! static int
! mark_template_parm (t, data)
!      tree t;
!      void* data;
! {
!   int level;
!   int idx;
!   struct template_parm_data* tpd = (struct template_parm_data*) data;
! 
!   if (TREE_CODE (t) == TEMPLATE_PARM_INDEX)
!     {
!       level = TEMPLATE_PARM_LEVEL (t);
!       idx = TEMPLATE_PARM_IDX (t);
!     }
!   else
!     {
!       level = TEMPLATE_TYPE_LEVEL (t);
!       idx = TEMPLATE_TYPE_IDX (t);
!     }
! 
!   if (level == tpd->level)
!     tpd->parms[idx] = 1;
! 
!   return 0;
! }
! 
  /* Creates a TEMPLATE_DECL for the indicated DECL using the template
     parameters given by current_template_args, or reuses a
     previously existing one, if appropriate.  Returns the DECL, or an
*************** push_template_decl (decl)
*** 1530,1535 ****
--- 1568,1633 ----
        tree mainargs = CLASSTYPE_TI_ARGS (type);
        tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl);
  
+       /* We check that each of the template parameters given in the
+ 	 partial specialization is used in the argument list to the
+ 	 specialization.  For example:
+ 	 
+ 	   template <class T> struct S;
+ 	   template <class T> struct S<T*>;
+ 
+ 	 The second declaration is OK because `T*' uses the template
+ 	 parameter T, whereas
+        
+            template <class T> struct S<int>;
+ 
+ 	 is no good.  Even trickier is:
+ 
+ 	   template <class T>
+ 	   struct S1
+ 	   {
+ 	      template <class U>
+ 	      struct S2;
+ 	      template <class U>
+ 	      struct S2<T>;
+ 	   };
+ 	   
+ 	 The S2<T> declaration is actually illegal; it is a
+ 	 full-specialization.  Of course, 
+ 
+               template <class U>
+               struct S2<T (*)(U)>;
+ 
+          or some such would have been OK.  */
+       int  i;
+       struct template_parm_data tpd;
+       int ntparms = TREE_VEC_LENGTH (TREE_VALUE (current_template_parms));
+       int did_error_intro = 0;
+ 
+       tpd.level = TREE_INT_CST_HIGH (TREE_PURPOSE (current_template_parms));
+       tpd.parms = alloca (sizeof (int) * ntparms);
+       for (i = 0; i < ntparms; ++i)
+ 	tpd.parms[i] = 0;
+       for (i = 0; i < TREE_VEC_LENGTH (mainargs); ++i)
+ 	for_each_template_parm (TREE_VEC_ELT (mainargs, i),
+ 				&mark_template_parm,
+ 				&tpd);
+       for (i = 0; i < ntparms; ++i)
+ 	if (tpd.parms[i] == 0)
+ 	  {
+ 	    /* One of the template parms was not used in the
+ 	       specialization.  */
+ 	    if (!did_error_intro)
+ 	      {
+ 		cp_error ("template parameters not used in partial specialization:");
+ 		did_error_intro = 1;
+ 	      }
+ 
+ 	    cp_error ("        `%D'", 
+ 		      TREE_VALUE (TREE_VEC_ELT 
+ 				  (TREE_VALUE (current_template_parms),
+ 				   i)));
+ 	  }
+ 
        for (; spec; spec = TREE_CHAIN (spec))
  	{
  	  /* purpose: args to main template
*************** lookup_template_class (d1, arglist, in_d
*** 2738,2746 ****
  /* Should be defined in parse.h.  */
  extern int yychar;
  
  int
! uses_template_parms (t)
       tree t;
  {
    if (!t)
      return 0;
--- 2836,2854 ----
  /* Should be defined in parse.h.  */
  extern int yychar;
  
+ /* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or
+    TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA.
+    If FN returns non-zero, the iteration is terminated, and
+    for_each_template_parm returns 1.  Otherwise, the iteration
+    continues.  If FN never returns a non-zero value, the value
+    returned by for_each_template_parm is 0.  If FN is NULL, it is
+    considered to be the function which always returns 1.  */
+ 
  int
! for_each_template_parm (t, fn, data)
       tree t;
+      tree_fn_t fn;
+      void* data;
  {
    if (!t)
      return 0;
*************** uses_template_parms (t)
*** 2751,2757 ****
        /* We assume that the object must be instantiated in order to build
  	 the COMPONENT_REF, so we test only whether the type of the
  	 COMPONENT_REF uses template parms.  */
!       return uses_template_parms (TREE_TYPE (t));
  
      case IDENTIFIER_NODE:
        if (!IDENTIFIER_TEMPLATE (t))
--- 2859,2865 ----
        /* We assume that the object must be instantiated in order to build
  	 the COMPONENT_REF, so we test only whether the type of the
  	 COMPONENT_REF uses template parms.  */
!       return for_each_template_parm (TREE_TYPE (t), fn, data);
  
      case IDENTIFIER_NODE:
        if (!IDENTIFIER_TEMPLATE (t))
*************** uses_template_parms (t)
*** 2763,2811 ****
        {
  	int i = TREE_VEC_LENGTH (t);
  	while (i--)
! 	  if (uses_template_parms (TREE_VEC_ELT (t, i)))
  	    return 1;
  	return 0;
        }
      case TREE_LIST:
!       if (uses_template_parms (TREE_PURPOSE (t))
! 	  || uses_template_parms (TREE_VALUE (t)))
  	return 1;
!       return uses_template_parms (TREE_CHAIN (t));
  
        /* constructed type nodes */
      case POINTER_TYPE:
      case REFERENCE_TYPE:
!       return uses_template_parms (TREE_TYPE (t));
      case RECORD_TYPE:
        if (TYPE_PTRMEMFUNC_FLAG (t))
! 	return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t));
      case UNION_TYPE:
        if (! CLASSTYPE_TEMPLATE_INFO (t))
  	return 0;
!       return uses_template_parms (TREE_VALUE (CLASSTYPE_TEMPLATE_INFO (t)));
      case FUNCTION_TYPE:
!       if (uses_template_parms (TYPE_ARG_TYPES (t)))
  	return 1;
!       return uses_template_parms (TREE_TYPE (t));
      case ARRAY_TYPE:
!       if (uses_template_parms (TYPE_DOMAIN (t)))
  	return 1;
!       return uses_template_parms (TREE_TYPE (t));
      case OFFSET_TYPE:
!       if (uses_template_parms (TYPE_OFFSET_BASETYPE (t)))
  	return 1;
!       return uses_template_parms (TREE_TYPE (t));
      case METHOD_TYPE:
!       if (uses_template_parms (TYPE_METHOD_BASETYPE (t)))
  	return 1;
!       if (uses_template_parms (TYPE_ARG_TYPES (t)))
  	return 1;
!       return uses_template_parms (TREE_TYPE (t));
  
        /* decl nodes */
      case TYPE_DECL:
!       return uses_template_parms (TREE_TYPE (t));
  
      case TEMPLATE_DECL:
        /* A template template parameter is encountered */
--- 2871,2922 ----
        {
  	int i = TREE_VEC_LENGTH (t);
  	while (i--)
! 	  if (for_each_template_parm (TREE_VEC_ELT (t, i), fn, data))
  	    return 1;
  	return 0;
        }
      case TREE_LIST:
!       if (for_each_template_parm (TREE_PURPOSE (t), fn, data)
! 	  || for_each_template_parm (TREE_VALUE (t), fn, data))
  	return 1;
!       return for_each_template_parm (TREE_CHAIN (t), fn, data);
  
        /* constructed type nodes */
      case POINTER_TYPE:
      case REFERENCE_TYPE:
!       return for_each_template_parm (TREE_TYPE (t), fn, data);
      case RECORD_TYPE:
        if (TYPE_PTRMEMFUNC_FLAG (t))
! 	return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE (t),
! 				       fn, data);
      case UNION_TYPE:
        if (! CLASSTYPE_TEMPLATE_INFO (t))
  	return 0;
!       return for_each_template_parm (TREE_VALUE
! 				     (CLASSTYPE_TEMPLATE_INFO (t)),
! 				     fn, data);
      case FUNCTION_TYPE:
!       if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
  	return 1;
!       return for_each_template_parm (TREE_TYPE (t), fn, data);
      case ARRAY_TYPE:
!       if (for_each_template_parm (TYPE_DOMAIN (t), fn, data))
  	return 1;
!       return for_each_template_parm (TREE_TYPE (t), fn, data);
      case OFFSET_TYPE:
!       if (for_each_template_parm (TYPE_OFFSET_BASETYPE (t), fn, data))
  	return 1;
!       return for_each_template_parm (TREE_TYPE (t), fn, data);
      case METHOD_TYPE:
!       if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
  	return 1;
!       if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
  	return 1;
!       return for_each_template_parm (TREE_TYPE (t), fn, data);
  
        /* decl nodes */
      case TYPE_DECL:
!       return for_each_template_parm (TREE_TYPE (t), fn, data);
  
      case TEMPLATE_DECL:
        /* A template template parameter is encountered */
*************** uses_template_parms (t)
*** 2817,2823 ****
        return 0;
        
      case CONST_DECL:
!       if (uses_template_parms (DECL_INITIAL (t)))
  	return 1;
        goto check_type_and_context;
  
--- 2928,2934 ----
        return 0;
        
      case CONST_DECL:
!       if (for_each_template_parm (DECL_INITIAL (t), fn, data))
  	return 1;
        goto check_type_and_context;
  
*************** uses_template_parms (t)
*** 2825,2857 ****
      case VAR_DECL:
        /* ??? What about FIELD_DECLs?  */
        if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
! 	  && uses_template_parms (DECL_TI_ARGS (t)))
  	return 1;
        /* fall through */
      case PARM_DECL:
      check_type_and_context:
!       if (uses_template_parms (TREE_TYPE (t)))
  	return 1;
!       if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t)))
  	return 1;
        return 0;
  
      case CALL_EXPR:
!       return uses_template_parms (TREE_TYPE (t));
      case ADDR_EXPR:
!       return uses_template_parms (TREE_OPERAND (t, 0));
  
        /* template parm nodes */
      case TEMPLATE_TYPE_PARM:
      case TEMPLATE_TEMPLATE_PARM:
      case TEMPLATE_PARM_INDEX:
!       return 1;
  
        /* simple type nodes */
      case INTEGER_TYPE:
!       if (uses_template_parms (TYPE_MIN_VALUE (t)))
  	return 1;
!       return uses_template_parms (TYPE_MAX_VALUE (t));
  
      case REAL_TYPE:
      case COMPLEX_TYPE:
--- 2936,2972 ----
      case VAR_DECL:
        /* ??? What about FIELD_DECLs?  */
        if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
! 	  && for_each_template_parm (DECL_TI_ARGS (t), fn, data))
  	return 1;
        /* fall through */
      case PARM_DECL:
      check_type_and_context:
!       if (for_each_template_parm (TREE_TYPE (t), fn, data))
  	return 1;
!       if (DECL_CONTEXT (t) 
! 	  && for_each_template_parm (DECL_CONTEXT (t), fn, data))
  	return 1;
        return 0;
  
      case CALL_EXPR:
!       return for_each_template_parm (TREE_TYPE (t), fn, data);
      case ADDR_EXPR:
!       return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
  
        /* template parm nodes */
      case TEMPLATE_TYPE_PARM:
      case TEMPLATE_TEMPLATE_PARM:
      case TEMPLATE_PARM_INDEX:
!       if (fn)
! 	return (*fn)(t, data);
!       else
! 	return 1;
  
        /* simple type nodes */
      case INTEGER_TYPE:
!       if (for_each_template_parm (TYPE_MIN_VALUE (t), fn, data))
  	return 1;
!       return for_each_template_parm (TYPE_MAX_VALUE (t), fn, data);
  
      case REAL_TYPE:
      case COMPLEX_TYPE:
*************** uses_template_parms (t)
*** 2864,2870 ****
  	tree v;
  
  	for (v = TYPE_VALUES (t); v != NULL_TREE; v = TREE_CHAIN (v))
! 	  if (uses_template_parms (TREE_VALUE (v)))
  	    return 1;
        }
        return 0;
--- 2979,2985 ----
  	tree v;
  
  	for (v = TYPE_VALUES (t); v != NULL_TREE; v = TREE_CHAIN (v))
! 	  if (for_each_template_parm (TREE_VALUE (v), fn, data))
  	    return 1;
        }
        return 0;
*************** uses_template_parms (t)
*** 2886,2897 ****
        return 1;
  
      case SCOPE_REF:
!       return uses_template_parms (TREE_OPERAND (t, 0));
  
      case CONSTRUCTOR:
        if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
! 	return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
!       return uses_template_parms (TREE_OPERAND (t, 1));
  
      case MODOP_EXPR:
      case CAST_EXPR:
--- 3001,3013 ----
        return 1;
  
      case SCOPE_REF:
!       return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
  
      case CONSTRUCTOR:
        if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
! 	return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
! 				       (TREE_TYPE (t)), fn, data);
!       return for_each_template_parm (TREE_OPERAND (t, 1), fn, data);
  
      case MODOP_EXPR:
      case CAST_EXPR:
*************** uses_template_parms (t)
*** 2906,2912 ****
  
      case SIZEOF_EXPR:
      case ALIGNOF_EXPR:
!       return uses_template_parms (TREE_OPERAND (t, 0));
  
      default:
        switch (TREE_CODE_CLASS (TREE_CODE (t)))
--- 3022,3028 ----
  
      case SIZEOF_EXPR:
      case ALIGNOF_EXPR:
!       return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
  
      default:
        switch (TREE_CODE_CLASS (TREE_CODE (t)))
*************** uses_template_parms (t)
*** 2918,2924 ****
  	  {
  	    int i;
  	    for (i = tree_code_length[(int) TREE_CODE (t)]; --i >= 0;)
! 	      if (uses_template_parms (TREE_OPERAND (t, i)))
  		return 1;
  	    return 0;
  	  }
--- 3034,3040 ----
  	  {
  	    int i;
  	    for (i = tree_code_length[(int) TREE_CODE (t)]; --i >= 0;)
! 	      if (for_each_template_parm (TREE_OPERAND (t, i), fn, data))
  		return 1;
  	    return 0;
  	  }
*************** uses_template_parms (t)
*** 2933,2938 ****
--- 3049,3061 ----
      }
  }
  
+ int
+ uses_template_parms (t)
+      tree t;
+ {
+   return for_each_template_parm (t, 0, 0);
+ }
+ 
  static struct tinst_level *current_tinst_level = 0;
  static struct tinst_level *free_tinst_level = 0;
  static int tinst_depth = 0;
Index: testsuite/g++.old-deja/g++.pt/crash4.C
===================================================================
RCS file: crash4.C
diff -N crash4.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- crash4.C	Sat Mar 21 18:29:40 1998
***************
*** 0 ****
--- 1,12 ----
+ // Build don't link:
+ 
+ template <unsigned rank>
+ class Tensor
+ {
+ };
+ 
+ template <unsigned rank>
+ class Tensor<2> : Tensor<rank> // ERROR - template parameters not used
+ {
+ };
+ 



More information about the Gcc-bugs mailing list