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]

C++ PATCH for `new'



This patch moves the semantic analysis of new-expressions to
semantic-analysis time, instead of RTL-generation time.  In addition,
I spotted an unmarked GC root, and marked it.

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

1999-09-24  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (CPTI_CLEANUP_TYPE): New macro.
	(cleanup_type): Likewise.
	(search_tree): Change prototype.
	* decl.c (local_variable_p): Adjust for new interface to
	search_tree.
	(check_default_argument): Likewise.
	* error.c (dump_expr): Handle INIT_EXPR.
	* except.c (expand_throw): Don't make cleanup_type a local static.
	* expr.c (cplus_expand_expr): Don't handle NEW_EXPR.
	* init.c (build_new): Call build_new_1 directly, rather than
	building a NEW_EXPR.
	(build_new_1): Tidy.  Don't build a VEC_INIT_EXPR except when
	processing file-scope initializers.
	* lex.c (init_parse): Add an opname_tab entry for INIT_EXPR.
	* tree.c: Include splay-tree.h
	(no_linkage_helper): Adjust for new interface to search_tree.
	(search_tree): Pass around pointers to tree nodes, rather than the
	nodes themselves.  Handle VEC_INIT_EXPR.
	(no_linkage_check): Adjust for new interface to search_tree.
	(mapcar): Handle VEC_INIT_EXPR.
	(target_remap): New variable.
	(bot_manip): Use it.
	(bot_replace): New function.
	(break_out_target_exprs): Use it to remap all variables used in a
	default argument expression.
	* typeck.c (build_modify_expr): Don't crash when outside a
	function and presented with an INIT_EXPR assignment
	* Makefile.in (tree.o): Depend on splay-tree.h.

Index: Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Makefile.in,v
retrieving revision 1.70
diff -c -p -r1.70 Makefile.in
*** Makefile.in	1999/09/20 20:19:04	1.70
--- Makefile.in	1999/09/24 20:48:15
*************** cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) 
*** 274,280 ****
  search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \
    $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h $(RTL_H)
  tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
!   $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h $(RTL_H)
  ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
  rtti.o : rtti.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
    $(srcdir)/../system.h $(srcdir)/../toplev.h
--- 274,281 ----
  search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \
    $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h $(RTL_H)
  tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
!   $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h $(RTL_H) \
!   $(srcdir)/../../include/splay-tree.h
  ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
  rtti.o : rtti.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
    $(srcdir)/../system.h $(srcdir)/../toplev.h
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.316
diff -c -p -r1.316 cp-tree.h
*** cp-tree.h	1999/09/24 01:29:28	1.316
--- cp-tree.h	1999/09/24 20:48:18
*************** enum cp_tree_index
*** 408,413 ****
--- 408,414 ----
      CPTI_WCHAR_DECL,
      CPTI_VTABLE_ENTRY_TYPE,
      CPTI_DELTA_TYPE,
+     CPTI_CLEANUP_TYPE,
  
      CPTI_TP_DESC_TYPE,
      CPTI_ACCESS_MODE_TYPE,
*************** extern tree cp_global_trees[CPTI_MAX];
*** 560,565 ****
--- 561,569 ----
  /* The declaration for `std::atexit'.  */
  #define atexit_node                     cp_global_trees[CPTI_ATEXIT]
  
+ /* The type of a destructor.  */
+ #define cleanup_type                    cp_global_trees[CPTI_CLEANUP_TYPE]
+ 
  /* Global state.  */
  
  struct saved_scope {
*************** extern void push_permanent_obstack      
*** 3855,3861 ****
  extern tree build_dummy_object			PROTO((tree));
  extern tree maybe_dummy_object			PROTO((tree, tree *));
  extern int is_dummy_object			PROTO((tree));
! extern tree search_tree                         PROTO((tree, tree (*)(tree)));
  extern int cp_valid_lang_attribute		PROTO((tree, tree, tree, tree));
  extern tree make_ptrmem_cst                     PROTO((tree, tree));
  extern tree cp_build_qualified_type_real        PROTO((tree, int, int));
--- 3859,3865 ----
  extern tree build_dummy_object			PROTO((tree));
  extern tree maybe_dummy_object			PROTO((tree, tree *));
  extern int is_dummy_object			PROTO((tree));
! extern tree search_tree                         PROTO((tree *, tree (*)(tree *)));
  extern int cp_valid_lang_attribute		PROTO((tree, tree, tree, tree));
  extern tree make_ptrmem_cst                     PROTO((tree, tree));
  extern tree cp_build_qualified_type_real        PROTO((tree, int, int));
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.467
diff -c -p -r1.467 decl.c
*** decl.c	1999/09/24 08:03:42	1.467
--- decl.c	1999/09/24 20:48:27
*************** static boolean typename_compare PROTO((h
*** 149,155 ****
  static void push_binding PROTO((tree, tree, struct binding_level*));
  static int add_binding PROTO((tree, tree));
  static void pop_binding PROTO((tree, tree));
! static tree local_variable_p PROTO((tree));
  static tree find_binding PROTO((tree, tree));
  static tree select_decl PROTO((tree, int));
  static int lookup_flags PROTO((int, int));
--- 149,155 ----
  static void push_binding PROTO((tree, tree, struct binding_level*));
  static int add_binding PROTO((tree, tree));
  static void pop_binding PROTO((tree, tree));
! static tree local_variable_p PROTO((tree *));
  static tree find_binding PROTO((tree, tree));
  static tree select_decl PROTO((tree, int));
  static int lookup_flags PROTO((int, int));
*************** require_complete_types_for_parms (parms)
*** 11190,11202 ****
      }
  }
  
! /* Returns DECL if DECL is a local variable (or parameter).  Returns
     NULL_TREE otherwise.  */
  
  static tree
! local_variable_p (t)
!      tree t;
  {
    if ((TREE_CODE (t) == VAR_DECL 
         /* A VAR_DECL with a context that is a _TYPE is a static data
  	  member.  */
--- 11190,11204 ----
      }
  }
  
! /* Returns *TP if *TP is a local variable (or parameter).  Returns
     NULL_TREE otherwise.  */
  
  static tree
! local_variable_p (tp)
!      tree *tp;
  {
+   tree t = *tp;
+ 
    if ((TREE_CODE (t) == VAR_DECL 
         /* A VAR_DECL with a context that is a _TYPE is a static data
  	  member.  */
*************** check_default_argument (decl, arg)
*** 11275,11281 ****
  
       The keyword `this' shall not be used in a default argument of a
       member function.  */
!   var = search_tree (arg, local_variable_p);
    if (var)
      {
        cp_error ("default argument `%E' uses local variable `%D'",
--- 11277,11283 ----
  
       The keyword `this' shall not be used in a default argument of a
       member function.  */
!   var = search_tree (&arg, local_variable_p);
    if (var)
      {
        cp_error ("default argument `%E' uses local variable `%D'",
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.89
diff -c -p -r1.89 error.c
*** error.c	1999/09/17 01:49:29	1.89
--- error.c	1999/09/24 20:48:28
*************** dump_expr (t, nop)
*** 1476,1481 ****
--- 1476,1482 ----
  	dump_expr (TREE_OPERAND (t, 1), 0);
        break;
  
+     case INIT_EXPR:
      case MODIFY_EXPR:
      case PLUS_EXPR:
      case MINUS_EXPR:
Index: except.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/except.c,v
retrieving revision 1.82
diff -c -p -r1.82 except.c
*** except.c	1999/09/18 01:22:54	1.82
--- except.c	1999/09/24 20:48:28
*************** expand_throw (exp)
*** 830,836 ****
       tree exp;
  {
    tree fn;
-   static tree cleanup_type;
  
    if (! doing_eh (1))
      return;
--- 830,835 ----
Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/expr.c,v
retrieving revision 1.31
diff -c -p -r1.31 expr.c
*** expr.c	1999/09/20 21:26:05	1.31
--- expr.c	1999/09/24 20:48:29
*************** cplus_expand_expr (exp, target, tmode, m
*** 239,247 ****
  			   integer_one_node),
  	  TREE_OPERAND (exp, 1), 0), target, tmode, modifier);
  
-     case NEW_EXPR:
-       return expand_expr (build_new_1 (exp), target, tmode, modifier);
- 
      case STMT_EXPR:
        {
  	tree rtl_expr = begin_stmt_expr ();
--- 239,244 ----
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.138
diff -c -p -r1.138 init.c
*** init.c	1999/09/20 21:26:05	1.138
--- init.c	1999/09/24 20:48:31
*************** build_new (placement, decl, init, use_gl
*** 2065,2070 ****
--- 2065,2073 ----
    rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init);
    NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
    TREE_SIDE_EFFECTS (rval) = 1;
+   rval = build_new_1 (rval);
+   if (rval == error_mark_node)
+     return error_mark_node;
  
    /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
    rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
*************** build_new_1 (exp)
*** 2188,2198 ****
  		      && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
  
    if (use_cookie)
!     {
!       tree extra = BI_header_size;
! 
!       size = size_binop (PLUS_EXPR, size, extra);
!     }
  
    if (has_array)
      {
--- 2191,2197 ----
  		      && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
  
    if (use_cookie)
!     size = size_binop (PLUS_EXPR, size, BI_header_size);
  
    if (has_array)
      {
*************** build_new_1 (exp)
*** 2378,2383 ****
--- 2377,2389 ----
  	  rval = newrval;
  	  TREE_HAS_CONSTRUCTOR (rval) = 1;
  	}
+       else if (current_function_decl)
+ 	rval = (build_vec_init
+ 		(NULL_TREE, 
+ 		 save_expr (rval),
+ 		 build_binary_op (MINUS_EXPR, nelts, integer_one_node),
+ 		 init,
+ 		 /*from_array=*/0));
        else
  	rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
  		      save_expr (rval), init, nelts);
Index: lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.155
diff -c -p -r1.155 lex.c
*** lex.c	1999/09/23 21:04:10	1.155
--- lex.c	1999/09/24 20:48:33
*************** init_parse (filename)
*** 795,800 ****
--- 795,801 ----
    opname_tab[(int) INDIRECT_REF] = "*";
    opname_tab[(int) ARRAY_REF] = "[]";
    opname_tab[(int) MODIFY_EXPR] = "=";
+   opname_tab[(int) INIT_EXPR] = "=";
    opname_tab[(int) NEW_EXPR] = "new";
    opname_tab[(int) DELETE_EXPR] = "delete";
    opname_tab[(int) VEC_NEW_EXPR] = "new []";
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.151
diff -c -p -r1.151 tree.c
*** tree.c	1999/09/15 22:49:33	1.151
--- tree.c	1999/09/24 20:48:34
*************** Boston, MA 02111-1307, USA.  */
*** 28,35 ****
--- 28,37 ----
  #include "rtl.h"
  #include "toplev.h"
  #include "ggc.h"
+ #include "splay-tree.h"
  
  static tree bot_manip PROTO((tree));
+ static tree bot_replace PROTO((tree *));
  static tree build_cplus_array_type_1 PROTO((tree, tree));
  static void list_hash_add PROTO((int, tree));
  static int list_hash PROTO((tree, tree, tree));
*************** static tree list_hash_lookup PROTO((int,
*** 37,43 ****
  static void propagate_binfo_offsets PROTO((tree, tree));
  static int avoid_overlap PROTO((tree, tree));
  static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
! static tree no_linkage_helper PROTO((tree));
  static tree build_srcloc PROTO((char *, int));
  static void mark_list_hash PROTO ((void *));
  
--- 39,45 ----
  static void propagate_binfo_offsets PROTO((tree, tree));
  static int avoid_overlap PROTO((tree, tree));
  static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
! static tree no_linkage_helper PROTO((tree *));
  static tree build_srcloc PROTO((char *, int));
  static void mark_list_hash PROTO ((void *));
  
*************** copy_template_template_parm (t)
*** 1529,1547 ****
     non-null, return that value.  */
  
  tree
! search_tree (t, func)
!      tree t;
!      tree (*func) PROTO((tree));
  {
! #define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp
  
    tree tmp;
    enum tree_code code; 
! 
    if (t == NULL_TREE)
!     return t;
    
!   tmp = func (t);
    if (tmp)
      return tmp;
  
--- 1531,1550 ----
     non-null, return that value.  */
  
  tree
! search_tree (tp, func)
!      tree *tp;
!      tree (*func) PROTO((tree *));
  {
! #define TRY(ARG) if (tmp=search_tree (&ARG, func), tmp != NULL_TREE) return tmp
  
+   tree t = *tp;
    tree tmp;
    enum tree_code code; 
!   
    if (t == NULL_TREE)
!     return NULL_TREE;
    
!   tmp = func (tp);
    if (tmp)
      return tmp;
  
*************** search_tree (t, func)
*** 1618,1623 ****
--- 1621,1627 ----
      case TARGET_EXPR:
      case AGGR_INIT_EXPR:
      case NEW_EXPR:
+     case VEC_INIT_EXPR:
        TRY (TREE_OPERAND (t, 0));
        TRY (TREE_OPERAND (t, 1));
        TRY (TREE_OPERAND (t, 2));
*************** search_tree (t, func)
*** 1737,1745 ****
  /* Passed to search_tree.  Checks for the use of types with no linkage.  */
  
  static tree
! no_linkage_helper (t)
!      tree t;
  {
    if (TYPE_P (t)
        && (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
        && (decl_function_context (TYPE_MAIN_DECL (t))
--- 1741,1751 ----
  /* Passed to search_tree.  Checks for the use of types with no linkage.  */
  
  static tree
! no_linkage_helper (tp)
!      tree *tp;
  {
+   tree t = *tp;
+ 
    if (TYPE_P (t)
        && (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
        && (decl_function_context (TYPE_MAIN_DECL (t))
*************** no_linkage_check (t)
*** 1760,1766 ****
    if (processing_template_decl)
      return NULL_TREE;
  
!   t = search_tree (t, no_linkage_helper);
    if (t != error_mark_node)
      return t;
    return NULL_TREE;
--- 1766,1772 ----
    if (processing_template_decl)
      return NULL_TREE;
  
!   t = search_tree (&t, no_linkage_helper);
    if (t != error_mark_node)
      return t;
    return NULL_TREE;
*************** mapcar (t, func)
*** 1986,1991 ****
--- 1992,1998 ----
        return t;
  
      case NEW_EXPR:
+     case VEC_INIT_EXPR:
        t = copy_node (t);
        TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
        TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
*************** array_type_nelts_total (type)
*** 2093,2100 ****
    return sz;
  }
  
! static
! tree
  bot_manip (t)
       tree t;
  {
--- 2100,2118 ----
    return sz;
  }
  
! /* When we parse a default argument expression, we may create
!    temporary variables via TARGET_EXPRs.  When we actually use the
!    default-argument expression, we make a copy of the expression, but
!    we must relpace the temporaries with appropriate local versions.  */
! 
! /* A map from VAR_DECLs declared in TARGET_EXPRs in a default argument
!    to corresponding "instantiations" of those variables.  */
! static splay_tree target_remap;
! static int target_remap_count;
! 
! /* Called from break_out_target_exprs via mapcar.  */
! 
! static tree
  bot_manip (t)
       tree t;
  {
*************** bot_manip (t)
*** 2102,2117 ****
      return t;
    else if (TREE_CODE (t) == TARGET_EXPR)
      {
        if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
  	{
  	  mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
! 	  return build_cplus_new
  	    (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
  	}
!       t = copy_node (t);
!       TREE_OPERAND (t, 0) = build (VAR_DECL, TREE_TYPE (t));
!       layout_decl (TREE_OPERAND (t, 0), 0);
!       return t;
      }
    else if (TREE_CODE (t) == CALL_EXPR)
      mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
--- 2120,2145 ----
      return t;
    else if (TREE_CODE (t) == TARGET_EXPR)
      {
+       tree u;
+ 
        if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
  	{
  	  mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
! 	  u = build_cplus_new
  	    (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
  	}
!       else 
! 	{
! 	  u = copy_node (t);
! 	  TREE_OPERAND (u, 0) = build (VAR_DECL, TREE_TYPE (t));
! 	  layout_decl (TREE_OPERAND (u, 0), 0);
! 	}
! 
!       /* Map the old variable to the new one.  */
!       splay_tree_insert (target_remap, 
! 			 (splay_tree_key) TREE_OPERAND (t, 0), 
! 			 (splay_tree_value) TREE_OPERAND (u, 0));
!       return u;
      }
    else if (TREE_CODE (t) == CALL_EXPR)
      mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
*************** bot_manip (t)
*** 2119,2131 ****
    return NULL_TREE;
  }
    
  /* Actually, we'll just clean out the target exprs for the moment.  */
  
  tree
  break_out_target_exprs (t)
       tree t;
  {
!   return mapcar (t, bot_manip);
  }
  
  /* Obstack used for allocating nodes in template function and variable
--- 2147,2189 ----
    return NULL_TREE;
  }
    
+ /* Replace all remapped VAR_DECLs in T with their new equivalents.  */
+ 
+ static tree
+ bot_replace (t)
+      tree *t;
+ {
+   if (TREE_CODE (*t) == VAR_DECL)
+     {
+       splay_tree_node n = splay_tree_lookup (target_remap,
+ 					     (splay_tree_key) *t);
+       if (n)
+ 	*t = (tree) n->value;
+     }
+ 
+   return NULL_TREE;
+ }
+ 	
  /* Actually, we'll just clean out the target exprs for the moment.  */
  
  tree
  break_out_target_exprs (t)
       tree t;
  {
!   if (!target_remap_count++)
!     target_remap = splay_tree_new (splay_tree_compare_pointers, 
! 				   /*splay_tree_delete_key_fn=*/NULL, 
! 				   /*splay_tree_delete_value_fn=*/NULL);
!   t = mapcar (t, bot_manip);
!   search_tree (&t, bot_replace);
! 
!   if (!--target_remap_count)
!     {
!       splay_tree_delete (target_remap);
!       target_remap = NULL;
!     }
! 
!   return t;
  }
  
  /* Obstack used for allocating nodes in template function and variable
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.216
diff -c -p -r1.216 typeck.c
*** typeck.c	1999/09/24 01:17:25	1.216
--- typeck.c	1999/09/24 20:48:39
*************** build_modify_expr (lhs, modifycode, rhs)
*** 5877,5883 ****
      {
        newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
  					   "assignment", NULL_TREE, 0);
!       if (lhs == DECL_RESULT (current_function_decl))
  	{
  	  if (DECL_INITIAL (lhs))
  	    warning ("return value from function receives multiple initializations");
--- 5877,5884 ----
      {
        newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
  					   "assignment", NULL_TREE, 0);
!       if (current_function_decl && 
! 	  lhs == DECL_RESULT (current_function_decl))
  	{
  	  if (DECL_INITIAL (lhs))
  	    warning ("return value from function receives multiple initializations");


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