OSDN Git Service

When a class template is explicitly instantiated, its member should be too.
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index e1a19b1..5f0872e 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -35,6 +35,8 @@ Boston, MA 02111-1307, USA.  */
 #include "except.h"
 #include "toplev.h"
 
+static bool begin_init_stmts (tree *, tree *);
+static tree finish_init_stmts (bool, tree, tree);
 static void construct_virtual_base (tree, tree);
 static void expand_aggr_init_1 (tree, tree, tree, tree, int);
 static void expand_default_init (tree, tree, tree, tree, int);
@@ -64,40 +66,29 @@ static tree build_vtbl_address (tree);
    pass them back to finish_init_stmts when the expression is
    complete.  */
 
-void
+static bool
 begin_init_stmts (tree *stmt_expr_p, tree *compound_stmt_p)
 {
-  if (building_stmt_tree ())
-    *stmt_expr_p = begin_stmt_expr ();
-  else
-    *stmt_expr_p = begin_global_stmt_expr ();
+  bool is_global = !building_stmt_tree ();
   
-  if (building_stmt_tree ())
-    *compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
+  *stmt_expr_p = begin_stmt_expr ();
+  *compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/true);
+
+  return is_global;
 }
 
 /* Finish out the statement-expression begun by the previous call to
    begin_init_stmts.  Returns the statement-expression itself.  */
 
-tree
-finish_init_stmts (tree stmt_expr, tree compound_stmt)
+static tree
+finish_init_stmts (bool is_global, tree stmt_expr, tree compound_stmt)
 {  
-  if (building_stmt_tree ())
-    finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
-  
-  if (building_stmt_tree ())
-    {
-      stmt_expr = finish_stmt_expr (stmt_expr);
-      STMT_EXPR_NO_SCOPE (stmt_expr) = true;
-    }
-  else
-    stmt_expr = finish_global_stmt_expr (stmt_expr);
+  finish_compound_stmt (compound_stmt);
   
-  /* To avoid spurious warnings about unused values, we set 
-     TREE_USED.  */
-  if (stmt_expr)
-    TREE_USED (stmt_expr) = 1;
+  stmt_expr = finish_stmt_expr (stmt_expr, true);
 
+  my_friendly_assert (!building_stmt_tree () == is_global, 20030726);
+  
   return stmt_expr;
 }
 
@@ -237,14 +228,17 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
       max_index = nelts ? nelts : array_type_nelts (type);
       my_friendly_assert (TREE_CODE (max_index) == INTEGER_CST, 20030618);
 
-      for (index = size_zero_node;
-          !tree_int_cst_lt (max_index, index);
-          index = size_binop (PLUS_EXPR, index, size_one_node))
-       inits = tree_cons (index,
-                          build_zero_init (TREE_TYPE (type),
-                                           /*nelts=*/NULL_TREE,
-                                           static_storage_p),
-                          inits);
+      /* A zero-sized array, which is accepted as an extension, will
+        have an upper bound of -1.  */
+      if (!tree_int_cst_equal (max_index, integer_minus_one_node))
+       for (index = size_zero_node;
+            !tree_int_cst_lt (max_index, index);
+            index = size_binop (PLUS_EXPR, index, size_one_node))
+         inits = tree_cons (index,
+                            build_zero_init (TREE_TYPE (type),
+                                             /*nelts=*/NULL_TREE,
+                                             static_storage_p),
+                            inits);
       CONSTRUCTOR_ELTS (init) = nreverse (inits);
     }
   else if (TREE_CODE (type) == REFERENCE_TYPE)
@@ -254,7 +248,10 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
 
   /* In all cases, the initializer is a constant.  */
   if (init)
-    TREE_CONSTANT (init) = 1;
+    {
+      TREE_CONSTANT (init) = 1;
+      TREE_INVARIANT (init) = 1;
+    }
 
   return init;
 }
@@ -301,7 +298,7 @@ build_default_init (tree type, tree nelts)
     return NULL_TREE;
       
   /* At this point, TYPE is either a POD class type, an array of POD
-     classes, or something even more inoccuous.  */
+     classes, or something even more innocuous.  */
   return build_zero_init (type, nelts, /*static_storage_p=*/false);
 }
 
@@ -346,8 +343,7 @@ perform_member_init (tree member, tree init)
          finish_expr_stmt (init);
        }
     }
-  else if (TYPE_NEEDS_CONSTRUCTING (type)
-          || (init && TYPE_HAS_CONSTRUCTOR (type)))
+  else if (TYPE_NEEDS_CONSTRUCTING (type))
     {
       if (explicit
          && TREE_CODE (type) == ARRAY_TYPE
@@ -377,19 +373,14 @@ perform_member_init (tree member, tree init)
          /* member traversal: note it leaves init NULL */
          else if (TREE_CODE (type) == REFERENCE_TYPE)
            pedwarn ("uninitialized reference member `%D'", member);
+         else if (CP_TYPE_CONST_P (type))
+           pedwarn ("uninitialized member `%D' with `const' type `%T'",
+                    member, type);
        }
       else if (TREE_CODE (init) == TREE_LIST)
-       {
-         /* There was an explicit member initialization.  Do some
-            work in that case.  */
-         if (TREE_CHAIN (init))
-           {
-             warning ("initializer list treated as compound expression");
-             init = build_compound_expr (init);
-           }
-         else
-           init = TREE_VALUE (init);
-       }
+       /* There was an explicit member initialization.  Do some work
+          in that case.  */
+       init = build_x_compound_expr_from_list (init, "member initializer");
 
       if (init)
        finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
@@ -531,6 +522,7 @@ sort_mem_initializers (tree t, tree mem_inits)
            cp_warning_at ("  `%#D'", subobject);
          else
            warning ("  base `%T'", subobject);
+         warning ("  when initialized here");
        }
 
       /* Look again, from the beginning of the list.  */
@@ -739,12 +731,9 @@ build_vtbl_address (tree binfo)
   TREE_USED (vtbl) = 1;
 
   /* Now compute the address to use when initializing the vptr.  */
-  vtbl = BINFO_VTABLE (binfo_for);
+  vtbl = unshare_expr (BINFO_VTABLE (binfo_for));
   if (TREE_CODE (vtbl) == VAR_DECL)
-    {
-      vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
-      TREE_CONSTANT (vtbl) = 1;
-    }
+    vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
 
   return vtbl;
 }
@@ -778,7 +767,8 @@ expand_virtual_init (tree binfo, tree decl)
                     TREE_TYPE (vtt_parm), 
                     vtt_parm,
                     vtt_index);
-      vtbl2 = build1 (INDIRECT_REF, TREE_TYPE (vtbl), vtbl2);
+      vtbl2 = build_indirect_ref (vtbl2, NULL);
+      vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
 
       /* The actual initializer is the VTT value only in the subobject
         constructor.  In maybe_clone_body we'll substitute NULL for
@@ -857,25 +847,17 @@ construct_virtual_base (tree vbase, tree arguments)
   flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
   inner_if_stmt = begin_if_stmt ();
   finish_if_stmt_cond (flag, inner_if_stmt);
-  compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
+  compound_stmt = begin_compound_stmt (/*has_no_scope=*/true);
 
   /* Compute the location of the virtual base.  If we're
      constructing virtual bases, then we must be the most derived
      class.  Therefore, we don't have to look up the virtual base;
      we already know where it is.  */
