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]

PATCH for template regression



Here's a fix for another memory corruption problem caused, at least
indirectly, by my recent template changes.  Unfortunately, I denoted
the original poster's email, so I cannot reply directly to that
message.

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

1999-08-20  Mark Mitchell  <mark@codesourcery.com>

	* semantics.c (finish_stmt_expr): Fix typo in comment.
	* tree.c (search_tree): Handle EXIT_EXPR, LOOP_EXPR.
	(mapcar): Likewise.
	* init.c (build_vec_delete_1): Make the children of a permanent
	BIND_EXPR permanent.
	* pt.c (register_specialization): Don't register a specialization
	more than once.
	

Index: testsuite/g++.old-deja/g++.pt/crash49.C
===================================================================
RCS file: crash49.C
diff -N crash49.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- crash49.C	Fri Aug 20 14:59:00 1999
***************
*** 0 ****
--- 1,37 ----
+ // Build don't link:
+ // Origin: Loring Holden <lsh@cs.brown.edu> 
+ 
+ template <class T>
+ class REFptr {
+    public:
+       virtual ~REFptr();
+       REFptr<T> &operator =  (const REFptr<T>& p);
+ };
+ 
+ class STR { };
+ class str_ptr : public REFptr<STR> { };
+ 
+ template <class T>
+ class ARRAY {
+  protected:
+    T      *_array; 
+    int     _num;   
+    int     _max;  
+  public:
+    virtual void realloc(int new_max) {
+        _max = new_max;
+        T *tmp = new T [_max];
+        if (tmp == 0) return;
+        for (int i=0; i<_num; i++) {
+           tmp[i] = _array[i];
+        }
+        delete [] _array;
+        _array = tmp;
+    }
+ };
+ 
+ int
+ main()
+ {
+    ARRAY<str_ptr> tags;
+ }
Index: cp/init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.120
diff -c -p -r1.120 init.c
*** init.c	1999/08/18 20:44:10	1.120
--- init.c	1999/08/20 21:59:08
*************** build_vec_delete_1 (base, maxindex, type
*** 2673,2678 ****
--- 2673,2687 ----
  
    if (controller)
      {
+       /* The CONTROLLER is a BIND_EXPR.  Such things are always
+ 	 allocated on at least the saveable obstack.  Since we may
+ 	 need to copy this expression to the permanent obstack, we
+ 	 must make sure that the operand is on the same obstack as the
+ 	 BIND_EXPR.  Otherwise, copy_to_permanent will not copy the
+ 	 operand, since it will assume that anything under a permanent
+ 	 node is permanent.  */
+       if (TREE_PERMANENT (controller))
+ 	body = copy_to_permanent (body);
        TREE_OPERAND (controller, 1) = body;
        return controller;
      }
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.337
diff -c -p -r1.337 pt.c
*** pt.c	1999/08/20 06:11:46	1.337
--- pt.c	1999/08/20 21:59:14
*************** register_specialization (spec, tmpl, arg
*** 842,900 ****
    for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
         s != NULL_TREE;
         s = TREE_CHAIN (s))
!     if (comp_template_args (TREE_PURPOSE (s), args))
!       {
! 	tree fn = TREE_VALUE (s);
! 
! 	if (DECL_TEMPLATE_SPECIALIZATION (spec))
! 	  {
! 	    if (DECL_TEMPLATE_INSTANTIATION (fn))
! 	      {
! 		if (TREE_USED (fn) 
! 		    || DECL_EXPLICIT_INSTANTIATION (fn))
! 		  {
! 		    cp_error ("specialization of %D after instantiation",
! 			      fn);
! 		    return spec;
! 		  }
! 		else
! 		  {
! 		    /* This situation should occur only if the first
! 		       specialization is an implicit instantiation,
! 		       the second is an explicit specialization, and
! 		       the implicit instantiation has not yet been
! 		       used.  That situation can occur if we have
! 		       implicitly instantiated a member function and
! 		       then specialized it later.
! 
! 		       We can also wind up here if a friend
! 		       declaration that looked like an instantiation
! 		       turns out to be a specialization:
! 
! 		         template <class T> void foo(T);
! 			 class S { friend void foo<>(int) };
! 			 template <> void foo(int);  
! 
! 		       We transform the existing DECL in place so that
! 		       any pointers to it become pointers to the
! 		       updated declaration.  
! 
! 		       If there was a definition for the template, but
! 		       not for the specialization, we want this to
! 		       look as if there is no definition, and vice
! 		       versa.  */
! 		    DECL_INITIAL (fn) = NULL_TREE;
! 		    duplicate_decls (spec, fn);
! 
! 		    return fn;
! 		  }
! 	      }
! 	    else if (DECL_TEMPLATE_SPECIALIZATION (fn))
! 	      {
! 		duplicate_decls (spec, fn);
! 		return fn;
! 	      }
! 	  }
        }
  
    DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
--- 842,909 ----
    for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
         s != NULL_TREE;
         s = TREE_CHAIN (s))
!     {
!       tree fn = TREE_VALUE (s);
! 
!       /* We can sometimes try to re-register a specialization that we've
! 	 already got.  In particular, regenerate_decl_from_template
! 	 calls duplicate_decls which will update the specialization
! 	 list.  But, we'll still get called again here anyhow.  It's
! 	 more convenient to simply allow this than to try to prevent it.  */
!       if (fn == spec)
! 	return spec;
!       else if (comp_template_args (TREE_PURPOSE (s), args))
! 	{
! 	  if (DECL_TEMPLATE_SPECIALIZATION (spec))
! 	    {
! 	      if (DECL_TEMPLATE_INSTANTIATION (fn))
! 		{
! 		  if (TREE_USED (fn) 
! 		      || DECL_EXPLICIT_INSTANTIATION (fn))
! 		    {
! 		      cp_error ("specialization of %D after instantiation",
! 				fn);
! 		      return spec;
! 		    }
! 		  else
! 		    {
! 		      /* This situation should occur only if the first
! 			 specialization is an implicit instantiation,
! 			 the second is an explicit specialization, and
! 			 the implicit instantiation has not yet been
! 			 used.  That situation can occur if we have
! 			 implicitly instantiated a member function and
! 			 then specialized it later.
! 
! 			 We can also wind up here if a friend
! 			 declaration that looked like an instantiation
! 			 turns out to be a specialization:
! 
! 			   template <class T> void foo(T);
! 			   class S { friend void foo<>(int) };
! 			   template <> void foo(int);  
! 
! 			 We transform the existing DECL in place so that
! 			 any pointers to it become pointers to the
! 			 updated declaration.  
! 
! 			 If there was a definition for the template, but
! 			 not for the specialization, we want this to
! 			 look as if there is no definition, and vice
! 			 versa.  */
! 		      DECL_INITIAL (fn) = NULL_TREE;
! 		      duplicate_decls (spec, fn);
! 
! 		      return fn;
! 		    }
! 		}
! 	      else if (DECL_TEMPLATE_SPECIALIZATION (fn))
! 		{
! 		  duplicate_decls (spec, fn);
! 		  return fn;
! 		}
! 	    }
! 	}
        }
  
    DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
Index: cp/semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.61
diff -c -p -r1.61 semantics.c
*** semantics.c	1999/08/19 08:06:17	1.61
--- semantics.c	1999/08/20 21:59:15
*************** finish_stmt_expr (rtl_expr, expr)
*** 1057,1063 ****
  
    if (TREE_CODE (expr) == BLOCK)
      {
!       /* Make a CP_BIND_EXPR for the BLOCK already made.  */
        if (building_stmt_tree ())
  	{
  	  result = build_min (STMT_EXPR, last_expr_type, last_tree);
--- 1057,1063 ----
  
    if (TREE_CODE (expr) == BLOCK)
      {
!       /* Make a BIND_EXPR for the BLOCK already made.  */
        if (building_stmt_tree ())
  	{
  	  result = build_min (STMT_EXPR, last_expr_type, last_tree);
Index: cp/tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.135
diff -c -p -r1.135 tree.c
*** tree.c	1999/08/19 08:06:17	1.135
--- tree.c	1999/08/20 21:59:16
*************** search_tree (t, func)
*** 1668,1673 ****
--- 1668,1675 ----
      case CLEANUP_POINT_EXPR:
      case LOOKUP_EXPR:
      case THROW_EXPR:
+     case EXIT_EXPR:
+     case LOOP_EXPR:
        TRY (TREE_OPERAND (t, 0));
        break;
  
*************** mapcar (t, func)
*** 2001,2006 ****
--- 2003,2010 ----
        return t;
  
      case LOOKUP_EXPR:
+     case EXIT_EXPR:
+     case LOOP_EXPR:
        t = copy_node (t);
        TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
        return t;


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