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: Fix PR 8338


This patch fixes PR 8338, a regression that caused the compiler to go
into an infinite loop.  The fix may actually speed up the compiler a
touch on some programs by avoiding walking the same nodes more than
once in for_each_template_parm.

A bigger speedup will be to use that function in dramatically fewer
situations; coming once the new parser gets checked in.

Tested on i686-pc-linux-gnu, applied on the mainline.  I'm just a bit
too nervous to put this on the branch.

-- 
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2002-11-07  Mark Mitchell  <mark@codesourcery.com>

	PR c++/8338
	* pt.c (for_each_template_parm): Add htab parameter.
	(process_partial_specialization): Adjust call.
	(push_template_decl_real): Likewise.
	(pair_fn_data): Add visited.
	(for_each_template_parm_r): Avoid walking duplicates more than
	once.
	(uses_template_parms): Adjust call to for_each_template_parm.

2002-11-07  Mark Mitchell  <mark@codesourcery.com>

	PR c++/8338
	* g++.dg/template/crash2.C: New test.

Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.628
diff -c -p -r1.628 pt.c
*** cp/pt.c	30 Oct 2002 15:54:07 -0000	1.628
--- cp/pt.c	8 Nov 2002 01:40:00 -0000
*************** static tree convert_nontype_argument PAR
*** 115,121 ****
  static tree convert_template_argument PARAMS ((tree, tree, tree,
  					       tsubst_flags_t, int, tree));
  static tree get_bindings_overload PARAMS ((tree, tree, tree));
! static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*));
  static tree build_template_parm_index PARAMS ((int, int, int, tree, tree));
  static int inline_needs_template_parms PARAMS ((tree));
  static void push_inline_template_parms_recursive PARAMS ((tree, int));
--- 115,121 ----
  static tree convert_template_argument PARAMS ((tree, tree, tree,
  					       tsubst_flags_t, int, tree));
  static tree get_bindings_overload PARAMS ((tree, tree, tree));
! static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*, htab_t));
  static tree build_template_parm_index PARAMS ((int, int, int, tree, tree));
  static int inline_needs_template_parms PARAMS ((tree));
  static void push_inline_template_parms_recursive PARAMS ((tree, int));
*************** process_partial_specialization (decl)
*** 2237,2243 ****
        tpd.current_arg = i;
        for_each_template_parm (TREE_VEC_ELT (inner_args, i),
  			      &mark_template_parm,
! 			      &tpd);
      }
    for (i = 0; i < ntparms; ++i)
      if (tpd.parms[i] == 0)
--- 2237,2244 ----
        tpd.current_arg = i;
        for_each_template_parm (TREE_VEC_ELT (inner_args, i),
  			      &mark_template_parm,
! 			      &tpd,
! 			      NULL);
      }
    for (i = 0; i < ntparms; ++i)
      if (tpd.parms[i] == 0)
*************** process_partial_specialization (decl)
*** 2318,2324 ****
  	      memset ((PTR) tpd2.parms, 0, sizeof (int) * nargs);
  	      for_each_template_parm (type,
  				      &mark_template_parm,
! 				      &tpd2);
  		  
  	      if (tpd2.arg_uses_template_parms [i])
  		{
--- 2319,2326 ----
  	      memset ((PTR) tpd2.parms, 0, sizeof (int) * nargs);
  	      for_each_template_parm (type,
  				      &mark_template_parm,
! 				      &tpd2,
! 				      NULL);
  		  
  	      if (tpd2.arg_uses_template_parms [i])
  		{
*************** push_template_decl_real (decl, is_friend
*** 2751,2757 ****
  	  
  	  if (for_each_template_parm (TREE_TYPE (TREE_TYPE (tmpl)),
  				      template_parm_this_level_p,
! 				      &depth))
  	    DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
  	}
      }
--- 2753,2760 ----
  	  
  	  if (for_each_template_parm (TREE_TYPE (TREE_TYPE (tmpl)),
  				      template_parm_this_level_p,
! 				      &depth,
! 				      NULL))
  	    DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
  	}
      }
*************** struct pair_fn_data 
*** 4337,4342 ****
--- 4340,4346 ----
  {
    tree_fn_t fn;
    void *data;
+   htab_t visited;
  };
  
  /* Called from for_each_template_parm via walk_tree.  */
