cp-tree.h (CPTI_CLEANUP_TYPE): New macro.
authorMark Mitchell <mark@codesourcery.com>
Fri, 24 Sep 1999 20:54:08 +0000 (20:54 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 24 Sep 1999 20:54:08 +0000 (20:54 +0000)
* 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.

From-SVN: r29659

gcc/cp/ChangeLog
gcc/cp/Makefile.in
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/expr.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/tree.c
gcc/cp/typeck.c

index ee850ce..19485a5 100644 (file)
@@ -1,3 +1,34 @@
+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.
+
 Fri Sep 24 10:48:10 1999  Bernd Schmidt  <bernds@cygnus.co.uk>
 
        * decl.c (duplicate_decls): Use DECL_BUILT_IN_CLASS rather than
index db32e7f..5f0b118 100644 (file)
@@ -274,7 +274,8 @@ cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h decl.h \
 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)/../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 cb46071..584600e 100644 (file)
@@ -408,6 +408,7 @@ enum cp_tree_index
     CPTI_WCHAR_DECL,
     CPTI_VTABLE_ENTRY_TYPE,
     CPTI_DELTA_TYPE,
+    CPTI_CLEANUP_TYPE,
 
     CPTI_TP_DESC_TYPE,
     CPTI_ACCESS_MODE_TYPE,
@@ -560,6 +561,9 @@ extern tree cp_global_trees[CPTI_MAX];
 /* 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 {
@@ -3855,7 +3859,7 @@ extern void push_permanent_obstack              PROTO((void));
 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 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 b3e676b..f456dbb 100644 (file)
@@ -149,7 +149,7 @@ static boolean typename_compare PROTO((hash_table_key, hash_table_key));
 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 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));
@@ -11188,13 +11188,15 @@ require_complete_types_for_parms (parms)
     }
 }
 
-/* Returns DECL if DECL is a local variable (or parameter).  Returns
+/* Returns *TP if *TP is a local variable (or parameter).  Returns
    NULL_TREE otherwise.  */
 
 static tree
-local_variable_p (t)
-     tree t;
+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.  */
@@ -11273,7 +11275,7 @@ check_default_argument (decl, arg)
 
      The keyword `this' shall not be used in a default argument of a
      member function.  */
-  var = search_tree (arg, local_variable_p);
+  var = search_tree (&arg, local_variable_p);
   if (var)
     {
       cp_error ("default argument `%E' uses local variable `%D'",
index 5bf5f0f..883a2e5 100644 (file)
@@ -1476,6 +1476,7 @@ dump_expr (t, nop)
        dump_expr (TREE_OPERAND (t, 1), 0);
       break;
 
+    case INIT_EXPR:
     case MODIFY_EXPR:
     case PLUS_EXPR:
     case MINUS_EXPR:
index 9bfc7a2..a078e65 100644 (file)
@@ -830,7 +830,6 @@ expand_throw (exp)
      tree exp;
 {
   tree fn;
-  static tree cleanup_type;
 
   if (! doing_eh (1))
     return;
index 0eb5de4..741174e 100644 (file)
@@ -239,9 +239,6 @@ cplus_expand_expr (exp, target, tmode, modifier)
                           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 ();
index c98324e..19d8c74 100644 (file)
@@ -2065,6 +2065,9 @@ build_new (placement, decl, init, use_global_new)
   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);
@@ -2188,11 +2191,7 @@ build_new_1 (exp)
                      && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
 
   if (use_cookie)
-    {
-      tree extra = BI_header_size;
-
-      size = size_binop (PLUS_EXPR, size, extra);
-    }
+    size = size_binop (PLUS_EXPR, size, BI_header_size);
 
   if (has_array)
     {
@@ -2378,6 +2377,13 @@ build_new_1 (exp)
          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 c396a50..b61cad4 100644 (file)
@@ -795,6 +795,7 @@ init_parse (filename)
   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 0805092..1253c94 100644 (file)
@@ -28,8 +28,10 @@ Boston, MA 02111-1307, USA.  */
 #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));
@@ -37,7 +39,7 @@ static tree list_hash_lookup PROTO((int, tree, tree, tree));
 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 no_linkage_helper PROTO((tree *));
 static tree build_srcloc PROTO((char *, int));
 static void mark_list_hash PROTO ((void *));
 
@@ -1529,19 +1531,20 @@ copy_template_template_parm (t)
    non-null, return that value.  */
 
 tree
-search_tree (t, func)
-     tree t;
-     tree (*func) PROTO((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
+#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 t;
+    return NULL_TREE;
   
-  tmp = func (t);
+  tmp = func (tp);
   if (tmp)
     return tmp;
 
@@ -1618,6 +1621,7 @@ search_tree (t, func)
     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));
@@ -1737,9 +1741,11 @@ search_tree (t, func)
 /* Passed to search_tree.  Checks for the use of types with no linkage.  */
 
 static tree
-no_linkage_helper (t)
-     tree t;
+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))
@@ -1760,7 +1766,7 @@ no_linkage_check (t)
   if (processing_template_decl)
     return NULL_TREE;
 
-  t = search_tree (t, no_linkage_helper);
+  t = search_tree (&t, no_linkage_helper);
   if (t != error_mark_node)
     return t;
   return NULL_TREE;
@@ -1986,6 +1992,7 @@ mapcar (t, func)
       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);
@@ -2093,8 +2100,19 @@ array_type_nelts_total (type)
   return sz;
 }
 
-static
-tree
+/* 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;
 {
@@ -2102,16 +2120,26 @@ bot_manip (t)
     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));
-         return build_cplus_new
+         u = 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 
+       {
+         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));
@@ -2119,13 +2147,43 @@ bot_manip (t)
   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;
 {
-  return mapcar (t, bot_manip);
+  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 3803a42..80be5f8 100644 (file)
@@ -5877,7 +5877,8 @@ build_modify_expr (lhs, modifycode, rhs)
     {
       newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
                                           "assignment", NULL_TREE, 0);
-      if (lhs == DECL_RESULT (current_function_decl))
+      if (current_function_decl && 
+         lhs == DECL_RESULT (current_function_decl))
        {
          if (DECL_INITIAL (lhs))
            warning ("return value from function receives multiple initializations");