langhooks.h (struct lang_hooks_for_tree_inlining): Add start_inlining, end_inlining.
[gcc.git] / gcc / cp / init.c
index f680ee0425cc9937ba22c94fb7a35e49f8310b95..098697fa5a7c309206f1d7f40c2559d1b8f9f4f3 100644 (file)
@@ -42,7 +42,7 @@ static tree build_vec_delete_1 PARAMS ((tree, tree, tree, special_function_kind,
 static void perform_member_init PARAMS ((tree, tree, int));
 static void sort_base_init PARAMS ((tree, tree, tree *, tree *));
 static tree build_builtin_delete_call PARAMS ((tree));
-static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
+static int member_init_ok_or_else PARAMS ((tree, tree, tree));
 static void expand_virtual_init PARAMS ((tree, tree));
 static tree sort_member_init PARAMS ((tree, tree));
 static tree initializing_context PARAMS ((tree));
@@ -130,7 +130,9 @@ finish_init_stmts (stmt_expr, compound_stmt)
 
 /* Constructors */
 
-/* Called from initialize_vtbl_ptrs via dfs_walk.  */
+/* Called from initialize_vtbl_ptrs via dfs_walk.  BINFO is the base
+   which we want to initialize the vtable pointer for, DATA is
+   TREE_LIST whose TREE_VALUE is the this ptr expression.  */
 
 static tree
 dfs_initialize_vtbl_ptrs (binfo, data)
@@ -142,16 +144,7 @@ dfs_initialize_vtbl_ptrs (binfo, data)
     {
       tree base_ptr = TREE_VALUE ((tree) data);
 
-      if (TREE_VIA_VIRTUAL (binfo))
-       base_ptr = convert_pointer_to_vbase (BINFO_TYPE (binfo),
-                                            base_ptr);
-      else
-       base_ptr 
-         = build_vbase_path (PLUS_EXPR, 
-                             build_pointer_type (BINFO_TYPE (binfo)),
-                             base_ptr,
-                             binfo,
-                             /*nonnull=*/1);
+      base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1);
 
       expand_virtual_init (binfo, base_ptr);
     }
@@ -175,21 +168,13 @@ initialize_vtbl_ptrs (addr)
   list = build_tree_list (type, addr);
 
   /* Walk through the hierarchy, initializing the vptr in each base
-     class.  We do these in pre-order because under the new ABI we
-     can't find the virtual bases for a class until we've initialized
-     the vtbl for that class.  */
+     class.  We do these in pre-order because can't find the virtual
+     bases for a class until we've initialized the vtbl for that
+     class.  */
   dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, 
                 NULL, dfs_unmarked_real_bases_queue_p, list);
   dfs_walk (TYPE_BINFO (type), dfs_unmark,
            dfs_marked_real_bases_queue_p, type);
-
-  /* If we're not using thunks, we may need to adjust the deltas in
-     the vtable to handle virtual base classes correctly.  When we are
-     using thunks, we either use construction vtables (which are
-     preloaded with the right answers) or nothing (in which case
-     vitual function calls sometimes don't work right.)  */
-  if (TYPE_USES_VIRTUAL_BASECLASSES (type) && !flag_vtable_thunks)
-    fixup_all_virtual_upcast_offsets (addr);
 }
 
 /* [dcl.init]:
@@ -565,68 +550,40 @@ sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr)
   tree vbases = NULL_TREE;
 
   /* First walk through and splice out vbase and invalid initializers.
-     Also replace names with binfos.  */
+     Also replace types with binfos.  */
 
   last = tree_cons (NULL_TREE, NULL_TREE, base_init_list);
   for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
     {
       tree basetype = TREE_PURPOSE (x);
-      tree binfo = NULL_TREE;
+      tree binfo = (TREE_CODE (basetype) == TREE_VEC
+                   ? basetype : binfo_or_else (basetype, t));
+      
+      if (binfo == NULL_TREE)
+       /* BASETYPE might be an inaccessible direct base (because it
+          is also an indirect base).  */
+       continue;
 
-      if (basetype == NULL_TREE)
+      if (TREE_VIA_VIRTUAL (binfo))
        {
-         /* Initializer for single base class.  Must not
-            use multiple inheritance or this is ambiguous.  */
-         switch (n_baseclasses)
-           {
-           case 0:
-             cp_error ("`%T' does not have a base class to initialize",
-                       current_class_type);
-             return;
-           case 1:
-             break;
-           default:
-             cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
-                       current_class_type);
-             return;
-           }
-         binfo = TREE_VEC_ELT (binfos, 0);
+         /* Virtual base classes are special cases.  Their
+            initializers are recorded with this constructor, and they
+            are used when this constructor is the top-level
+            constructor called.  */
+         tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
+         vbases = tree_cons (v, TREE_VALUE (x), vbases);
        }
