langhooks.h (struct lang_hooks_for_tree_inlining): Add start_inlining, end_inlining.
[gcc.git] / gcc / cp / init.c
index 9d20955a7533f2f52d44e87367e16c01d8fb55fd..098697fa5a7c309206f1d7f40c2559d1b8f9f4f3 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -42,7 +42,7 @@ static tree build_vec_delete_1 PARAMS ((tree, tree, tree, special_function_kind,
 static void perform_member_init PARAMS ((tree, tree, int));
 static void sort_base_init PARAMS ((tree, tree, tree *, tree *));
 static tree build_builtin_delete_call PARAMS ((tree));
-static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
+static int member_init_ok_or_else PARAMS ((tree, tree, tree));
 static void expand_virtual_init PARAMS ((tree, tree));
 static tree sort_member_init PARAMS ((tree, tree));
 static tree initializing_context PARAMS ((tree));
@@ -65,8 +65,6 @@ void init_init_processing ()
 {
   tree fields[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_aggr_type (RECORD_TYPE);
@@ -132,28 +130,21 @@ finish_init_stmts (stmt_expr, compound_stmt)
 
 /* Constructors */
 
-/* Called from initialize_vtbl_ptrs via dfs_walk.  */
+/* Called from initialize_vtbl_ptrs via dfs_walk.  BINFO is the base
+   which we want to initialize the vtable pointer for, DATA is
+   TREE_LIST whose TREE_VALUE is the this ptr expression.  */
 
 static tree
 dfs_initialize_vtbl_ptrs (binfo, data)
      tree binfo;
      void *data;
 {
-  if (!BINFO_PRIMARY_MARKED_P (binfo) 
+  if ((!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
     {
       tree base_ptr = TREE_VALUE ((tree) data);
 
-      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);
+      base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1);
 
       expand_virtual_init (binfo, base_ptr);
     }
@@ -177,21 +168,13 @@ initialize_vtbl_ptrs (addr)
   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.  */
+     class.  We do these in pre-order because 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 we're not using thunks, we may need to adjust the deltas in
-     the vtable to handle virtual base classes correctly.  When we are
-     using thunks, we either use construction vtables (which are
-     preloaded with the right answers) or nothing (in which case
-     vitual function calls sometimes don't work right.)  */
-  if (TYPE_USES_VIRTUAL_BASECLASSES (type) && !flag_vtable_thunks)
-    fixup_all_virtual_upcast_offsets (addr);
 }
 
 /* [dcl.init]:
@@ -220,7 +203,7 @@ build_default_init (type)
        anything with a CONSTRUCTOR for arrays here, as that would imply
        copy-initialization.  */
     return NULL_TREE;
-  else if (AGGREGATE_TYPE_P (type))
+  else if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
     {
       /* This is a default initialization of an aggregate, but not one of
         non-POD class type.  We cleverly notice that the initialization
@@ -232,7 +215,13 @@ build_default_init (type)
     /*   --if T is a reference type, no initialization is performed.  */
     return NULL_TREE;
   else
-    init = integer_zero_node;
+    {
+      init = integer_zero_node;
+      
+      if (TREE_CODE (type) == ENUMERAL_TYPE)
+        /* We must make enumeral types the right type. */
+        init = fold (build1 (NOP_EXPR, type, init));
+    }
 
   init = digest_init (type, init, 0);
   return init;
@@ -561,68 +550,40 @@ sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr)
   tree vbases = NULL_TREE;
 
   /* First walk through and splice out vbase and invalid initializers.
-     Also replace names with binfos.  */
+     Also replace types with binfos.  */
 
   last = tree_cons (NULL_TREE, NULL_TREE, base_init_list);
   for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
     {
       tree basetype = TREE_PURPOSE (x);
-      tree binfo = NULL_TREE;
+      tree binfo = (TREE_CODE (basetype) == TREE_VEC
+                   ? basetype : binfo_or_else (basetype, t));
+      
+      if (binfo == NULL_TREE)
+       /* BASETYPE might be an inaccessible direct base (because it
+          is also an indirect base).  */
+       continue;
 
-      if (basetype == NULL_TREE)
+      if (TREE_VIA_VIRTUAL (binfo))
        {
-         /* Initializer for single base class.  Must not
-            use multiple inheritance or this is ambiguous.  */
-         switch (n_baseclasses)
-           {
-           case 0:
-             cp_error ("`%T' does not have a base class to initialize",
-                       current_class_type);
-             return;
-           case 1:
-             break;
-           default:
-             cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
-                       current_class_type);
-             return;
-           }
-         binfo = TREE_VEC_ELT (binfos, 0);
+         /* Virtual base classes are special cases.  Their
+            initializers are recorded with this constructor, and they
+            are used when this constructor is the top-level
+            constructor called.  */
+         tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
+         vbases = tree_cons (v, TREE_VALUE (x), vbases);
        }
-      else if (is_aggr_type (basetype, 1))
+      else
        {
-         binfo = binfo_or_else (basetype, t);
-         if (binfo == NULL_TREE)
-           continue;
-
-         /* Virtual base classes are special cases.  Their initializers
-            are recorded with this constructor, and they are used when
-            this constructor is the top-level constructor called.  */
-         if (TREE_VIA_VIRTUAL (binfo))
-           {
-             tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
-             vbases = tree_cons (v, TREE_VALUE (x), vbases);
-             continue;
-           }
-         else
-           {
-             /* Otherwise, if it is not an immediate base class, complain.  */
-             for (i = n_baseclasses-1; i >= 0; i--)
-               if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
-                 break;
-             if (i < 0)
-               {
-                 cp_error ("`%T' is not an immediate base class of `%T'",
-                           basetype, current_class_type);
-                 continue;
-               }
-           }
+         /* Otherwise, it must be an immediate base class.  */
+         my_friendly_assert
+           (same_type_p (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
+                         t), 20011113);
+
+         TREE_PURPOSE (x) = binfo;
+         TREE_CHAIN (last) = x;
+         last = x;
        }
-      else
-       my_friendly_abort (365);
-
-      TREE_PURPOSE (x) = binfo;
-      TREE_CHAIN (last) = x;
-      last = x;
     }
   TREE_CHAIN (last) = NULL_TREE;
 
@@ -692,10 +653,7 @@ sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr)
 
    If there is a need for a call to a constructor, we must surround
    that call with a pushlevel/poplevel pair, since we are technically
-   at the PARM level of scope.
-
-   Note that emit_base_init does *not* initialize virtual base
-   classes.  That is done specially, elsewhere.  */
+   at the PARM level of scope.  */
 
 void
 emit_base_init (mem_init_list, base_init_list)
@@ -747,9 +705,10 @@ emit_base_init (mem_init_list, base_init_list)
 
       if (init != void_list_node)
        {
-         member = convert_pointer_to_real (base_binfo, current_class_ptr);
+         member = build_base_path (PLUS_EXPR, current_class_ptr,
+                                   base_binfo, 1);
          expand_aggr_init_1 (base_binfo, NULL_TREE,
-                             build_indirect_ref (member, NULL_PTR), init,
+                             build_indirect_ref (member, NULL), init,
                              LOOKUP_NORMAL);
        }
 
@@ -798,16 +757,27 @@ static tree
 build_vtbl_address (binfo)
      tree binfo;
 {
+  tree binfo_for = binfo;
   tree vtbl;
 
+  if (BINFO_VPTR_INDEX (binfo) && TREE_VIA_VIRTUAL (binfo)
+      && BINFO_PRIMARY_P (binfo))
+    /* If this is a virtual primary base, then the vtable we want to store
+       is that for the base this is being used as the primary base of.  We
+       can't simply skip the initialization, because we may be expanding the
+       inits of a subobject constructor where the virtual base layout
+       can be different.  */
+    while (BINFO_PRIMARY_BASE_OF (binfo_for))
+      binfo_for = BINFO_PRIMARY_BASE_OF (binfo_for);
+
   /* Figure out what vtable BINFO's vtable is based on, and mark it as
      used.  */
-  vtbl = get_vtbl_decl_for_binfo (binfo);
+  vtbl = get_vtbl_decl_for_binfo (binfo_for);
   assemble_external (vtbl);
   TREE_USED (vtbl) = 1;
 
   /* Now compute the address to use when initializing the vptr.  */
-  vtbl = BINFO_VTABLE (binfo);
+  vtbl = BINFO_VTABLE (binfo_for);
   if (TREE_CODE (vtbl) == VAR_DECL)
     {
       vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
@@ -827,20 +797,14 @@ static void
 expand_virtual_init (binfo, decl)
      tree binfo, decl;
 {
-  tree type = BINFO_TYPE (binfo);
   tree vtbl, vtbl_ptr;
-  tree vtype, vtype_binfo;
   tree vtt_index;
 
-  /* Compute the location of the vtable.  */
-  vtype = DECL_CONTEXT (TYPE_VFIELD (type));
-  vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
-  
   /* Compute the initializer for vptr.  */
   vtbl = build_vtbl_address (binfo);
 
-  /* Under the new ABI, we may get this vptr from a VTT, if this is a
-     subobject constructor or subobject destructor.  */
+  /* We may get this vptr from a VTT, if this is a subobject
+     constructor or subobject destructor.  */
   vtt_index = BINFO_VPTR_INDEX (binfo);
   if (vtt_index)
     {
@@ -848,7 +812,7 @@ expand_virtual_init (binfo, decl)
       tree vtt_parm;
 
       /* Compute the value to use, when there's a VTT.  */
-      vtt_parm = DECL_VTT_PARM (current_function_decl);
+      vtt_parm = current_vtt_parm;
       vtbl2 = build (PLUS_EXPR, 
                     TREE_TYPE (vtt_parm), 
                     vtt_parm,
@@ -860,16 +824,16 @@ expand_virtual_init (binfo, decl)
         the vtt_parm in the case of the non-subobject constructor.  */
       vtbl = build (COND_EXPR, 
                    TREE_TYPE (vtbl), 
-                   DECL_USE_VTT_PARM (current_function_decl),
+                   build (EQ_EXPR, boolean_type_node,
+                          current_in_charge_parm, integer_zero_node),
                    vtbl2, 
                    vtbl);
     }
 
   /* 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;
+  vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL),
+                              TREE_TYPE (binfo));
+  my_friendly_assert (vtbl_ptr != error_mark_node, 20010730);
 
   /* Assign the vtable to the vptr.  */
   vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
@@ -912,7 +876,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
      tree binfo, exp, addr, init_list;
 {
   tree init = purpose_member (binfo, init_list);
-  tree ref = build_indirect_ref (addr, NULL_PTR);
+  tree ref = build_indirect_ref (addr, NULL);
 
   if (init)
     init = TREE_VALUE (init);
@@ -938,22 +902,6 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
   /* 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 (!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))
@@ -1030,19 +978,19 @@ static int
 member_init_ok_or_else (field, type, member_name)
      tree field;
      tree type;
-     const char *member_name;
+     tree member_name;
 {
   if (field == error_mark_node)
     return 0;
   if (field == NULL_TREE || initializing_context (field) != type)
     {
-      cp_error ("class `%T' does not have any field named `%s'", type,
+      cp_error ("class `%T' does not have any field named `%D'", type,
                member_name);
       return 0;
     }
   if (TREE_STATIC (field))
     {
-      cp_error ("field `%#D' is static; only point of initialization is its declaration",
+      cp_error ("field `%#D' is static; the only point of initialization is its definition",
                field);
       return 0;
     }
@@ -1050,17 +998,16 @@ member_init_ok_or_else (field, type, member_name)
   return 1;
 }
 
-/* If NAME is a viable field name for the aggregate DECL,
-   and PARMS is a viable parameter list, then expand an _EXPR
-   which describes this initialization.
+/* EXP is an expression of aggregate type. NAME is an IDENTIFIER_NODE
+   which names a field, or it is a _TYPE node or TYPE_DECL which names
+   a base for that type.  INIT is a parameter list for that field's or
+   base's constructor.  Check the validity of NAME, and return a
+   TREE_LIST of the base _TYPE or FIELD_DECL and the INIT. EXP is used
+   only to get its type.  If NAME is invalid, return NULL_TREE and
+   issue a diagnostic.
 
-   Note that we do not need to chase through the class's base classes
-   to look for NAME, because if it's in that list, it will be handled
-   by the constructor for that base class.
-
-   We do not yet have a fixed-point finder to instantiate types
-   being fed to overloaded constructors.  If there is a unique
-   constructor, then argument types can be got from that one.  */
+   An old style unnamed direct single base construction is permitted,
+   where NAME is NULL.  */
 
 tree
 expand_member_init (exp, name, init)
@@ -1073,72 +1020,56 @@ expand_member_init (exp, name, init)
     return NULL_TREE;
 
   type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+  my_friendly_assert (IS_AGGR_TYPE (type), 20011113);
 
-  if (name && TYPE_P (name))
+  if (!name)
     {
-      basetype = name;
-      name = TYPE_IDENTIFIER (name);
+      /* This is an obsolete unnamed base class initializer.  The
+        parser will already have warned about its use.  */
+      switch (CLASSTYPE_N_BASECLASSES (type))
+       {
+       case 0:
+         cp_error ("unnamed initializer for `%T', which has no base classes",
+                   type);
+         return NULL_TREE;
+       case 1:
+         basetype = TYPE_BINFO_BASETYPE (type, 0);
+         break;
+       default:
+         cp_error ("unnamed initializer for `%T', which uses multiple inheritance",
+                   type);
+         return NULL_TREE;
+      }
     }
-  else if (name && TREE_CODE (name) == TYPE_DECL)
+  else if (TYPE_P (name))
     {
-      basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
-      name = DECL_NAME (name);
+      basetype = name;
+      name = TYPE_NAME (name);
     }
-
-  if (name == NULL_TREE && IS_AGGR_TYPE (type))
-    switch (CLASSTYPE_N_BASECLASSES (type))
-      {
-      case 0:
-       error ("base class initializer specified, but no base class to initialize");
-       return NULL_TREE;
-      case 1:
-       basetype = TYPE_BINFO_BASETYPE (type, 0);
-       break;
-      default:
-       error ("initializer for unnamed base class ambiguous");
-       cp_error ("(type `%T' uses multiple inheritance)", type);
-       return NULL_TREE;
-      }
+  else if (TREE_CODE (name) == TYPE_DECL)
+    basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
 
   my_friendly_assert (init != NULL_TREE, 0);
 
-  /* The grammar should not allow fields which have names that are
-     TYPENAMEs.  Therefore, if the field has a non-NULL TREE_TYPE, we
-     may assume that this is an attempt to initialize a base class
-     member of the current type.  Otherwise, it is an attempt to
-     initialize a member field.  */
-
   if (init == void_type_node)
     init = NULL_TREE;
 
-  if (name == NULL_TREE || basetype)
+  if (basetype)
     {
-      if (name == NULL_TREE)
-       {
-#if 0
-         if (basetype)
-           name = TYPE_IDENTIFIER (basetype);
-         else
-           {
-             error ("no base class to initialize");
-             return;
-           }
-#endif
-       }
-      else if (basetype != type
-              && ! current_template_parms
-              && ! vec_binfo_member (basetype,
-                                     TYPE_BINFO_BASETYPES (type))
-              && ! binfo_for_vbase (basetype, type))
+      if (current_template_parms)
+       ;
+      else if (vec_binfo_member (basetype, TYPE_BINFO_BASETYPES (type)))
+       /* A direct base.  */;
+      else if (binfo_for_vbase (basetype, type))
+       /* A virtual base.  */;
+      else
        {
-         if (IDENTIFIER_CLASS_VALUE (name))
-           goto try_member;
          if (TYPE_USES_VIRTUAL_BASECLASSES (type))
-           cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
-                     basetype, type);
+           cp_error ("type `%D' is not a direct or virtual base of `%T'",
+                     name, type);
          else
-           cp_error ("type `%T' is not an immediate basetype for `%T'",
-                     basetype, type);
+           cp_error ("type `%D' is not a direct base of `%T'",
+                     name, type);
          return NULL_TREE;
        }
 
@@ -1146,10 +1077,9 @@ expand_member_init (exp, name, init)
     }
   else
     {
-    try_member:
       field = lookup_field (type, name, 1, 0);
 
-      if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
+      if (! member_init_ok_or_else (field, type, name))
        return NULL_TREE;
 
       init = build_tree_list (field, init);
@@ -1235,7 +1165,7 @@ build_aggr_init (exp, init, flags)
          cp_error ("bad array initializer");
          return error_mark_node;
        }
-      if (CP_TYPE_QUALS (type) != TYPE_UNQUALIFIED)
+      if (cp_type_quals (type) != TYPE_UNQUALIFIED)
        {
          TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
          if (init)
@@ -1514,9 +1444,6 @@ build_member_call (type, name, parmlist)
   if (DECL_P (name))
     name = DECL_NAME (name);
 
-  if (type == fake_std_node)
-    return build_x_function_call (do_scoped_id (name, 0), parmlist,
-                                 current_class_ref);
   if (TREE_CODE (type) == NAMESPACE_DECL)
     return build_x_function_call (lookup_namespace_name (type, name),
                                  parmlist, current_class_ref);
@@ -1547,7 +1474,8 @@ build_member_call (type, name, parmlist)
       tree ns = lookup_name (type, 0);
       if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
        {
-         return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);
+         return build_x_function_call (build_offset_ref (type, name),
+                                       parmlist, current_class_ref);
        }
     }
 
@@ -1580,7 +1508,7 @@ build_member_call (type, name, parmlist)
        {
          tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));
          decl = convert_force (build_pointer_type (newtype), olddecl, 0);
-         decl = build_indirect_ref (decl, NULL_PTR);
+         decl = build_indirect_ref (decl, NULL);
        }
     }
 
@@ -1649,9 +1577,6 @@ build_offset_ref (type, name)
   if (TREE_CODE (name) == TEMPLATE_DECL)
     return name;
 
-  if (type == fake_std_node)
-    return do_scoped_id (name, 0);
-
   if (processing_template_decl || uses_template_parms (type))
     return build_min_nt (SCOPE_REF, type, name);
 
@@ -1906,14 +1831,17 @@ resolve_offset_ref (exp)
       if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
        base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type));
 
-      addr = build_unary_op (ADDR_EXPR, base, 0);
-      addr = convert_pointer_to (basetype, addr);
+      /* Don't check access on the conversion; we might be after a member
+        promoted by an access- or using-declaration, and we have already
+        checked access for the member itself.  */
+      basetype = lookup_base (TREE_TYPE (base), basetype, ba_ignore, NULL);
+      expr = build_base_path (PLUS_EXPR, base, basetype, 1);
 
-      if (addr == error_mark_node)
+      if (expr == error_mark_node)
        return error_mark_node;
 
       expr = build (COMPONENT_REF, TREE_TYPE (member),
-                   build_indirect_ref (addr, NULL_PTR), member);
+                   expr, member);
       return convert_from_reference (expr);
     }
 