-  exp = build (PLUS_EXPR,
-              TREE_TYPE (current_class_ptr),
-              current_class_ptr,
-              fold (build1 (NOP_EXPR, TREE_TYPE (current_class_ptr),
-                            BINFO_OFFSET (vbase))));
-  exp = build1 (NOP_EXPR, 
-               build_pointer_type (BINFO_TYPE (vbase)), 
-               exp);
-  exp = build1 (INDIRECT_REF, BINFO_TYPE (vbase), exp);
-
-  expand_aggr_init_1 (vbase, current_class_ref, exp,
-                     arguments, LOOKUP_COMPLAIN);
-  finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
+  exp = convert_to_base_statically (current_class_ref, vbase);
+
+  expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, 
+                     LOOKUP_COMPLAIN);
+  finish_compound_stmt (compound_stmt);
   finish_then_clause (inner_if_stmt);
   finish_if_stmt ();
 
@@ -986,16 +968,50 @@ expand_member_init (tree name)
 
   if (basetype)
     {
-      tree binfo;
+      tree class_binfo;
+      tree direct_binfo;
+      tree virtual_binfo;
+      int i;
 
       if (current_template_parms)
        return basetype;
 
-      binfo = lookup_base (current_class_type, basetype, 
-                          ba_ignore, NULL);
-      if (!binfo || (!TREE_VIA_VIRTUAL (binfo)
-                    && (BINFO_INHERITANCE_CHAIN (binfo)
-                        != TYPE_BINFO (current_class_type))))
+      class_binfo = TYPE_BINFO (current_class_type);
+      direct_binfo = NULL_TREE;
+      virtual_binfo = NULL_TREE;
+
+      /* Look for a direct base.  */
+      for (i = 0; i < BINFO_N_BASETYPES (class_binfo); ++i)
+       if (same_type_p (basetype, 
+                        TYPE_BINFO_BASETYPE (current_class_type, i)))
+         {
+           direct_binfo = BINFO_BASETYPE (class_binfo, i);
+           break;
+         }
+      /* Look for a virtual base -- unless the direct base is itself
+        virtual.  */
+      if (!direct_binfo || !TREE_VIA_VIRTUAL (direct_binfo))
+       {
+         virtual_binfo 
+           = purpose_member (basetype,
+                             CLASSTYPE_VBASECLASSES (current_class_type));
+         if (virtual_binfo)
+           virtual_binfo = TREE_VALUE (virtual_binfo);
+       }
+
+      /* [class.base.init]
+        
+         If a mem-initializer-id is ambiguous because it designates
+        both a direct non-virtual base class and an inherited virtual
+        base class, the mem-initializer is ill-formed.  */
+      if (direct_binfo && virtual_binfo)
+       {
+         error ("'%D' is both a direct base and an indirect virtual base",
+                basetype);
+         return NULL_TREE;
+       }
+
+      if (!direct_binfo && !virtual_binfo)
        {
          if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
            error ("type `%D' is not a direct or virtual base of `%T'",
@@ -1005,7 +1021,8 @@ expand_member_init (tree name)
                   name, current_class_type);
          return NULL_TREE;
        }
-      return binfo;
+
+      return direct_binfo ? direct_binfo : virtual_binfo;
     }
   else
     {
@@ -1061,6 +1078,7 @@ build_aggr_init (tree exp, tree init, int flags)
   tree type = TREE_TYPE (exp);
   int was_const = TREE_READONLY (exp);
   int was_volatile = TREE_THIS_VOLATILE (exp);
+  int is_global;
 
   if (init == error_mark_node)
     return error_mark_node;
@@ -1073,34 +1091,25 @@ build_aggr_init (tree exp, tree init, int flags)
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      /* Must arrange to initialize each element of EXP
-        from elements of INIT.  */
-      tree itype = init ? TREE_TYPE (init) : NULL_TREE;
-      
-      if (init && !itype)
+      tree itype;
+
+      /* An array may not be initialized use the parenthesized
+        initialization form -- unless the initializer is "()".  */
+      if (init && TREE_CODE (init) == TREE_LIST)
        {
-         /* Handle bad initializers like:
-            class COMPLEX {
-            public:
-              double re, im;
-              COMPLEX(double r = 0.0, double i = 0.0) {re = r; im = i;};
-              ~COMPLEX() {};
-            };
-
-            int main(int argc, char **argv) {
-              COMPLEX zees(1.0, 0.0)[10];
-            }
-         */
          error ("bad array initializer");
          return error_mark_node;
        }
+      /* Must arrange to initialize each element of EXP
+        from elements of INIT.  */
+      itype = init ? TREE_TYPE (init) : NULL_TREE;
       if (cp_type_quals (type) != TYPE_UNQUALIFIED)
        TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
       if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
-       TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
+       itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
       stmt_expr = build_vec_init (exp, NULL_TREE, init,
-                                 init && same_type_p (TREE_TYPE (init),
-                                                      TREE_TYPE (exp)));
+                                 itype && same_type_p (itype,
+                                                       TREE_TYPE (exp)));
       TREE_READONLY (exp) = was_const;
       TREE_THIS_VOLATILE (exp) = was_volatile;
       TREE_TYPE (exp) = type;
@@ -1110,16 +1119,16 @@ build_aggr_init (tree exp, tree init, int flags)
     }
 
   if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
-    /* just know that we've seen something for this node */
+    /* Just know that we've seen something for this node.  */
     TREE_USED (exp) = 1;
 
   TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
-  begin_init_stmts (&stmt_expr, &compound_stmt);
+  is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
   destroy_temps = stmts_are_full_exprs_p ();
   current_stmt_tree ()->stmts_are_full_exprs_p = 0;
   expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
                      init, LOOKUP_NORMAL|flags);
-  stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
+  stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
   TREE_TYPE (exp) = type;
   TREE_READONLY (exp) = was_const;
@@ -1135,9 +1144,13 @@ build_init (tree decl, tree init, int flags)
 {
   tree expr;
 
-  if (IS_AGGR_TYPE (TREE_TYPE (decl))
-      || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+  if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
     expr = build_aggr_init (decl, init, flags);
+  else if (CLASS_TYPE_P (TREE_TYPE (decl)))
+    expr = build_special_member_call (decl, complete_ctor_identifier,
+                                     build_tree_list (NULL_TREE, init),
+                                     TYPE_BINFO (TREE_TYPE (decl)),
+                                     LOOKUP_NORMAL|flags);
   else
     expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
 
@@ -1172,8 +1185,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
           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 if (TREE_CODE (init) == CONSTRUCTOR 
-              && TREE_HAS_CONSTRUCTOR (init))
+      else if (BRACE_ENCLOSED_INITIALIZER_P (init))
        {
          /* A brace-enclosed initializer for an aggregate.  */
          my_friendly_assert (CP_AGGREGATE_TYPE_P (type), 20021016);
@@ -1216,12 +1228,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
 
   rval = build_special_member_call (exp, ctor_name, parms, binfo, flags);
   if (TREE_SIDE_EFFECTS (rval))
-    {
-      if (building_stmt_tree ())
-       finish_expr_stmt (rval);
-      else
-       genrtl_expr_stmt (rval);
-    }
+    finish_expr_stmt (convert_to_void (rval, NULL));
 }
 
 /* This function is responsible for initializing EXP with INIT
@@ -1241,8 +1248,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
    from TRUE_EXP.  In constructors, we don't know anything about
    the value being initialized.
 
-   FLAGS is just passes to `build_method_call'.  See that function for
-   its description.  */
+   FLAGS is just passed to `build_new_method_call'.  See that function
+   for its description.  */
 
 static void
 expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags)
@@ -1265,8 +1272,9 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags)
       /* If store_init_value returns NULL_TREE, the INIT has been
         record in the DECL_INITIAL for EXP.  That means there's
         nothing more we have to do.  */
-      if (store_init_value (exp, init))
-       finish_expr_stmt (build (INIT_EXPR, type, exp, init));
+      init = store_init_value (exp, init);
+      if (init)
+       finish_expr_stmt (init);
       return;
     }
 
@@ -1337,161 +1345,11 @@ get_type_value (tree name)
     return NULL_TREE;
 }
 
-\f
-/* This code could just as well go in `class.c', but is placed here for
-   modularity.  */
-
-/* For an expression of the form TYPE :: NAME (PARMLIST), build
-   the appropriate function call.  */
-
-tree
-build_member_call (tree type, tree name, tree parmlist)
-{
-  tree t;
-  tree method_name;
-  tree fns;
-  int dtor = 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.  */
-      method_name = TREE_OPERAND (name, 0);
-      /* FIXME: Since we don't do independent names right yet, the
-        name might also be a LOOKUP_EXPR. Once we resolve this to a
-        real decl earlier, this can go. This may happen during
-        tsubst'ing.  */
-      if (TREE_CODE (method_name) == LOOKUP_EXPR)
-       {
-         method_name = lookup_namespace_name 
-           (type, TREE_OPERAND (method_name, 0));
-         TREE_OPERAND (name, 0) = method_name;
-       }
-      my_friendly_assert (is_overloaded_fn (method_name), 980519);
-      return finish_call_expr (name, parmlist, /*disallow_virtual=*/true);
-    }
-
-  if (DECL_P (name))
-    name = DECL_NAME (name);
-
-  if (TREE_CODE (type) == NAMESPACE_DECL)
-    return finish_call_expr (lookup_namespace_name (type, name),
-                            parmlist,
-                            /*disallow_virtual=*/true);
-
-  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-    {
-      method_name = TREE_OPERAND (name, 0);
-      if (TREE_CODE (method_name) == COMPONENT_REF)
-       method_name = TREE_OPERAND (method_name, 1);
-      if (is_overloaded_fn (method_name))
-       method_name = DECL_NAME (OVL_CURRENT (method_name));
-      TREE_OPERAND (name, 0) = method_name;
-    }
-  else
-    method_name = name;
-
-  if (TREE_CODE (method_name) == BIT_NOT_EXPR)
-    {
-      method_name = TREE_OPERAND (method_name, 0);
-      dtor = 1;
-    }
-
-  /* This shouldn't be here, and build_member_call shouldn't appear in
-     parse.y!  (mrs)  */
-  if (type && TREE_CODE (type) == IDENTIFIER_NODE
-      && get_aggr_from_typedef (type, 0) == 0)
-    {
-      tree ns = lookup_name (type, 0);
-      if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
-       return finish_call_expr (lookup_namespace_name (ns, name),
-                                parmlist,
-                                /*disallow_virtual=*/true);
-    }
-
-  if (type == NULL_TREE || ! is_aggr_type (type, 1))
-    return error_mark_node;
-
-  /* An operator we did not like.  */
-  if (name == NULL_TREE)
-    return error_mark_node;
-
-  if (dtor)
-    {
-      error ("cannot call destructor `%T::~%T' without object", type,
-               method_name);
-      return error_mark_node;
-    }
-
-  decl = maybe_dummy_object (type, &basetype_path);
-
-  fns = lookup_fnfields (basetype_path, method_name, 0);
-  if (fns)
-    {
-      if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-       BASELINK_FUNCTIONS (fns) = build_nt (TEMPLATE_ID_EXPR,
-                                            BASELINK_FUNCTIONS (fns),
-                                            TREE_OPERAND (name, 1));
-      return build_new_method_call (decl, fns, parmlist,
-                                   /*conversion_path=*/NULL_TREE,
-                                   LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
-    }
-
-  /* Convert 'this' to the specified type to disambiguate conversion
-     to the function's context.  */
-  if (decl == current_class_ref
-      /* ??? this is wrong, but if this conversion is invalid we need to
-        defer it until we know whether we are calling a static or
-        non-static member function.  Be conservative for now.  */
-      && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
-    {
-      basetype_path = NULL_TREE;
-      decl = build_scoped_ref (decl, type, &basetype_path);
-      if (decl == error_mark_node)
-       return error_mark_node;
-    }
-
-  if (constructor_name_p (method_name, type))
-    return build_functional_cast (type, parmlist);
-  if (TREE_CODE (name) == IDENTIFIER_NODE
-      && ((t = lookup_field (TYPE_BINFO (type), name, 1, false))))
-    {
-      if (t == error_mark_node)
-       return error_mark_node;
-      if (TREE_CODE (t) == FIELD_DECL)
-       {
-         if (is_dummy_object (decl))
-           {
-             error ("invalid use of non-static field `%D'", t);
-             return error_mark_node;
-           }
-         decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t);
-       }
-      else if (TREE_CODE (t) == VAR_DECL)
-       decl = t;
-      else
-       {
-         error ("invalid use of member `%D'", t);
-         return error_mark_node;
-       }
-      if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
-       return build_new_op (CALL_EXPR, LOOKUP_NORMAL, decl,
-                            parmlist, NULL_TREE);
-      return build_function_call (decl, parmlist);
-    }
-  else
-    {
-      error ("no method `%T::%D'", type, name);
-      return error_mark_node;
-    }
-}
-
-/* Build a reference to a member of an aggregate.  This is not a
-   C++ `&', but really something which can have its address taken,
-   and then act as a pointer to member, for example TYPE :: FIELD
-   can have its address taken by saying & TYPE :: FIELD.
+/* Build a reference to a member of an aggregate.  This is not a C++
+   `&', but really something which can have its address taken, and
+   then act as a pointer to member, for example TYPE :: FIELD can have
+   its address taken by saying & TYPE :: FIELD.  ADDRESS_P is true if
+   this expression is the operand of "&".
 
    @@ Prints out lousy diagnostics for operator <typename>
    @@ fields.
@@ -1499,7 +1357,7 @@ build_member_call (tree type, tree name, tree parmlist)
    @@ This function should be rewritten and placed in search.c.  */
 
 tree
-build_offset_ref (tree type, tree name)
+build_offset_ref (tree type, tree name, bool address_p)
 {
   tree decl;
   tree member;
@@ -1510,7 +1368,7 @@ build_offset_ref (tree type, tree name)
   if (TREE_CODE (name) == TEMPLATE_DECL)
     return name;
 
-  if (processing_template_decl || uses_template_parms (type))
+  if (dependent_type_p (type) || type_dependent_expression_p (name))
     return build_min_nt (SCOPE_REF, type, name);
 
   if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
@@ -1525,16 +1383,10 @@ build_offset_ref (tree type, tree name)
        name = DECL_NAME (name);
       else
        {
-         if (TREE_CODE (name) == LOOKUP_EXPR)
-           /* This can happen during tsubst'ing.  */
-           name = TREE_OPERAND (name, 0);
-         else
-           {
-             if (TREE_CODE (name) == COMPONENT_REF)
-               name = TREE_OPERAND (name, 1);
-             if (TREE_CODE (name) == OVERLOAD)
-               name = DECL_NAME (OVL_CURRENT (name));
-           }
+         if (TREE_CODE (name) == COMPONENT_REF)
+           name = TREE_OPERAND (name, 1);
+         if (TREE_CODE (name) == OVERLOAD)
+           name = DECL_NAME (OVL_CURRENT (name));
        }
 
       my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
@@ -1592,8 +1444,41 @@ build_offset_ref (tree type, tree name)
        return error_mark_node;
     }
 
+  if (!member)
+    {
+      error ("`%D' is not a member of type `%T'", name, type);
+      return error_mark_node;
+    }
+
+  if (processing_template_decl)
+    {
+      if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
+       return build_min (SCOPE_REF, TREE_TYPE (member), type, orig_name);
+      else
+       return build_min (SCOPE_REF, TREE_TYPE (member), type, name);
+    }
+
+  if (TREE_CODE (member) == TYPE_DECL)
+    {
+      TREE_USED (member) = 1;
+      return member;
+    }
+  /* static class members and class-specific enum
+     values can be returned without further ado.  */
+  if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
+    {
+      mark_used (member);
+      return convert_from_reference (member);
+    }
+
+  if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
+    {
+      error ("invalid pointer to bit-field `%D'", member);
+      return error_mark_node;
+    }
+
   /* A lot of this logic is now handled in lookup_member.  */
-  if (member && BASELINK_P (member))
+  if (BASELINK_P (member))
     {
       /* Go from the TREE_BASELINK to the member function info.  */
       tree fnfields = member;
@@ -1624,120 +1509,123 @@ build_offset_ref (tree type, tree name)
 
       if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
        {
-         /* Get rid of a potential OVERLOAD around it */
+         /* Get rid of a potential OVERLOAD around it */
          t = OVL_CURRENT (t);
 
-         /* unique functions are handled easily.  */
-         perform_or_defer_access_check (basebinfo, t);
+         /* Unique functions are handled easily.  */
+
+         /* For non-static member of base class, we need a special rule
+            for access checking [class.protected]:
+
+              If the access is to form a pointer to member, the
+              nested-name-specifier shall name the derived class
+              (or any class derived from that class).  */
+         if (address_p && DECL_P (t)
+             && DECL_NONSTATIC_MEMBER_P (t))
+           perform_or_defer_access_check (TYPE_BINFO (type), t);
+         else
+           perform_or_defer_access_check (basebinfo, t);
+
          mark_used (t);
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
-         t = build (OFFSET_REF, TREE_TYPE (t), decl, t);
-         PTRMEM_OK_P (t) = 1;
-         return t;
+         member = t;
+       }
+      else
+       {
+         TREE_TYPE (fnfields) = unknown_type_node;
+         member = fnfields;
        }
-
-      TREE_TYPE (fnfields) = unknown_type_node;
-      
-      t = build (OFFSET_REF, unknown_type_node, decl, fnfields);
-      PTRMEM_OK_P (t) = 1;
-      return t;
     }
+  else if (address_p && TREE_CODE (member) == FIELD_DECL)
+    /* We need additional test besides the one in
+       check_accessibility_of_qualified_id in case it is
+       a pointer to non-static member.  */
+    perform_or_defer_access_check (TYPE_BINFO (type), member);
 
-  if (member == NULL_TREE)
+  if (!address_p)
     {
-      error ("`%D' is not a member of type `%T'", name, type);
-      return error_mark_node;
-    }
+      /* If MEMBER is non-static, then the program has fallen afoul of
+        [expr.prim]:
 
-  if (TREE_CODE (member) == TYPE_DECL)
-    {
-      TREE_USED (member) = 1;
-      return member;
-    }
-  /* static class members and class-specific enum
-     values can be returned without further ado.  */
-  if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
-    {
-      mark_used (member);
-      return convert_from_reference (member);
-    }
+          An id-expression that denotes a nonstatic data member or
+          nonstatic member function of a class can only be used:
 
-  if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
-    {
-      error ("invalid pointer to bit-field `%D'", member);
-      return error_mark_node;
-    }
+          -- as part of a class member access (_expr.ref_) in which the
+          object-expression refers to the member's class or a class
+          derived from that class, or
 
-  /* static class functions too.  */
-  if (TREE_CODE (member) == FUNCTION_DECL
-      && TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
-    abort ();
+          -- to form a pointer to member (_expr.unary.op_), or
+
+          -- in the body of a nonstatic member function of that class or
+          of a class derived from that class (_class.mfct.nonstatic_), or
+
+          -- in a mem-initializer for a constructor for that class or for
+          a class derived from that class (_class.base.init_).  */
+      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
+       {
+         /* Build a representation of a the qualified name suitable
+            for use as the operand to "&" -- even though the "&" is
+            not actually present.  */
+         member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
+         /* In Microsoft mode, treat a non-static member function as if
+            it were a pointer-to-member.  */
+         if (flag_ms_extensions)
+           {
+             PTRMEM_OK_P (member) = 1;
+             return build_unary_op (ADDR_EXPR, member, 0);
+           }
+         error ("invalid use of non-static member function `%D'", 
+                TREE_OPERAND (member, 1));
+         return member;
+       }
+      else if (TREE_CODE (member) == FIELD_DECL)
+       {
+         error ("invalid use of non-static data member `%D'", member);
+         return error_mark_node;
+       }
+      return member;
+    }
 
   /* In member functions, the form `type::name' is no longer
      equivalent to `this->type::name', at least not until
      resolve_offset_ref.  */
-  member = build (OFFSET_REF, build_offset_type (type, TREE_TYPE (member)), 
-                 decl, member);
+  member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
   PTRMEM_OK_P (member) = 1;
   return member;
 }
 
-/* If a OFFSET_REF made it through to here, then it did
-   not have its address taken.  */
-
-tree
-resolve_offset_ref (tree exp)
-{
-  tree member;
-
-  my_friendly_assert (TREE_CODE (exp) == OFFSET_REF, 20030703);
-
-  member = TREE_OPERAND (exp, 1);
-
-  /* If MEMBER is non-static, then the program has fallen afoul of
-     [expr.prim]:
-
-       An id-expression that denotes a nonstatic data member or
-       nonstatic member function of a class can only be used:
-
-       -- as part of a class member access (_expr.ref_) in which the
-       object-expression refers to the member's class or a class
-       derived from that class, or
-
-       -- to form a pointer to member (_expr.unary.op_), or
-
-       -- in the body of a nonstatic member function of that class or
-       of a class derived from that class (_class.mfct.nonstatic_), or
-
-       -- in a mem-initializer for a constructor for that class or for
-       a class derived from that class (_class.base.init_).  */
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
-    {
-      /* In Microsoft mode, treat a non-static member function as if
-        it were a pointer-to-member.  */
-      if (flag_ms_extensions)
-       return build_unary_op (ADDR_EXPR, exp, 0);
-      error ("invalid use of non-static member function `%D'", member);
-      return error_mark_node;
-    }
-  else if (TREE_CODE (member) == FIELD_DECL)
-    {
-      error ("invalid use of non-static data member `%D'", member);
-      return error_mark_node;
-    }
-
-  return member;
-}
-
 /* If DECL is a `const' declaration, and its value is a known
    constant, then return that value.  */
 
 tree
 decl_constant_value (tree decl)
 {
-  if (TREE_READONLY_DECL_P (decl)
-      && ! TREE_THIS_VOLATILE (decl)
+  /* When we build a COND_EXPR, we don't know whether it will be used
+     as an lvalue or as an rvalue.  If it is an lvalue, it's not safe
+     to replace the second and third operands with their
+     initializers.  So, we do that here.  */
+  if (TREE_CODE (decl) == COND_EXPR)
+    {
+      tree d1;
+      tree d2;
+
+      d1 = decl_constant_value (TREE_OPERAND (decl, 1));
+      d2 = decl_constant_value (TREE_OPERAND (decl, 2));
+
+      if (d1 != TREE_OPERAND (decl, 1) || d2 != TREE_OPERAND (decl, 2))
+       return build (COND_EXPR,
+                     TREE_TYPE (decl),
+                     TREE_OPERAND (decl, 0), d1, d2);
+    }
+
+  if (DECL_P (decl)
+      && (/* Enumeration constants are constant.  */
+         TREE_CODE (decl) == CONST_DECL
+         /* And so are variables with a 'const' type -- unless they
+            are also 'volatile'.  */
+         || CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))
+      && TREE_CODE (decl) != PARM_DECL
       && DECL_INITIAL (decl)
       && DECL_INITIAL (decl) != error_mark_node
       /* This is invalid if initial value is not constant.
@@ -1818,7 +1706,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
 
       if (absdcl && TREE_CODE (absdcl) == ARRAY_REF)
        {
-         /* probably meant to be a vec new */
+         /* Probably meant to be a vec new.  */
          tree this_nelts;
 
          while (TREE_OPERAND (absdcl, 0)
@@ -1908,6 +1796,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
       rval = build_min (NEW_EXPR, build_pointer_type (type), 
                        placement, t, init);
       NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
+      TREE_SIDE_EFFECTS (rval) = 1;
       return rval;
     }
 
@@ -1950,7 +1839,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
 
   /* 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;
+  TREE_NO_WARNING (rval) = 1;
 
   return rval;
 }
@@ -1973,7 +1862,7 @@ build_java_class_ref (tree type)
       jclass_node = TREE_TYPE (jclass_node);
     }
 
-  /* Mangle the class$ field */
+  /* Mangle the class$ field */
   {
     tree field;
     for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
@@ -2033,7 +1922,7 @@ static tree
 build_new_1 (tree exp)
 {
   tree placement, init;
-  tree true_type, size, rval, t;
+  tree true_type, size, rval;
   /* The type of the new-expression.  (This type is always a pointer
      type.)  */
   tree pointer_type;
@@ -2067,13 +1956,14 @@ build_new_1 (tree exp)
   bool placement_allocation_fn_p;
   tree args = NULL_TREE;
   /* True if the storage must be initialized, either by a constructor
-     or due to an explicit new-intiailizer.  */
+     or due to an explicit new-initializer.  */
   bool is_initialized;
   /* The address of the thing allocated, not including any cookie.  In
      particular, if an array cookie is in use, DATA_ADDR is the
      address of the first array element.  This node is a VAR_DECL, and
      is therefore reusable.  */
   tree data_addr;
+  tree init_preeval_expr = NULL_TREE;
 
   placement = TREE_OPERAND (exp, 0);
   type = TREE_OPERAND (exp, 1);
@@ -2133,23 +2023,31 @@ build_new_1 (tree exp)
     {
       tree class_addr, alloc_decl;
       tree class_decl = build_java_class_ref (true_type);
-      tree class_size = size_in_bytes (true_type);
       static const char alloc_name[] = "_Jv_AllocObject";
-      use_java_new = 1;
-      alloc_decl = IDENTIFIER_GLOBAL_VALUE (get_identifier (alloc_name));
-      if (alloc_decl == NULL_TREE)
-       fatal_error ("call to Java constructor with `%s' undefined",
-                    alloc_name);
 
+      use_java_new = 1;
+      alloc_decl = NULL;
+      if (!get_global_value_if_present (get_identifier (alloc_name), 
+                                       &alloc_decl))
+       {
+         error ("call to Java constructor with `%s' undefined", alloc_name);
+         return error_mark_node;
+       }
+      else if (really_overloaded_fn (alloc_decl))
+       {
+         error ("`%D' should never be overloaded", alloc_decl);
+         return error_mark_node;
+       }
+      alloc_decl = OVL_CURRENT (alloc_decl);
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
       alloc_call = (build_function_call
                    (alloc_decl,
-                    tree_cons (NULL_TREE, class_addr,
-                               build_tree_list (NULL_TREE, class_size))));
+                    build_tree_list (NULL_TREE, class_addr)));
     }
   else
     {
       tree fnname;
+      tree fns;
 
       fnname = ansi_opname (code);
 
@@ -2168,11 +2066,18 @@ build_new_1 (tree exp)
            }
          /* Create the argument list.  */
          args = tree_cons (NULL_TREE, size, placement);
-         /* Call the function.  */
-         alloc_call = build_method_call (build_dummy_object (true_type),
-                                         fnname, args, 
-                                         TYPE_BINFO (true_type),
-                                         LOOKUP_NORMAL);
+         /* Do name-lookup to find the appropriate operator.  */
+         fns = lookup_fnfields (true_type, fnname, /*protect=*/2);
+         if (TREE_CODE (fns) == TREE_LIST)
+           {
+             error ("request for member `%D' is ambiguous", fnname);
+             print_candidates (fns);
+             return error_mark_node;
+           }
+         alloc_call = build_new_method_call (build_dummy_object (true_type),
+                                             fns, args,
+                                             /*conversion_path=*/NULL_TREE,
+                                             LOOKUP_NORMAL);
        }
       else
        {
@@ -2191,13 +2096,22 @@ build_new_1 (tree exp)
   if (alloc_call == error_mark_node)
     return error_mark_node;
 
-  /* The ALLOC_CALL should be a CALL_EXPR -- or a COMPOUND_EXPR whose
-     right-hand-side is ultimately a CALL_EXPR -- and the first
-     operand should be the address of a known FUNCTION_DECL.  */
-  t = alloc_call;
-  while (TREE_CODE (t) == COMPOUND_EXPR) 
-    t = TREE_OPERAND (t, 1);
-  alloc_fn = get_callee_fndecl (t);
+  /* In the simple case, we can stop now.  */
+  pointer_type = build_pointer_type (type);
+  if (!cookie_size && !is_initialized)
+    return build_nop (pointer_type, alloc_call);
+
+  /* While we're working, use a pointer to the type we've actually
+     allocated. Store the result of the call in a variable so that we
+     can use it more than once.  */
+  full_pointer_type = build_pointer_type (full_type);
+  alloc_expr = get_target_expr (build_nop (full_pointer_type, alloc_call));
+  alloc_node = TARGET_EXPR_SLOT (alloc_expr);
+
+  /* Strip any COMPOUND_EXPRs from ALLOC_CALL.  */
+  while (TREE_CODE (alloc_call) == COMPOUND_EXPR) 
+    alloc_call = TREE_OPERAND (alloc_call, 1);
+  alloc_fn = get_callee_fndecl (alloc_call);
   my_friendly_assert (alloc_fn != NULL_TREE, 20020325);
 
   /* Now, check to see if this function is actually a placement
@@ -2214,6 +2128,17 @@ build_new_1 (tree exp)
     = (type_num_arguments (TREE_TYPE (alloc_fn)) > 1 
        || varargs_function_p (alloc_fn));
 
+  /* Preevaluate the placement args so that we don't reevaluate them for a
+     placement delete.  */
+  if (placement_allocation_fn_p)
+    {
+      tree inits;
+      stabilize_call (alloc_call, &inits);
+      if (inits)
+       alloc_expr = build (COMPOUND_EXPR, TREE_TYPE (alloc_expr), inits,
+                           alloc_expr);
+    }
+
   /*        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_,
@@ -2227,18 +2152,6 @@ build_new_1 (tree exp)
   nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
   check_new = (flag_check_new || nothrow) && ! use_java_new;
 
-  /* In the simple case, we can stop now.  */
-  pointer_type = build_pointer_type (type);
-  if (!cookie_size && !is_initialized)
-    return build_nop (pointer_type, alloc_call);
-
-  /* While we're working, use a pointer to the type we've actually
-     allocated. Store the result of the call in a variable so that we
-     can use it more than once.  */
-  full_pointer_type = build_pointer_type (full_type);
-  alloc_expr = get_target_expr (build_nop (full_pointer_type, alloc_call));
-  alloc_node = TARGET_EXPR_SLOT (alloc_expr);
-
   if (cookie_size)
     {
       tree cookie;
@@ -2263,47 +2176,57 @@ build_new_1 (tree exp)
       data_addr = alloc_node;
     }
 
-  /* Now initialize the allocated object.  */
+  /* Now initialize the allocated object.  Note that we preevaluate the
+     initialization expression, apart from the actual constructor call or
+     assignment--we do this because we want to delay the allocation as long
+     as possible in order to minimize the size of the exception region for
+     placement delete.  */
   if (is_initialized)
     {
+      bool stable;
+
       init_expr = build_indirect_ref (data_addr, NULL);
 
       if (init == void_zero_node)
        init = build_default_init (full_type, nelts);
-      else if (init && pedantic && has_array)
+      else if (init && has_array)
        pedwarn ("ISO C++ forbids initialization in array new");
 
       if (has_array)
-       init_expr
-         = build_vec_init (init_expr,
-                           cp_build_binary_op (MINUS_EXPR, outer_nelts,
-                                               integer_one_node),
-                           init, /*from_array=*/0);
+       {
+         init_expr
+           = build_vec_init (init_expr,
+                             cp_build_binary_op (MINUS_EXPR, outer_nelts,
+                                                 integer_one_node),
+                             init, /*from_array=*/0);
+
+         /* An array initialization is stable because the initialization
+            of each element is a full-expression, so the temporaries don't
+            leak out.  */
+         stable = true;
+       }
       else if (TYPE_NEEDS_CONSTRUCTING (type))
-       init_expr = build_special_member_call (init_expr, 
-                                              complete_ctor_identifier,
-                                              init, TYPE_BINFO (true_type),
-                                              LOOKUP_NORMAL);
+       {
+         init_expr = build_special_member_call (init_expr, 
+                                                complete_ctor_identifier,
+                                                init, TYPE_BINFO (true_type),
+                                                LOOKUP_NORMAL);
+         stable = stabilize_init (init_expr, &init_preeval_expr);
+       }
       else
        {
          /* We are processing something like `new int (10)', which
             means allocate an int, and initialize it with 10.  */
 
          if (TREE_CODE (init) == TREE_LIST)
-           {
-             if (TREE_CHAIN (init) != NULL_TREE)
-               pedwarn
-                 ("initializer list being treated as compound expression");
-             init = build_compound_expr (init);
-           }
+           init = build_x_compound_expr_from_list (init, "new initializer");
+
          else if (TREE_CODE (init) == CONSTRUCTOR
                   && TREE_TYPE (init) == NULL_TREE)
-           {
-             pedwarn ("ISO C++ forbids aggregate initializer to new");
-             init = digest_init (type, init, 0);
-           }
+           abort ();
 
          init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
+         stable = stabilize_init (init_expr, &init_preeval_expr);
        }
 
       if (init_expr == error_mark_node)
@@ -2321,43 +2244,33 @@ build_new_1 (tree exp)
        {
          enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
          tree cleanup;
-         int flags = (LOOKUP_NORMAL 
-                      | (globally_qualified_p * LOOKUP_GLOBAL));
 
          /* The Standard is unclear here, but the right thing to do
             is to use the same method for finding deallocation
             functions that we use for finding allocation functions.  */
-         flags |= LOOKUP_SPECULATIVELY;
-
-         cleanup = build_op_delete_call (dcode, alloc_node, size, flags,
+         cleanup = build_op_delete_call (dcode, alloc_node, size, 
+                                         globally_qualified_p,
                                          (placement_allocation_fn_p 
                                           ? alloc_call : NULL_TREE));
 
-         /* Ack!  First we allocate the memory.  Then we set our sentry
-            variable to true, and expand a cleanup that deletes the memory
-            if sentry is true.  Then we run the constructor, and finally
-            clear the sentry.
-
-            It would be nice to be able to handle this without the sentry
-            variable, perhaps with a TRY_CATCH_EXPR, but this doesn't
-            work.  We allocate the space first, so if there are any
-            temporaries with cleanups in the constructor args we need this
-            EH region to extend until end of full-expression to preserve
-            nesting.
-
-            If the backend had some mechanism so that we could force the
-            allocation to be expanded after all the other args to the
-            constructor, that would fix the nesting problem and we could
-            do away with this complexity.  But that would complicate other
-            things; in particular, it would make it difficult to bail out
-            if the allocation function returns null.  Er, no, it wouldn't;
-            we just don't run the constructor.  The standard says it's
-            unspecified whether or not the args are evaluated.
-
-            FIXME FIXME FIXME inline invisible refs as refs.  That way we
-            can preevaluate value parameters.  */
-
-         if (cleanup)
+         if (!cleanup)
+           /* We're done.  */;
+         else if (stable)
+           /* This is much simpler if we were able to preevaluate all of
+              the arguments to the constructor call.  */
+           init_expr = build (TRY_CATCH_EXPR, void_type_node,
+                              init_expr, cleanup);
+         else
+           /* 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
+              finally clear the sentry.
+
+              We need to do this because we allocate the space first, so
+              if there are any temporaries with cleanups in the
+              constructor args and we weren't able to preevaluate them, we
+              need this EH region to extend until end of full-expression
+              to preserve nesting.  */
            {
              tree end, sentry, begin;
 
@@ -2378,6 +2291,7 @@ build_new_1 (tree exp)
                         build (COMPOUND_EXPR, void_type_node, init_expr,
                                end));
            }
+           
        }
     }
   else
@@ -2410,8 +2324,17 @@ build_new_1 (tree exp)
       rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
     }
 
+  if (init_preeval_expr)
+    rval = build (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval);
+
   /* Convert to the final type.  */
-  return build_nop (pointer_type, rval);
+  rval = build_nop (pointer_type, rval);
+
+  /* A new-expression is never an lvalue.  */
+  if (real_lvalue_p (rval))
+    rval = build1 (NON_LVALUE_EXPR, TREE_TYPE (rval), rval);
+
+  return rval;
 }
 \f
 static tree
@@ -2430,7 +2353,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   tree body;
 
   /* This is the LOOP_EXPR that governs the deletion of the elements.  */
-  tree loop;
+  tree loop = 0;
 
   /* This is the thing that governs what to do after the loop has run.  */
   tree deallocate_expr = 0;
@@ -2446,10 +2369,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
     abort ();
 
   if (! IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
-    {
-      loop = integer_zero_node;
-      goto no_destructor;
-    }
+    goto no_destructor;
 
   /* The below is short by the cookie size.  */
   virtual_size = size_binop (MULT_EXPR, size_exp,
@@ -2464,32 +2384,21 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (controller) = 1;
 
-  body = NULL_TREE;
-
-  body = tree_cons (NULL_TREE,
-                   build_delete (ptype, tbase, sfk_complete_destructor,
-                                 LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
-                   body);
-
-  body = tree_cons (NULL_TREE,
-                   build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
-                   body);
+  body = build (EXIT_EXPR, void_type_node,
+               build (EQ_EXPR, boolean_type_node, base, tbase));
+  body = build_compound_expr
+    (body, build_modify_expr (tbase, NOP_EXPR,
+                             build (MINUS_EXPR, ptype, tbase, size_exp)));
+  body = build_compound_expr
+    (body, build_delete (ptype, tbase, sfk_complete_destructor,
+                        LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1));
 
-  body = tree_cons (NULL_TREE,
-                   build (EXIT_EXPR, void_type_node,
-                          build (EQ_EXPR, boolean_type_node, base, tbase)),
-                   body);
-
-  loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
-
-  loop = tree_cons (NULL_TREE, tbase_init,
-                   tree_cons (NULL_TREE, loop, NULL_TREE));
-  loop = build_compound_expr (loop);
+  loop = build (LOOP_EXPR, void_type_node, body);
+  loop = build_compound_expr (tbase_init, loop);
 
  no_destructor:
   /* If the delete flag is one, or anything else with the low bit set,
      delete the storage.  */
-  deallocate_expr = integer_zero_node;
   if (auto_delete_vec != sfk_base_destructor)
     {
       tree base_tbd;
@@ -2522,19 +2431,22 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
                                          virtual_size);
     }
 
-  if (loop && deallocate_expr != integer_zero_node)
-    {
-      body = tree_cons (NULL_TREE, loop,
-                       tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
-      body = build_compound_expr (body);
-    }
+  body = loop;
+  if (!deallocate_expr)
+    ;
+  else if (!body)
+    body = deallocate_expr;
   else
-    body = loop;
-
+    body = build_compound_expr (body, deallocate_expr);
+  
+  if (!body)
+    body = integer_zero_node;
+  
   /* Outermost wrapper: If pointer is null, punt.  */
   body = fold (build (COND_EXPR, void_type_node,
                      fold (build (NE_EXPR, boolean_type_node, base,
-                                  integer_zero_node)),
+                                  convert (TREE_TYPE (base),
+                                           integer_zero_node))),
                      body, integer_zero_node));
   body = build1 (NOP_EXPR, void_type_node, body);
 
@@ -2581,10 +2493,8 @@ get_temp_regvar (tree type, tree init)
   tree decl;
 
   decl = create_temporary_var (type);
-  if (building_stmt_tree ())
-    add_decl_stmt (decl);
-  else
-    SET_DECL_RTL (decl, assign_temp (type, 2, 0, 1));
+  add_decl_stmt (decl);
+  
   finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
 
   return decl;
@@ -2626,7 +2536,8 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
   tree try_block = NULL_TREE;
   tree try_body = NULL_TREE;
   int num_initialized_elts = 0;
-
+  bool is_global;
+  
   if (TYPE_DOMAIN (atype))
     maxindex = array_type_nelts (atype);
 
@@ -2656,10 +2567,10 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
   ptype = build_pointer_type (type);
   size = size_in_bytes (type);
   if (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
-    base = cp_convert (ptype, default_conversion (base));
+    base = cp_convert (ptype, decay_conversion (base));
 
   /* The code we are generating looks like:
-
+     ({
        T* t1 = (T*) base;
        T* rval = t1;
        ptrdiff_t iterator = maxindex;
@@ -2671,7 +2582,8 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
        } catch (...) {
          ... destroy elements that were constructed ...
        }
-       return rval;
+       rval;
+     })
        
      We can omit the try and catch blocks if we know that the
      initialization will never throw an exception, or if the array
@@ -2687,7 +2599,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
      of whatever cleverness the back-end has for dealing with copies
      of blocks of memory.  */
 
-  begin_init_stmts (&stmt_expr, &compound_stmt);
+  is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
   destroy_temps = stmts_are_full_exprs_p ();
   current_stmt_tree ()->stmts_are_full_exprs_p = 0;
   rval = get_temp_regvar (ptype, base);
@@ -2701,7 +2613,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
       && from_array != 2)
     {
       try_block = begin_try_block ();
-      try_body = begin_compound_stmt (/*has_no_scope=*/1);
+      try_body = begin_compound_stmt (/*has_no_scope=*/true);
     }
 
   if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
@@ -2719,11 +2631,13 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
 
          num_initialized_elts++;
 
+         current_stmt_tree ()->stmts_are_full_exprs_p = 1;
          if (IS_AGGR_TYPE (type) || TREE_CODE (type) == ARRAY_TYPE)
            finish_expr_stmt (build_aggr_init (baseref, elt, 0));
          else
            finish_expr_stmt (build_modify_expr (baseref, NOP_EXPR,
                                                 elt));
+         current_stmt_tree ()->stmts_are_full_exprs_p = 0;
 
          finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base, 0));
          finish_expr_stmt (build_unary_op (PREDECREMENT_EXPR, iterator, 0));
@@ -2739,7 +2653,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
         checking.  */ 
       if (init)
        {
-         base2 = default_conversion (init);
+         base2 = decay_conversion (init);
          itype = TREE_TYPE (base2);
          base2 = get_temp_regvar (itype, base2);
          itype = TREE_TYPE (itype);
@@ -2780,21 +2694,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
                       for_stmt);
 
       /* Otherwise, loop through the elements.  */
-      for_body = begin_compound_stmt (/*has_no_scope=*/1);
-
-      /* When we're not building a statement-tree, things are a little
-        complicated.  If, when we recursively call build_aggr_init,
-        an expression containing a TARGET_EXPR is expanded, then it
-        may get a cleanup.  Then, the result of that expression is
-        passed to finish_expr_stmt, which will call
-        expand_start_target_temps/expand_end_target_temps.  However,
-        the latter call will not cause the cleanup to run because
-        that block will still be on the block stack.  So, we call
-        expand_start_target_temps here manually; the corresponding
-        call to expand_end_target_temps below will cause the cleanup
-        to be performed.  */
-      if (!building_stmt_tree ())
-       expand_start_target_temps ();
+      for_body = begin_compound_stmt (/*has_no_scope=*/true);
 
       if (from_array)
        {
@@ -2827,25 +2727,15 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
        elt_init = build_aggr_init (build1 (INDIRECT_REF, type, base), 
                                    init, 0);
       
-      /* The initialization of each array element is a
-        full-expression, as per core issue 124.  */
-      if (!building_stmt_tree ())
-       {
-         genrtl_expr_stmt (elt_init);
-         expand_end_target_temps ();
-       }
-      else
-       {
-         current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-         finish_expr_stmt (elt_init);
-         current_stmt_tree ()->stmts_are_full_exprs_p = 0;
-       }
+      current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+      finish_expr_stmt (elt_init);
+      current_stmt_tree ()->stmts_are_full_exprs_p = 0;
 
       finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base, 0));
       if (base2)
        finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base2, 0));
 
-      finish_compound_stmt (/*has_no_scope=*/1, for_body);
+      finish_compound_stmt (for_body);
       finish_for_stmt (for_stmt);
     }
 
@@ -2865,20 +2755,24 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
          type = strip_array_types (type);
        }
 
-      finish_compound_stmt (/*has_no_scope=*/1, try_body);
+      finish_compound_stmt (try_body);
       finish_cleanup_try_block (try_block);
-      e = build_vec_delete_1 (rval, m,
-                             type,
-                             sfk_base_destructor,
+      e = build_vec_delete_1 (rval, m, type, sfk_base_destructor,
                              /*use_global_delete=*/0);
       finish_cleanup (e, try_block);
     }
 
-  /* The value of the array initialization is the address of the
-     first element in the array.  */
-  finish_expr_stmt (rval);
+  /* The value of the array initialization is the array itself, RVAL
+     is a pointer to the first element.  */
+  finish_stmt_expr_expr (rval);
 
-  stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
+  stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
+
+  /* Now convert make the result have the correct type.  */
+  atype = build_pointer_type (atype);
+  stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
+  stmt_expr = build_indirect_ref (stmt_expr, NULL);
+  
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
   return stmt_expr;
 }
@@ -2903,9 +2797,9 @@ build_x_delete (tree addr, int which_delete, tree virtual_size)
   int use_global_delete = which_delete & 1;
   int use_vec_delete = !!(which_delete & 2);
   enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR;
-  int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL);
 
-  return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE);
+  return build_op_delete_call (code, addr, virtual_size, use_global_delete, 
+                              NULL_TREE);
 }
 
 /* Call the DTOR_KIND destructor for EXP.  FLAGS are as for
@@ -2915,7 +2809,7 @@ static tree
 build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
 {
   tree name;
-
+  tree fn;
   switch (dtor_kind)
     {
     case sfk_complete_destructor:
@@ -2933,8 +2827,13 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
     default:
       abort ();
     }
-  return build_method_call (exp, name, NULL_TREE, 
-                           TYPE_BINFO (TREE_TYPE (exp)), flags);
+
+  exp = convert_from_reference (exp);
+  fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2);
+  return build_new_method_call (exp, fn, 
+                               /*args=*/NULL_TREE,
+                               /*conversion_path=*/NULL_TREE,
+                               flags);
 }
 
 /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -2964,27 +2863,39 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
+      bool complete_p = true;
+
       type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
       if (TREE_CODE (type) == ARRAY_TYPE)
        goto handle_array;
 
-      if (VOID_TYPE_P (type)
-         /* We don't want to warn about delete of void*, only other
-            incomplete types.  Deleting other incomplete types
-            invokes undefined behavior, but it is not ill-formed, so
-            compile to something that would even do The Right Thing
-            (TM) should the type have a trivial dtor and no delete
-            operator.  */
-         || !complete_type_or_diagnostic (type, addr, 1)
-         || !IS_AGGR_TYPE (type))
+      /* We don't want to warn about delete of void*, only other
+         incomplete types.  Deleting other incomplete types
+         invokes undefined behavior, but it is not ill-formed, so
+         compile to something that would even do The Right Thing
+         (TM) should the type have a trivial dtor and no delete
+         operator.  */
+      if (!VOID_TYPE_P (type))
        {
-         /* Call the builtin operator delete.  */
-         return build_builtin_delete_call (addr);
+         complete_type (type);
+         if (!COMPLETE_TYPE_P (type))
+           {
+             warning ("possible problem detected in invocation of "
+                      "delete operator:");
+             cxx_incomplete_type_diagnostic (addr, type, 1);
+             inform ("neither the destructor nor the class-specific "\r
+                     "operator delete will be called, even if they are "\r
+                     "declared when the class is defined.");
+             complete_p = false;
+           }
        }
+      if (VOID_TYPE_P (type) || !complete_p || !IS_AGGR_TYPE (type))
+       /* Call the builtin operator delete.  */
+       return build_builtin_delete_call (addr);
       if (TREE_SIDE_EFFECTS (addr))
        addr = save_expr (addr);
 
-      /* throw away const and volatile on target type of addr */
+      /* Throw away const and volatile on target type of addr.  */
       addr = convert_force (build_pointer_type (type), addr, 0);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
@@ -3019,8 +2930,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
        return void_zero_node;
 
       return build_op_delete_call
-       (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
-        LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
+       (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), use_global_delete,
         NULL_TREE);
     }
   else
@@ -3055,7 +2965,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          do_delete = build_op_delete_call (DELETE_EXPR,
                                            addr,
                                            cxx_sizeof_nowarn (type),
-                                           LOOKUP_NORMAL,
+                                           /*global_p=*/false,
                                            NULL_TREE);
          /* Call the complete object destructor.  */
          auto_delete = sfk_complete_destructor;
@@ -3066,7 +2976,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          /* Make sure we have access to the member op delete, even though
             we'll actually be calling it from the destructor.  */
          build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
-                               LOOKUP_NORMAL, NULL_TREE);
+                               /*global_p=*/false, NULL_TREE);
        }
 
       expr = build_dtor_call (build_indirect_ref (addr, NULL),
@@ -3095,7 +3005,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
    Called from begin_destructor_body.  */
 
 void
-push_base_cleanups ()
+push_base_cleanups (void)
 {
   tree binfos;
   int i, n_baseclasses;
@@ -3180,24 +3090,23 @@ tree
 build_vbase_delete (tree type, tree decl)
 {
   tree vbases = CLASSTYPE_VBASECLASSES (type);
-  tree result = NULL_TREE;
+  tree result;
   tree addr = build_unary_op (ADDR_EXPR, decl, 0);
 
   my_friendly_assert (addr != error_mark_node, 222);
 
-  while (vbases)
+  for (result = convert_to_void (integer_zero_node, NULL);
+       vbases; vbases = TREE_CHAIN (vbases))
     {
-      tree this_addr 
-       = convert_force (build_pointer_type (BINFO_TYPE (TREE_VALUE (vbases))),
-                        addr, 0);
-      result = tree_cons (NULL_TREE,
-                         build_delete (TREE_TYPE (this_addr), this_addr,
-                                       sfk_base_destructor,
-                                       LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0),
-                         result);
-      vbases = TREE_CHAIN (vbases);
+      tree base_addr = convert_force
+       (build_pointer_type (BINFO_TYPE (TREE_VALUE (vbases))), addr, 0);
+      tree base_delete = build_delete
+       (TREE_TYPE (base_addr), base_addr, sfk_base_destructor,
+        LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
+      
+      result = build_compound_expr (result, base_delete);
     }
-  return build_compound_expr (nreverse (result));
+  return result;
 }
 
 /* Build a C++ vector delete expression.
@@ -3245,7 +3154,8 @@ build_vec_delete (tree base, tree maxindex,
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      /* get the total number of things in the array, maxindex is a bad name */
+      /* Get the total number of things in the array, maxindex is a
+        bad name.  */
       maxindex = array_type_nelts_total (type);
       type = strip_array_types (type);
       base = build_unary_op (ADDR_EXPR, base, 1);