OSDN Git Service

* cp-tree.h (merge_primary_and_secondary_vtables_p): New macro.
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index e0a1d13..e08b2fa 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle initialization things in C++.
-   Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1987, 89, 92-98, 1999, 2000 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -33,22 +33,22 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #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 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));
-static int member_init_ok_or_else PROTO((tree, tree, const char *));
-static void expand_virtual_init PROTO((tree, tree));
-static tree sort_member_init PROTO((tree));
-static tree initializing_context PROTO((tree));
-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));
+static void expand_aggr_vbase_init_1 PARAMS ((tree, tree, tree, tree));
+static void construct_virtual_bases PARAMS ((tree, tree, tree, tree, tree));
+static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
+static void expand_default_init PARAMS ((tree, tree, tree, tree, int));
+static tree build_vec_delete_1 PARAMS ((tree, tree, tree, tree, int));
+static void perform_member_init PARAMS ((tree, tree, tree, int));
+static void sort_base_init PARAMS ((tree, tree *, tree *));
+static tree build_builtin_delete_call PARAMS ((tree));
+static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
+static void expand_virtual_init PARAMS ((tree, tree));
+static tree sort_member_init PARAMS ((tree));
+static tree initializing_context PARAMS ((tree));
+static tree build_java_class_ref PARAMS ((tree));
+static void expand_cleanup_for_base PARAMS ((tree, tree));
+static tree get_temp_regvar PARAMS ((tree, tree));
+static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
 
 /* Set up local variable for this file.  MUST BE CALLED AFTER
    INIT_DECL_PROCESSING.  */
@@ -63,72 +63,74 @@ void init_init_processing ()
 
   /* Define the structure that holds header information for
      arrays allocated via operator new.  */
-  BI_header_type = make_lang_type (RECORD_TYPE);
+  BI_header_type = make_aggr_type (RECORD_TYPE);
   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
-   virtual function table pointers, except those that come from
-   virtual base classes.  Initialize binfo's vtable pointer, if
-   INIT_SELF is true.  CAN_ELIDE is true when we know that all virtual
-   function table pointers in all bases have been initialized already,
-   probably because their constructors have just be run.  ADDR is the
-   pointer to the object whos vtables we are going to initialize.
+/* Called from initialize_vtbl_ptrs via dfs_walk.  */
 
-   REAL_BINFO is usually the same as BINFO, except when addr is not of
-   pointer to the type of the real derived type that we want to
-   initialize for.  This is the case when addr is a pointer to a sub
-   object of a complete object, and we only want to do part of the
-   complete object's initialization of vtable pointers.  This is done
-   for all virtual table pointers in virtual base classes.  REAL_BINFO
-   is used to find the BINFO_VTABLE that we initialize with.  BINFO is
-   used for conversions of addr to subobjects.
+static tree
+dfs_initialize_vtbl_ptrs (binfo, data)
+     tree binfo;
+     void *data;
+{
+  if (!BINFO_PRIMARY_MARKED_P (binfo) 
+      && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+    {
+      tree base_ptr = TREE_VALUE ((tree) data);
 
-   BINFO_TYPE (real_binfo) must be BINFO_TYPE (binfo).
+      if (TREE_VIA_VIRTUAL (binfo))
+       base_ptr = convert_pointer_to_vbase (BINFO_TYPE (binfo),
+                                            base_ptr);
+      else
+       base_ptr 
+         = build_vbase_path (PLUS_EXPR, 
+                             build_pointer_type (BINFO_TYPE (binfo)),
+                             base_ptr,
+                             binfo,
+                             /*nonnull=*/1);
 
-   Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE
-   (addr))).  */
+      expand_virtual_init (binfo, base_ptr);
+    }
+
+  SET_BINFO_MARKED (binfo);
+
+  return NULL_TREE;
+}
+
+/* Initialize all the vtable pointers for the hierarchy dominated by
+   TYPE. */
 
 void
-expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
-     tree real_binfo, binfo, addr;
-     int init_self, can_elide;
+initialize_vtbl_ptrs (type, addr)
+     tree type;
+     tree addr;
 {
-  tree real_binfos = BINFO_BASETYPES (real_binfo);
-  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);
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      int is_not_base_vtable
-       = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
-      if (! TREE_VIA_VIRTUAL (real_base_binfo))
-       expand_direct_vtbls_init (real_base_binfo, base_binfo,
-                                 is_not_base_vtable, can_elide, addr);
-    }
-#if 0
-  /* Before turning this on, make sure it is correct.  */
-  if (can_elide && ! BINFO_MODIFIED (binfo))
-    return;
-#endif
-  /* Should we use something besides CLASSTYPE_VFIELDS? */
-  if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
-    {
-      tree base_ptr = convert_pointer_to_real (binfo, addr);
-      expand_virtual_init (real_binfo, base_ptr);
-    }
-  pop_momentary ();
+  tree list = build_tree_list (type, addr);
+
+  /* Walk through the hierarchy, initializing the vptr in each base
+     class.  We do these in pre-order because under the new ABI we
+     can't find the virtual bases for a class until we've initialized
+     the vtbl for that class.  */
+  dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, 
+                NULL, dfs_unmarked_real_bases_queue_p, list);
+  dfs_walk (TYPE_BINFO (type), dfs_unmark,
+           dfs_marked_real_bases_queue_p, type);
+  if (TYPE_USES_VIRTUAL_BASECLASSES (type))
+    expand_indirect_vtbls_init (TYPE_BINFO (type), addr);
 }
+
 \f
 /* 348 - 351 */
 /* Subroutine of emit_base_init.  */
@@ -143,13 +145,15 @@ perform_member_init (member, name, init, explicit)
 
   decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
 
+  if (decl == error_mark_node)
+    return;
+
   /* Deal with this here, as we will get confused if we try to call the
      assignment op for an anonymous union.  This can happen in a
      synthesized copy constructor.  */
   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)
@@ -158,7 +162,7 @@ perform_member_init (member, name, init, explicit)
       /* Since `init' is already a TREE_LIST on the current_member_init_list,
         only build it into one if we aren't already a list.  */
       if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)
-       init = build_expr_list (NULL_TREE, init);
+       init = build_tree_list (NULL_TREE, init);
 
       if (explicit
          && TREE_CODE (type) == ARRAY_TYPE
@@ -385,10 +389,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
             this constructor is the top-level constructor called.  */
          if (TREE_VIA_VIRTUAL (binfo))
            {
-             tree v = CLASSTYPE_VBASECLASSES (t);
-             while (BINFO_TYPE (v) != BINFO_TYPE (binfo))
-               v = TREE_CHAIN (v);
-
+             tree v = BINFO_FOR_VBASE (BINFO_TYPE (binfo), t);
              vbases = tree_cons (v, TREE_VALUE (x), vbases);
              continue;
            }
@@ -483,7 +484,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.  */
 
-void
+tree
 emit_base_init (t)
      tree t;
 {
@@ -547,14 +548,8 @@ emit_base_init (t)
       rbase_init_list = TREE_CHAIN (rbase_init_list);
     }
 
-  /* Initialize all the virtual function table fields that
-     do come from virtual base classes.  */
-  if (TYPE_USES_VIRTUAL_BASECLASSES (t))
-    expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr);
-
-  /* Initialize all the virtual function table fields that
-     do not come from virtual base classes.  */
-  expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr);
+  /* Initialize the vtable pointers for the class.  */
+  initialize_vtbl_ptrs (t, current_class_ptr);
 
   for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
     {
@@ -623,10 +618,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
@@ -658,21 +652,38 @@ expand_virtual_init (binfo, decl)
   tree vtbl, vtbl_ptr;
   tree vtype, vtype_binfo;
 
-  /* This code is crusty.  Should be simple, like:
-     vtbl = BINFO_VTABLE (binfo);
-     */
-  vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));
+  /* Compute the location of the vtable.  */
+  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));
-  assemble_external (vtbl);
-  TREE_USED (vtbl) = 1;
-  vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
+  vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
+
+  if (TREE_CODE (vtbl) == VAR_DECL)
+    {
+      assemble_external (vtbl);
+      TREE_USED (vtbl) = 1;
+      vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
+    }
+  else
+    /* Under the new ABI, secondary vtables are stored with the
+       primary vtable.  So, the BINFO_VTABLE may be an expression for
+       computing the secondary vtable, rather than the secondary
+       vtable itself.  */
+    my_friendly_assert (merge_primary_and_secondary_vtables_p (), 
+                       20000220);
+
+  /* Under the new ABI, we need to point into the middle of the
+     vtable.  */
+  if (vbase_offsets_in_vtable_p ())
+    vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, 
+                 size_extra_vtbl_entries (binfo));
+
+  /* Compute the location of the vtpr.  */
   decl = convert_pointer_to_real (vtype_binfo, decl);
   vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
   if (vtbl_ptr == error_mark_node)
     return;
 
-  /* Have to convert VTBL since array sizes may be different.  */
+  /* Assign the vtable to the vptr.  */
   vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
   finish_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
 }
@@ -696,7 +707,7 @@ expand_cleanup_for_base (binfo, flag)
   /* Call the destructor.  */
   expr = (build_scoped_method_call
          (current_class_ref, binfo, dtor_identifier,
-          build_expr_list (NULL_TREE, integer_zero_node)));
+          build_tree_list (NULL_TREE, integer_zero_node)));
   if (flag)
     expr = fold (build (COND_EXPR, void_type_node,
                        truthvalue_conversion (flag),
@@ -725,7 +736,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
 /* Construct the virtual base-classes of THIS_REF (whose address is
    THIS_PTR).  The object has the indicated TYPE.  The construction
    actually takes place only if FLAG is non-zero.  INIT_LIST is list
-   of initialization for constructor to perform.  */
+   of initializations for constructors to perform.  */
 
 static void
 construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
@@ -736,33 +747,33 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
      tree flag;
 {
   tree vbases;
-  tree result;
-  tree if_stmt;
 
   /* If there are no virtual baseclasses, we shouldn't even be here.  */
   my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
 
   /* First set the pointers in our object that tell us where to find
      our virtual baseclasses.  */
-  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);
-  finish_if_stmt ();
+  if (!vbase_offsets_in_vtable_p ())
+    {
+      tree if_stmt;
+      tree result;
+
+      if_stmt = begin_if_stmt ();
+      finish_if_stmt_cond (flag, if_stmt);
+      result = init_vbase_pointers (type, this_ptr);
+      if (result)
+       finish_expr_stmt (build_compound_expr (result));
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+    }
 
   /* Now, run through the baseclasses, initializing each.  */ 
   for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
        vbases = TREE_CHAIN (vbases))
     {
-      tree tmp = purpose_member (vbases, result);
       tree inner_if_stmt;
       tree compound_stmt;
+      tree exp;
 
       /* If there are virtual base classes with destructors, we need to
         emit cleanups to destroy them if an exception is thrown during
@@ -781,18 +792,26 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
       inner_if_stmt = begin_if_stmt ();
       finish_if_stmt_cond (flag, inner_if_stmt);
       compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
-      expand_aggr_vbase_init_1 (vbases, this_ref,
-                               TREE_OPERAND (TREE_VALUE (tmp), 0),
-                               init_list);
+
+      /* Compute the location of the virtual base.  If we're
+        constructing virtual bases, then we must be the most derived
+        class.  Therefore, we don't have to look up the virtual base;
+        we already know where it is.  */
+      exp = build (PLUS_EXPR,
+                  TREE_TYPE (this_ptr),
+                  this_ptr,
+                  BINFO_OFFSET (vbases));
+      exp = build1 (NOP_EXPR, 
+                   build_pointer_type (BINFO_TYPE (vbases)), 
+                   exp);
+
+      expand_aggr_vbase_init_1 (vbases, this_ref, exp, 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.  */
@@ -921,7 +940,7 @@ expand_member_init (exp, name, init)
               && ! current_template_parms
               && ! vec_binfo_member (basetype,
                                      TYPE_BINFO_BASETYPES (type))
-              && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
+              && ! BINFO_FOR_VBASE (basetype, type))
        {
          if (IDENTIFIER_CLASS_VALUE (name))
            goto try_member;
@@ -984,7 +1003,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);
 }
@@ -997,11 +1015,8 @@ finish_init_stmts (stmt_expr, compound_stmt)
      tree stmt_expr;
      tree compound_stmt;
 {
-  pop_momentary ();
-  stmt_expr 
-    = 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.  */
@@ -1024,11 +1039,6 @@ finish_init_stmts (stmt_expr, compound_stmt)
    If `init' is a CONSTRUCTOR, then we emit a warning message,
    explaining that such initializations are invalid.
 
-   ALIAS_THIS is nonzero iff we are initializing something which is
-   essentially an alias for current_class_ref.  In this case, the base
-   constructor may move it on us, and we must keep track of such
-   deviations.
-
    If INIT resolves to a CALL_EXPR which happens to return
    something of the type we are looking for, then we know
    that we can safely use that call to perform the
@@ -1188,7 +1198,7 @@ expand_default_init (binfo, true_exp, exp, init, flags)
        init = TREE_VALUE (parms);
     }
   else
-    parms = build_expr_list (NULL_TREE, init);
+    parms = build_tree_list (NULL_TREE, init);
 
   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
     {
@@ -1222,8 +1232,6 @@ expand_default_init (binfo, true_exp, exp, init, flags)
    from TRUE_EXP.  In constructors, we don't know anything about
    the value being initialized.
 
-   ALIAS_THIS serves the same purpose it serves for expand_aggr_init.
-
    FLAGS is just passes to `build_method_call'.  See that function for
    its description.  */
 
@@ -1257,11 +1265,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;
     }
 
@@ -1369,7 +1373,7 @@ get_type_value (name)
   else
     return NULL_TREE;
 }
-  
+
 \f
 /* This code could just as well go in `class.c', but is placed here for
    modularity.  */
@@ -1627,7 +1631,7 @@ build_offset_ref (type, name)
            /* The code in instantiate_type which will process this
               expects to encounter OVERLOADs, not raw functions.  */
            t = ovl_cons (t, NULL_TREE);
-         
+
          return build (OFFSET_REF, 
                        unknown_type_node,
                        decl,
@@ -1780,7 +1784,7 @@ resolve_offset_ref (exp)
        basetype = DECL_CONTEXT (member);
 
       base = current_class_ptr;
-      
+
       if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0)
        {
          error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base)));
@@ -1820,7 +1824,7 @@ resolve_offset_ref (exp)
       basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
       addr = convert_pointer_to (basetype, addr);
       member = cp_convert (ptrdiff_type_node, member);
-      
+
       /* Pointer to data members are offset by one, so that a null
         pointer with a real value of 0 is distinguishable from an
         offset of the first member of a structure.  */
@@ -1869,7 +1873,7 @@ build_builtin_delete_call (addr)
 {
   mark_used (global_delete_fndecl);
   return build_call (global_delete_fndecl, 
-                    void_type_node, build_expr_list (NULL_TREE, addr));
+                    void_type_node, build_tree_list (NULL_TREE, addr));
 }
 \f
 /* Generate a C++ "new" expression. DECL is either a TREE_LIST
@@ -1910,8 +1914,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;
 
@@ -1919,14 +1921,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;
 
@@ -1990,17 +1988,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)
     {
@@ -2031,9 +2019,9 @@ build_new (placement, decl, init, use_global_new)
   if (processing_template_decl)
     {
       if (has_array)
-       t = min_tree_cons (min_tree_cons (NULL_TREE, type, NULL_TREE),
-                          build_min_nt (ARRAY_REF, NULL_TREE, nelts),
-                          NULL_TREE);
+       t = tree_cons (tree_cons (NULL_TREE, type, NULL_TREE),
+                      build_min_nt (ARRAY_REF, NULL_TREE, nelts),
+                      NULL_TREE);
       else
        t = type;
        
@@ -2075,15 +2063,14 @@ 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;
 }
 
@@ -2108,7 +2095,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;
@@ -2117,7 +2103,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;
 }
@@ -2198,11 +2183,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)
     {
@@ -2214,18 +2195,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);
@@ -2244,20 +2214,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, 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-
@@ -2307,11 +2267,10 @@ build_new_1 (exp)
                    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
        (tree_cons (NULL_TREE, exp1,
-                        build_expr_list (NULL_TREE, rval)));
+                   build_tree_list (NULL_TREE, rval)));
     }
 
   if (rval == error_mark_node)
@@ -2400,8 +2359,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
@@ -2417,9 +2380,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.  */
@@ -2432,8 +2392,6 @@ build_new_1 (exp)
 
          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
@@ -2446,17 +2404,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);
 
@@ -2498,10 +2453,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;
@@ -2536,7 +2490,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,
@@ -2545,29 +2499,10 @@ 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 = tree_cons (NULL_TREE,
-                   build_delete (ptype, tbase, auto_delete,
+                   build_delete (ptype, tbase, integer_two_node,
                                  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
                    body);
 
@@ -2613,11 +2548,12 @@ 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)
@@ -2630,9 +2566,10 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
     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)
@@ -2677,7 +2614,6 @@ get_temp_regvar (type, init)
   decl = create_temporary_var (type);
   if (building_stmt_tree ())
     add_decl_stmt (decl);
-  DECL_REGISTER (decl) = 1;
   if (!building_stmt_tree ())
     DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
   finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
@@ -2721,22 +2657,13 @@ build_vec_init (decl, base, maxindex, init, from_array)
   tree compound_stmt;
   int destroy_temps;
   tree try_block = NULL_TREE;
-  tree try_body;
+  tree try_body = NULL_TREE;
   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);
@@ -2827,9 +2754,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)
     {
@@ -2958,13 +2882,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,
@@ -2991,17 +2908,10 @@ build_vec_init (decl, base, maxindex, init, from_array)
                                               iterator),
                              type,
                              /*auto_delete_vec=*/integer_zero_node,
-                             /*auto_delete=*/integer_zero_node,
                              /*use_global_delete=*/0);
       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);
@@ -3102,8 +3012,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
     {
@@ -3162,7 +3071,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
        passed_auto_delete = auto_delete;
 
       expr = build_method_call
-       (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete),
+       (ref, dtor_identifier, build_tree_list (NULL_TREE, passed_auto_delete),
         NULL_TREE, flags);
 
       if (do_delete)
@@ -3211,7 +3120,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
        cond = NULL_TREE;
 
       if (cond)
-       exprstmt = build_expr_list (NULL_TREE, cond);
+       exprstmt = build_tree_list (NULL_TREE, cond);
 
       if (base_binfo
          && ! TREE_VIA_VIRTUAL (base_binfo)
@@ -3226,7 +3135,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));
+            build_tree_list (NULL_TREE, this_auto_delete));
          exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
        }
 
@@ -3240,7 +3149,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, integer_zero_node));
+            build_tree_list (NULL_TREE, integer_zero_node));
 
          exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
        }
@@ -3297,7 +3206,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.
 
@@ -3309,10 +3217,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;
@@ -3354,6 +3261,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);
 }