@@ -1936,17 +1864,12 @@ resolve_offset_ref (exp)
        }
 
       basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
-      addr = convert_pointer_to (basetype, addr);
+      basetype = lookup_base (TREE_TYPE (TREE_TYPE (addr)),
+                             basetype, ba_check, NULL);
+      addr = build_base_path (PLUS_EXPR, addr, basetype, 1);
+      
       member = cp_convert (ptrdiff_type_node, member);
 
-      if (!flag_new_abi)
-       /* 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.  */
-       member = cp_build_binary_op (MINUS_EXPR, member,
-                                    cp_convert (ptrdiff_type_node, 
-                                                integer_one_node));
-
       return build1 (INDIRECT_REF, type,
                     build (PLUS_EXPR, build_pointer_type (type),
                            addr, member));
@@ -2076,8 +1999,8 @@ build_new (placement, decl, init, use_global_new)
                }
              else
                {
-                 int flags = pedantic ? WANT_INT : (WANT_INT | WANT_ENUM);
-                 if (build_expr_type_conversion (flags, this_nelts, 0)
+                 if (build_expr_type_conversion (WANT_INT | WANT_ENUM, 
+                                                 this_nelts, 0)
                      == NULL_TREE)
                    pedwarn ("size in array new must have integral type");
 
@@ -2195,18 +2118,33 @@ tree
 build_java_class_ref (type)
      tree type;
 {
-  tree name, class_decl;
+  tree name = NULL_TREE, class_decl;
   static tree CL_suffix = NULL_TREE;
   if (CL_suffix == NULL_TREE)
     CL_suffix = get_identifier("class$");
   if (jclass_node == NULL_TREE)
     {
-      jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier("jclass"));
+      jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
       if (jclass_node == NULL_TREE)
-       fatal("call to Java constructor, while `jclass' undefined");
+       fatal_error ("call to Java constructor, while `jclass' undefined");
+
       jclass_node = TREE_TYPE (jclass_node);
     }
-  name = build_static_name (type, CL_suffix);
+
+  /* Mangle the class$ field */
+  {
+    tree field;
+    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      if (DECL_NAME (field) == CL_suffix)
+       {
+         mangle_decl (field);
+         name = DECL_ASSEMBLER_NAME (field);
+         break;
+       }
+    if (!field)
+      internal_error ("can't find class$");
+    }
+
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
   if (class_decl == NULL_TREE)
     {
@@ -2217,7 +2155,7 @@ build_java_class_ref (type)
       DECL_ARTIFICIAL (class_decl) = 1;
       DECL_IGNORED_P (class_decl) = 1;
       pushdecl_top_level (class_decl);
-      make_decl_rtl (class_decl, NULL_PTR, 1);
+      make_decl_rtl (class_decl, NULL);
     }
   return class_decl;
 }
@@ -2232,27 +2170,17 @@ get_cookie_size (type)
 {
   tree cookie_size;
 
-  if (flag_new_abi)
-    {
-      /* Under the new ABI, we need to allocate an additional max
-        (sizeof (size_t), alignof (true_type)) bytes.  */
-      tree sizetype_size;
-      tree type_align;
-
-      sizetype_size = size_in_bytes (sizetype);
-      type_align = size_int (TYPE_ALIGN_UNIT (type));
-      if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
-       cookie_size = sizetype_size;
-      else
-       cookie_size = type_align;
-    }
+  /* We need to allocate an additional max (sizeof (size_t), alignof
+     (true_type)) bytes.  */
+  tree sizetype_size;
+  tree type_align;
+  
+  sizetype_size = size_in_bytes (sizetype);
+  type_align = size_int (TYPE_ALIGN_UNIT (type));
+  if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
+    cookie_size = sizetype_size;
   else
-    {
-      if (TYPE_ALIGN (type) > TYPE_ALIGN (BI_header_type))
-       return size_int (TYPE_ALIGN_UNIT (type));
-      else
-       return size_in_bytes (BI_header_type);
-    }
+    cookie_size = type_align;
 
   return cookie_size;
 }
@@ -2283,6 +2211,9 @@ build_new_1 (exp)
      beginning of the storage allocated for an array-new expression in
      order to store the number of elements.  */
   tree cookie_size = NULL_TREE;
+  /* True if the function we are calling is a placement allocation
+     function.  */
+  bool placement_allocation_fn_p;
 
   placement = TREE_OPERAND (exp, 0);
   type = TREE_OPERAND (exp, 1);
@@ -2347,14 +2278,12 @@ build_new_1 (exp)
   if (!has_array || !TYPE_VEC_NEW_USES_COOKIE (true_type))
     use_cookie = 0;
   /* When using placement new, users may not realize that they need
-     the extra storage.  Under the old ABI, we don't allocate the
-     cookie whenever they use one placement argument of type `void
-     *'.  Under the new ABI, we require that the operator called be
+     the extra storage.  We require that the operator called be
      the global placement operator delete[].  */
   else if (placement && !TREE_CHAIN (placement) 
           && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
                           ptr_type_node))
