]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/init.c
Warning fixes:
[gcc.git] / gcc / cp / init.c
index 006e13f83e5cd5d188cc6a2fa69069abd964b6c2..71fd08b1d4c34078a463617b9cccfbaf22a6d59b 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle initialization things in C++.
-   Copyright (C) 1987, 89, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -19,15 +19,18 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-
 /* High-level class interface.  */
 
 #include "config.h"
+#include "system.h"
 #include "tree.h"
 #include "rtl.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
@@ -40,22 +43,23 @@ Boston, MA 02111-1307, USA.  */
    line.  Perhaps this was not intended.  */
 tree current_base_init_list, current_member_init_list;
 
-extern tree cleanups_this_call;
-
-void emit_base_init ();
-void check_base_init ();
-static void expand_aggr_vbase_init ();
-void expand_member_init ();
-void expand_aggr_init ();
-
-static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int, int));
+static void expand_aggr_vbase_init_1 PROTO((tree, tree, tree, tree));
+static void expand_aggr_vbase_init PROTO((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));
-tree expand_vec_init ();
-
-static void add_friend (), add_friends ();
-
-/* Cache _builtin_new and _builtin_delete exprs.  */
-static tree BIN, BID, BIVN, BIVD;
+static tree sort_member_init PROTO((tree));
+static tree build_partial_cleanup_for PROTO((tree));
+static tree initializing_context PROTO((tree));
+static void expand_vec_init_try_block PROTO((tree));
+static void expand_vec_init_catch_clause PROTO((tree, tree, tree, tree));
+static tree build_java_class_ref PROTO((tree));
 
 /* Cache the identifier nodes for the magic field of a new cookie.  */
 static tree nc_nelts_field_id;
@@ -71,15 +75,6 @@ void init_init_processing ()
 {
   tree fields[1];
 
-  /* Define implicit `operator new' and `operator delete' functions.  */
-  BIN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) NEW_EXPR])));
-  TREE_USED (TREE_OPERAND (BIN, 0)) = 0;
-  BID = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR])));
-  TREE_USED (TREE_OPERAND (BID, 0)) = 0;
-  BIVN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_NEW_EXPR])));
-  TREE_USED (TREE_OPERAND (BIVN, 0)) = 0;
-  BIVD = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_DELETE_EXPR])));
-  TREE_USED (TREE_OPERAND (BIVD, 0)) = 0;
   minus_one = build_int_2 (-1, -1);
 
   /* Define the structure that holds header information for
@@ -127,8 +122,8 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
     {
       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));
+      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);
@@ -156,13 +151,8 @@ perform_member_init (member, name, init, explicit)
 {
   tree decl;
   tree type = TREE_TYPE (member);
-  extern int temp_slot_level;
-  extern int target_temp_slot_level; 
-  tree old_cleanups = cleanups_this_call;
-  int old_temp_level = target_temp_slot_level;
-  push_temp_slots ();
-  push_temp_slots ();
-  target_temp_slot_level = temp_slot_level;
+
+  expand_start_target_temps ();
 
   if (TYPE_NEEDS_CONSTRUCTING (type)
       || (init && TYPE_HAS_CONSTRUCTOR (type)))
@@ -170,7 +160,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_tree_list (NULL_TREE, init);
+       init = build_expr_list (NULL_TREE, init);
 
       decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
 
@@ -185,7 +175,7 @@ perform_member_init (member, name, init, explicit)
                           array_type_nelts (type), TREE_VALUE (init), 1);
        }
       else
-       expand_aggr_init (decl, init, 0, 0);
+       expand_aggr_init (decl, init, 0);
     }
   else
     {
@@ -193,9 +183,17 @@ perform_member_init (member, name, init, explicit)
        {
          if (explicit)
            {
-             cp_error ("incomplete initializer for member `%D' of class `%T' which has no constructor",
-                       member, current_class_type);
-             init = error_mark_node;
+             /* default-initialization.  */
+             if (AGGREGATE_TYPE_P (type))
+               init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+             else if (TREE_CODE (type) == REFERENCE_TYPE)
+               {
+                 cp_error ("default-initialization of `%#D', which has reference type",
+                           member);
+                 init = error_mark_node;
+               }
+             else
+               init = integer_zero_node;
            }
          /* member traversal: note it leaves init NULL */
          else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE)
@@ -218,29 +216,32 @@ perform_member_init (member, name, init, explicit)
         current_member_init_list.  */
       if (init || explicit)
        {
-         decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
+         decl = build_component_ref (current_class_ref, name, NULL_TREE,
+                                     explicit);
          expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
        }
     }
-  expand_cleanups_to (old_cleanups);
-  pop_temp_slots ();
-  pop_temp_slots ();
-  target_temp_slot_level = old_temp_level;
-  /* There might something left from building the trees.  */
-  if (cleanups_this_call)
-    {
-      expand_cleanups_to (NULL_TREE);
-    }
+
+  expand_end_target_temps ();
   free_temp_slots ();
 
   if (TYPE_NEEDS_DESTRUCTOR (type))
     {
-      tree expr = build_component_ref (current_class_ref, name, NULL_TREE, 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,
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
 
       if (expr != error_mark_node)
        add_partial_entry (expr);
+
+      pop_obstacks ();
     }
 }
 
@@ -255,7 +256,7 @@ sort_member_init (t)
   tree x, member, name, field;
   tree init_list = NULL_TREE;
   int last_pos = 0;
-  tree last_field;
+  tree last_field = NULL_TREE;
 
   for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member))
     {
@@ -365,7 +366,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
   for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
     {
       tree basetype = TREE_PURPOSE (x);
-      tree binfo;
+      tree binfo = NULL_TREE;
 
       if (basetype == NULL_TREE)
        {
@@ -483,13 +484,9 @@ static tree
 build_partial_cleanup_for (binfo)
      tree binfo;
 {
-  tree expr = convert_pointer_to_real (binfo,
-                                      build_unary_op (ADDR_EXPR, current_class_ref, 0));
-
-  return build_delete (TREE_TYPE (expr),
-                      expr,
-                      integer_zero_node,
-                      LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+  return build_scoped_method_call
+    (current_class_ref, binfo, dtor_identifier,
+     build_expr_list (NULL_TREE, integer_zero_node));
 }
 
 /* Perform whatever initializations have yet to be done on the base
@@ -570,40 +567,29 @@ emit_base_init (t, immediately)
       if (TREE_VIA_VIRTUAL (base_binfo))
        continue;
 
-#if 0 /* Once unsharing happens soon enough.  */
-      my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo, 999);
-#else
-      BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
-#endif
+      my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo,
+                         999);
 
       if (TREE_PURPOSE (rbase_init_list))
        init = TREE_VALUE (rbase_init_list);
       else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
-       init = NULL_TREE;
+       {
+         init = NULL_TREE;
+         if (extra_warnings && copy_args_p (current_function_decl))
+           cp_warning ("base class `%#T' should be explicitly initialized in the copy constructor",
+                       BINFO_TYPE (base_binfo));
+       }
 
       if (init != void_list_node)
        {
-         extern int temp_slot_level;
-         extern int target_temp_slot_level; 
-         tree old_cleanups = cleanups_this_call;
-         int old_temp_level = target_temp_slot_level;
-         push_temp_slots ();
-         push_temp_slots ();
-         target_temp_slot_level = temp_slot_level;
+         expand_start_target_temps ();
 
          member = convert_pointer_to_real (base_binfo, current_class_ptr);
          expand_aggr_init_1 (base_binfo, NULL_TREE,
                              build_indirect_ref (member, NULL_PTR), init,
-                             BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
-         expand_cleanups_to (old_cleanups);
-         pop_temp_slots ();
-         pop_temp_slots ();
-         target_temp_slot_level = old_temp_level;
-         /* There might something left from building the trees.  */
-         if (cleanups_this_call)
-           {
-             expand_cleanups_to (NULL_TREE);
-           }
+                             LOOKUP_NORMAL);
+
+         expand_end_target_temps ();
          free_temp_slots ();
        }
 
@@ -665,6 +651,12 @@ emit_base_init (t, immediately)
          init = DECL_INITIAL (member);
 
          from_init_list = 0;
+
+         /* Effective C++ rule 12.  */
+         if (warn_ecpp && init == NULL_TREE
+             && !DECL_ARTIFICIAL (member)
+             && TREE_CODE (TREE_TYPE (member)) != ARRAY_TYPE)
+           cp_warning ("`%D' should be initialized in the member initialization list", member);            
        }
 
       perform_member_init (member, name, init, from_init_list);
@@ -785,28 +777,14 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
   tree init = purpose_member (binfo, init_list);
   tree ref = build_indirect_ref (addr, NULL_PTR);
 
-  extern int temp_slot_level;
-  extern int target_temp_slot_level; 
-  tree old_cleanups = cleanups_this_call;
-  int old_temp_level = target_temp_slot_level;
-  push_temp_slots ();
-  push_temp_slots ();
-  target_temp_slot_level = temp_slot_level;
+  expand_start_target_temps ();
 
   if (init)
     init = TREE_VALUE (init);
   /* Call constructors, but don't set up vtables.  */
-  expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
+  expand_aggr_init_1 (binfo, exp, ref, init, LOOKUP_COMPLAIN);
 
-  expand_cleanups_to (old_cleanups);
-  pop_temp_slots ();
-  pop_temp_slots ();
-  target_temp_slot_level = old_temp_level;
-  /* There might something left from building the trees.  */
-  if (cleanups_this_call)
-    {
-      expand_cleanups_to (NULL_TREE);
-    }
+  expand_end_target_temps ();
   free_temp_slots ();
 }
 
@@ -843,34 +821,6 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list)
     }
 }
 
-/* Subroutine to perform parser actions for member initialization.
-   S_ID is the scoped identifier.
-   NAME is the name of the member.
-   INIT is the initializer, or `void_type_node' if none.  */
-
-void
-do_member_init (s_id, name, init)
-     tree s_id, name, init;
-{
-  tree binfo, base;
-
-  if (current_class_type == NULL_TREE
-      || ! is_aggr_typedef (s_id, 1))
-    return;
-  binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id),
-                         current_class_type, 1);
-  if (binfo == error_mark_node)
-    return;
-  if (binfo == 0)
-    {
-      error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type);
-      return;
-    }
-
-  base = convert_pointer_to (binfo, current_class_ptr);
-  expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
-}
-
 /* Find the context in which this FIELD can be initialized.  */
 
 static tree
@@ -881,7 +831,7 @@ initializing_context (field)
 
   /* Anonymous union members can be initialized in the first enclosing
      non-anonymous union context.  */
-  while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+  while (t && ANON_UNION_TYPE_P (t))
     t = TYPE_CONTEXT (t);
   return t;
 }
@@ -897,7 +847,7 @@ static int
 member_init_ok_or_else (field, type, member_name)
      tree field;
      tree type;
-     char *member_name;
+     const char *member_name;
 {
   if (field == error_mark_node)
     return 0;
@@ -937,11 +887,8 @@ void
 expand_member_init (exp, name, init)
      tree exp, name, init;
 {
-  extern tree ptr_type_node;   /* should be in tree.h */
-
   tree basetype = NULL_TREE, field;
-  tree parm;
-  tree rval, type;
+  tree type;
 
   if (exp == NULL_TREE)
     return;                    /* complain about this later */
@@ -950,7 +897,7 @@ expand_member_init (exp, name, init)
 
   if (name && TREE_CODE (name) == TYPE_DECL)
     {
-      basetype = TREE_TYPE (name);
+      basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
       name = DECL_NAME (name);
     }
 
@@ -969,166 +916,84 @@ expand_member_init (exp, name, init)
        return;
       }
 
-  if (init)
-    {
-      /* 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.  */
+  my_friendly_assert (init != NULL_TREE, 0);
 
-      if (init == void_type_node)
-       init = NULL_TREE;
+  /* 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 (name == NULL_TREE || basetype)
-       {
-         tree base_init;
+  if (init == void_type_node)
+    init = NULL_TREE;
 
-         if (name == NULL_TREE)
-           {
+  if (name == NULL_TREE || basetype)
+    {
+      tree base_init;
+
+      if (name == NULL_TREE)
+       {
 #if 0
-             if (basetype)
-               name = TYPE_IDENTIFIER (basetype);
-             else
-               {
-                 error ("no base class to initialize");
-                 return;
-               }
-#endif
-           }
+         if (basetype)
+           name = TYPE_IDENTIFIER (basetype);
          else
            {
-             if (basetype != type
-                 && ! vec_binfo_member (basetype, TYPE_BINFO_BASETYPES (type))
-                 && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
-               {
-                 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);
-                 else
-                   cp_error ("type `%T' is not an immediate basetype for `%T'",
-                             basetype, type);
-                 return;
-               }
-           }
-
-         if (purpose_member (basetype, current_base_init_list))
-           {
-             cp_error ("base class `%T' already initialized", basetype);
+             error ("no base class to initialize");
              return;
            }
-
-         if (warn_reorder && current_member_init_list)
-           {
-             cp_warning ("base initializer for `%T'", basetype);
-             warning ("   will be re-ordered to precede member initializations");
-           }
-
-         base_init = build_tree_list (basetype, init);
-         current_base_init_list = chainon (current_base_init_list, base_init);
+#endif
        }
-      else
-       {
-         tree member_init;
-
-       try_member:
-         field = lookup_field (type, name, 1, 0);
-
-         if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
-           return;
-
-         if (purpose_member (name, current_member_init_list))
-           {
-             cp_error ("field `%D' already initialized", field);
-             return;
-           }
-
-         member_init = build_tree_list (name, init);
-         current_member_init_list = chainon (current_member_init_list, member_init);
+      else if (basetype != type
+              && ! current_template_parms
+              && ! vec_binfo_member (basetype,
+                                     TYPE_BINFO_BASETYPES (type))
+              && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
+       {
+         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);
+         else
+           cp_error ("type `%T' is not an immediate basetype for `%T'",
+                     basetype, type);
+         return;
        }
-      return;
-    }
-  else if (name == NULL_TREE)
-    {
-      compiler_error ("expand_member_init: name == NULL_TREE");
-      return;
-    }
 
-  basetype = type;
-  field = lookup_field (basetype, name, 0, 0);
-
-  if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name)))
-    return;
-
-  /* now see if there is a constructor for this type
-     which will take these args.  */
-
-  if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))
-    {
-      tree parmtypes, fndecl;
-
-      if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
+      if (purpose_member (basetype, current_base_init_list))
        {
-         /* just know that we've seen something for this node */
-         DECL_INITIAL (exp) = error_mark_node;
-         TREE_USED (exp) = 1;
+         cp_error ("base class `%T' already initialized", basetype);
+         return;
        }
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
-      parm = build_component_ref (exp, name, NULL_TREE, 0);
-
-      /* Now get to the constructors.  */
-      fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
 
-      if (fndecl)
-       my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209);
-
-      /* If the field is unique, we can use the parameter
-        types to guide possible type instantiation.  */
-      if (DECL_CHAIN (fndecl) == NULL_TREE)
-       {
-         /* There was a confusion here between
-            FIELD and FNDECL.  The following code
-            should be correct, but abort is here
-            to make sure.  */
-         my_friendly_abort (48);
-         parmtypes = FUNCTION_ARG_CHAIN (fndecl);
-       }
-      else
+      if (warn_reorder && current_member_init_list)
        {
-         parmtypes = NULL_TREE;
-         fndecl = NULL_TREE;
+         cp_warning ("base initializer for `%T'", basetype);
+         warning ("   will be re-ordered to precede member initializations");
        }
 
-      init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL);
-      if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node)
-       rval = build_method_call (NULL_TREE, ctor_identifier, init,
-                                 TYPE_BINFO (type), LOOKUP_NORMAL);
-      else
+      base_init = build_tree_list (basetype, init);
+      current_base_init_list = chainon (current_base_init_list, base_init);
+    }
+  else
+    {
+      tree member_init;
+
+    try_member:
+      field = lookup_field (type, name, 1, 0);
+
+      if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
        return;
 
-      if (rval != error_mark_node)
+      if (purpose_member (name, current_member_init_list))
        {
-         /* Now, fill in the first parm with our guy */
-         TREE_VALUE (TREE_OPERAND (rval, 1))
-           = build_unary_op (ADDR_EXPR, parm, 0);
-         TREE_TYPE (rval) = ptr_type_node;
-         TREE_SIDE_EFFECTS (rval) = 1;
+         cp_error ("field `%D' already initialized", field);
+         return;
        }
-    }
-  else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
-    {
-      parm = build_component_ref (exp, name, NULL_TREE, 0);
-      expand_aggr_init (parm, NULL_TREE, 0, 0);
-      rval = error_mark_node;
-    }
 
-  /* Now initialize the member.  It does not have to
-     be of aggregate type to receive initialization.  */
-  if (rval != error_mark_node)
-    expand_expr_stmt (rval);
+      member_init = build_tree_list (name, init);
+      current_member_init_list = chainon (current_member_init_list, member_init);
+    }
 }
 
 /* This is like `expand_member_init', only it stores one aggregate
@@ -1170,9 +1035,8 @@ expand_member_init (exp, name, init)
    perform the initialization, but not both, as it would be ambiguous.  */
 
 void
-expand_aggr_init (exp, init, alias_this, flags)
+expand_aggr_init (exp, init, flags)
      tree exp, init;
-     int alias_this;
      int flags;
 {
   tree type = TREE_TYPE (exp);
@@ -1193,7 +1057,7 @@ expand_aggr_init (exp, init, alias_this, flags)
       /* Must arrange to initialize each element of EXP
         from elements of INIT.  */
       tree itype = init ? TREE_TYPE (init) : NULL_TREE;
-      if (TYPE_READONLY (TREE_TYPE (type)) || TYPE_VOLATILE (TREE_TYPE (type)))
+      if (CP_TYPE_QUALS (type) != TYPE_UNQUALIFIED)
        {
          TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
          if (init)
@@ -1217,7 +1081,8 @@ expand_aggr_init (exp, init, alias_this, flags)
          return;
        }
       expand_vec_init (exp, exp, array_type_nelts (type), init,
-                      init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));
+                      init && same_type_p (TREE_TYPE (init),
+                                           TREE_TYPE (exp)));
       TREE_READONLY (exp) = was_const;
       TREE_THIS_VOLATILE (exp) = was_volatile;
       TREE_TYPE (exp) = type;
@@ -1241,18 +1106,17 @@ expand_aggr_init (exp, init, alias_this, flags)
 
   TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
   expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
-                     init, alias_this, LOOKUP_NORMAL|flags);
+                     init, LOOKUP_NORMAL|flags);
   TREE_TYPE (exp) = type;
   TREE_READONLY (exp) = was_const;
   TREE_THIS_VOLATILE (exp) = was_volatile;
 }
 
 static void
-expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
+expand_default_init (binfo, true_exp, exp, init, flags)
      tree binfo;
      tree true_exp, exp;
      tree init;
-     int alias_this;
      int flags;
 {
   tree type = TREE_TYPE (exp);
@@ -1266,24 +1130,33 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
   tree rval;
   tree parms;
 
-  if (flag_ansi_overloading && init && TREE_CODE (init) != TREE_LIST
+  if (init && TREE_CODE (init) != TREE_LIST
       && (flags & LOOKUP_ONLYCONVERTING))
     {
       /* Base subobjects should only get direct-initialization.  */
       if (true_exp != exp)
        abort ();
 
-      /* We special-case TARGET_EXPRs here to avoid an error about
-        private copy constructors for temporaries bound to reference vars.
-        If the TARGET_EXPR represents a call to a function that has
-        permission to create such objects, a reference can bind directly
-        to the return value.  An object variable must be initialized
-        via the copy constructor, even if the call is elided.  */
-      if (! (TREE_CODE (exp) == VAR_DECL && DECL_ARTIFICIAL (exp)
-            && TREE_CODE (init) == TARGET_EXPR && TREE_TYPE (init) == type))
-       init = cp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
-
-      expand_assignment (exp, init, 0, 0);
+      if (flags & DIRECT_BIND)
+       /* Do nothing.  We hit this in two cases:  Reference initialization,
+          where we aren't initializing a real variable, so we don't want
+          to run a new constructor; and catching an exception, where we
+          have already built up the constructor call so we could wrap it
+          in an exception region.  */;
+      else
+       init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
+
+      if (TREE_CODE (init) == TRY_CATCH_EXPR)
+       /* We need to protect the initialization of a catch parm
+          with a call to terminate(), which shows up as a TRY_CATCH_EXPR
+          around the TARGET_EXPR for the copy constructor.  See
+          expand_start_catch_block.  */
+       TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp,
+                                       TREE_OPERAND (init, 0));
+      else
+       init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);
+      TREE_SIDE_EFFECTS (init) = 1;
+      expand_expr_stmt (init);
       return;
     }
 
@@ -1294,73 +1167,22 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
       if (parms)
        init = TREE_VALUE (parms);
     }
-  else if (! flag_ansi_overloading
-          && TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)
-          && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
-    {
-      rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
-      TREE_USED (rval) = 1;
-      expand_expr_stmt (rval);
-      return;
-    }
   else
-    parms = build_tree_list (NULL_TREE, init);
+    parms = build_expr_list (NULL_TREE, init);
 
   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
     {
       if (true_exp == exp)
-       parms = tree_cons (NULL_TREE, integer_one_node, parms);
+       parms = expr_tree_cons (NULL_TREE, integer_one_node, parms);
       else
-       parms = tree_cons (NULL_TREE, integer_zero_node, parms);
+       parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms);
       flags |= LOOKUP_HAS_IN_CHARGE;
     }
 
-  if (flag_ansi_overloading)
-    {
-      rval = build_method_call (exp, ctor_identifier,
-                               parms, binfo, flags);
-      expand_expr_stmt (rval);
-      return;
-    }
-
-  if (init && TREE_CHAIN (parms) == NULL_TREE
-      && TYPE_HAS_TRIVIAL_INIT_REF (type)
-      && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
-    {
-      rval = build (INIT_EXPR, type, exp, init);
-      TREE_SIDE_EFFECTS (rval) = 1;
-      expand_expr_stmt (rval);
-    }
-  else
-    {
-      if (flags & LOOKUP_ONLYCONVERTING)
-       flags |= LOOKUP_NO_CONVERSION;
-      rval = build_method_call (exp, ctor_identifier,
-                               parms, binfo, flags);
-
-      /* Private, protected, or otherwise unavailable.  */
-      if (rval == error_mark_node)
-       {
-         if (flags & LOOKUP_COMPLAIN)
-           cp_error ("in base initialization for %sclass `%T'",
-                     TREE_VIA_VIRTUAL (binfo) ? "virtual base " : "",
-                     binfo);
-       }
-      else if (rval == NULL_TREE)
-       my_friendly_abort (361);
-      else
-       {
-         /* p. 222: if the base class assigns to `this', then that
-            value is used in the derived class.  */
-         if ((flag_this_is_variable & 1) && alias_this)
-           {
-             TREE_TYPE (rval) = TREE_TYPE (current_class_ptr);
-             expand_assignment (current_class_ptr, rval, 0, 0);
-           }
-         else
-           expand_expr_stmt (rval);
-       }
-    }
+  rval = build_method_call (exp, ctor_identifier,
+                           parms, binfo, flags);
+  if (TREE_SIDE_EFFECTS (rval))
+    expand_expr_stmt (rval);
 }
 
 /* This function is responsible for initializing EXP with INIT
@@ -1386,15 +1208,13 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
    its description.  */
 
 static void
-expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
+expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
      tree binfo;
      tree true_exp, exp;
      tree init;
-     int alias_this;
      int flags;
 {
   tree type = TREE_TYPE (exp);
-  tree init_type = NULL_TREE;
 
   my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
 
@@ -1420,174 +1240,9 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
       return;
     }
 
-  if (init && ! flag_ansi_overloading)
-    {
-      tree init_list = NULL_TREE;
-
-      if (TREE_CODE (init) == TREE_LIST)
-       {
-         init_list = init;
-         if (TREE_CHAIN (init) == NULL_TREE)
-           init = TREE_VALUE (init);
-       }
-
-      init_type = TREE_TYPE (init);
-
-      if (TREE_CODE (init) != TREE_LIST)
-       {
-         if (TREE_CODE (init_type) == ERROR_MARK)
-           return;
-
-         /* This happens when we use C++'s functional cast notation.
-            If the types match, then just use the TARGET_EXPR
-            directly.  Otherwise, we need to create the initializer
-            separately from the object being initialized.  */
-         if (TREE_CODE (init) == TARGET_EXPR)
-           {
-             if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type))
-               {
-                 if (TREE_CODE (exp) == VAR_DECL
-                     || TREE_CODE (exp) == RESULT_DECL)
-                   /* Unify the initialization targets.  */
-                   DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);
-                 else
-                   DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, VOIDmode, 0);
-
-                 expand_expr_stmt (init);
-                 return;
-               }
-           }
-
-         if (init_type == type && TREE_CODE (init) == CALL_EXPR)
-           {
-             /* A CALL_EXPR is a legitimate form of initialization, so
-                we should not print this warning message.  */
-
-             expand_assignment (exp, init, 0, 0);
-             if (exp == DECL_RESULT (current_function_decl))
-               {
-                 /* Failing this assertion means that the return value
-                    from receives multiple initializations.  */
-                 my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE
-                                     || DECL_INITIAL (exp) == error_mark_node,
-                                     212);
-                 DECL_INITIAL (exp) = init;
-               }
-             return;
-           }
-         else if (init_type == type
-                  && TREE_CODE (init) == COND_EXPR)
-           {
-             /* Push value to be initialized into the cond, where possible.
-                Avoid spurious warning messages when initializing the
-                result of this function.  */
-             TREE_OPERAND (init, 1)
-               = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1));
-             if (exp == DECL_RESULT (current_function_decl))
-               DECL_INITIAL (exp) = NULL_TREE;
-             TREE_OPERAND (init, 2)
-               = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2));
-             if (exp == DECL_RESULT (current_function_decl))
-               DECL_INITIAL (exp) = init;
-             TREE_SIDE_EFFECTS (init) = 1;
-             expand_expr (init, const0_rtx, VOIDmode, 0);
-             free_temp_slots ();
-             return;
-           }
-       }
-
-      /* We did not know what we were initializing before.  Now we do.  */
-      if (TREE_CODE (init) == TARGET_EXPR)
-       {
-         tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);
-
-         if (tmp && TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR
-             && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node)
-           {
-             /* In order for this to work for RESULT_DECLs, if their
-                type has a constructor, then they must be BLKmode
-                so that they will be meaningfully addressable.  */
-             tree arg = build_unary_op (ADDR_EXPR, exp, 0);
-             init = TREE_OPERAND (init, 1);
-             init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),
-                           TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), NULL_TREE);
-             TREE_SIDE_EFFECTS (init) = 1;
-             TREE_VALUE (TREE_OPERAND (init, 1))
-               = convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
-
-             if (alias_this)
-               {
-                 expand_assignment (current_function_decl, init, 0, 0);
-                 return;
-               }
-             if (exp == DECL_RESULT (current_function_decl))
-               {
-                 if (DECL_INITIAL (DECL_RESULT (current_function_decl)))
-                   fatal ("return value from function receives multiple initializations");
-                 DECL_INITIAL (exp) = init;
-               }
-             expand_expr_stmt (init);
-             return;
-           }
-       }
-
-      /* Handle this case: when calling a constructor: xyzzy foo(bar);
-        which really means:  xyzzy foo = bar; Ugh!
-
-        More useful for this case: xyzzy *foo = new xyzzy (bar);  */
-
-      if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type))
-       {
-         if (init_list && TREE_CHAIN (init_list))
-           {
-             warning ("initializer list being treated as compound expression");
-             init = convert (type, build_compound_expr (init_list));
-             if (init == error_mark_node)
-               return;
-           }
-
-         expand_assignment (exp, init, 0, 0);
-
-         return;
-       }
-
-      /* If this is copy-initialization, see whether we can go through a
-        type conversion operator.  */
-      if (TREE_CODE (init) != TREE_LIST && (flags & LOOKUP_ONLYCONVERTING))
-       {
-         tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE
-           ? TREE_TYPE (init_type) : init_type;
-
-         if (ttype != type && IS_AGGR_TYPE (ttype))
-           {
-             tree rval = build_type_conversion (CONVERT_EXPR, type, init, 1);
-
-             if (rval)
-               {
-                 /* See if there is a constructor for``type'' that takes a
-                    ``ttype''-typed object.  */
-                 tree parms = build_tree_list (NULL_TREE, init);
-                 tree as_cons = NULL_TREE;
-                 if (TYPE_HAS_CONSTRUCTOR (type))
-                   as_cons = build_method_call (exp, ctor_identifier,
-                                                parms, binfo,
-                                                LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION);
-                 if (as_cons != NULL_TREE && as_cons != error_mark_node)
-                   /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
-                   cp_error ("ambiguity between conversion to `%T' and constructor",
-                             type);
-                 else
-                   if (rval != error_mark_node)
-                     expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags);
-                 return;
-               }
-           }
-       }
-    }
-
   /* We know that expand_default_init can handle everything we want
      at this point.  */
-  expand_default_init (binfo, true_exp, exp, init, alias_this, flags);
+  expand_default_init (binfo, true_exp, exp, init, flags);
 }
 
 /* Report an error if NAME is not the name of a user-defined,
@@ -1613,7 +1268,8 @@ is_aggr_typedef (name, or_else)
     }
 
   if (! IS_AGGR_TYPE (type)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
+      && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
     {
       if (or_else)
        cp_error ("`%T' is not an aggregate type", type);
@@ -1634,7 +1290,8 @@ is_aggr_type (type, or_else)
     return 0;
 
   if (! IS_AGGR_TYPE (type)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
+      && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
     {
       if (or_else)
        cp_error ("`%T' is not an aggregate type", type);
@@ -1665,7 +1322,8 @@ get_aggr_from_typedef (name, or_else)
     }
 
   if (! IS_AGGR_TYPE (type)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
+      && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
     {
       if (or_else)
        cp_error ("type `%T' is of non-aggregate type", type);
@@ -1699,11 +1357,35 @@ build_member_call (type, name, parmlist)
      tree type, name, parmlist;
 {
   tree t;
-  tree method_name = name;
+  tree method_name;
   int dtor = 0;
-  int dont_use_this = 0;
   tree basetype_path, decl;
 
+  if (TREE_CODE (name) == TEMPLATE_ID_EXPR
+      && TREE_CODE (type) == NAMESPACE_DECL)
+    {
+      /* 'name' already refers to the decls from the namespace, since we
+        hit do_identifier for template_ids.  */
+      my_friendly_assert (is_overloaded_fn (TREE_OPERAND (name, 0)), 980519);
+      return build_x_function_call (name, parmlist, current_class_ref);
+    }
+
+  if (type == 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);
+
+  if (TREE_CODE (name) != TEMPLATE_ID_EXPR)
+    method_name = name;
+  else
+    {
+      method_name = TREE_OPERAND (name, 0);
+      if (is_overloaded_fn (method_name))
+       method_name = DECL_NAME (OVL_CURRENT (method_name));
+    }
+
   if (TREE_CODE (method_name) == BIT_NOT_EXPR)
     {
       method_name = TREE_OPERAND (method_name, 0);
@@ -1736,43 +1418,33 @@ build_member_call (type, name, parmlist)
       return error_mark_node;
     }
 
-  /* No object?  Then just fake one up, and let build_method_call
-     figure out what to do.  */
-  if (current_class_type == 0
-      || get_base_distance (type, current_class_type, 0, &basetype_path) == -1)
-    dont_use_this = 1;
+  decl = maybe_dummy_object (type, &basetype_path);
 
-  if (dont_use_this)
-    {
-      basetype_path = TYPE_BINFO (type);
-      decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
-    }
-  else if (current_class_ptr == 0)
-    {
-      dont_use_this = 1;
-      decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
-    }
-  else
+  /* Convert 'this' to the specified type to disambiguate conversion
+     to the function's context.  Apparently Standard C++ says that we
+     shouldn't do this.  */
+  if (decl == current_class_ref
+      && ! pedantic
+      && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
     {
       tree olddecl = current_class_ptr;
       tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
       if (oldtype != type)
        {
-         tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
-                                            TYPE_VOLATILE (oldtype));
+         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);
        }
-      else
-       decl = olddecl;
     }
 
-  decl = build_indirect_ref (decl, NULL_PTR);
-
   if (method_name == constructor_name (type)
       || method_name == constructor_name_full (type))
     return build_functional_cast (type, parmlist);
-  if (t = lookup_fnfields (basetype_path, method_name, 0))
-    return build_method_call (decl, method_name, parmlist, basetype_path,
+  if ((t = lookup_fnfields (basetype_path, method_name, 0)))
+    return build_method_call (decl, 
+                             TREE_CODE (name) == TEMPLATE_ID_EXPR
+                             ? name : method_name,
+                             parmlist, basetype_path,
                              LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
   if (TREE_CODE (name) == IDENTIFIER_NODE
       && ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))
@@ -1781,7 +1453,7 @@ build_member_call (type, name, parmlist)
        return error_mark_node;
       if (TREE_CODE (t) == FIELD_DECL)
        {
-         if (dont_use_this)
+         if (is_dummy_object (decl))
            {
              cp_error ("invalid use of non-static field `%D'", t);
              return error_mark_node;
@@ -1795,9 +1467,9 @@ build_member_call (type, name, parmlist)
          cp_error ("invalid use of member `%D'", t);
          return error_mark_node;
        }
-      if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl))
-         && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (decl)))
-       return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, parmlist, NULL_TREE);
+      if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
+       return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl,
+                              parmlist, NULL_TREE);
       return build_function_call (decl, parmlist);
     }
   else
@@ -1821,139 +1493,135 @@ tree
 build_offset_ref (type, name)
      tree type, name;
 {
-  tree decl, fnfields, fields, t = error_mark_node;
+  tree decl, t = error_mark_node;
+  tree member;
   tree basebinfo = NULL_TREE;
-  int dtor = 0;
+  tree orig_name = name;
 
-  if (processing_template_decl)
+  /* class templates can come in as TEMPLATE_DECLs here.  */
+  if (TREE_CODE (name) == TEMPLATE_DECL)
+    return name;
+
+  if (type == std_node)
+    return do_scoped_id (name, 0);
+
+  if (processing_template_decl || uses_template_parms (type))
     return build_min_nt (SCOPE_REF, type, name);
 
   /* Handle namespace names fully here.  */
-  if (TREE_CODE (type) == IDENTIFIER_NODE
-      && get_aggr_from_typedef (type, 0) == 0)
+  if (TREE_CODE (type) == NAMESPACE_DECL)
     {
-      tree ns = lookup_name (type, 0);
-      tree val;
-      if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
+      t = lookup_namespace_name (type, name);
+      if (t != error_mark_node && ! type_unknown_p (t))
        {
-         val = lookup_namespace_name (ns, name);
-         if (val)
-           return val;
-         cp_error ("namespace `%D' has no member named `%D'", ns, name);
-         return error_mark_node;
+         mark_used (t);
+         t = convert_from_reference (t);
        }
+      return t;
     }
 
   if (type == NULL_TREE || ! is_aggr_type (type, 1))
     return error_mark_node;
 
-  if (TREE_CODE (name) == BIT_NOT_EXPR)
+  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
     {
-      dtor = 1;
-      name = TREE_OPERAND (name, 0);
-    }
+      /* If the NAME is a TEMPLATE_ID_EXPR, we are looking at
+        something like `a.template f<int>' or the like.  For the most
+        part, we treat this just like a.f.  We do remember, however,
+        the template-id that was used.  */
+      name = TREE_OPERAND (orig_name, 0);
+
+      if (TREE_CODE (name) == LOOKUP_EXPR)
+       /* This can happen during tsubst'ing.  */
+       name = TREE_OPERAND (name, 0);
 
-  if (name == constructor_name_full (type))
-    name = constructor_name (type);
+      my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
+    }
 
-  if (TYPE_SIZE (complete_type (type)) == 0)
+  if (TREE_CODE (name) == BIT_NOT_EXPR)
     {
-      if (type == current_class_type)
-       t = IDENTIFIER_CLASS_VALUE (name);
-      else
-       t = NULL_TREE;
-      if (t == 0)
-       {
-         cp_error ("incomplete type `%T' does not have member `%D'", type,
-                     name);
-         return error_mark_node;
-       }
-      if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL
-         || TREE_CODE (t) == CONST_DECL)
-       {
-         mark_used (t);
-         return t;
-       }
-      if (TREE_CODE (t) == FIELD_DECL)
-       sorry ("use of member in incomplete aggregate type");
-      else if (TREE_CODE (t) == FUNCTION_DECL)
-       sorry ("use of member function in incomplete aggregate type");
-      else
-       my_friendly_abort (52);
-      return error_mark_node;
+      if (! check_dtor_name (type, name))
+       cp_error ("qualified type `%T' does not match destructor name `~%T'",
+                 type, TREE_OPERAND (name, 0));
+      name = dtor_identifier;
     }
+#if 0
+  /* I think this is wrong, but the draft is unclear.  --jason 6/15/98 */
+  else if (name == constructor_name_full (type)
+          || name == constructor_name (type))
+    name = ctor_identifier;
+#endif
 
-  if (current_class_type == 0
-      || get_base_distance (type, current_class_type, 0, &basebinfo) == -1)
+  if (TYPE_SIZE (complete_type (type)) == 0
+      && !TYPE_BEING_DEFINED (type))
     {
-      basebinfo = TYPE_BINFO (type);
-      decl = build1 (NOP_EXPR, type, error_mark_node);
+      cp_error ("incomplete type `%T' does not have member `%D'", type,
+               name);
+      return error_mark_node;
     }
-  else if (current_class_ptr == 0)
-    decl = build1 (NOP_EXPR, type, error_mark_node);
-  else
-    decl = current_class_ref;
 
-  if (constructor_name (BINFO_TYPE (basebinfo)) == name)
-    if (dtor)
-      name = dtor_identifier;
-    else
-      name = ctor_identifier;
-  else
-    if (dtor)
-      my_friendly_abort (999);
+  decl = maybe_dummy_object (type, &basebinfo);
 
-    
-  fnfields = lookup_fnfields (basebinfo, name, 1);
-  fields = lookup_field (basebinfo, name, 0, 0);
+  member = lookup_member (basebinfo, name, 1, 0);
 
-  if (fields == error_mark_node || fnfields == error_mark_node)
+  if (member == error_mark_node)
     return error_mark_node;
 
   /* A lot of this logic is now handled in lookup_field and
      lookup_fnfield.  */
-  if (fnfields)
+  if (member && TREE_CODE (member) == TREE_LIST)
     {
-      extern int flag_save_memoized_contexts;
-      basebinfo = TREE_PURPOSE (fnfields);
-
       /* Go from the TREE_BASELINK to the member function info.  */
+      tree fnfields = member;
       t = TREE_VALUE (fnfields);
 
-      if (DECL_CHAIN (t) == NULL_TREE)
+      if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
+       {
+         /* The FNFIELDS are going to contain functions that aren't
+            necessarily templates, and templates that don't
+            necessarily match the explicit template parameters.  We
+            save all the functions, and the explicit parameters, and
+            then figure out exactly what to instantiate with what
+            arguments in instantiate_type.  */
+
+         if (TREE_CODE (t) != OVERLOAD)
+           /* 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, 
+                       build_offset_type (type, unknown_type_node),
+                       decl,
+                       build (TEMPLATE_ID_EXPR, 
+                              TREE_TYPE (t),
+                              t,
+                              TREE_OPERAND (orig_name, 1)));
+       }
+
+      if (!really_overloaded_fn (t))
        {
-         tree access;
+         /* Get rid of a potential OVERLOAD around it */
+         t = OVL_CURRENT (t);
 
          /* unique functions are handled easily.  */
-       unique:
-         access = compute_access (basebinfo, t);
-         if (access == access_protected_node)
-           {
-             cp_error_at ("member function `%#D' is protected", t);
-             error ("in this context");
-             return error_mark_node;
-           }
-         if (access == access_private_node)
-           {
-             cp_error_at ("member function `%#D' is private", t);
-             error ("in this context");
-             return error_mark_node;
-           }
+         basebinfo = TREE_PURPOSE (fnfields);
+         if (!enforce_access (basebinfo, t))
+           return error_mark_node;
          mark_used (t);
+         if (DECL_STATIC_FUNCTION_P (t))
+           return t;
          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 (either for memoization
-        or for use as an initializer for a static variable), then
-        do so here.
+        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)
-         && ((flag_save_memoized_contexts && global_bindings_p ())
-             || ! allocation_temporary_p ()))
+         && ! allocation_temporary_p ())
        fnfields = copy_list (fnfields);
 
       t = build_tree_list (error_mark_node, fnfields);
@@ -1961,14 +1629,7 @@ build_offset_ref (type, name)
       return t;
     }
 