-      else if (is_aggr_type (basetype, 1))
+      else
        {
-         binfo = binfo_or_else (basetype, t);
-         if (binfo == NULL_TREE)
-           continue;
-
-         /* Virtual base classes are special cases.  Their initializers
-            are recorded with this constructor, and they are used when
-            this constructor is the top-level constructor called.  */
-         if (TREE_VIA_VIRTUAL (binfo))
-           {
-             tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
-             vbases = tree_cons (v, TREE_VALUE (x), vbases);
-             continue;
-           }
-         else
-           {
-             /* Otherwise, if it is not an immediate base class, complain.  */
-             for (i = n_baseclasses-1; i >= 0; i--)
-               if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
-                 break;
-             if (i < 0)
-               {
-                 cp_error ("`%T' is not an immediate base class of `%T'",
-                           basetype, current_class_type);
-                 continue;
-               }
-           }
+         /* Otherwise, it must be an immediate base class.  */
+         my_friendly_assert
+           (same_type_p (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
+                         t), 20011113);
+
+         TREE_PURPOSE (x) = binfo;
+         TREE_CHAIN (last) = x;
+         last = x;
        }
-      else
-       my_friendly_abort (365);
-
-      TREE_PURPOSE (x) = binfo;
-      TREE_CHAIN (last) = x;
-      last = x;
     }
   TREE_CHAIN (last) = NULL_TREE;
 
@@ -748,9 +705,10 @@ emit_base_init (mem_init_list, base_init_list)
 
       if (init != void_list_node)
        {
-         member = convert_pointer_to_real (base_binfo, current_class_ptr);
+         member = build_base_path (PLUS_EXPR, current_class_ptr,
+                                   base_binfo, 1);
          expand_aggr_init_1 (base_binfo, NULL_TREE,
-                             build_indirect_ref (member, NULL_PTR), init,
+                             build_indirect_ref (member, NULL), init,
                              LOOKUP_NORMAL);
        }
 
@@ -839,20 +797,14 @@ static void
 expand_virtual_init (binfo, decl)
      tree binfo, decl;
 {
-  tree type = BINFO_TYPE (binfo);
   tree vtbl, vtbl_ptr;
-  tree vtype, vtype_binfo;
   tree vtt_index;
 
-  /* Compute the location of the vtable.  */
-  vtype = DECL_CONTEXT (TYPE_VFIELD (type));
-  vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
-  
   /* Compute the initializer for vptr.  */
   vtbl = build_vtbl_address (binfo);
 
-  /* Under the new ABI, we may get this vptr from a VTT, if this is a
-     subobject constructor or subobject destructor.  */
+  /* We may get this vptr from a VTT, if this is a subobject
+     constructor or subobject destructor.  */
   vtt_index = BINFO_VPTR_INDEX (binfo);
   if (vtt_index)
     {
@@ -879,10 +831,9 @@ expand_virtual_init (binfo, decl)
     }
 
   /* Compute the location of the vtpr.  */
-  decl = convert_pointer_to_real (vtype_binfo, decl);
-  vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
-  if (vtbl_ptr == error_mark_node)
-    return;
+  vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL),
+                              TREE_TYPE (binfo));
+  my_friendly_assert (vtbl_ptr != error_mark_node, 20010730);
 
   /* Assign the vtable to the vptr.  */
   vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
@@ -925,7 +876,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
      tree binfo, exp, addr, init_list;
 {
   tree init = purpose_member (binfo, init_list);
-  tree ref = build_indirect_ref (addr, NULL_PTR);
+  tree ref = build_indirect_ref (addr, NULL);
 
   if (init)
     init = TREE_VALUE (init);
@@ -951,22 +902,6 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
   /* If there are no virtual baseclasses, we shouldn't even be here.  */
   my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
 
-  /* First set the pointers in our object that tell us where to find
-     our virtual baseclasses.  */
-  if (!vbase_offsets_in_vtable_p ())
-    {
-      tree if_stmt;
-      tree result;
-
-      if_stmt = begin_if_stmt ();
-      finish_if_stmt_cond (flag, if_stmt);
-      result = init_vbase_pointers (type, this_ptr);
-      if (result)
-       finish_expr_stmt (build_compound_expr (result));
-      finish_then_clause (if_stmt);
-      finish_if_stmt ();
-    }
-
   /* Now, run through the baseclasses, initializing each.  */ 
   for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
        vbases = TREE_CHAIN (vbases))
@@ -1043,19 +978,19 @@ static int
 member_init_ok_or_else (field, type, member_name)
      tree field;
      tree type;
-     const char *member_name;
+     tree member_name;
 {
   if (field == error_mark_node)
     return 0;
   if (field == NULL_TREE || initializing_context (field) != type)
     {
-      cp_error ("class `%T' does not have any field named `%s'", type,
+      cp_error ("class `%T' does not have any field named `%D'", type,
                member_name);
       return 0;
     }
   if (TREE_STATIC (field))
     {
-      cp_error ("field `%#D' is static; only point of initialization is its declaration",
+      cp_error ("field `%#D' is static; the only point of initialization is its definition",
                field);
       return 0;
     }
@@ -1063,17 +998,16 @@ member_init_ok_or_else (field, type, member_name)
   return 1;
 }
 
-/* If NAME is a viable field name for the aggregate DECL,
-   and PARMS is a viable parameter list, then expand an _EXPR
-   which describes this initialization.
+/* EXP is an expression of aggregate type. NAME is an IDENTIFIER_NODE
+   which names a field, or it is a _TYPE node or TYPE_DECL which names
+   a base for that type.  INIT is a parameter list for that field's or
+   base's constructor.  Check the validity of NAME, and return a
+   TREE_LIST of the base _TYPE or FIELD_DECL and the INIT. EXP is used
+   only to get its type.  If NAME is invalid, return NULL_TREE and
+   issue a diagnostic.
 
-   Note that we do not need to chase through the class's base classes
-   to look for NAME, because if it's in that list, it will be handled
-   by the constructor for that base class.
-
-   We do not yet have a fixed-point finder to instantiate types
-   being fed to overloaded constructors.  If there is a unique
-   constructor, then argument types can be got from that one.  */
+   An old style unnamed direct single base construction is permitted,
+   where NAME is NULL.  */
 
 tree
 expand_member_init (exp, name, init)
@@ -1086,72 +1020,56 @@ expand_member_init (exp, name, init)
     return NULL_TREE;
 
   type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+  my_friendly_assert (IS_AGGR_TYPE (type), 20011113);
 
-  if (name && TYPE_P (name))
+  if (!name)
     {
-      basetype = name;
-      name = TYPE_IDENTIFIER (name);
+      /* This is an obsolete unnamed base class initializer.  The
+        parser will already have warned about its use.  */
+      switch (CLASSTYPE_N_BASECLASSES (type))
+       {
+       case 0:
+         cp_error ("unnamed initializer for `%T', which has no base classes",
+                   type);
+         return NULL_TREE;
+       case 1:
+         basetype = TYPE_BINFO_BASETYPE (type, 0);
+         break;
+       default:
+         cp_error ("unnamed initializer for `%T', which uses multiple inheritance",
+                   type);
+         return NULL_TREE;
+      }
     }
-  else if (name && TREE_CODE (name) == TYPE_DECL)
+  else if (TYPE_P (name))
     {
-      basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
-      name = DECL_NAME (name);
+      basetype = name;
+      name = TYPE_NAME (name);
     }
-
-  if (name == NULL_TREE && IS_AGGR_TYPE (type))
-    switch (CLASSTYPE_N_BASECLASSES (type))
-      {
-      case 0:
-       error ("base class initializer specified, but no base class to initialize");
-       return NULL_TREE;
-      case 1:
-       basetype = TYPE_BINFO_BASETYPE (type, 0);
-       break;
-      default:
-       error ("initializer for unnamed base class ambiguous");
-       cp_error ("(type `%T' uses multiple inheritance)", type);
-       return NULL_TREE;
-      }
+  else if (TREE_CODE (name) == TYPE_DECL)
+    basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
 
   my_friendly_assert (init != NULL_TREE, 0);
 
-  /* The grammar should not allow fields which have names that are
-     TYPENAMEs.  Therefore, if the field has a non-NULL TREE_TYPE, we
-     may assume that this is an attempt to initialize a base class
-     member of the current type.  Otherwise, it is an attempt to
-     initialize a member field.  */
-
   if (init == void_type_node)
     init = NULL_TREE;
 
-  if (name == NULL_TREE || basetype)
+  if (basetype)
     {
-      if (name == NULL_TREE)
-       {
-#if 0
-         if (basetype)
-           name = TYPE_IDENTIFIER (basetype);
-         else
-           {
-             error ("no base class to initialize");
-             return;
-           }
-#endif
-       }
-      else if (basetype != type
-              && ! current_template_parms
-              && ! vec_binfo_member (basetype,
-                                     TYPE_BINFO_BASETYPES (type))
-              && ! binfo_for_vbase (basetype, type))
+      if (current_template_parms)
+       ;
+      else if (vec_binfo_member (basetype, TYPE_BINFO_BASETYPES (type)))
+       /* A direct base.  */;
+      else if (binfo_for_vbase (basetype, type))
+       /* A virtual base.  */;
+      else
        {
-         if (IDENTIFIER_CLASS_VALUE (name))
-           goto try_member;
          if (TYPE_USES_VIRTUAL_BASECLASSES (type))
-           cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
-                     basetype, type);
+           cp_error ("type `%D' is not a direct or virtual base of `%T'",
+                     name, type);
          else
-           cp_error ("type `%T' is not an immediate basetype for `%T'",
-                     basetype, type);
+           cp_error ("type `%D' is not a direct base of `%T'",
+                     name, type);
          return NULL_TREE;
        }
 
@@ -1159,10 +1077,9 @@ expand_member_init (exp, name, init)
     }
   else
     {
-    try_member:
       field = lookup_field (type, name, 1, 0);
 
-      if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
+      if (! member_init_ok_or_else (field, type, name))
        return NULL_TREE;
 
       init = build_tree_list (field, init);
@@ -1248,7 +1165,7 @@ build_aggr_init (exp, init, flags)
          cp_error ("bad array initializer");
          return error_mark_node;
        }
-      if (CP_TYPE_QUALS (type) != TYPE_UNQUALIFIED)
+      if (cp_type_quals (type) != TYPE_UNQUALIFIED)
        {
          TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
          if (init)
@@ -1527,9 +1444,6 @@ build_member_call (type, name, parmlist)
   if (DECL_P (name))
     name = DECL_NAME (name);
 
-  if (type == fake_std_node)
-    return build_x_function_call (do_scoped_id (name, 0), parmlist,
-                                 current_class_ref);
   if (TREE_CODE (type) == NAMESPACE_DECL)
     return build_x_function_call (lookup_namespace_name (type, name),
                                  parmlist, current_class_ref);
@@ -1560,7 +1474,8 @@ build_member_call (type, name, parmlist)
       tree ns = lookup_name (type, 0);
       if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
        {
-         return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);
+         return build_x_function_call (build_offset_ref (type, name),
+                                       parmlist, current_class_ref);
        }
     }
 
@@ -1593,7 +1508,7 @@ build_member_call (type, name, parmlist)
        {
          tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));
          decl = convert_force (build_pointer_type (newtype), olddecl, 0);
-         decl = build_indirect_ref (decl, NULL_PTR);
+         decl = build_indirect_ref (decl, NULL);
        }
     }
 
@@ -1662,9 +1577,6 @@ build_offset_ref (type, name)
   if (TREE_CODE (name) == TEMPLATE_DECL)
     return name;
 
-  if (type == fake_std_node)
-    return do_scoped_id (name, 0);
-
   if (processing_template_decl || uses_template_parms (type))
     return build_min_nt (SCOPE_REF, type, name);
 
@@ -1919,14 +1831,17 @@ resolve_offset_ref (exp)
       if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
        base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type));
 
-      addr = build_unary_op (ADDR_EXPR, base, 0);
-      addr = convert_pointer_to (basetype, addr);
+      /* Don't check access on the conversion; we might be after a member
+        promoted by an access- or using-declaration, and we have already
+        checked access for the member itself.  */
+      basetype = lookup_base (TREE_TYPE (base), basetype, ba_ignore, NULL);
+      expr = build_base_path (PLUS_EXPR, base, basetype, 1);
 
-      if (addr == error_mark_node)
+      if (expr == error_mark_node)
        return error_mark_node;
 
       expr = build (COMPONENT_REF, TREE_TYPE (member),
-                   build_indirect_ref (addr, NULL_PTR), member);
+                   expr, member);
       return convert_from_reference (expr);
     }
 
@@ -1949,7 +1864,10 @@ resolve_offset_ref (exp)
        }
 
       basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
-      addr = convert_pointer_to (basetype, addr);
+      basetype = lookup_base (TREE_TYPE (TREE_TYPE (addr)),
+                             basetype, ba_check, NULL);
+      addr = build_base_path (PLUS_EXPR, addr, basetype, 1);
+      
       member = cp_convert (ptrdiff_type_node, member);
 
       return build1 (INDIRECT_REF, type,
@@ -2200,7 +2118,7 @@ tree
 build_java_class_ref (type)
      tree type;
 {
-  tree name, class_decl;
+  tree name = NULL_TREE, class_decl;
   static tree CL_suffix = NULL_TREE;
   if (CL_suffix == NULL_TREE)
     CL_suffix = get_identifier("class$");
@@ -2213,7 +2131,7 @@ build_java_class_ref (type)
       jclass_node = TREE_TYPE (jclass_node);
     }
 
-  /* Mangle the class$ field, new and old ABI */
+  /* Mangle the class$ field */
   {
     tree field;
     for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
@@ -2224,7 +2142,7 @@ build_java_class_ref (type)
          break;
        }
     if (!field)
-      internal_error ("Can't find class$");
+      internal_error ("can't find class$");
     }
 
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
@@ -2237,7 +2155,7 @@ build_java_class_ref (type)
       DECL_ARTIFICIAL (class_decl) = 1;
       DECL_IGNORED_P (class_decl) = 1;
       pushdecl_top_level (class_decl);
-      make_decl_rtl (class_decl, NULL_PTR);
+      make_decl_rtl (class_decl, NULL);
     }
   return class_decl;
 }
@@ -2252,8 +2170,8 @@ get_cookie_size (type)
 {
   tree cookie_size;
 
-  /* Under the new ABI, we need to allocate an additional max
-     (sizeof (size_t), alignof (true_type)) bytes.  */
+  /* We need to allocate an additional max (sizeof (size_t), alignof
+     (true_type)) bytes.  */
   tree sizetype_size;
   tree type_align;
   
@@ -2293,6 +2211,9 @@ build_new_1 (exp)
      beginning of the storage allocated for an array-new expression in
      order to store the number of elements.  */
   tree cookie_size = NULL_TREE;
+  /* True if the function we are calling is a placement allocation
+     function.  */
+  bool placement_allocation_fn_p;
 
   placement = TREE_OPERAND (exp, 0);
   type = TREE_OPERAND (exp, 1);
@@ -2357,9 +2278,7 @@ build_new_1 (exp)
   if (!has_array || !TYPE_VEC_NEW_USES_COOKIE (true_type))
     use_cookie = 0;
   /* When using placement new, users may not realize that they need
-     the extra storage.  Under the old ABI, we don't allocate the
-     cookie whenever they use one placement argument of type `void
-     *'.  Under the new ABI, we require that the operator called be
+     the extra storage.  We require that the operator called be
      the global placement operator delete[].  */
   else if (placement && !TREE_CHAIN (placement) 
           && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
@@ -2384,7 +2303,7 @@ build_new_1 (exp)
       tree class_addr, alloc_decl;
       tree class_decl = build_java_class_ref (true_type);
       tree class_size = size_in_bytes (true_type);
-      static char alloc_name[] = "_Jv_AllocObject";
+      static const char alloc_name[] = "_Jv_AllocObject";
       use_java_new = 1;
       alloc_decl = IDENTIFIER_GLOBAL_VALUE (get_identifier (alloc_name));
       if (alloc_decl == NULL_TREE)
@@ -2418,8 +2337,25 @@ build_new_1 (exp)
   if (alloc_call == error_mark_node)
     return error_mark_node;
 
-  if (alloc_call == NULL_TREE)
-    abort ();
+  /* The ALLOC_CALL should be a CALL_EXPR, and the first operand
+     should be the address of a known FUNCTION_DECL.  */
+  my_friendly_assert (TREE_CODE (alloc_call) == CALL_EXPR, 20000521);
+  t = TREE_OPERAND (alloc_call, 0);
+  my_friendly_assert (TREE_CODE (t) == ADDR_EXPR, 20000521);
+  t = TREE_OPERAND (t, 0);
+  my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL, 20000521);
+  /* Now, check to see if this function is actually a placement
+     allocation function.  This can happen even when PLACEMENT is NULL
+     because we might have something like:
+
+       struct S { void* operator new (size_t, int i = 0); };
+
+     A call to `new S' will get this allocation function, even though
+     there is no explicit placement argument.  If there is more than
+     one argument, or there are variable arguments, then this is a
+     placement allocation function.  */
+  placement_allocation_fn_p 
+    = (type_num_arguments (TREE_TYPE (t)) > 1 || varargs_function_p (t));
 
   /*        unless an allocation function is declared with an empty  excep-
      tion-specification  (_except.spec_),  throw(), it indicates failure to
@@ -2459,12 +2395,11 @@ build_new_1 (exp)
       tree cookie;
 
       /* Store the number of bytes allocated so that we can know how
-        many elements to destroy later.  Under the new ABI, we use
-        the last sizeof (size_t) bytes to store the number of
-        elements.  */
+        many elements to destroy later.  We use the last sizeof
+        (size_t) bytes to store the number of elements.  */
       cookie = build (MINUS_EXPR, build_pointer_type (sizetype),
                      alloc_node, size_in_bytes (sizetype));
-      cookie = build_indirect_ref (cookie, NULL_PTR);
+      cookie = build_indirect_ref (cookie, NULL);
 
       cookie_expr = build (MODIFY_EXPR, void_type_node, cookie, nelts);
       TREE_SIDE_EFFECTS (cookie_expr) = 1;
@@ -2476,7 +2411,7 @@ build_new_1 (exp)
   init_expr = NULL_TREE;
   if (TYPE_NEEDS_CONSTRUCTING (type) || init)
     {
-      init_expr = build_indirect_ref (alloc_node, NULL_PTR);
+      init_expr = build_indirect_ref (alloc_node, NULL);
 
       if (init == void_zero_node)
        init = build_default_init (full_type);
@@ -2536,7 +2471,8 @@ build_new_1 (exp)
          flags |= LOOKUP_SPECULATIVELY;
 
          cleanup = build_op_delete_call (dcode, alloc_node, size, flags,
-                                         alloc_call);
+                                         (placement_allocation_fn_p 
+                                          ? alloc_call : NULL_TREE));
 
          /* Ack!  First we allocate the memory.  Then we set our sentry
             variable to true, and expand a cleanup that deletes the memory
@@ -3155,7 +3091,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
 {
   tree member;
   tree expr;
-  tree ref;
 
   if (addr == error_mark_node)
     return error_mark_node;
@@ -3184,7 +3119,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
 
       /* throw away const and volatile on target type of addr */
       addr = convert_force (build_pointer_type (type), addr, 0);
-      ref = build_indirect_ref (addr, NULL_PTR);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -3209,8 +3143,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
        addr = save_expr (addr);
 
       addr = convert_force (build_pointer_type (type), addr, 0);
-
-      ref = build_indirect_ref (addr, NULL_PTR);
     }
 
   my_friendly_assert (IS_AGGR_TYPE (type), 220);
@@ -3239,6 +3171,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
         delete'.  */
       if (use_global_delete && auto_delete == sfk_deleting_destructor)
        {
+         /* We will use ADDR multiple times so we must save it.  */
+         addr = save_expr (addr);
          /* Delete the object. */
          do_delete = build_builtin_delete_call (addr);
          /* Otherwise, treat this like a complete object destructor
@@ -3251,7 +3185,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       else if (!DECL_VIRTUAL_P (CLASSTYPE_DESTRUCTORS (type))
               && auto_delete == sfk_deleting_destructor)
        {
-         /* Buidl the call.  */
+         /* We will use ADDR multiple times so we must save it.  */
+         addr = save_expr (addr);
+         /* Build the call.  */
          do_delete = build_op_delete_call (DELETE_EXPR,
                                            addr,
                                            c_sizeof_nowarn (type),
@@ -3261,7 +3197,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
          auto_delete = sfk_complete_destructor;
        }
 
-      expr = build_dtor_call (ref, auto_delete, flags);
+      expr = build_dtor_call (build_indirect_ref (addr, NULL),
+                             auto_delete, flags);
       if (do_delete)
        expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
 
@@ -3285,6 +3222,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
       int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
       tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
       tree exprstmt = NULL_TREE;
+      tree ref = build_indirect_ref (addr, NULL);
 
       /* Set this again before we call anything, as we might get called
         recursively.  */
@@ -3402,7 +3340,7 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
                           build_pointer_type (sizetype),
                           base,
                           TYPE_SIZE_UNIT (sizetype));
-      maxindex = build_indirect_ref (cookie_addr, NULL_PTR);
+      maxindex = build_indirect_ref (cookie_addr, NULL);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {