OSDN Git Service

1999-11-25 Mark Mitchell <mark@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index 3c549fb..1361b96 100644 (file)
@@ -25,31 +25,19 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
-#include "function.h"
 #include "cp-tree.h"
 #include "flags.h"
 #include "output.h"
 #include "except.h"
 #include "expr.h"
 #include "toplev.h"
-
-/* In C++, structures with well-defined constructors are initialized by
-   those constructors, unasked.  CURRENT_BASE_INIT_LIST
-   holds a list of stmts for a BASE_INIT term in the grammar.
-   This list has one element for each base class which must be
-   initialized.  The list elements are [basename, init], with
-   type basetype.  This allows the possibly anachronistic form
-   (assuming d : a, b, c) "d (int a) : c(a+5), b (a-4), a (a+3)"
-   where each successive term can be handed down the constructor
-   line.  Perhaps this was not intended.  */
-tree current_base_init_list, current_member_init_list;
+#include "ggc.h"
 
 static void expand_aggr_vbase_init_1 PROTO((tree, tree, tree, tree));
 static void construct_virtual_bases PROTO((tree, tree, tree, tree, tree));
 static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int));
 static void expand_default_init PROTO((tree, tree, tree, tree, int));
-static tree build_vec_delete_1 PROTO((tree, tree, tree, tree, tree,
-                                     int));
+static tree build_vec_delete_1 PROTO((tree, tree, tree, tree, int));
 static void perform_member_init PROTO((tree, tree, tree, int));
 static void sort_base_init PROTO((tree, tree *, tree *));
 static tree build_builtin_delete_call PROTO((tree));
@@ -61,11 +49,6 @@ static tree build_java_class_ref PROTO((tree));
 static void expand_cleanup_for_base PROTO((tree, tree));
 static tree get_temp_regvar PROTO((tree, tree));
 
-/* Cache the identifier nodes for the magic field of a new cookie.  */
-static tree nc_nelts_field_id;
-
-static tree minus_one;
-
 /* Set up local variable for this file.  MUST BE CALLED AFTER
    INIT_DECL_PROCESSING.  */
 
@@ -75,16 +58,23 @@ void init_init_processing ()
 {
   tree fields[1];
 
-  minus_one = build_int_2 (-1, -1);
+  minus_one_node = build_int_2 (-1, -1);
 
   /* Define the structure that holds header information for
      arrays allocated via operator new.  */
   BI_header_type = make_lang_type (RECORD_TYPE);
-  nc_nelts_field_id = get_identifier ("nelts");
-  fields[0] = build_lang_decl (FIELD_DECL, nc_nelts_field_id, sizetype);
+  nelts_identifier = get_identifier ("nelts");
+  fields[0] = build_lang_decl (FIELD_DECL, nelts_identifier, sizetype);
+
+  /* Use the biggest alignment supported by the target to prevent operator
+     new from returning misaligned pointers. */
+  TYPE_ALIGN (BI_header_type) = BIGGEST_ALIGNMENT;
   finish_builtin_type (BI_header_type, "__new_cookie", fields,
-                      0, double_type_node);
+                      0, BI_header_type);
   BI_header_size = size_in_bytes (BI_header_type);
+
+  ggc_add_tree_root (&BI_header_type, 1);
+  ggc_add_tree_root (&BI_header_size, 1);
 }
 
 /* Subroutine of emit_base_init.  For BINFO, initialize all the
@@ -118,7 +108,6 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
   tree binfos = BINFO_BASETYPES (binfo);
   int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0;
 
-  push_momentary ();
   for (i = 0; i < n_baselinks; i++)
     {
       tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
@@ -140,7 +129,6 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
       tree base_ptr = convert_pointer_to_real (binfo, addr);
       expand_virtual_init (real_binfo, base_ptr);
     }
-  pop_momentary ();
 }
 \f
 /* 348 - 351 */
@@ -162,7 +150,6 @@ perform_member_init (member, name, init, explicit)
   if (ANON_AGGR_TYPE_P (type))
     {
       init = build (INIT_EXPR, type, decl, TREE_VALUE (init));
-      TREE_SIDE_EFFECTS (init) = 1;
       finish_expr_stmt (init);
     }
   else if (TYPE_NEEDS_CONSTRUCTING (type)
@@ -238,10 +225,6 @@ perform_member_init (member, name, init, explicit)
     {
       tree expr;
 
-      /* All cleanups must be on the function_obstack.  */
-      push_obstacks_nochange ();
-      resume_temporary_allocation ();
-
       expr = build_component_ref (current_class_ref, name, NULL_TREE,
                                  explicit);
       expr = build_delete (type, expr, integer_zero_node,
@@ -249,8 +232,6 @@ perform_member_init (member, name, init, explicit)
 
       if (expr != error_mark_node)
        finish_subobject (expr);
-
-      pop_obstacks ();
     }
 }
 
@@ -502,9 +483,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
    Note that emit_base_init does *not* initialize virtual base
    classes.  That is done specially, elsewhere.  */
 
-extern tree base_init_expr;
-
-void
+tree
 emit_base_init (t)
      tree t;
 {
@@ -644,10 +623,9 @@ emit_base_init (t)
       mem_init_list = TREE_CHAIN (mem_init_list);
     }
 
-  base_init_expr = finish_init_stmts (stmt_expr, compound_stmt);
-
   /* All the implicit try blocks we built up will be zapped
      when we come to a real binding contour boundary.  */
+  return finish_init_stmts (stmt_expr, compound_stmt);
 }
 
 /* Check that all fields are properly initialized after
@@ -682,9 +660,9 @@ expand_virtual_init (binfo, decl)
   /* This code is crusty.  Should be simple, like:
      vtbl = BINFO_VTABLE (binfo);
      */
-  vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));
+  vtype = DECL_CONTEXT (TYPE_VFIELD (type));
   vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
-  vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
+  vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
   assemble_external (vtbl);
   TREE_USED (vtbl) = 1;
   vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
@@ -714,10 +692,6 @@ expand_cleanup_for_base (binfo, flag)
   if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
     return;
 
-  /* All cleanups must be on the function_obstack.  */
-  push_obstacks_nochange ();
-  resume_temporary_allocation ();
-
   /* Call the destructor.  */
   expr = (build_scoped_method_call
          (current_class_ref, binfo, dtor_identifier,
@@ -727,7 +701,6 @@ expand_cleanup_for_base (binfo, flag)
                        truthvalue_conversion (flag),
                        expr, integer_zero_node));
 
-  pop_obstacks ();
   finish_subobject (expr);
 }
 
@@ -773,10 +746,6 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
   if_stmt = begin_if_stmt ();
   finish_if_stmt_cond (flag, if_stmt);
   result = init_vbase_pointers (type, this_ptr);
-  /* The RESULT will contain entries on the momentary obstack.  They
-     must live until the end of this function; we use them in the loop
-     below.  */
-  push_momentary ();
   if (result)
     finish_expr_stmt (build_compound_expr (result));
   finish_then_clause (if_stmt);
@@ -811,14 +780,11 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
                                TREE_OPERAND (TREE_VALUE (tmp), 0),
                                init_list);
       finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
-      finish_then_clause (if_stmt);
+      finish_then_clause (inner_if_stmt);
       finish_if_stmt ();
       
       expand_cleanup_for_base (vbases, flag);
     }
-
-  /* Undo the call to push_momentary above.  */
-  pop_momentary ();
 }
 
 /* Find the context in which this FIELD can be initialized.  */
@@ -1010,7 +976,6 @@ begin_init_stmts (stmt_expr_p, compound_stmt_p)
      tree *stmt_expr_p;
      tree *compound_stmt_p;
 {
-  push_momentary ();
   *stmt_expr_p = begin_stmt_expr ();
   *compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
 }
@@ -1023,10 +988,15 @@ finish_init_stmts (stmt_expr, compound_stmt)
      tree stmt_expr;
      tree compound_stmt;
 {
-  pop_momentary ();
-  return finish_stmt_expr (stmt_expr,
-                          finish_compound_stmt (/*has_no_scope=*/1, 
-                                                compound_stmt));
+  finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
+  stmt_expr = finish_stmt_expr (stmt_expr);
+
+  /* To avoid spurious warnings about unused values, we set 
+     TREE_USED.  */
+  if (stmt_expr)
+    TREE_USED (stmt_expr) = 1;
+
+  return stmt_expr;
 }
 
 /* This is like `expand_member_init', only it stores one aggregate
@@ -1211,9 +1181,9 @@ expand_default_init (binfo, true_exp, exp, init, flags)
   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
     {
       if (true_exp == exp)
-       parms = expr_tree_cons (NULL_TREE, integer_one_node, parms);
+       parms = tree_cons (NULL_TREE, integer_one_node, parms);
       else
-       parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms);
+       parms = tree_cons (NULL_TREE, integer_zero_node, parms);
       flags |= LOOKUP_HAS_IN_CHARGE;
     }
 
@@ -1275,11 +1245,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
            expand_decl_init (exp);
        }
       else
-       {
-         tree t = build (INIT_EXPR, type, exp, init);
-         TREE_SIDE_EFFECTS (t) = 1;
-         finish_expr_stmt (t);
-       }
+       finish_expr_stmt (build (INIT_EXPR, type, exp, init));
       return;
     }
 
@@ -1670,17 +1636,6 @@ build_offset_ref (type, name)
          return build (OFFSET_REF, TREE_TYPE (t), decl, t);
        }
 
-      /* FNFIELDS is most likely allocated on the search_obstack,
-        which will go away after this class scope.  If we need
-        to save this value for later (i.e. for use as an initializer
-        for a static variable), then do so here.
-
-        ??? The smart thing to do for the case of saving initializers
-        is to resolve them before we're done with this scope.  */
-      if (!TREE_PERMANENT (fnfields)
-         && ! allocation_temporary_p ())
-       fnfields = copy_list (fnfields);
-
       TREE_TYPE (fnfields) = unknown_type_node;
       return build (OFFSET_REF, unknown_type_node, decl, fnfields);
     }
@@ -1939,8 +1894,6 @@ build_new (placement, decl, init, use_global_new)
   tree nelts = NULL_TREE, t;
   int has_array = 0;
 
-  tree pending_sizes = NULL_TREE;
-
   if (decl == error_mark_node)
     return error_mark_node;
 
@@ -1948,14 +1901,10 @@ build_new (placement, decl, init, use_global_new)
     {
       tree absdcl = TREE_VALUE (decl);
       tree last_absdcl = NULL_TREE;
-      int old_immediate_size_expand = 0;
 
       if (current_function_decl
          && DECL_CONSTRUCTOR_P (current_function_decl))
-       {
-         old_immediate_size_expand = immediate_size_expand;
-         immediate_size_expand = 0;
-       }
+       my_friendly_assert (immediate_size_expand == 0, 19990926);
 
       nelts = integer_one_node;
 
@@ -2019,17 +1968,7 @@ build_new (placement, decl, init, use_global_new)
 
       type = groktypename (decl);
       if (! type || type == error_mark_node)
-       {
-         immediate_size_expand = old_immediate_size_expand;
-         return error_mark_node;
-       }
-
-      if (current_function_decl
-         && DECL_CONSTRUCTOR_P (current_function_decl))
-       {
-         pending_sizes = get_pending_sizes ();
-         immediate_size_expand = old_immediate_size_expand;
-       }
+       return error_mark_node;
     }
   else if (TREE_CODE (decl) == IDENTIFIER_NODE)
     {
@@ -2104,22 +2043,17 @@ 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);
   TREE_NO_UNUSED_WARNING (rval) = 1;
 
-  if (pending_sizes)
-    rval = build_compound_expr (chainon (pending_sizes,
-                                        build_expr_list (NULL_TREE, rval)));
-
   return rval;
 }
 
-/* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*). */
-
-static tree jclass_node = NULL_TREE;
-
 /* Given a Java class, return a decl for the corresponding java.lang.Class. */
 
 static tree
@@ -2141,7 +2075,6 @@ build_java_class_ref (type)
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
   if (class_decl == NULL_TREE)
     {
-      push_permanent_obstack ();
       class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
       TREE_STATIC (class_decl) = 1;
       DECL_EXTERNAL (class_decl) = 1;
@@ -2150,7 +2083,6 @@ build_java_class_ref (type)
       DECL_IGNORED_P (class_decl) = 1;
       pushdecl_top_level (class_decl);
       make_decl_rtl (class_decl, NULL_PTR, 1);
-      pop_obstacks ();
     }
   return class_decl;
 }
@@ -2231,11 +2163,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)
     {
@@ -2247,18 +2175,7 @@ build_new_1 (exp)
 
   /* Allocate the object.  */
   
-  if (! has_array && ! placement && flag_this_is_variable > 0
-      && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
-    {
-      if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
-       rval = NULL_TREE;
-      else
-       {
-         error ("constructors take parameter lists");
-         return error_mark_node;
-       }
-    }
-  else if (! placement && TYPE_FOR_JAVA (true_type))
+  if (! placement && TYPE_FOR_JAVA (true_type))
     {
       tree class_addr, alloc_decl;
       tree class_decl = build_java_class_ref (true_type);
@@ -2277,20 +2194,10 @@ build_new_1 (exp)
     }
   else
     {
-      int susp = 0;
-
-      if (flag_exceptions)
-       /* We will use RVAL when generating an exception handler for
-          this new-expression, so we must save it.  */
-       susp = suspend_momentary ();
-
       rval = build_op_new_call
-       (code, true_type, expr_tree_cons (NULL_TREE, size, placement),
+       (code, true_type, tree_cons (NULL_TREE, size, placement),
         LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL));
       rval = cp_convert (build_pointer_type (true_type), rval);
-
-      if (flag_exceptions)
-       resume_momentary (susp);
     }
 
   /*        unless an allocation function is declared with an empty  excep-
@@ -2337,13 +2244,12 @@ build_new_1 (exp)
                                          build_pointer_type (BI_header_type),
                                          rval, extra), NULL_PTR);
       exp1 = build (MODIFY_EXPR, void_type_node,
-                   build_component_ref (cookie, nc_nelts_field_id,
+                   build_component_ref (cookie, nelts_identifier,
                                         NULL_TREE, 0),
                    nelts);
-      TREE_SIDE_EFFECTS (exp1) = 1;
       rval = cp_convert (build_pointer_type (true_type), rval);
       rval = build_compound_expr
-       (expr_tree_cons (NULL_TREE, exp1,
+       (tree_cons (NULL_TREE, exp1,
                         build_expr_list (NULL_TREE, rval)));
     }
 
@@ -2408,7 +2314,7 @@ build_new_1 (exp)
 
          if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
            {
-             init = expr_tree_cons (NULL_TREE, integer_one_node, init);
+             init = tree_cons (NULL_TREE, integer_one_node, init);
              flags |= LOOKUP_HAS_IN_CHARGE;
            }
 
@@ -2433,8 +2339,12 @@ build_new_1 (exp)
          TREE_HAS_CONSTRUCTOR (rval) = 1;
        }
       else
-       rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
-                     save_expr (rval), init, nelts);
+       rval = (build_vec_init
+               (NULL_TREE, 
+                save_expr (rval),
+                build_binary_op (MINUS_EXPR, nelts, integer_one_node),
+                init,
+                /*from_array=*/0));
 
       /* If any part of the object initialization terminates by throwing an
         exception and a suitable deallocation function can be found, the
@@ -2450,9 +2360,6 @@ build_new_1 (exp)
          tree cleanup, fn = NULL_TREE;
          int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL);
 
-         /* All cleanups must last longer than normal.  */
-         int yes = suspend_momentary ();
-
          /* The Standard is unclear here, but the right thing to do
              is to use the same method for finding deallocation
              functions that we use for finding allocation functions.  */
@@ -2463,13 +2370,8 @@ build_new_1 (exp)
          fn = TREE_OPERAND (alloc_expr, 1);
          fn = TREE_OPERAND (fn, 0);
 
-         /* Copy size to the saveable obstack.  */
-         size = mapcar (size, permanent_p);
-
          cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
 