-  /* Now that we know we are looking for a field, see if we
-     have access to that field.  Lookup_field will give us the
-     error message.  */
-
-  t = lookup_field (basebinfo, name, 1, 0);
-
-  if (t == error_mark_node)
-    return error_mark_node;
+  t = member;
 
   if (t == NULL_TREE)
     {
@@ -1986,10 +1647,10 @@ build_offset_ref (type, name)
   if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
     {
       mark_used (t);
-      return t;
+      return convert_from_reference (t);
     }
 
-  if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t))
+  if (TREE_CODE (t) == FIELD_DECL && DECL_C_BIT_FIELD (t))
     {
       cp_error ("illegal pointer to bit field `%D'", t);
       return error_mark_node;
@@ -2019,7 +1680,10 @@ resolve_offset_ref (exp)
   tree basetype, addr;
 
   if (TREE_CODE (exp) == TREE_LIST)
-    return build_unary_op (ADDR_EXPR, exp, 0);
+    {
+      cp_pedwarn ("assuming & on overloaded member function");
+      return build_unary_op (ADDR_EXPR, exp, 0);
+    }
 
   if (TREE_CODE (exp) == OFFSET_REF)
     {
@@ -2040,7 +1704,8 @@ resolve_offset_ref (exp)
     }
 
   if ((TREE_CODE (member) == VAR_DECL
-       && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member)))
+       && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member))
+       && ! TYPE_PTRMEM_P (TREE_TYPE (member)))
       || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE
       || TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
     {
@@ -2070,11 +1735,10 @@ resolve_offset_ref (exp)
 
   /* The first case is really just a reference to a member of `this'.  */
   if (TREE_CODE (member) == FIELD_DECL
-      && (base == current_class_ref
-         || (TREE_CODE (base) == NOP_EXPR
-             && TREE_OPERAND (base, 0) == error_mark_node)))
+      && (base == current_class_ref || is_dummy_object (base)))
     {
-      tree basetype_path, access;
+      tree basetype_path;
+      tree expr;
 
       if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
        basetype = TYPE_OFFSET_BASETYPE (type);
@@ -2088,40 +1752,30 @@ resolve_offset_ref (exp)
          error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base)));
          return error_mark_node;
        }
+      /* Kludge: we need to use basetype_path now, because
+        convert_pointer_to will bash it.  */
+      enforce_access (basetype_path, member);
       addr = convert_pointer_to (basetype, base);
-      access = compute_access (basetype_path, member);
-      if (access == access_public_node)
-       return build (COMPONENT_REF, TREE_TYPE (member),
-                     build_indirect_ref (addr, NULL_PTR), member);
-      if (access == access_protected_node)
-       {
-         cp_error_at ("member `%D' is protected", member);
-         error ("in this context");
-         return error_mark_node;
-       }
-      if (access == access_private_node)
-       {
-         cp_error_at ("member `%D' is private", member);
-         error ("in this context");
-         return error_mark_node;
-       }
-      my_friendly_abort (55);
+
+      /* Even in the case of illegal access, we form the
+        COMPONENT_REF; that will allow better error recovery than
+        just feeding back error_mark_node.  */
+      expr = build (COMPONENT_REF, TREE_TYPE (member),
+                   build_indirect_ref (addr, NULL_PTR), member);
+      return convert_from_reference (expr);
     }
 
   /* Ensure that we have an object.  */
-  if (TREE_CODE (base) == NOP_EXPR
-      && TREE_OPERAND (base, 0) == error_mark_node)
+  if (is_dummy_object (base))
     addr = error_mark_node;
   else
-    {
-      /* If this is a reference to a member function, then return the
-        address of the member function (which may involve going
-        through the object's vtable), otherwise, return an expression
-        for the dereferenced pointer-to-member construct.  */
-      addr = build_unary_op (ADDR_EXPR, base, 0);
-    }
+    /* If this is a reference to a member function, then return the
+       address of the member function (which may involve going
+       through the object's vtable), otherwise, return an expression
+       for the dereferenced pointer-to-member construct.  */
+    addr = build_unary_op (ADDR_EXPR, base, 0);
 
-  if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
+  if (TYPE_PTRMEM_P (TREE_TYPE (member)))
     {
       if (addr == error_mark_node)
        {
@@ -2129,16 +1783,15 @@ resolve_offset_ref (exp)
          return error_mark_node;
        }
 
-      basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
+      basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
       addr = convert_pointer_to (basetype, addr);
-      member = convert (ptrdiff_type_node,
-                       build_unary_op (ADDR_EXPR, member, 0));
+      member = cp_convert (ptrdiff_type_node, member);
       
-      /* Pointer to data mebers are offset by one, so that a null
+      /* 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 = build_binary_op (MINUS_EXPR, member,
-                               convert (ptrdiff_type_node, integer_one_node),
+                               cp_convert (ptrdiff_type_node, integer_one_node),
                                0);
 
       return build1 (INDIRECT_REF, type,
@@ -2161,444 +1814,29 @@ decl_constant_value (decl)
      tree decl;
 {
   if (! TREE_THIS_VOLATILE (decl)
-#if 0
-      /* These may be necessary for C, but they break C++.  */
-      ! TREE_PUBLIC (decl)
-      /* Don't change a variable array bound or initial value to a constant
-        in a place where a variable is invalid.  */
-      && ! pedantic
-#endif /* 0 */
-      && DECL_INITIAL (decl) != 0
-      && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
+      && DECL_INITIAL (decl)
+      && DECL_INITIAL (decl) != error_mark_node
       /* This is invalid if initial value is not constant.
         If it has either a function call, a memory reference,
         or a variable, then re-evaluating it could give different results.  */
       && TREE_CONSTANT (DECL_INITIAL (decl))
       /* Check for cases where this is sub-optimal, even though valid.  */
-      && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
-#if 0
-      /* We must allow this to work outside of functions so that
-        static constants can be used for array sizes.  */
-      && current_function_decl != 0
-      && DECL_MODE (decl) != BLKmode
-#endif
-      )
+      && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
     return DECL_INITIAL (decl);
   return decl;
 }
 \f
-/* Friend handling routines.  */
-/* Friend data structures:
-
-   Lists of friend functions come from TYPE_DECL nodes.  Since all
-   aggregate types are automatically typedef'd, these nodes are guaranteed
-   to exist.
-
-   The TREE_PURPOSE of a friend list is the name of the friend,
-   and its TREE_VALUE is another list.
-
-   For each element of that list, either the TREE_VALUE or the TREE_PURPOSE
-   will be filled in, but not both.  The TREE_VALUE of that list is an
-   individual function which is a friend.  The TREE_PURPOSE of that list
-   indicates a type in which all functions by that name are friends.
-
-   Lists of friend classes come from _TYPE nodes.  Love that consistency
-   thang.  */
-
-int
-is_friend_type (type1, type2)
-     tree type1, type2;
-{
-  return is_friend (type1, type2);
-}
-
-int
-is_friend (type, supplicant)
-     tree type, supplicant;
-{
-  int declp;
-  register tree list;
-
-  if (supplicant == NULL_TREE || type == NULL_TREE)
-    return 0;
-
-  declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd');
-
-  if (declp)
-    /* It's a function decl.  */
-    {
-      tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
-      tree name = DECL_NAME (supplicant);
-      tree ctype;
-
-      if (DECL_FUNCTION_MEMBER_P (supplicant))
-       ctype = DECL_CLASS_CONTEXT (supplicant);
-      else
-       ctype = NULL_TREE;
-
-      for (; list ; list = TREE_CHAIN (list))
-       {
-         if (name == TREE_PURPOSE (list))
-           {
-             tree friends = TREE_VALUE (list);
-             for (; friends ; friends = TREE_CHAIN (friends))
-               {
-                 if (ctype == TREE_PURPOSE (friends))
-                   return 1;
-                 if (comptypes (TREE_TYPE (supplicant),
-                                TREE_TYPE (TREE_VALUE (friends)), 1))
-                   return 1;
-               }
-             break;
-           }
-       }
-    }
-  else
-    /* It's a type.  */
-    {
-      if (type == supplicant)
-       return 1;
-      
-      list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
-      for (; list ; list = TREE_CHAIN (list))
-       if (supplicant == TREE_VALUE (list))
-         return 1;
-    }      
-
-  {
-    tree context;
-
-    if (! declp)
-      {
-       /* Are we a nested or local class?  If so, we aren't friends
-           with the CONTEXT.  */
-       if (IS_AGGR_TYPE (supplicant))
-         context = NULL_TREE;
-       else
-         context = DECL_CONTEXT (TYPE_MAIN_DECL (supplicant));
-      }
-    else if (DECL_FUNCTION_MEMBER_P (supplicant))
-      context = DECL_CLASS_CONTEXT (supplicant);
-    else
-      context = NULL_TREE;
-
-    if (context)
-      return is_friend (type, context);
-  }
-
-  return 0;
-}
-
-/* Add a new friend to the friends of the aggregate type TYPE.
-   DECL is the FUNCTION_DECL of the friend being added.  */
-
-static void
-add_friend (type, decl)
-     tree type, decl;
-{
-  tree typedecl = TYPE_MAIN_DECL (type);
-  tree list = DECL_FRIENDLIST (typedecl);
-  tree name = DECL_NAME (decl);
-
-  while (list)
-    {
-      if (name == TREE_PURPOSE (list))
-       {
-         tree friends = TREE_VALUE (list);
-         for (; friends ; friends = TREE_CHAIN (friends))
-           {
-             if (decl == TREE_VALUE (friends))
-               {
-                 cp_warning ("`%D' is already a friend of class `%T'",
-                             decl, type);
-                 cp_warning_at ("previous friend declaration of `%D'",
-                                TREE_VALUE (friends));
-                 return;
-               }
-           }
-         TREE_VALUE (list) = tree_cons (error_mark_node, decl,
-                                        TREE_VALUE (list));
-         return;
-       }
-      list = TREE_CHAIN (list);
-    }
-  DECL_FRIENDLIST (typedecl)
-    = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
-                DECL_FRIENDLIST (typedecl));
-  if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
-    {
-      tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
-      TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
-      if (parmtypes && TREE_CHAIN (parmtypes))
-       {
-         tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
-         if (TREE_CODE (parmtype) == REFERENCE_TYPE
-             && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
-           TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
-       }
-    }
-}
-
-/* Declare that every member function NAME in FRIEND_TYPE
-   (which may be NULL_TREE) is a friend of type TYPE.  */
-
-static void
-add_friends (type, name, friend_type)
-     tree type, name, friend_type;
-{
-  tree typedecl = TYPE_MAIN_DECL (type);
-  tree list = DECL_FRIENDLIST (typedecl);
-
-  while (list)
-    {
-      if (name == TREE_PURPOSE (list))
-       {
-         tree friends = TREE_VALUE (list);
-         while (friends && TREE_PURPOSE (friends) != friend_type)
-           friends = TREE_CHAIN (friends);
-         if (friends)
-           if (friend_type)
-             warning ("method `%s::%s' is already a friend of class",
-                      TYPE_NAME_STRING (friend_type),
-                      IDENTIFIER_POINTER (name));
-           else
-             warning ("function `%s' is already a friend of class `%s'",
-                      IDENTIFIER_POINTER (name),
-                      IDENTIFIER_POINTER (DECL_NAME (typedecl)));
-         else
-           TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE,
-                                          TREE_VALUE (list));
-         return;
-       }
-      list = TREE_CHAIN (list);
-    }
-  DECL_FRIENDLIST (typedecl) =
-    tree_cons (name,
-              build_tree_list (friend_type, NULL_TREE),
-              DECL_FRIENDLIST (typedecl));
-  if (! strncmp (IDENTIFIER_POINTER (name),
-                IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]),
-                strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]))))
-    {
-      TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
-      sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
-    }
-}
-
-/* Make FRIEND_TYPE a friend class to TYPE.  If FRIEND_TYPE has already
-   been defined, we make all of its member functions friends of
-   TYPE.  If not, we make it a pending friend, which can later be added
-   when its definition is seen.  If a type is defined, then its TYPE_DECL's
-   DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
-   classes that are not defined.  If a type has not yet been defined,
-   then the DECL_WAITING_FRIENDS contains a list of types
-   waiting to make it their friend.  Note that these two can both
-   be in use at the same time!  */
-
-void
-make_friend_class (type, friend_type)
-     tree type, friend_type;
-{
-  tree classes;
-
-  if (IS_SIGNATURE (type))
-    {
-      error ("`friend' declaration in signature definition");
-      return;
-    }
-  if (IS_SIGNATURE (friend_type))
-    {
-      error ("signature type `%s' declared `friend'",
-            IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type)));
-      return;
-    }
-  if (type == friend_type)
-    {
-      pedwarn ("class `%s' is implicitly friends with itself",
-              TYPE_NAME_STRING (type));
-      return;
-    }
-
-  GNU_xref_hier (TYPE_NAME_STRING (type),
-                TYPE_NAME_STRING (friend_type), 0, 0, 1);
-
-  classes = CLASSTYPE_FRIEND_CLASSES (type);
-  while (classes && TREE_VALUE (classes) != friend_type)
-    classes = TREE_CHAIN (classes);
-  if (classes)
-    warning ("class `%s' is already friends with class `%s'",
-            TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type));
-  else
-    {
-      CLASSTYPE_FRIEND_CLASSES (type)
-       = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
-    }
-}
-
-/* Main friend processor.  This is large, and for modularity purposes,
-   has been removed from grokdeclarator.  It returns `void_type_node'
-   to indicate that something happened, though a FIELD_DECL is
-   not returned.
-
-   CTYPE is the class this friend belongs to.
-
-   DECLARATOR is the name of the friend.
-
-   DECL is the FUNCTION_DECL that the friend is.
-
-   In case we are parsing a friend which is part of an inline
-   definition, we will need to store PARM_DECL chain that comes
-   with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
-
-   FLAGS is just used for `grokclassfn'.
-
-   QUALS say what special qualifies should apply to the object
-   pointed to by `this'.  */
-
-tree
-do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
-     tree ctype, declarator, decl, parmdecls;
-     enum overload_flags flags;
-     tree quals;
-     int funcdef_flag;
-{
-  /* Every decl that gets here is a friend of something.  */
-  DECL_FRIEND_P (decl) = 1;
-
-  if (ctype)
-    {
-      tree cname = TYPE_NAME (ctype);
-      if (TREE_CODE (cname) == TYPE_DECL)
-       cname = DECL_NAME (cname);
-
-      /* A method friend.  */
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-       {
-         if (flags == NO_SPECIAL && ctype && declarator == cname)
-           DECL_CONSTRUCTOR_P (decl) = 1;
-
-         /* This will set up DECL_ARGUMENTS for us.  */
-         grokclassfn (ctype, cname, decl, flags, quals);
-         if (TYPE_SIZE (ctype) != 0)
-           decl = check_classfn (ctype, decl);
-
-         if (TREE_TYPE (decl) != error_mark_node)
-           {
-             if (TYPE_SIZE (ctype))
-               add_friend (current_class_type, decl);
-             else
-               {
-                 cp_error ("member `%D' declared as friend before type `%T' defined",
-                           decl, ctype);
-               }
-           }
-       }
-      else
-       {
-         /* Possibly a bunch of method friends.  */
-
-         /* Get the class they belong to.  */
-         tree ctype = IDENTIFIER_TYPE_VALUE (cname);
-         tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0);
-
-         if (fields)
-           add_friends (current_class_type, declarator, ctype);
-         else
-           error ("method `%s' is not a member of class `%s'",
-                  IDENTIFIER_POINTER (declarator),
-                  IDENTIFIER_POINTER (cname));
-         decl = void_type_node;
-       }
-    }
-  else if (TREE_CODE (decl) == FUNCTION_DECL
-          && ((IDENTIFIER_LENGTH (declarator) == 4
-               && IDENTIFIER_POINTER (declarator)[0] == 'm'
-               && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
-              || (IDENTIFIER_LENGTH (declarator) > 10
-                  && IDENTIFIER_POINTER (declarator)[0] == '_'
-                  && IDENTIFIER_POINTER (declarator)[1] == '_'
-                  && strncmp (IDENTIFIER_POINTER (declarator)+2,
-                              "builtin_", 8) == 0)))
-    {
-      /* raw "main", and builtin functions never gets overloaded,
-        but they can become friends.  */
-      add_friend (current_class_type, decl);
-      DECL_FRIEND_P (decl) = 1;
-      decl = void_type_node;
-    }
-  /* A global friend.
-     @@ or possibly a friend from a base class ?!?  */
-  else if (TREE_CODE (decl) == FUNCTION_DECL)
-    {
-      /* Friends must all go through the overload machinery,
-        even though they may not technically be overloaded.
-
-        Note that because classes all wind up being top-level
-        in their scope, their friend wind up in top-level scope as well.  */
-      DECL_ASSEMBLER_NAME (decl)
-       = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
-                              TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
-      DECL_ARGUMENTS (decl) = parmdecls;
-      if (funcdef_flag)
-       DECL_CLASS_CONTEXT (decl) = current_class_type;
-
-      /* We can call pushdecl here, because the TREE_CHAIN of this
-        FUNCTION_DECL is not needed for other purposes.  */
-      decl = pushdecl (decl);
-
-      make_decl_rtl (decl, NULL_PTR, 1);
-      add_friend (current_class_type, decl);
-
-      DECL_FRIEND_P (decl) = 1;
-    }
-  else
-    {
-      /* @@ Should be able to ingest later definitions of this function
-        before use.  */
-      tree decl = lookup_name_nonclass (declarator);
-      if (decl == NULL_TREE)
-       {
-         warning ("implicitly declaring `%s' as struct",
-                  IDENTIFIER_POINTER (declarator));
-         decl = xref_tag (record_type_node, declarator, NULL_TREE, 1);
-         decl = TYPE_MAIN_DECL (decl);
-       }
-
-      /* Allow abbreviated declarations of overloaded functions,
-        but not if those functions are really class names.  */
-      if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl)))
-       {
-         warning ("`friend %s' archaic, use `friend class %s' instead",
-                  IDENTIFIER_POINTER (declarator),
-                  IDENTIFIER_POINTER (declarator));
-         decl = TREE_TYPE (TREE_PURPOSE (decl));
-       }
-
-      if (TREE_CODE (decl) == TREE_LIST)
-       add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE);
-      else
-       make_friend_class (current_class_type, TREE_TYPE (decl));
-      decl = void_type_node;
-    }
-  return decl;
-}
-\f
 /* Common subroutines of build_new and build_vec_delete.  */
 
-/* Common interface for calling "builtin" functions that are not
-   really builtin.  */
+/* Call the global __builtin_delete to delete ADDR.  */
 
-tree
-build_builtin_call (type, node, arglist)
-     tree type;
-     tree node;
-     tree arglist;
+static tree
+build_builtin_delete_call (addr)
+     tree addr;
 {
-  tree rval = build (CALL_EXPR, type, node, arglist, NULL_TREE);
-  TREE_SIDE_EFFECTS (rval) = 1;
-  assemble_external (TREE_OPERAND (node, 0));
-  TREE_USED (TREE_OPERAND (node, 0)) = 1;
-  return rval;
+  mark_used (global_delete_fndecl);
+  return build_call (global_delete_fndecl, 
+                    void_type_node, build_expr_list (NULL_TREE, addr));
 }
 \f
 /* Generate a C++ "new" expression. DECL is either a TREE_LIST
@@ -2635,12 +1873,9 @@ build_new (placement, decl, init, use_global_new)
      tree decl, init;
      int use_global_new;
 {
-  tree type, true_type, size, rval;
-  tree nelts;
-  tree alloc_expr, alloc_temp;
+  tree type, rval;
+  tree nelts = NULL_TREE, t;
   int has_array = 0;
-  enum tree_code code = NEW_EXPR;
-  int use_cookie;
 
   tree pending_sizes = NULL_TREE;
 
@@ -2651,7 +1886,7 @@ build_new (placement, decl, init, use_global_new)
     {
       tree absdcl = TREE_VALUE (decl);
       tree last_absdcl = NULL_TREE;
-      int old_immediate_size_expand;
+      int old_immediate_size_expand = 0;
 
       if (current_function_decl
          && DECL_CONSTRUCTOR_P (current_function_decl))
@@ -2695,7 +1930,12 @@ build_new (placement, decl, init, use_global_new)
                }
              else
                {
-                 this_nelts = save_expr (convert (sizetype, this_nelts));
+                 int flags = pedantic ? WANT_INT : (WANT_INT | WANT_ENUM);
+                 if (build_expr_type_conversion (flags, this_nelts, 0)
+                     == NULL_TREE)
+                   pedwarn ("size in array new must have integral type");
+
+                 this_nelts = save_expr (cp_convert (sizetype, this_nelts));
                  absdcl = TREE_OPERAND (absdcl, 0);
                  if (this_nelts == integer_zero_node)
                    {
@@ -2715,7 +1955,7 @@ build_new (placement, decl, init, use_global_new)
       else
        TREE_VALUE (decl) = absdcl;
 
-      type = true_type = groktypename (decl);
+      type = groktypename (decl);
       if (! type || type == error_mark_node)
        {
          immediate_size_expand = old_immediate_size_expand;
@@ -2744,23 +1984,19 @@ build_new (placement, decl, init, use_global_new)
          my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 215);
          type = TREE_TYPE (decl);
        }
-      true_type = type;
     }
   else if (TREE_CODE (decl) == TYPE_DECL)
     {
       type = TREE_TYPE (decl);
-      true_type = type;
     }
   else
     {
       type = decl;
-      true_type = type;
       decl = TYPE_MAIN_DECL (type);
     }
 
   if (processing_template_decl)
     {
-      tree t;
       if (has_array)
        t = min_tree_cons (min_tree_cons (NULL_TREE, type, NULL_TREE),
                           build_min_nt (ARRAY_REF, NULL_TREE, nelts),
@@ -2779,7 +2015,7 @@ build_new (placement, decl, init, use_global_new)
   if (TREE_CODE (type) == REFERENCE_TYPE)
     {
       error ("new cannot be applied to a reference type");
-      type = true_type = TREE_TYPE (type);
+      type = TREE_TYPE (type);
     }
 
   if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -2795,10 +2031,100 @@ build_new (placement, decl, init, use_global_new)
     {
       nelts = array_type_nelts_top (type);
       has_array = 1;
-      type = true_type = TREE_TYPE (type);
+      type = TREE_TYPE (type);
     }
 
-  if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
+  if (has_array)
+    t = build_nt (ARRAY_REF, type, nelts);
+  else
+    t = type;
+
+  rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init);
+  NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
+  TREE_SIDE_EFFECTS (rval) = 1;
+
+  /* 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
+build_java_class_ref (type)
+     tree type;
+{
+  tree name, class_decl;
+  static tree CL_prefix = NULL_TREE;
+  if (CL_prefix == NULL_TREE)
+    CL_prefix = get_identifier("_CL_");
+  if (jclass_node == NULL_TREE)
+    {
+      jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier("jclass"));
+      if (jclass_node == NULL_TREE)
+       fatal("call to Java constructor, while `jclass' undefined");
+      jclass_node = TREE_TYPE (jclass_node);
+    }
+  name = build_overload_with_type (CL_prefix, type);
+  class_decl = IDENTIFIER_GLOBAL_VALUE (name);
+  if (class_decl == NULL_TREE)
+    {
+      push_obstacks_nochange ();
+      end_temporary_allocation ();
+      class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
+      TREE_STATIC (class_decl) = 1;
+      DECL_EXTERNAL (class_decl) = 1;
+      TREE_PUBLIC (class_decl) = 1;
+      DECL_ARTIFICIAL (class_decl) = 1;
+      DECL_IGNORED_P (class_decl) = 1;
+      pushdecl_top_level (class_decl);
+      make_decl_rtl (class_decl, NULL_PTR, 1);
+      pop_obstacks ();
+    }
+  return class_decl;
+}
+
+/* Called from cplus_expand_expr when expanding a NEW_EXPR.  The return
+   value is immediately handed to expand_expr.  */
+
+tree
+build_new_1 (exp)
+     tree exp;
+{
+  tree placement, init;
+  tree type, true_type, size, rval;
+  tree nelts = NULL_TREE;
+  tree alloc_expr, alloc_node = NULL_TREE;
+  int has_array = 0;
+  enum tree_code code = NEW_EXPR;
+  int use_cookie, nothrow, check_new;
+  int use_global_new;
+  int use_java_new = 0;
+
+  placement = TREE_OPERAND (exp, 0);
+  type = TREE_OPERAND (exp, 1);
+  init = TREE_OPERAND (exp, 2);
+  use_global_new = NEW_EXPR_USE_GLOBAL (exp);
+
+  if (TREE_CODE (type) == ARRAY_REF)
+    {
+      has_array = 1;
+      nelts = TREE_OPERAND (type, 1);
+      type = TREE_OPERAND (type, 0);
+    }
+  true_type = type;
+
+  if (CP_TYPE_QUALS (type))
     type = TYPE_MAIN_VARIANT (type);
 
   /* If our base type is an array, then make sure we know how many elements
@@ -2810,11 +2136,8 @@ build_new (placement, decl, init, use_global_new)
       true_type = TREE_TYPE (true_type);
     }
 
-  if (TYPE_SIZE (complete_type (true_type)) == 0)
-    {
-      incomplete_type_error (0, true_type);
-      return error_mark_node;
-    }
+  if (!complete_type_or_else (true_type, exp))
+    return error_mark_node;
 
   if (has_array)
     size = fold (build_binary_op (MULT_EXPR, size_in_bytes (true_type),
@@ -2822,7 +2145,7 @@ build_new (placement, decl, init, use_global_new)
   else
     size = size_in_bytes (type);
 
-  if (true_type == void_type_node)
+  if (TREE_CODE (true_type) == VOID_TYPE)
     {
       error ("invalid type `void' for new");
       return error_mark_node;
@@ -2853,10 +2176,7 @@ build_new (placement, decl, init, use_global_new)
      array, if this is either non-placement new or new (nothrow).  */
   
   use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
-               && (! placement
-                   || (IS_AGGR_TYPE (TREE_TYPE (placement))
-                       && (TYPE_IDENTIFIER (TREE_TYPE (placement))
-                           == get_identifier ("nothrow_t")))));
+               && (! placement || nothrow));
 #endif
 
   if (use_cookie)
@@ -2875,18 +2195,9 @@ build_new (placement, decl, init, use_global_new)
     }
 
   /* Allocate the object.  */
-  if (! use_global_new && TYPE_LANG_SPECIFIC (true_type)
-      && (TYPE_GETS_NEW (true_type) & (1 << has_array)))
-    rval = build_opfncall (code, LOOKUP_NORMAL,
-                          build_pointer_type (true_type), size, placement);
-  else if (placement)
-    {
-      rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
-                            ptr_type_node, size, placement);
-      rval = convert (build_pointer_type (true_type), rval);
-    }
-  else if (! has_array && flag_this_is_variable > 0
-          && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
+  
+  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;
@@ -2896,16 +2207,70 @@ build_new (placement, decl, init, use_global_new)
          return error_mark_node;
        }
     }
+  else if (! placement && TYPE_FOR_JAVA (true_type))
+    {
+      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";
+      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);
+      class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
+      rval = build_function_call (alloc_decl,
+                                 tree_cons (NULL_TREE, class_addr,
+                                            build_tree_list (NULL_TREE,
+                                                             class_size)));
+      rval = cp_convert (build_pointer_type (true_type), rval);
+    }
   else
     {
-      rval = build_builtin_call (build_pointer_type (true_type),
-                                has_array ? BIVN : BIN,
-                                build_tree_list (NULL_TREE, size));
-      TREE_CALLS_NEW (rval) = 1;
+      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),
+        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-
+     tion-specification  (_except.spec_),  throw(), it indicates failure to
+     allocate storage by throwing a bad_alloc exception  (clause  _except_,
+     _lib.bad.alloc_); it returns a non-null pointer otherwise If the allo-
+     cation function is declared  with  an  empty  exception-specification,
+     throw(), it returns null to indicate failure to allocate storage and a
+     non-null pointer otherwise.
+
+     So check for a null exception spec on the op new we just called.  */
+
+  nothrow = 0;
+  if (rval)
+    {
+      /* The CALL_EXPR.  */
+      tree t = TREE_OPERAND (rval, 0);
+      /* The function.  */
+      t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+      t = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t));
+
+      if (t && TREE_VALUE (t) == NULL_TREE)
+       nothrow = 1;
     }
+  check_new = (flag_check_new || nothrow) && ! use_java_new;
 
-  if (flag_check_new && rval)
-    alloc_expr = rval = save_expr (rval);
+  if ((check_new || flag_exceptions) && rval)
+    {
+      alloc_expr = get_target_expr (rval);
+      alloc_node = rval = TREE_OPERAND (alloc_expr, 0);
+    }
   else
     alloc_expr = NULL_TREE;
 
@@ -2917,21 +2282,21 @@ build_new (placement, decl, init, use_global_new)
     {
       tree extra = BI_header_size;
       tree cookie, exp1;
-      rval = convert (ptr_type_node, rval);    /* convert to void * first */
-      rval = convert (string_type_node, rval); /* lets not add void* and ints */
+      rval = convert (string_type_node, rval); /* for ptr arithmetic */
       rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1));
       /* Store header info.  */
-      cookie = build_indirect_ref (build (MINUS_EXPR, build_pointer_type (BI_header_type),
+      cookie = build_indirect_ref (build (MINUS_EXPR,
+                                         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, NULL_TREE, 0),
+                   build_component_ref (cookie, nc_nelts_field_id,
+                                        NULL_TREE, 0),
                    nelts);
       TREE_SIDE_EFFECTS (exp1) = 1;
-      rval = convert (build_pointer_type (true_type), rval);
-      TREE_CALLS_NEW (rval) = 1;
-      TREE_SIDE_EFFECTS (rval) = 1;
-      rval = build_compound_expr (tree_cons (NULL_TREE, exp1,
-                                            build_tree_list (NULL_TREE, rval)));
+      rval = cp_convert (build_pointer_type (true_type), rval);
+      rval = build_compound_expr
+       (expr_tree_cons (NULL_TREE, exp1,
+                        build_expr_list (NULL_TREE, rval)));
     }
 
   if (rval == error_mark_node)
@@ -2946,12 +2311,26 @@ build_new (placement, decl, init, use_global_new)
       if (! TYPE_NEEDS_CONSTRUCTING (type)
          && ! IS_AGGR_TYPE (type) && ! has_array)
        {
-         /* New 2.0 interpretation: `new int (10)' means
-            allocate an int, and initialize it with 10.  */
+         /* We are processing something like `new int (10)', which
+            means allocate an int, and initialize it with 10.  */
          tree deref;
+         tree deref_type;
 
+         /* At present RVAL is a temporary variable, created to hold
+            the value from the call to `operator new'.  We transform
+            it to (*RVAL = INIT, RVAL).  */
          rval = save_expr (rval);
          deref = build_indirect_ref (rval, NULL_PTR);
+
+         /* Even for something like `new const int (10)' we must
+            allow the expression to be non-const while we do the
+            initialization.  */
+         deref_type = TREE_TYPE (deref);
+         if (CP_TYPE_CONST_P (deref_type))
+           TREE_TYPE (deref) 
+             = cp_build_qualified_type (deref_type,
+                                        CP_TYPE_QUALS (deref_type) 
+                                        & ~TYPE_QUAL_CONST);
          TREE_READONLY (deref) = 0;
 
          if (TREE_CHAIN (init) != NULL_TREE)
@@ -2970,7 +2349,6 @@ build_new (placement, decl, init, use_global_new)
                        rval);
          TREE_NO_UNUSED_WARNING (rval) = 1;
          TREE_SIDE_EFFECTS (rval) = 1;
-         TREE_CALLS_NEW (rval) = 1;
        }
       else if (! has_array)
        {
@@ -2982,10 +2360,12 @@ build_new (placement, decl, init, use_global_new)
 
          if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type))
            {
-             init = tree_cons (NULL_TREE, integer_one_node, init);
+             init = expr_tree_cons (NULL_TREE, integer_one_node, init);
              flags |= LOOKUP_HAS_IN_CHARGE;
            }
 
+         if (use_java_new)
+           rval = save_expr (rval);
          newrval = rval;
 
          if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
@@ -2994,123 +2374,110 @@ build_new (placement, decl, init, use_global_new)
          newrval = build_method_call (newrval, ctor_identifier,
                                       init, TYPE_BINFO (true_type), flags);
 
-         if (newrval)
-           {
-             rval = newrval;
-             TREE_HAS_CONSTRUCTOR (rval) = 1;
-           }
-         else
-           rval = error_mark_node;
+         if (newrval == NULL_TREE || newrval == error_mark_node)
+           return error_mark_node;
+
+         /* Java constructors compiled by jc1 do not return this. */
+         if (use_java_new)
+           newrval = build (COMPOUND_EXPR, TREE_TYPE (newrval),
+                            newrval, rval);
+         rval = newrval;
+         TREE_HAS_CONSTRUCTOR (rval) = 1;
        }
       else
        rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
                      save_expr (rval), init, nelts);
-#if 0  
-      else if (current_function_decl == NULL_TREE)
-       {
-         extern tree static_aggregates;
 
-         /* In case of static initialization, SAVE_EXPR is good enough.  */
-         rval = save_expr (rval);
-         rval = copy_to_permanent (rval);
-         init = copy_to_permanent (init);
-         init = expand_vec_init (decl, rval,
-                                 build_binary_op (MINUS_EXPR, nelts,
-                                                  integer_one_node, 1),
-                                 init, 0);
-         init = copy_to_permanent (init);
-         static_aggregates = perm_tree_cons (init, rval, static_aggregates);
-       }
-      else
+      /* If any part of the object initialization terminates by throwing
+        an exception and the new-expression does not contain a
+        new-placement, then the deallocation function is called to free
+        the memory in which the object was being constructed.  */
+      if (flag_exceptions && alloc_expr && ! use_java_new)
        {
-         /* Have to wrap this in RTL_EXPR for two cases:
-            in base or member initialization and if we
-            are a branch of a ?: operator.  Since we
-            can't easily know the latter, just do it always.  */
-         tree xval = make_node (RTL_EXPR);
-
-         /* If we want to check the value of the allocation expression,
-             and the number of elements in the array is not a constant, we
-             *must* expand the SAVE_EXPR for nelts in alloc_expr before we
-             expand it in the actual initialization.  So we need to build up
-             an RTL_EXPR for alloc_expr.  Sigh.  */
-         if (alloc_expr && ! TREE_CONSTANT (nelts))
+         enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
+         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 ();
+
+         if (placement)
            {
-             tree xval = make_node (RTL_EXPR);
-             rtx rtxval;
-             TREE_TYPE (xval) = TREE_TYPE (alloc_expr);
-             do_pending_stack_adjust ();
-             start_sequence_for_rtl_expr (xval);
-             emit_note (0, -1);
-             rtxval = expand_expr (alloc_expr, NULL_RTX, VOIDmode, 0);
-             do_pending_stack_adjust ();
-             TREE_SIDE_EFFECTS (xval) = 1;
-             RTL_EXPR_SEQUENCE (xval) = get_insns ();
-             end_sequence ();
-             RTL_EXPR_RTL (xval) = rtxval;
-             TREE_TYPE (xval) = TREE_TYPE (alloc_expr);
-             alloc_expr = xval;
-           }
+             flags |= LOOKUP_SPECULATIVELY;
 
-         TREE_TYPE (xval) = TREE_TYPE (rval);
-         do_pending_stack_adjust ();
-         start_sequence_for_rtl_expr (xval);
+             /* We expect alloc_expr to look like a TARGET_EXPR around
+                a NOP_EXPR around the CALL_EXPR we want.  */
+             fn = TREE_OPERAND (alloc_expr, 1);
+             fn = TREE_OPERAND (fn, 0);
+           }
 
-         /* As a matter of principle, `start_sequence' should do this.  */
-         emit_note (0, -1);
+         /* Copy size to the saveable obstack.  */
+         size = copy_node (size);
 
-         rval = save_expr (rval);
-         rval = expand_vec_init (decl, rval,
-                                 build_binary_op (MINUS_EXPR, nelts,
-                                                  integer_one_node, 1),
-                                 init, 0);
+         cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
 
-         do_pending_stack_adjust ();
+         resume_momentary (yes);
 
-         TREE_SIDE_EFFECTS (xval) = 1;
-         TREE_CALLS_NEW (xval) = 1;
-         RTL_EXPR_SEQUENCE (xval) = get_insns ();
-         end_sequence ();
+         /* 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
+            returned pointer in buf.  Then we clear sentry and return buf.  */
 
-         if (TREE_CODE (rval) == SAVE_EXPR)
-           {
-             /* Errors may cause this to not get evaluated.  */
-             if (SAVE_EXPR_RTL (rval) == 0)
-               SAVE_EXPR_RTL (rval) = const0_rtx;
-             RTL_EXPR_RTL (xval) = SAVE_EXPR_RTL (rval);
-           }
-         else
+         if (cleanup)
            {
-             my_friendly_assert (TREE_CODE (rval) == VAR_DECL, 217);
-             RTL_EXPR_RTL (xval) = DECL_RTL (rval);
+             tree end, sentry, begin, buf, t = TREE_TYPE (rval);
+
+             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);
+
+             rval = build (COMPOUND_EXPR, t, begin,
+                           build (COMPOUND_EXPR, t, rval,
+                                  build (COMPOUND_EXPR, t, end, buf)));
            }
-         rval = xval;
        }
-#endif
     }
-  else if (TYPE_READONLY (true_type))
+  else if (CP_TYPE_CONST_P (true_type))
     cp_error ("uninitialized const in `new' of `%#T'", true_type);
 
  done:
 
-  if (alloc_expr && rval != alloc_expr)
+  if (alloc_expr && rval == alloc_node)
+    {
+      rval = TREE_OPERAND (alloc_expr, 1);
+      alloc_expr = NULL_TREE;
+    }
+
+  if (check_new && alloc_expr)
     {
       /* Did we modify the storage?  */
-      tree ifexp = build_binary_op (NE_EXPR, alloc_expr,
+      tree ifexp = build_binary_op (NE_EXPR, alloc_node,
                                    integer_zero_node, 1);
-      rval = build_conditional_expr (ifexp, rval, alloc_expr);
+      rval = build_conditional_expr (ifexp, rval, alloc_node);
     }
 
+  if (alloc_expr)
+    rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
+
   if (rval && TREE_TYPE (rval) != build_pointer_type (type))
     {
       /* The type of new int [3][3] is not int *, but int [3] * */
       rval = build_c_cast (build_pointer_type (type), rval);
     }
 
-  if (pending_sizes)
-    rval = build_compound_expr (chainon (pending_sizes,
-                                        build_tree_list (NULL_TREE, rval)));
-
   return rval;
 }
 \f
@@ -3144,9 +2511,6 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
      This is also the containing expression returned by this function.  */
   tree controller = NULL_TREE;
 
-  /* This is the BLOCK to record the symbol binding for debugging.  */
-  tree block;
-
   if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
     {
       loop = integer_zero_node;
@@ -3164,21 +2528,19 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
   DECL_REGISTER (tbase) = 1;
   controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (controller) = 1;
-  block = build_block (tbase, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
-  add_block_current_level (block);
 
   if (auto_delete != integer_zero_node
       && auto_delete != integer_two_node)
     {
-      tree base_tbd = convert (ptype,
-                              build_binary_op (MINUS_EXPR,
-                                               convert (ptr_type_node, base),
-                                               BI_header_size,
-                                               1));
+      tree base_tbd = cp_convert (ptype,
+                                 build_binary_op (MINUS_EXPR,
+                                                  cp_convert (ptr_type_node, base),
+                                                  BI_header_size,
+                                                  1));
       /* This is the real size */
       virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
-      body = build_tree_list (NULL_TREE,
-                             build_x_delete (ptype, base_tbd,
+      body = build_expr_list (NULL_TREE,
+                             build_x_delete (base_tbd,
                                              2 | use_global_delete,
                                              virtual_size));
       body = build (COND_EXPR, void_type_node,
@@ -3189,31 +2551,30 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
   else
     body = NULL_TREE;
 
-  body = tree_cons (NULL_TREE,
+  body = expr_tree_cons (NULL_TREE,
                    build_delete (ptype, tbase, auto_delete,
                                  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
                    body);
 
-  body = tree_cons (NULL_TREE,
+  body = expr_tree_cons (NULL_TREE,
                    build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
                    body);
 
-  body = tree_cons (NULL_TREE,
+  body = expr_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 = tree_cons (NULL_TREE, tbase_init,
-                   tree_cons (NULL_TREE, loop, NULL_TREE));
+  loop = expr_tree_cons (NULL_TREE, tbase_init,
+                   expr_tree_cons (NULL_TREE, loop, NULL_TREE));
   loop = build_compound_expr (loop);
 
  no_destructor:
   /* If the delete flag is one, or anything else with the low bit set,
      delete the storage.  */
-  if (auto_delete_vec == integer_zero_node
-      || auto_delete_vec == integer_two_node)
+  if (auto_delete_vec == integer_zero_node)
     deallocate_expr = integer_zero_node;
   else
     {
@@ -3227,15 +2588,15 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
        base_tbd = base;
       else
        {
-         base_tbd = convert (ptype,
-                             build_binary_op (MINUS_EXPR,
-                                              convert (string_type_node, base),
-                                              BI_header_size,
-                                              1));
+         base_tbd = cp_convert (ptype,
+                                build_binary_op (MINUS_EXPR,
+                                                 cp_convert (string_type_node, base),
+                                                 BI_header_size,
+                                                 1));
          /* True size with header.  */
          virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
        }
-      deallocate_expr = build_x_delete (ptype, base_tbd,
+      deallocate_expr = build_x_delete (base_tbd,
                                        2 | use_global_delete,
                                        virtual_size);
       if (auto_delete_vec != integer_one_node)
@@ -3247,8 +2608,8 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
 
   if (loop && deallocate_expr != integer_zero_node)
     {
-      body = tree_cons (NULL_TREE, loop,
-                       tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
+      body = expr_tree_cons (NULL_TREE, loop,
+                       expr_tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
       body = build_compound_expr (body);
     }
   else
@@ -3266,21 +2627,83 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
       return controller;
     }
   else
-    return convert (void_type_node, body);
+    return cp_convert (void_type_node, body);
 }
 
-/* Build a tree to cleanup partially built arrays.
-   BASE is that starting address of the array.
-   COUNT is the count of objects that have been built, that need destroying.
-   TYPE is the type of elements in the array.  */
+/* Protect the vector initialization with a try-block so that we can
+   destroy the first few elements if constructing a later element
+   causes an exception to be thrown.  TYPE is the type of the array
+   elements.  */
 
-static tree
-build_array_eh_cleanup (base, count, type)
-     tree base, count, type;
+static void
+expand_vec_init_try_block (type)
+     tree type;
+{
+  if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions)
+    return;
+
+  /* The code we generate looks like:
+
+       try {
+         // Initialize the vector.
+       } catch (...) {
+         // Destory the elements that need destroying.
+        throw;
+       } 
+
+     Here we're just beginning the `try'.  */
+
+  expand_eh_region_start ();
+}
+
+/* Add code to destroy the array elements constructed so far if the
+   construction of some element in the array causes an exception to be
+   thrown.  RVAL is the address of the last element in the array.
+   TYPE is the type of the array elements.  MAXINDEX is the maximum
+   allowable index into the array.  ITERATOR is an integer variable
+   indicating how many elements remain to be constructed.  */
+
+static void
+expand_vec_init_catch_clause (rval, type, maxindex, iterator)
+     tree rval;
+     tree type;
+     tree maxindex;
+     tree iterator;
 {
-  tree expr = build_vec_delete_1 (base, count, type, integer_two_node,
-                                 integer_zero_node, 0);
-  return expr;
+  tree e;
+  tree cleanup;
+
+  if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions)
+    return;
+    
+  /* We have to ensure that this can live to the cleanup expansion
+     time, since we know it is only ever needed once, generate code
+     now.  */
+  push_obstacks_nochange ();
+  resume_temporary_allocation ();
+
+  cleanup = make_node (RTL_EXPR);
+  TREE_TYPE (cleanup) = void_type_node;
+  RTL_EXPR_RTL (cleanup) = const0_rtx;
+  TREE_SIDE_EFFECTS (cleanup) = 1;
+  do_pending_stack_adjust ();
+  start_sequence_for_rtl_expr (cleanup);
+    
+  e = build_vec_delete_1 (rval,
+                         build_binary_op (MINUS_EXPR, maxindex, 
+                                          iterator, 1),
+                         type,
+                         /*auto_delete_vec=*/integer_zero_node,
+                         /*auto_delete=*/integer_zero_node,
+                         /*use_global_delete=*/0);
+  expand_expr (e, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  do_pending_stack_adjust ();
+  RTL_EXPR_SEQUENCE (cleanup) = get_insns ();
+  end_sequence ();
+  cleanup = protect_with_terminate (cleanup);
+  expand_eh_region_end (cleanup);
+  pop_obstacks ();
 }
 
 /* `expand_vec_init' performs initialization of a vector of aggregate
@@ -3306,11 +2729,14 @@ expand_vec_init (decl, base, maxindex, init, from_array)
      int from_array;
 {
   tree rval;
-  tree iterator, base2 = NULL_TREE;
+  tree base2 = NULL_TREE;
   tree type = TREE_TYPE (TREE_TYPE (base));
   tree size;
+  tree itype = NULL_TREE;
+  tree iterator;
+  int num_initialized_elts = 0;
 
-  maxindex = convert (ptrdiff_type_node, maxindex);
+  maxindex = cp_convert (ptrdiff_type_node, maxindex);
   if (maxindex == error_mark_node)
     return error_mark_node;
 
@@ -3325,105 +2751,102 @@ expand_vec_init (decl, base, maxindex, init, from_array)
 
   size = size_in_bytes (type);
 
-  /* Set to zero in case size is <= 0.  Optimizer will delete this if
-     it is not needed.  */
-  rval = get_temp_regvar (build_pointer_type (type),
-                         convert (build_pointer_type (type), null_pointer_node));
   base = default_conversion (base);
-  base = convert (build_pointer_type (type), base);
-  expand_assignment (rval, base, 0, 0);
+  base = cp_convert (build_pointer_type (type), base);
+  rval = get_temp_regvar (build_pointer_type (type), base);
   base = get_temp_regvar (build_pointer_type (type), base);
+  iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
 
-  if (init != NULL_TREE && TREE_CODE (init) == TREE_LIST)
-    init = build_compound_expr (init);
+  /* Protect the entire array initialization so that we can destroy
+     the partially constructed array if an exception is thrown.  */
+  expand_vec_init_try_block (type);
 
-  if (init != NULL_TREE
-      && TREE_CODE (init) == CONSTRUCTOR
-      && (! decl || TREE_TYPE (init) == TREE_TYPE (decl)))
+  if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR
+      && (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl))))
     {
-      /* Initialization of array from {...}.  */
-      tree elts = CONSTRUCTOR_ELTS (init);
+      /* Do non-default initialization resulting from brace-enclosed
+        initializers.  */
+
+      tree elts;
       tree baseref = build1 (INDIRECT_REF, type, base);
-      tree baseinc = build (PLUS_EXPR, build_pointer_type (type), base, size);
-      int host_i = TREE_INT_CST_LOW (maxindex);
 
-      if (IS_AGGR_TYPE (type))
+      from_array = 0;
+
+      for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts))
        {
-         while (elts)
-           {
-             host_i -= 1;
-             expand_aggr_init (baseref, TREE_VALUE (elts), 0, 0);
+         tree elt = TREE_VALUE (elts);
 
-             expand_assignment (base, baseinc, 0, 0);
-             elts = TREE_CHAIN (elts);
-           }
-         /* Initialize any elements by default if possible.  */
-         if (host_i >= 0)
-           {
-             if (TYPE_NEEDS_CONSTRUCTING (type) == 0)
-               {
-                 if (obey_regdecls)
-                   use_variable (DECL_RTL (base));
-                 goto done_init;
-               }
+         num_initialized_elts++;
 
-             iterator = get_temp_regvar (ptrdiff_type_node,
-                                         build_int_2 (host_i, 0));
-             init = NULL_TREE;
-             goto init_by_default;
-           }
+         if (IS_AGGR_TYPE (type) || TREE_CODE (type) == ARRAY_TYPE)
+           expand_aggr_init (baseref, elt, 0);
+         else
+           expand_assignment (baseref, elt, 0, 0);
+
+         expand_assignment (base, 
+                            build (PLUS_EXPR, build_pointer_type (type),
+                                   base, size),
+                            0, 0);
+         expand_assignment (iterator,
+                            build (MINUS_EXPR, ptrdiff_type_node,
+                                   iterator, integer_one_node),
+                            0, 0);
        }
-      else
-       while (elts)
-         {
-           expand_assignment (baseref, TREE_VALUE (elts), 0, 0);
 
-           expand_assignment (base, baseinc, 0, 0);
-           elts = TREE_CHAIN (elts);
-         }
+      /* Clear out INIT so that we don't get confused below.  */
+      init = NULL_TREE;
 
       if (obey_regdecls)
        use_variable (DECL_RTL (base));
     }
-  else
+  else if (from_array)
     {
-      tree itype;
+      /* If initializing one array from another, initialize element by
+        element.  We rely upon the below calls the do argument
+        checking.  */ 
+      if (decl == NULL_TREE)
+       {
+         sorry ("initialization of array from dissimilar array type");
+         return error_mark_node;
+       }
+      if (init)
+       {
+         base2 = default_conversion (init);
+         itype = TREE_TYPE (base2);
+         base2 = get_temp_regvar (itype, base2);
+         itype = TREE_TYPE (itype);
+       }
+      else if (TYPE_LANG_SPECIFIC (type)
+              && TYPE_NEEDS_CONSTRUCTING (type)
+              && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+       {
+         error ("initializer ends prematurely");
+         return error_mark_node;
+       }
+    }
 
-      iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
+  /* Now, default-initialize any remaining elements.  We don't need to
+     do that if a) the type does not need constructing, or b) we've
+     already initialized all the elements.
 
-    init_by_default:
+     We do need to keep going if we're copying an array.  */
 
-      /* If initializing one array from another,
-        initialize element by element.  */
-      if (from_array)
-       {
-         /* We rely upon the below calls the do argument checking */
-         if (decl == NULL_TREE)
-           {
-             sorry ("initialization of array from dissimilar array type");
-             return error_mark_node;
-           }
-         if (init)
-           {
-             base2 = default_conversion (init);
-             itype = TREE_TYPE (base2);
-             base2 = get_temp_regvar (itype, base2);
-             itype = TREE_TYPE (itype);
-           }
-         else if (TYPE_LANG_SPECIFIC (type)
-                  && TYPE_NEEDS_CONSTRUCTING (type)
-                  && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
-           {
-             error ("initializer ends prematurely");
-             return error_mark_node;
-           }
-       }
+  if (from_array
+      || (TYPE_NEEDS_CONSTRUCTING (type)
+         && !(TREE_CODE (maxindex) == INTEGER_CST
+              && num_initialized_elts == TREE_INT_CST_LOW (maxindex) + 1)))
+    {
+      /* If the ITERATOR is equal to -1, then we don't have to loop;
+        we've already initialized all the elements.  */
+      expand_start_cond (build (NE_EXPR, boolean_type_node,
+                               iterator, minus_one),
+                        0);
 
-      expand_start_cond (build (GE_EXPR, boolean_type_node,
-                               iterator, integer_zero_node), 0);
-      if (TYPE_NEEDS_DESTRUCTOR (type))
-       expand_eh_region_start ();
+      /* Otherwise, loop through the elements.  */
       expand_start_loop_continue_elsewhere (1);
+  
+      /* The initialization of each array element is a full-expression.  */
+      expand_start_target_temps ();
 
       if (from_array)
        {
@@ -3438,7 +2861,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
          if (from_array == 2)
            expand_expr_stmt (build_modify_expr (to, NOP_EXPR, from));
          else if (TYPE_NEEDS_CONSTRUCTING (type))
-           expand_aggr_init (to, from, 0, 0);
+           expand_aggr_init (to, from, 0);
          else if (from)
            expand_assignment (to, from, 0, 0);
          else
@@ -3448,73 +2871,55 @@ expand_vec_init (decl, base, maxindex, init, from_array)
        {
          if (init != 0)
            sorry ("cannot initialize multi-dimensional array with initializer");
-         expand_vec_init (decl, build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), base),
+         expand_vec_init (decl, 
+                          build1 (NOP_EXPR, 
+                                  build_pointer_type (TREE_TYPE
+                                                      (type)),
+                                  base),
                           array_type_nelts (type), 0, 0);
        }
       else
-       {
-         tree targ = build1 (INDIRECT_REF, type, base);
-         tree rhs;
-
-         if (init)
-           rhs = convert_for_initialization (targ, type, init, LOOKUP_NORMAL,
-                                             "initialization", NULL_TREE, 0);
-         else
-           rhs = NULL_TREE;
-
-         expand_aggr_init (targ, rhs, 0, 0);
-       }
+       expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0);
 
       expand_assignment (base,
-                        build (PLUS_EXPR, build_pointer_type (type), base, size),
-                        0, 0);
+                        build (PLUS_EXPR, build_pointer_type (type), 
+                               base, size), 0, 0);
       if (base2)
        expand_assignment (base2,
-                          build (PLUS_EXPR, build_pointer_type (type), base2, size), 0, 0);
+                          build (PLUS_EXPR, build_pointer_type (type), 
+                                 base2, size), 0, 0);
+
+      /* Cleanup any temporaries needed for the initial value.  */
+      expand_end_target_temps ();
+  
       expand_loop_continue_here ();
       expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node,
-                                          build (PREDECREMENT_EXPR, ptrdiff_type_node, iterator, integer_one_node), minus_one));
-
+                                          build (PREDECREMENT_EXPR, 
+                                                 ptrdiff_type_node, 
+                                                 iterator,
+                                                 integer_one_node), 
+                                          minus_one));
+  
       if (obey_regdecls)
        {
          use_variable (DECL_RTL (base));
          if (base2)
            use_variable (DECL_RTL (base2));
        }
+
       expand_end_loop ();
-      if (TYPE_NEEDS_DESTRUCTOR (type) && flag_exceptions)
-       {
-         /* We have to ensure that this can live to the cleanup
-            expansion time, since we know it is only ever needed
-            once, generate code now.  */
-         push_obstacks_nochange ();
-         resume_temporary_allocation ();
-         {
-           tree e1, e2 = make_node (RTL_EXPR);
-           TREE_TYPE (e2) = void_type_node;
-           RTL_EXPR_RTL (e2) = const0_rtx;
-           TREE_SIDE_EFFECTS (e2) = 1;
-           start_sequence_for_rtl_expr (e2);
-
-           e1 = build_array_eh_cleanup
-             (rval,
-              build_binary_op (MINUS_EXPR, maxindex, iterator, 1),
-              type);
-           expand_expr (e1, const0_rtx, VOIDmode, 0);
-           RTL_EXPR_SEQUENCE (e2) = get_insns ();
-           end_sequence ();
-           expand_eh_region_end (e2);
-         }
-         pop_obstacks ();
-       }
       expand_end_cond ();
-      if (obey_regdecls)
-       use_variable (DECL_RTL (iterator));
     }
- done_init:
+
+  /* Make sure to cleanup any partially constructed elements.  */
+  expand_vec_init_catch_clause (rval, type, maxindex, iterator);
 
   if (obey_regdecls)
-    use_variable (DECL_RTL (rval));
+    {
+      use_variable (DECL_RTL (iterator));
+      use_variable (DECL_RTL (rval));
+    }
+
   return rval;
 }
 
@@ -3533,23 +2938,17 @@ expand_vec_init (decl, base, maxindex, init, from_array)
    This does not call any destructors.  */
 
 tree
-build_x_delete (type, addr, which_delete, virtual_size)
-     tree type, addr;
+build_x_delete (addr, which_delete, virtual_size)
+     tree addr;
      int which_delete;
      tree virtual_size;
 {
   int use_global_delete = which_delete & 1;
   int use_vec_delete = !!(which_delete & 2);
-  tree rval;
   enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR;
+  int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL);
 
-  if (! use_global_delete && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
-      && (TYPE_GETS_DELETE (TREE_TYPE (type)) & (1 << use_vec_delete)))
-    rval = build_opfncall (code, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE);
-  else
-    rval = build_builtin_call (void_type_node, use_vec_delete ? BIVD : BID,
-                              build_tree_list (NULL_TREE, addr));
-  return rval;
+  return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE);
 }
 
 /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -3571,11 +2970,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
      int flags;
      int use_global_delete;
 {
-  tree function;
   tree member;
   tree expr;
   tree ref;
-  int ptr;
 
   if (addr == error_mark_node)
     return error_mark_node;
@@ -3590,18 +2987,14 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
   if (TREE_CODE (type) == POINTER_TYPE)
     {
       type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      if (TYPE_SIZE (complete_type (type)) == 0)
-       {
-         incomplete_type_error (0, type);
-         return error_mark_node;
-       }
+      if (type != void_type_node && !complete_type_or_else (type, addr))
+       return error_mark_node;
       if (TREE_CODE (type) == ARRAY_TYPE)
        goto handle_array;
       if (! IS_AGGR_TYPE (type))
        {
          /* Call the builtin operator delete.  */
-         return build_builtin_call (void_type_node, BID,
-                                    build_tree_list (NULL_TREE, addr));
+         return build_builtin_delete_call (addr);
        }
       if (TREE_SIDE_EFFECTS (addr))
        addr = save_expr (addr);
@@ -3609,7 +3002,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);
-      ptr = 1;
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -3622,7 +3014,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_two_node,
+                              auto_delete, integer_zero_node,
                               use_global_delete);
     }
   else
@@ -3639,12 +3031,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       else
        addr = convert_force (build_pointer_type (type), addr, 0);
 
-      if (TREE_CODE (addr) == NOP_EXPR
-         && TREE_OPERAND (addr, 0) == current_class_ptr)
-       ref = current_class_ref;
-      else
-       ref = build_indirect_ref (addr, NULL_PTR);
-      ptr = 0;
+      ref = build_indirect_ref (addr, NULL_PTR);
     }
 
   my_friendly_assert (IS_AGGR_TYPE (type), 220);
@@ -3654,18 +3041,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       if (auto_delete == integer_zero_node)
        return void_zero_node;
 
-      /* Pass the size of the object down to the operator delete() in
-        addition to the ADDR.  */
-      if (TYPE_GETS_REG_DELETE (type) && !use_global_delete)
-       {
-         tree virtual_size = c_sizeof_nowarn (type);
-         return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
-                                virtual_size, NULL_TREE);
-       }
-
-      /* Call the builtin operator delete.  */
-      return build_builtin_call (void_type_node, BID,
-                                build_tree_list (NULL_TREE, addr));
+      return build_op_delete_call
+       (DELETE_EXPR, addr, c_sizeof_nowarn (type),
+        LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
+        NULL_TREE);
     }
 
   /* Below, we will reverse the order in which these calls are made.
@@ -3673,17 +3052,15 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
      of the base classes; otherwise, we must do that here.  */
   if (TYPE_HAS_DESTRUCTOR (type))
     {
-      tree parms = build_tree_list (NULL_TREE, addr);
-      tree dtor = DECL_MAIN_VARIANT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1));
       tree passed_auto_delete;
       tree do_delete = NULL_TREE;
+      tree ifexp;
 
       if (use_global_delete)
        {
          tree cond = fold (build (BIT_AND_EXPR, integer_type_node,
                                   auto_delete, integer_one_node));
-         tree call = build_builtin_call
-           (void_type_node, BID, build_tree_list (NULL_TREE, addr));
+         tree call = build_builtin_delete_call (addr);
 
          cond = fold (build (COND_EXPR, void_type_node, cond,
                              call, void_zero_node));
@@ -3696,108 +3073,29 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       else
        passed_auto_delete = auto_delete;
 
-      if (flags & LOOKUP_PROTECT)
-       {
-         tree access;
-         tree basetypes = NULL_TREE;
-         if (current_class_type != NULL_TREE)
-           basetypes = get_binfo (type, current_class_type, 0);
-         if (basetypes == NULL_TREE)
-           basetypes = TYPE_BINFO (type);
-         access = compute_access (basetypes, dtor);
-
-         if (access == access_private_node)
-           {
-             if (flags & LOOKUP_COMPLAIN)
-               cp_error ("destructor for type `%T' is private in this scope", type);
-             return error_mark_node;
-           }
-         else if (access == access_protected_node)
-           {
-             if (flags & LOOKUP_COMPLAIN)
-               cp_error ("destructor for type `%T' is protected in this scope", type);
-             return error_mark_node;
-           }
-       }
-
-      /* Once we are in a destructor, try not going through
-        the virtual function table to find the next destructor.  */
-      if (DECL_VINDEX (dtor)
-         && ! (flags & LOOKUP_NONVIRTUAL)
-         && TREE_CODE (auto_delete) != PARM_DECL
-         && (ptr == 1 || ! resolves_to_fixed_type_p (ref, 0)))
-       {
-         tree binfo, basetype;
-         /* The code below is probably all broken.  See call.c for the
-            complete right way to do this. this offsets may not be right
-            in the below.  (mrs) */
-         /* This destructor must be called via virtual function table.  */
-         dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (DECL_CONTEXT (dtor)), 1);
-         basetype = DECL_CLASS_CONTEXT (dtor);
-         binfo = get_binfo (basetype,
-                            TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))),
-                            0);
-         expr = convert_pointer_to_real (binfo, TREE_VALUE (parms));
-         if (expr != TREE_VALUE (parms))
-           {
-             expr = fold (expr);
-             ref = build_indirect_ref (expr, NULL_PTR);
-             TREE_VALUE (parms) = expr;
-           }
-         function = build_vfn_ref (&TREE_VALUE (parms), ref, DECL_VINDEX (dtor));
-         if (function == error_mark_node)
-           return error_mark_node;
-         TREE_TYPE (function) = build_pointer_type (TREE_TYPE (dtor));
-         TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete);
-         expr = build_function_call (function, parms);
-         if (do_delete)
-           expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
-         if (ptr && (flags & LOOKUP_DESTRUCTOR) == 0)
-           {
-             /* Handle the case where a virtual destructor is
-                being called on an item that is 0.
+      expr = build_method_call
+       (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete),
+        NULL_TREE, flags);
 
-                @@ Does this really need to be done?  */
-             tree ifexp = build_binary_op(NE_EXPR, addr, integer_zero_node,1);
+      if (do_delete)
+       expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
 
-             expr = build (COND_EXPR, void_type_node,
-                           ifexp, expr, void_zero_node);
-           }
-       }
+      if (flags & LOOKUP_DESTRUCTOR)
+       /* Explicit destructor call; don't check for null pointer.  */
+       ifexp = integer_one_node;
       else
-       {
-         tree ifexp;
-
-         if ((flags & LOOKUP_DESTRUCTOR)
-             || TREE_CODE (ref) == VAR_DECL
-             || TREE_CODE (ref) == PARM_DECL
-             || TREE_CODE (ref) == COMPONENT_REF
-             || TREE_CODE (ref) == ARRAY_REF)
-           /* These can't be 0.  */
-           ifexp = integer_one_node;
-         else
-           /* Handle the case where a non-virtual destructor is
-              being called on an item that is 0.  */
-           ifexp = build_binary_op (NE_EXPR, addr, integer_zero_node, 1);
-
-         /* Used to mean that this destructor was known to be empty,
-            but that's now obsolete.  */
-         my_friendly_assert (DECL_INITIAL (dtor) != void_type_node, 221);
-
-         TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete);
-         expr = build_function_call (dtor, parms);
-         if (do_delete)
-           expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
-
-         if (ifexp != integer_one_node)
-           expr = build (COND_EXPR, void_type_node,
-                         ifexp, expr, void_zero_node);
-       }
+       /* Handle deleting a null pointer.  */
+       ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node, 1));
+
+      if (ifexp != integer_one_node)
+       expr = build (COND_EXPR, void_type_node,
+                     ifexp, expr, void_zero_node);
+
       return expr;
     }
   else
     {
-      /* This can get visibilities wrong.  */
+      /* We only get here from finish_function for a destructor.  */
       tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
       int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
       tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
@@ -3805,51 +3103,27 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       tree parent_auto_delete = auto_delete;
       tree cond;
 
-      /* If this type does not have a destructor, but does have
-        operator delete, call the parent parent destructor (if any),
-        but let this node do the deleting.  Otherwise, it is ok
-        to let the parent destructor do the deleting.  */
-      if (TYPE_GETS_REG_DELETE (type) && !use_global_delete)
-       {
-         parent_auto_delete = integer_zero_node;
-         if (auto_delete == integer_zero_node)
-           cond = NULL_TREE;
-         else
-           {
-             tree virtual_size;
-
-               /* This is probably wrong. It should be the size of the
-                  virtual object being deleted.  */
-             virtual_size = c_sizeof_nowarn (type);
-
-             expr = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
-                                    virtual_size, NULL_TREE);
-             if (expr == error_mark_node)
-               return error_mark_node;
-             if (auto_delete != integer_one_node)
-               cond = build (COND_EXPR, void_type_node,
-                             build (BIT_AND_EXPR, integer_type_node,
-                                    auto_delete, integer_one_node),
-                             expr, void_zero_node);
-             else
-               cond = expr;
-           }
-       }
+      /* Set this again before we call anything, as we might get called
+        recursively.  */
+      TYPE_HAS_DESTRUCTOR (type) = 1;
+
+      /* If we have member delete or vbases, we call delete in
+        finish_function.  */
+      if (auto_delete == integer_zero_node)
+       cond = NULL_TREE;
       else if (base_binfo == NULL_TREE
-              || (TREE_VIA_VIRTUAL (base_binfo) == 0
-                  && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))))
+              || ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
        {
          cond = build (COND_EXPR, void_type_node,
                        build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
-                       build_builtin_call (void_type_node, BID,
-                                           build_tree_list (NULL_TREE, addr)),
+                       build_builtin_delete_call (addr),
                        void_zero_node);
        }
       else
        cond = NULL_TREE;
 
       if (cond)
-       exprstmt = build_tree_list (NULL_TREE, cond);
+       exprstmt = build_expr_list (NULL_TREE, cond);
 
       if (base_binfo
          && ! TREE_VIA_VIRTUAL (base_binfo)
@@ -3862,9 +3136,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
          else
            this_auto_delete = integer_zero_node;
 
-         expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), addr,
-                              this_auto_delete, flags, 0);
-         exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
+         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);
        }
 
       /* Take care of the remaining baseclasses.  */
@@ -3875,15 +3150,11 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
              || TREE_VIA_VIRTUAL (base_binfo))
            continue;
 
-         /* May be zero offset if other baseclasses are virtual.  */
-         expr = fold (build (PLUS_EXPR, build_pointer_type (BINFO_TYPE (base_binfo)),
-                             addr, BINFO_OFFSET (base_binfo)));
-
-         expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), expr,
-                              integer_zero_node,
-                              flags, 0);
+         expr = build_scoped_method_call
+           (ref, base_binfo, dtor_identifier,
+            build_expr_list (NULL_TREE, integer_zero_node));
 
-         exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
+         exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
        }
 
       for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
@@ -3895,7 +3166,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 = tree_cons (NULL_TREE, expr, exprstmt);
+             exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
            }
        }
 
@@ -3922,7 +3193,7 @@ build_vbase_delete (type, decl)
     {
       tree this_addr = convert_force (build_pointer_type (BINFO_TYPE (vbases)),
                                      addr, 0);
-      result = tree_cons (NULL_TREE,
+      result = expr_tree_cons (NULL_TREE,
                          build_delete (TREE_TYPE (this_addr), this_addr,
                                        integer_zero_node,
                                        LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0),
This page took 0.108187 seconds and 5 git commands to generate.