*************** for_each_template_parm_r (tp, walk_subtr
*** 4351,4359 ****
    struct pair_fn_data *pfd = (struct pair_fn_data *) d;
    tree_fn_t fn = pfd->fn;
    void *data = pfd->data;
!   
    if (TYPE_P (t)
!       && for_each_template_parm (TYPE_CONTEXT (t), fn, data))
      return error_mark_node;
  
    switch (TREE_CODE (t))
--- 4355,4374 ----
    struct pair_fn_data *pfd = (struct pair_fn_data *) d;
    tree_fn_t fn = pfd->fn;
    void *data = pfd->data;
!   void **slot;
! 
!   /* If we have already visited this tree, there's no need to walk
!      subtrees.  Otherwise, add it to the visited table.  */
!   slot = htab_find_slot (pfd->visited, *tp, INSERT);
!   if (*slot)
!     {
!       *walk_subtrees = 0;
!       return NULL_TREE;
!     }
!   *slot = *tp;
! 
    if (TYPE_P (t)
!       && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited))
      return error_mark_node;
  
    switch (TREE_CODE (t))
*************** for_each_template_parm_r (tp, walk_subtr
*** 4368,4387 ****
        if (!TYPE_TEMPLATE_INFO (t))
  	*walk_subtrees = 0;
        else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
! 				       fn, data))
  	return error_mark_node;
        break;
  
      case METHOD_TYPE:
        /* Since we're not going to walk subtrees, we have to do this
  	 explicitly here.  */
!       if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
  	return error_mark_node;
        /* Fall through.  */
  
      case FUNCTION_TYPE:
        /* Check the return type.  */
!       if (for_each_template_parm (TREE_TYPE (t), fn, data))
  	return error_mark_node;
  
        /* Check the parameter types.  Since default arguments are not
--- 4383,4403 ----
        if (!TYPE_TEMPLATE_INFO (t))
  	*walk_subtrees = 0;
        else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
! 				       fn, data, pfd->visited))
  	return error_mark_node;
        break;
  
      case METHOD_TYPE:
        /* Since we're not going to walk subtrees, we have to do this
  	 explicitly here.  */
!       if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data,
! 				  pfd->visited))
  	return error_mark_node;
        /* Fall through.  */
  
      case FUNCTION_TYPE:
        /* Check the return type.  */
!       if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
  	return error_mark_node;
  
        /* Check the parameter types.  Since default arguments are not
*************** for_each_template_parm_r (tp, walk_subtr
*** 4394,4400 ****
  	tree parm;
  
  	for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
! 	  if (for_each_template_parm (TREE_VALUE (parm), fn, data))
  	    return error_mark_node;
  
  	/* Since we've already handled the TYPE_ARG_TYPES, we don't
--- 4410,4417 ----
  	tree parm;
  
  	for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
! 	  if (for_each_template_parm (TREE_VALUE (parm), fn, data,
! 				      pfd->visited))
  	    return error_mark_node;
  
  	/* Since we've already handled the TYPE_ARG_TYPES, we don't
*************** for_each_template_parm_r (tp, walk_subtr
*** 4406,4425 ****
      case FUNCTION_DECL:
      case VAR_DECL:
        if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
! 	  && for_each_template_parm (DECL_TI_ARGS (t), fn, data))
  	return error_mark_node;
        /* Fall through.  */
  
      case CONST_DECL:
      case PARM_DECL:
        if (DECL_CONTEXT (t) 
! 	  && for_each_template_parm (DECL_CONTEXT (t), fn, data))
  	return error_mark_node;
        break;
  
      case BOUND_TEMPLATE_TEMPLATE_PARM:
        /* Record template parameters such as `T' inside `TT<T>'.  */
!       if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
  	return error_mark_node;
        /* Fall through.  */
  
--- 4423,4444 ----
      case FUNCTION_DECL:
      case VAR_DECL:
        if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
! 	  && for_each_template_parm (DECL_TI_ARGS (t), fn, data,
! 				     pfd->visited))
  	return error_mark_node;
        /* Fall through.  */
  
      case CONST_DECL:
      case PARM_DECL:
        if (DECL_CONTEXT (t) 
! 	  && for_each_template_parm (DECL_CONTEXT (t), fn, data,
! 				     pfd->visited))
  	return error_mark_node;
        break;
  
      case BOUND_TEMPLATE_TEMPLATE_PARM:
        /* Record template parameters such as `T' inside `TT<T>'.  */
!       if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited))
  	return error_mark_node;
        /* Fall through.  */
  
*************** for_each_template_parm_r (tp, walk_subtr
*** 4435,4441 ****
      case TEMPLATE_DECL:
        /* A template template parameter is encountered */
        if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
! 	  && for_each_template_parm (TREE_TYPE (t), fn, data))
  	return error_mark_node;
  
        /* Already substituted template template parameter */
--- 4454,4460 ----
      case TEMPLATE_DECL:
        /* A template template parameter is encountered */
        if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
! 	  && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
  	return error_mark_node;
  
        /* Already substituted template template parameter */
*************** for_each_template_parm_r (tp, walk_subtr
*** 4443,4456 ****
        break;
  
      case TYPENAME_TYPE:
!       if (!fn || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn, data))
  	return error_mark_node;
        break;
  
      case CONSTRUCTOR:
        if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
  	  && for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
! 				     (TREE_TYPE (t)), fn, data))
  	return error_mark_node;
        break;
        
--- 4462,4478 ----
        break;
  
      case TYPENAME_TYPE:
!       if (!fn 
! 	  || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn,
! 				     data, pfd->visited))
  	return error_mark_node;
        break;
  
      case CONSTRUCTOR:
        if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
  	  && for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
! 				     (TREE_TYPE (t)), fn, data,
! 				     pfd->visited))
  	return error_mark_node;
        break;
        
*************** for_each_template_parm_r (tp, walk_subtr
*** 4482,4488 ****
  	 the BINFO hierarchy, which is circular, and therefore
  	 confuses walk_tree.  */
        *walk_subtrees = 0;
!       if (for_each_template_parm (BASELINK_FUNCTIONS (*tp), fn, data))
  	return error_mark_node;
        break;
  
--- 4504,4511 ----
  	 the BINFO hierarchy, which is circular, and therefore
  	 confuses walk_tree.  */
        *walk_subtrees = 0;
!       if (for_each_template_parm (BASELINK_FUNCTIONS (*tp), fn, data,
! 				  pfd->visited))
  	return error_mark_node;
        break;
  
*************** for_each_template_parm_r (tp, walk_subtr
*** 4504,4513 ****
     considered to be the function which always returns 1.  */
  
  static int
! for_each_template_parm (t, fn, data)
       tree t;
       tree_fn_t fn;
       void* data;
  {
    struct pair_fn_data pfd;
  
--- 4527,4537 ----
     considered to be the function which always returns 1.  */
  
  static int
! for_each_template_parm (t, fn, data, visited)
       tree t;
       tree_fn_t fn;
       void* data;
+      htab_t visited;
  {
    struct pair_fn_data pfd;
  
*************** for_each_template_parm (t, fn, data)
*** 4518,4524 ****
    /* Walk the tree.  (Conceptually, we would like to walk without
       duplicates, but for_each_template_parm_r recursively calls
       for_each_template_parm, so we would need to reorganize a fair
!      bit to use walk_tree_without_duplicates.)  */
    return walk_tree (&t, 
  		    for_each_template_parm_r, 
  		    &pfd,
--- 4542,4554 ----
    /* Walk the tree.  (Conceptually, we would like to walk without
       duplicates, but for_each_template_parm_r recursively calls
       for_each_template_parm, so we would need to reorganize a fair
!      bit to use walk_tree_without_duplicates, so we keep our own
!      visited list.)  */
!   if (visited)
!     pfd.visited = visited;
!   else
!     pfd.visited = htab_create (37, htab_hash_pointer, htab_eq_pointer, 
! 			       NULL);
    return walk_tree (&t, 
  		    for_each_template_parm_r, 
  		    &pfd,
*************** int
*** 4529,4535 ****
  uses_template_parms (t)
       tree t;
  {
!   return for_each_template_parm (t, 0, 0);
  }
  
  static int tinst_depth;
--- 4559,4565 ----
  uses_template_parms (t)
       tree t;
  {
!   return for_each_template_parm (t, 0, 0, NULL);
  }
  
  static int tinst_depth;
Index: testsuite/g++.dg/template/crash2.C
===================================================================
RCS file: testsuite/g++.dg/template/crash2.C
diff -N testsuite/g++.dg/template/crash2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/crash2.C	8 Nov 2002 01:40:02 -0000
***************
*** 0 ****
--- 1,31 ----
+ // { dg-options "" }
+ 
+ template <class EnumType>
+ class A
+ {
+ public:
+   static const EnumType size = max; // { dg-error "" }
+   int table[size];
+ };
+ template <class EnumType>
+ const EnumType A<EnumType>::size;
+  
+  
+ namespace N
+ {
+ enum E { max = 5 };
+  
+ struct B
+ {
+   A<E> a; // { dg-error "" }
+ };
+  
+ }
+  
+ int
+ main()
+ {
+   N::B b;
+  
+   return 0;
+ }


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