-         resume_momentary (yes);
-
          /* Ack!  First we allocate the memory.  Then we set our sentry
             variable to true, and expand a cleanup that deletes the memory
             if sentry is true.  Then we run the constructor and store the
@@ -2482,17 +2384,14 @@ build_new_1 (exp)
              begin = get_target_expr (boolean_true_node);
              sentry = TREE_OPERAND (begin, 0);
 
-             yes = suspend_momentary ();
              TREE_OPERAND (begin, 2)
                = build (COND_EXPR, void_type_node, sentry,
                         cleanup, void_zero_node);
-             resume_momentary (yes);
 
              rval = get_target_expr (rval);
 
              end = build (MODIFY_EXPR, TREE_TYPE (sentry),
                           sentry, boolean_false_node);
-             TREE_SIDE_EFFECTS (end) = 1;
 
              buf = TREE_OPERAND (rval, 0);
 
@@ -2534,10 +2433,9 @@ build_new_1 (exp)
 }
 \f
 static tree
-build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
-                   use_global_delete)
+build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
      tree base, maxindex, type;
-     tree auto_delete_vec, auto_delete;
+     tree auto_delete_vec;
      int use_global_delete;
 {
   tree virtual_size;
@@ -2572,7 +2470,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
   /* The below is short by BI_header_size */
   virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
 
-  tbase = build_decl (VAR_DECL, NULL_TREE, ptype);
+  tbase = create_temporary_var (ptype);
   tbase_init = build_modify_expr (tbase, NOP_EXPR,
                                  fold (build (PLUS_EXPR, ptype,
                                               base,
@@ -2581,45 +2479,26 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
   controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (controller) = 1;
 
-  if (auto_delete != integer_zero_node
-      && auto_delete != integer_two_node)
-    {
-      tree base_tbd = cp_convert (ptype,
-                                 build_binary_op (MINUS_EXPR,
-                                                  cp_convert (ptr_type_node, base),
-                                                  BI_header_size));
-      /* This is the real size */
-      virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
-      body = build_expr_list (NULL_TREE,
-                             build_x_delete (base_tbd,
-                                             2 | use_global_delete,
-                                             virtual_size));
-      body = build (COND_EXPR, void_type_node,
-                   build (BIT_AND_EXPR, integer_type_node,
-                          auto_delete, integer_one_node),
-                   body, integer_zero_node);
-    }
-  else
-    body = NULL_TREE;
+  body = NULL_TREE;
 
-  body = expr_tree_cons (NULL_TREE,
-                   build_delete (ptype, tbase, auto_delete,
+  body = tree_cons (NULL_TREE,
+                   build_delete (ptype, tbase, integer_two_node,
                                  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
                    body);
 
-  body = expr_tree_cons (NULL_TREE,
+  body = tree_cons (NULL_TREE,
                    build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
                    body);
 
-  body = expr_tree_cons (NULL_TREE,
+  body = tree_cons (NULL_TREE,
                    build (EXIT_EXPR, void_type_node,
                           build (EQ_EXPR, boolean_type_node, base, tbase)),
                    body);
 
   loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
 
-  loop = expr_tree_cons (NULL_TREE, tbase_init,
-                   expr_tree_cons (NULL_TREE, loop, NULL_TREE));
+  loop = tree_cons (NULL_TREE, tbase_init,
+                   tree_cons (NULL_TREE, loop, NULL_TREE));
   loop = build_compound_expr (loop);
 
  no_destructor:
@@ -2649,39 +2528,32 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
       deallocate_expr = build_x_delete (base_tbd,
                                        2 | use_global_delete,
                                        virtual_size);
-      if (auto_delete_vec != integer_one_node)
-       deallocate_expr = build (COND_EXPR, void_type_node,
-                                build (BIT_AND_EXPR, integer_type_node,
-                                       auto_delete_vec, integer_one_node),
-                                deallocate_expr, integer_zero_node);
+      deallocate_expr = fold (build (COND_EXPR, void_type_node,
+                                    fold (build (BIT_AND_EXPR,
+                                                 integer_type_node,
+                                                 auto_delete_vec,
+                                                 integer_one_node)),
+                                    deallocate_expr, integer_zero_node));
     }
 
   if (loop && deallocate_expr != integer_zero_node)
     {
-      body = expr_tree_cons (NULL_TREE, loop,
-                       expr_tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
+      body = tree_cons (NULL_TREE, loop,
+                       tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
       body = build_compound_expr (body);
     }
   else
     body = loop;
 
   /* Outermost wrapper: If pointer is null, punt.  */
-  body = build (COND_EXPR, void_type_node,
-               build (NE_EXPR, boolean_type_node, base, integer_zero_node),
-               body, integer_zero_node);
+  body = fold (build (COND_EXPR, void_type_node,
+                     fold (build (NE_EXPR, boolean_type_node, base,
+                                  integer_zero_node)),
+                     body, integer_zero_node));
   body = build1 (NOP_EXPR, void_type_node, body);
 
   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;
     }
@@ -2701,9 +2573,7 @@ create_temporary_var (type)
   DECL_SOURCE_FILE (decl) = input_filename;
   DECL_SOURCE_LINE (decl) = lineno;
   DECL_IGNORED_P (decl) = 1;
-
-  if (building_stmt_tree ())
-    add_decl_stmt (decl);
+  DECL_CONTEXT (decl) = current_function_decl;
 
   return decl;
 }
@@ -2722,7 +2592,8 @@ get_temp_regvar (type, init)
   tree decl;
 
   decl = create_temporary_var (type);
-  DECL_REGISTER (decl) = 1;
+  if (building_stmt_tree ())
+    add_decl_stmt (decl);
   if (!building_stmt_tree ())
     DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
   finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
@@ -2766,21 +2637,13 @@ build_vec_init (decl, base, maxindex, init, from_array)
   tree compound_stmt;
   int destroy_temps;
   tree try_block = NULL_TREE;
+  tree try_body;
   int num_initialized_elts = 0;
 
   maxindex = cp_convert (ptrdiff_type_node, maxindex);
   if (maxindex == error_mark_node)
     return error_mark_node;
 
-  if (current_function_decl == NULL_TREE)
-    {
-      rval = make_tree_vec (3);
-      TREE_VEC_ELT (rval, 0) = base;
-      TREE_VEC_ELT (rval, 1) = maxindex;
-      TREE_VEC_ELT (rval, 2) = init;
-      return rval;
-    }
-
   type = TREE_TYPE (TREE_TYPE (base));
   ptype = build_pointer_type (type);
   size = size_in_bytes (type);
@@ -2830,7 +2693,10 @@ build_vec_init (decl, base, maxindex, init, from_array)
   /* Protect the entire array initialization so that we can destroy
      the partially constructed array if an exception is thrown.  */
   if (flag_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
-    try_block = begin_try_block ();
+    {
+      try_block = begin_try_block ();
+      try_body = begin_compound_stmt (/*has_no_scope=*/1);
+    }
 
   if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR
       && (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl))))
@@ -2868,9 +2734,6 @@ build_vec_init (decl, base, maxindex, init, from_array)
 
       /* Clear out INIT so that we don't get confused below.  */
       init = NULL_TREE;
-
-      if (obey_regdecls && !building_stmt_tree ())
-       use_variable (DECL_RTL (base));
     }
   else if (from_array)
     {
@@ -2918,7 +2781,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
 
       if_stmt = begin_if_stmt ();
       finish_if_stmt_cond (build (NE_EXPR, boolean_type_node,
-                                 iterator, minus_one),
+                                 iterator, minus_one_node),
                           if_stmt);
 
       /* Otherwise, loop through the elements.  */
@@ -2999,13 +2862,6 @@ build_vec_init (decl, base, maxindex, init, from_array)
                           build (PLUS_EXPR, build_pointer_type (type), 
                                  base2, size)));
 
-      if (obey_regdecls && !building_stmt_tree ())
-       {
-         use_variable (DECL_RTL (base));
-         if (base2)
-           use_variable (DECL_RTL (base2));
-       }
-
       finish_compound_stmt (/*has_no_scope=*/1, do_body);
       finish_do_body (do_stmt);
       finish_do_stmt (build (NE_EXPR, boolean_type_node,
@@ -3013,7 +2869,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
                                    ptrdiff_type_node, 
                                    iterator,
                                    integer_one_node), 
-                            minus_one),
+                            minus_one_node),
                      do_stmt);
 
       finish_then_clause (if_stmt);
@@ -3025,30 +2881,17 @@ build_vec_init (decl, base, maxindex, init, from_array)
     {
       tree e;
 
-      /* Because CLEANUP will not be processed until later, it must go
-        on the temporary obstack.  */
-      push_obstacks_nochange ();
-      resume_temporary_allocation ();
-      /* And MAXINDEX needs to be copied to the current obstack.  It's
-        probably on the momentary obstack now.  */
-      maxindex = mapcar (maxindex, permanent_p);
+      finish_compound_stmt (/*has_no_scope=*/1, try_body);
+      finish_cleanup_try_block (try_block);
       e = build_vec_delete_1 (rval,
                              build_binary_op (MINUS_EXPR, maxindex, 
                                               iterator),
                              type,
                              /*auto_delete_vec=*/integer_zero_node,
-                             /*auto_delete=*/integer_zero_node,
                              /*use_global_delete=*/0);
-      pop_obstacks ();
       finish_cleanup (e, try_block);
     }
 
-  if (obey_regdecls && !building_stmt_tree ())
-    {
-      use_variable (DECL_RTL (iterator));
-      use_variable (DECL_RTL (rval));
-    }
-
   /* The value of the array initialization is the address of the
      first element in the array.  */
   finish_expr_stmt (rval);
@@ -3149,8 +2992,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
          return error_mark_node;
        }
       return build_vec_delete (addr, array_type_nelts (type),
-                              auto_delete, integer_zero_node,
-                              use_global_delete);
+                              auto_delete, use_global_delete);
     }
   else
     {
@@ -3274,7 +3116,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
          expr = build_scoped_method_call
            (ref, base_binfo, dtor_identifier,
             build_expr_list (NULL_TREE, this_auto_delete));
-         exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
+         exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
        }
 
       /* Take care of the remaining baseclasses.  */
@@ -3289,7 +3131,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
            (ref, base_binfo, dtor_identifier,
             build_expr_list (NULL_TREE, integer_zero_node));
 
-         exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
+         exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
        }
 
       for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
@@ -3301,7 +3143,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
              tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0);
              tree this_type = TREE_TYPE (member);
              expr = build_delete (this_type, this_member, integer_two_node, flags, 0);
-             exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
+             exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
            }
        }
 
@@ -3328,7 +3170,7 @@ build_vbase_delete (type, decl)
     {
       tree this_addr = convert_force (build_pointer_type (BINFO_TYPE (vbases)),
                                      addr, 0);
-      result = expr_tree_cons (NULL_TREE,
+      result = tree_cons (NULL_TREE,
                          build_delete (TREE_TYPE (this_addr), this_addr,
                                        integer_zero_node,
                                        LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0),
@@ -3344,7 +3186,6 @@ build_vbase_delete (type, decl)
    BASE is the expression that should yield the store to be deleted.
    This function expands (or synthesizes) these calls itself.
    AUTO_DELETE_VEC says whether the container (vector) should be deallocated.
-   AUTO_DELETE say whether each item in the container should be deallocated.
 
    This also calls delete for virtual baseclasses of elements of the vector.
 
@@ -3356,10 +3197,9 @@ build_vbase_delete (type, decl)
    be worth bothering.)  */
 
 tree
-build_vec_delete (base, maxindex, auto_delete_vec, auto_delete,
-                 use_global_delete)
+build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
      tree base, maxindex;
-     tree auto_delete_vec, auto_delete;
+     tree auto_delete_vec;
      int use_global_delete;
 {
   tree type;
@@ -3381,7 +3221,7 @@ build_vec_delete (base, maxindex, auto_delete_vec, auto_delete,
       tree cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
                                base, BI_header_size);
       tree cookie = build_indirect_ref (cookie_addr, NULL_PTR);
-      maxindex = build_component_ref (cookie, nc_nelts_field_id, NULL_TREE, 0);
+      maxindex = build_component_ref (cookie, nelts_identifier, NULL_TREE, 0);
       do
        type = TREE_TYPE (type);
       while (TREE_CODE (type) == ARRAY_TYPE);
@@ -3401,6 +3241,6 @@ build_vec_delete (base, maxindex, auto_delete_vec, auto_delete,
       return error_mark_node;
     }
 
-  return build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
+  return build_vec_delete_1 (base, maxindex, type, auto_delete_vec,
                             use_global_delete);
 }