-    use_cookie = (!flag_new_abi || !use_global_new);
+    use_cookie = !use_global_new;
   /* Otherwise, we need the cookie.  */
   else
     use_cookie = 1;
@@ -2374,11 +2303,13 @@ build_new_1 (exp)
       tree class_addr, alloc_decl;
       tree class_decl = build_java_class_ref (true_type);
       tree class_size = size_in_bytes (true_type);
-      static char alloc_name[] = "_Jv_AllocObject";
+      static const char alloc_name[] = "_Jv_AllocObject";
       use_java_new = 1;
       alloc_decl = IDENTIFIER_GLOBAL_VALUE (get_identifier (alloc_name));
       if (alloc_decl == NULL_TREE)
-       fatal("call to Java constructor, while `%s' undefined", alloc_name);
+       fatal_error ("call to Java constructor with `%s' undefined",
+                    alloc_name);
+
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
       alloc_call = (build_function_call
                    (alloc_decl,
@@ -2406,8 +2337,25 @@ build_new_1 (exp)
   if (alloc_call == error_mark_node)
     return error_mark_node;
 
-  if (alloc_call == NULL_TREE)
-    abort ();
+  /* The ALLOC_CALL should be a CALL_EXPR, and the first operand
+     should be the address of a known FUNCTION_DECL.  */
+  my_friendly_assert (TREE_CODE (alloc_call) == CALL_EXPR, 20000521);
+  t = TREE_OPERAND (alloc_call, 0);
+  my_friendly_assert (TREE_CODE (t) == ADDR_EXPR, 20000521);
+  t = TREE_OPERAND (t, 0);
+  my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL, 20000521);
+  /* Now, check to see if this function is actually a placement
+     allocation function.  This can happen even when PLACEMENT is NULL
+     because we might have something like:
+
+       struct S { void* operator new (size_t, int i = 0); };
+
+     A call to `new S' will get this allocation function, even though
+     there is no explicit placement argument.  If there is more than
+     one argument, or there are variable arguments, then this is a
+     placement allocation function.  */
+  placement_allocation_fn_p 
+    = (type_num_arguments (TREE_TYPE (t)) > 1 || varargs_function_p (t));
 
   /*        unless an allocation function is declared with an empty  excep-
      tion-specification  (_except.spec_),  throw(), it indicates failure to
@@ -2447,23 +2395,12 @@ build_new_1 (exp)
       tree cookie;
 
       /* Store the number of bytes allocated so that we can know how
-        many elements to destroy later.  */
-      if (flag_new_abi)
-       {
-         /* Under the new ABI, we use the last sizeof (size_t) bytes
-            to store the number of elements.  */
-         cookie = build (MINUS_EXPR, build_pointer_type (sizetype),
-                         alloc_node, size_in_bytes (sizetype));
-         cookie = build_indirect_ref (cookie, NULL_PTR);
-       }
-      else
-       {
-         cookie = build (MINUS_EXPR, build_pointer_type (BI_header_type),
-                         alloc_node, cookie_size);
-         cookie = build_indirect_ref (cookie, NULL_PTR);
-         cookie = build_component_ref (cookie, nelts_identifier,
-                                       NULL_TREE, 0);
-       }
+        many elements to destroy later.  We use the last sizeof
+        (size_t) bytes to store the number of elements.  */
+      cookie = build (MINUS_EXPR, build_pointer_type (sizetype),
+                     alloc_node, size_in_bytes (sizetype));
+      cookie = build_indirect_ref (cookie, NULL);
+
       cookie_expr = build (MODIFY_EXPR, void_type_node, cookie, nelts);
       TREE_SIDE_EFFECTS (cookie_expr) = 1;
     }
@@ -2474,7 +2411,7 @@ build_new_1 (exp)
   init_expr = NULL_TREE;
   if (TYPE_NEEDS_CONSTRUCTING (type) || init)
     {
-      init_expr = build_indirect_ref (alloc_node, NULL_PTR);
+      init_expr = build_indirect_ref (alloc_node, NULL);
 
       if (init == void_zero_node)
        init = build_default_init (full_type);
@@ -2534,7 +2471,8 @@ build_new_1 (exp)
          flags |= LOOKUP_SPECULATIVELY;
 
          cleanup = build_op_delete_call (dcode, alloc_node, size, flags,
-                                         alloc_call);
+                                         (placement_allocation_fn_p 
+                                          ? alloc_call : NULL_TREE));
 
          /* Ack!  First we allocate the memory.  Then we set our sentry
             variable to true, and expand a cleanup that deletes the memory
@@ -2778,7 +2716,7 @@ get_temp_regvar (type, init)
   if (building_stmt_tree ())
     add_decl_stmt (decl);
   if (!building_stmt_tree ())
-    DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
+    SET_DECL_RTL (decl, assign_temp (type, 2, 0, 1));
   finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
 
   return decl;
@@ -2967,7 +2905,7 @@ build_vec_init (base, init, from_array)
 
       if_stmt = begin_if_stmt ();
       finish_if_stmt_cond (build (NE_EXPR, boolean_type_node,
-                                 iterator, minus_one_node),
+                                 iterator, integer_minus_one_node),
                           if_stmt);
 
       /* Otherwise, loop through the elements.  */
@@ -3041,7 +2979,7 @@ build_vec_init (base, init, from_array)
       finish_do_body (do_stmt);
       finish_do_stmt (build (NE_EXPR, boolean_type_node,
                             build_unary_op (PREDECREMENT_EXPR, iterator, 0),
-                            minus_one_node),
+                            integer_minus_one_node),
                      do_stmt);
 
       finish_then_clause (if_stmt);
@@ -3153,7 +3091,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
 {
   tree member;
   tree expr;
-  tree ref;
 
   if (addr == error_mark_node)
     return error_mark_node;
@@ -3182,7 +3119,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
 
       /* throw away const and volatile on target type of addr */
       addr = convert_force (build_pointer_type (type), addr, 0);
-      ref = build_indirect_ref (addr, NULL_PTR);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -3206,19 +3142,14 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       if (TREE_SIDE_EFFECTS (addr))
        addr = save_expr (addr);
 
-      if (TREE_CONSTANT (addr))
-       addr = convert_pointer_to (type, addr);
-      else
-       addr = convert_force (build_pointer_type (type), addr, 0);
-
-      ref = build_indirect_ref (addr, NULL_PTR);
+      addr = convert_force (build_pointer_type (type), addr, 0);
     }
 
   my_friendly_assert (IS_AGGR_TYPE (type), 220);
 
   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     {
-      if (auto_delete == sfk_base_destructor)
+      if (auto_delete != sfk_deleting_destructor)
        return void_zero_node;
 
       return build_op_delete_call
@@ -3235,16 +3166,39 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       tree do_delete = NULL_TREE;
       tree ifexp;
 
+      /* For `::delete x', we must not use the deleting destructor
+        since then we would not be sure to get the global `operator
+        delete'.  */
       if (use_global_delete && auto_delete == sfk_deleting_destructor)
        {
+         /* We will use ADDR multiple times so we must save it.  */
+         addr = save_expr (addr);
          /* Delete the object. */
          do_delete = build_builtin_delete_call (addr);
          /* Otherwise, treat this like a complete object destructor
             call.  */
          auto_delete = sfk_complete_destructor;
        }
+      /* If the destructor is non-virtual, there is no deleting
+        variant.  Instead, we must explicitly call the appropriate
+        `operator delete' here.  */
+      else if (!DECL_VIRTUAL_P (CLASSTYPE_DESTRUCTORS (type))
+              && auto_delete == sfk_deleting_destructor)
+       {
+         /* We will use ADDR multiple times so we must save it.  */
+         addr = save_expr (addr);
+         /* Build the call.  */
+         do_delete = build_op_delete_call (DELETE_EXPR,
+                                           addr,
+                                           c_sizeof_nowarn (type),
+                                           LOOKUP_NORMAL,
+                                           NULL_TREE);
+         /* Call the complete object destructor.  */
+         auto_delete = sfk_complete_destructor;
+       }
 
-      expr = build_dtor_call (ref, auto_delete, flags);
+      expr = build_dtor_call (build_indirect_ref (addr, NULL),
+                             auto_delete, flags);
       if (do_delete)
        expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
 
@@ -3268,6 +3222,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
       tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
       tree exprstmt = NULL_TREE;
+      tree ref = build_indirect_ref (addr, NULL);
 
       /* Set this again before we call anything, as we might get called
         recursively.  */
@@ -3381,24 +3336,11 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
       tree cookie_addr;
 
       type = strip_array_types (TREE_TYPE (type));
-      if (flag_new_abi)
-       {
-         cookie_addr = build (MINUS_EXPR,
-                              build_pointer_type (sizetype),
-                              base,
-                              TYPE_SIZE_UNIT (sizetype));
-         maxindex = build_indirect_ref (cookie_addr, NULL_PTR);
-       }
-      else
-       {
-         tree cookie;
-
-         cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
-                              base, get_cookie_size (type));
-         cookie = build_indirect_ref (cookie_addr, NULL_PTR);
-         maxindex = build_component_ref (cookie, nelts_identifier, 
-                                         NULL_TREE, 0);
-       }
+      cookie_addr = build (MINUS_EXPR,
+                          build_pointer_type (sizetype),
+                          base,
+                          TYPE_SIZE_UNIT (sizetype));
+      maxindex = build_indirect_ref (cookie_addr, NULL);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {