OSDN Git Service

Revert the accidental checkin in revision 158918.
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index 3e9e612..4fc90e6 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, 2004, 2005, 2006, 2007, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -54,6 +54,7 @@ static tree dfs_initialize_vtbl_ptrs (tree, void *);
 static tree build_dtor_call (tree, special_function_kind, int);
 static tree build_field_list (tree, tree, int *);
 static tree build_vtbl_address (tree);
+static void diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool);
 
 /* We are about to generate some complex initialization code.
    Conceptually, it is all a single expression.  However, we may want
@@ -219,7 +220,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
 
       /* Iterate over the array elements, building initializations.  */
       if (nelts)
-       max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts),
+       max_index = fold_build2_loc (input_location,
+                                MINUS_EXPR, TREE_TYPE (nelts),
                                 nelts, integer_one_node);
       else
        max_index = array_type_nelts (type);
@@ -266,59 +268,11 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
   return init;
 }
 
-/* Build an expression for the default-initialization of an object of
-   the indicated TYPE.  If NELTS is non-NULL, and TYPE is an
-   ARRAY_TYPE, NELTS is the number of elements in the array.  If
-   initialization of TYPE requires calling constructors, this function
-   returns NULL_TREE; the caller is responsible for arranging for the
-   constructors to be called.  */
-
-tree
-build_default_init (tree type, tree nelts)
-{
-  /* [dcl.init]:
-
-    To default-initialize an object of type T means:
-
-    --if T is a non-POD class type (clause _class_), the default construc-
-      tor  for  T is called (and the initialization is ill-formed if T has
-      no accessible default constructor);
-
-    --if T is an array type, each element is default-initialized;
-
-    --otherwise, the storage for the object is zero-initialized.
-
-    A program that calls for default-initialization of an entity of refer-
-    ence type is ill-formed.  */
-
-  /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for
-     performing the initialization.  This is confusing in that some
-     non-PODs do not have TYPE_NEEDS_CONSTRUCTING set.  (For example,
-     a class with a pointer-to-data member as a non-static data member
-     does not have TYPE_NEEDS_CONSTRUCTING set.)  Therefore, we end up
-     passing non-PODs to build_zero_init below, which is contrary to
-     the semantics quoted above from [dcl.init].
-
-     It happens, however, that the behavior of the constructor the
-     standard says we should have generated would be precisely the
-     same as that obtained by calling build_zero_init below, so things
-     work out OK.  */
-  if (TYPE_NEEDS_CONSTRUCTING (type)
-      || (nelts && TREE_CODE (nelts) != INTEGER_CST))
-    return NULL_TREE;
-
-  /* At this point, TYPE is either a POD class type, an array of POD
-     classes, or something even more innocuous.  */
-  return build_zero_init (type, nelts, /*static_storage_p=*/false);
-}
-
 /* Return a suitable initializer for value-initializing an object of type
-   TYPE, as described in [dcl.init].  If HAVE_CTOR is true, the initializer
-   for an enclosing object is already calling the constructor for this
-   object.  */
+   TYPE, as described in [dcl.init].  */
 
-static tree
-build_value_init_1 (tree type, bool have_ctor)
+tree
+build_value_init (tree type)
 {
   /* [dcl.init]
 
@@ -346,17 +300,44 @@ build_value_init_1 (tree type, bool have_ctor)
 
   if (CLASS_TYPE_P (type))
     {
-      if (TYPE_HAS_USER_CONSTRUCTOR (type) && !have_ctor)
-       return build_cplus_new
+      if (type_has_user_provided_constructor (type))
+       return build_aggr_init_expr
          (type,
           build_special_member_call (NULL_TREE, complete_ctor_identifier,
-                                     NULL_TREE, type, LOOKUP_NORMAL,
+                                     NULL, type, LOOKUP_NORMAL,
                                      tf_warning_or_error));
-      else if (TREE_CODE (type) != UNION_TYPE)
+      else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
+       {
+         /* This is a class that needs constructing, but doesn't have
+            a user-provided constructor.  So we need to zero-initialize
+            the object and then call the implicitly defined ctor.
+            This will be handled in simplify_aggr_init_expr.  */
+         tree ctor = build_special_member_call
+           (NULL_TREE, complete_ctor_identifier,
+            NULL, type, LOOKUP_NORMAL, tf_warning_or_error);
+
+         ctor = build_aggr_init_expr (type, ctor);
+         AGGR_INIT_ZERO_FIRST (ctor) = 1;
+         return ctor;
+       }
+    }
+  return build_value_init_noctor (type);
+}
+
+/* Like build_value_init, but don't call the constructor for TYPE.  Used
+   for base initializers.  */
+
+tree
+build_value_init_noctor (tree type)
+{
+  if (CLASS_TYPE_P (type))
+    {
+      gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type));
+       
+      if (TREE_CODE (type) != UNION_TYPE)
        {
-         tree field, init;
+         tree field;
          VEC(constructor_elt,gc) *v = NULL;
-         bool call_ctor = !have_ctor && TYPE_NEEDS_CONSTRUCTING (type);
 
          /* Iterate over the fields, building initializations.  */
          for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
@@ -381,35 +362,14 @@ build_value_init_1 (tree type, bool have_ctor)
                 corresponding to base classes as well.  Thus, iterating
                 over TYPE_FIELDs will result in correct initialization of
                 all of the subobjects.  */
-             value = build_value_init_1 (ftype, have_ctor || call_ctor);
+             value = build_value_init (ftype);
 
              if (value)
                CONSTRUCTOR_APPEND_ELT(v, field, value);
            }
 
          /* Build a constructor to contain the zero- initializations.  */
-         init = build_constructor (type, v);
-         if (call_ctor)
-           {
-             /* This is a class that needs constructing, but doesn't have
-                a user-defined constructor.  So we need to zero-initialize
-                the object and then call the implicitly defined ctor.
-                Implement this by sticking the zero-initialization inside
-                the TARGET_EXPR for the constructor call;
-                cp_gimplify_init_expr will know how to handle it.  */
-             tree ctor = build_special_member_call
-               (NULL_TREE, complete_ctor_identifier,
-                NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error);
-
-             ctor = build_cplus_new (type, ctor);
-             init = build2 (INIT_EXPR, void_type_node,
-                            TARGET_EXPR_SLOT (ctor), init);
-             init = build2 (COMPOUND_EXPR, void_type_node, init,
-                            TARGET_EXPR_INITIAL (ctor));
-             TARGET_EXPR_INITIAL (ctor) = init;
-             return ctor;
-           }
-         return init;
+         return build_constructor (type, v);
        }
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
@@ -441,7 +401,11 @@ build_value_init_1 (tree type, bool have_ctor)
            ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
                                max_index);
 
-         ce->value = build_value_init_1 (TREE_TYPE (type), have_ctor);
+         ce->value = build_value_init (TREE_TYPE (type));
+
+         /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs.  */
+         gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR
+                     && TREE_CODE (ce->value) != AGGR_INIT_EXPR);
        }
 
       /* Build a constructor to contain the initializations.  */
@@ -451,15 +415,6 @@ build_value_init_1 (tree type, bool have_ctor)
   return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
 }
 
-/* Return a suitable initializer for value-initializing an object of type
-   TYPE, as described in [dcl.init].  */
-
-tree
-build_value_init (tree type)
-{
-  return build_value_init_1 (type, false);
-}
-
 /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
    arguments.  If TREE_LIST is void_type_node, an empty initializer
    list was given; if NULL_TREE no initializer was given.  */
@@ -469,18 +424,13 @@ perform_member_init (tree member, tree init)
 {
   tree decl;
   tree type = TREE_TYPE (member);
-  bool explicit;
-
-  explicit = (init != NULL_TREE);
 
   /* Effective C++ rule 12 requires that all data members be
      initialized.  */
-  if (warn_ecpp && !explicit && TREE_CODE (type) != ARRAY_TYPE)
-    warning (OPT_Weffc__, "%J%qD should be initialized in the member initialization "
-            "list", current_function_decl, member);
-
-  if (init == void_type_node)
-    init = NULL_TREE;
+  if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE)
+    warning_at (DECL_SOURCE_LOCATION (current_function_decl), OPT_Weffc__,
+               "%qD should be initialized in the member initialization list",
+               member);
 
   /* Get an lvalue for the data member.  */
   decl = build_class_member_access_expr (current_class_ref, member,
@@ -490,10 +440,34 @@ perform_member_init (tree member, tree init)
   if (decl == error_mark_node)
     return;
 
+  if (init == void_type_node)
+    {
+      /* mem() means value-initialization.  */
+      if (TREE_CODE (type) == ARRAY_TYPE)
+       {
+         init = build_vec_init (decl, NULL_TREE, NULL_TREE,
+                                /*explicit_value_init_p=*/true,
+                                /* from_array=*/0,
+                                tf_warning_or_error);
+         finish_expr_stmt (init);
+       }
+      else
+       {
+         if (TREE_CODE (type) == REFERENCE_TYPE)
+           permerror (DECL_SOURCE_LOCATION (current_function_decl),
+                      "value-initialization of %q#D, which has reference type",
+                      member);
+         else
+           {
+             init = build2 (INIT_EXPR, type, decl, build_value_init (type));
+             finish_expr_stmt (init);
+           }
+       }
+    }
   /* Deal with this here, as we will get confused if we try to call the
      assignment op for an anonymous union.  This can happen in a
      synthesized copy constructor.  */
-  if (ANON_AGGR_TYPE_P (type))
+  else if (ANON_AGGR_TYPE_P (type))
     {
       if (init)
        {
@@ -503,41 +477,52 @@ perform_member_init (tree member, tree init)
     }
   else if (TYPE_NEEDS_CONSTRUCTING (type))
     {
-      if (explicit
+      if (init != NULL_TREE
          && TREE_CODE (type) == ARRAY_TYPE
-         && init != NULL_TREE
          && TREE_CHAIN (init) == NULL_TREE
          && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
        {
          /* Initialization of one array from another.  */
          finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
-                                           /*explicit_default_init_p=*/false,
+                                           /*explicit_value_init_p=*/false,
                                            /* from_array=*/1,
                                             tf_warning_or_error));
        }
       else
-       finish_expr_stmt (build_aggr_init (decl, init, 0, 
-                                           tf_warning_or_error));
+       {
+         if (CP_TYPE_CONST_P (type)
+             && init == NULL_TREE
+             && !type_has_user_provided_default_constructor (type))
+           /* TYPE_NEEDS_CONSTRUCTING can be set just because we have a
+              vtable; still give this diagnostic.  */
+           permerror (DECL_SOURCE_LOCATION (current_function_decl),
+                      "uninitialized member %qD with %<const%> type %qT",
+                      member, type);
+         finish_expr_stmt (build_aggr_init (decl, init, 0, 
+                                            tf_warning_or_error));
+       }
     }
   else
     {
       if (init == NULL_TREE)
        {
-         if (explicit)
-           {
-             init = build_default_init (type, /*nelts=*/NULL_TREE);
-             if (TREE_CODE (type) == REFERENCE_TYPE)
-               warning (0, "%Jdefault-initialization of %q#D, "
-                        "which has reference type",
-                        current_function_decl, member);
-           }
+         tree core_type;
          /* member traversal: note it leaves init NULL */
-         else if (TREE_CODE (type) == REFERENCE_TYPE)
-           permerror ("%Juninitialized reference member %qD",
-                      current_function_decl, member);
+         if (TREE_CODE (type) == REFERENCE_TYPE)
+           permerror (DECL_SOURCE_LOCATION (current_function_decl),
+                      "uninitialized reference member %qD",
+                      member);
          else if (CP_TYPE_CONST_P (type))
-           permerror ("%Juninitialized member %qD with %<const%> type %qT",
-                      current_function_decl, member, type);
+           permerror (DECL_SOURCE_LOCATION (current_function_decl),
+                      "uninitialized member %qD with %<const%> type %qT",
+                      member, type);
+
+         core_type = strip_array_types (type);
+         if (CLASS_TYPE_P (core_type)
+             && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+                 || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
+           diagnose_uninitialized_cst_or_ref_member (core_type,
+                                                     /*using_new=*/false);
        }
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
@@ -690,7 +675,8 @@ sort_mem_initializers (tree t, tree mem_inits)
            warning (OPT_Wreorder, "  %q+#D", subobject);
          else
            warning (OPT_Wreorder, "  base %qT", subobject);
-         warning (OPT_Wreorder, "%J  when initialized here", current_function_decl);
+         warning_at (DECL_SOURCE_LOCATION (current_function_decl),
+                     OPT_Wreorder, "  when initialized here");
        }
 
       /* Look again, from the beginning of the list.  */
@@ -706,11 +692,13 @@ sort_mem_initializers (tree t, tree mem_inits)
       if (TREE_VALUE (subobject_init))
        {
          if (TREE_CODE (subobject) == FIELD_DECL)
-           error ("%Jmultiple initializations given for %qD",
-                  current_function_decl, subobject);
+           error_at (DECL_SOURCE_LOCATION (current_function_decl),
+                     "multiple initializations given for %qD",
+                     subobject);
          else
-           error ("%Jmultiple initializations given for base %qT",
-                  current_function_decl, subobject);
+           error_at (DECL_SOURCE_LOCATION (current_function_decl),
+                     "multiple initializations given for base %qT",
+                     subobject);
        }
 
       /* Record the initialization.  */
@@ -776,8 +764,9 @@ sort_mem_initializers (tree t, tree mem_inits)
                  if (same_type_p (last_field_type, field_type))
                    {
                      if (TREE_CODE (field_type) == UNION_TYPE)
-                       error ("%Jinitializations for multiple members of %qT",
-                              current_function_decl, last_field_type);
+                       error_at (DECL_SOURCE_LOCATION (current_function_decl),
+                                 "initializations for multiple members of %qT",
+                                 last_field_type);
                      done = 1;
                      break;
                    }
@@ -839,14 +828,10 @@ emit_mem_initializers (tree mem_inits)
       if (extra_warnings && !arguments
          && DECL_COPY_CONSTRUCTOR_P (current_function_decl)
          && type_has_user_nondefault_constructor (BINFO_TYPE (subobject)))
-       warning (OPT_Wextra, "%Jbase class %q#T should be explicitly initialized in the "
-                "copy constructor",
-                current_function_decl, BINFO_TYPE (subobject));
-
-      /* If an explicit -- but empty -- initializer list was present,
-        treat it just like default initialization at this point.  */
-      if (arguments == void_type_node)
-       arguments = NULL_TREE;
+       warning_at (DECL_SOURCE_LOCATION (current_function_decl), OPT_Wextra,
+                   "base class %q#T should be explicitly initialized in the "
+                   "copy constructor",
+                   BINFO_TYPE (subobject));
 
       /* Initialize the base.  */
       if (BINFO_VIRTUAL_P (subobject))
@@ -858,7 +843,7 @@ emit_mem_initializers (tree mem_inits)
          base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
                                       subobject, 1);
          expand_aggr_init_1 (subobject, NULL_TREE,
-                             cp_build_indirect_ref (base_addr, NULL,
+                             cp_build_indirect_ref (base_addr, RO_NULL,
                                                      tf_warning_or_error),
                              arguments,
                              LOOKUP_NORMAL,
@@ -903,7 +888,6 @@ build_vtbl_address (tree binfo)
   /* Figure out what vtable BINFO's vtable is based on, and mark it as
      used.  */
   vtbl = get_vtbl_decl_for_binfo (binfo_for);
-  assemble_external (vtbl);
   TREE_USED (vtbl) = 1;
 
   /* Now compute the address to use when initializing the vptr.  */
@@ -943,7 +927,7 @@ expand_virtual_init (tree binfo, tree decl)
                      TREE_TYPE (vtt_parm),
                      vtt_parm,
                      vtt_index);
-      vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error);
+      vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error);
       vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
 
       /* The actual initializer is the VTT value only in the subobject
@@ -958,7 +942,7 @@ expand_virtual_init (tree binfo, tree decl)
     }
 
   /* Compute the location of the vtpr.  */
-  vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL, 
+  vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL, 
                                                       tf_warning_or_error),
                               TREE_TYPE (binfo));
   gcc_assert (vtbl_ptr != error_mark_node);
@@ -986,13 +970,14 @@ expand_cleanup_for_base (tree binfo, tree flag)
   /* Call the destructor.  */
   expr = build_special_member_call (current_class_ref,
                                    base_dtor_identifier,
-                                   NULL_TREE,
+                                   NULL,
                                    binfo,
                                    LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                     tf_warning_or_error);
   if (flag)
-    expr = fold_build3 (COND_EXPR, void_type_node,
-                       c_common_truthvalue_conversion (flag),
+    expr = fold_build3_loc (input_location,
+                       COND_EXPR, void_type_node,
+                       c_common_truthvalue_conversion (input_location, flag),
                        expr, integer_zero_node);
 
   finish_eh_cleanup (expr);
@@ -1272,13 +1257,13 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
       /* 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)
-       itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
+      if (cv_qualified_p (type))
+       TREE_TYPE (exp) = cv_unqualified (type);
+      if (itype && cv_qualified_p (itype))
+       TREE_TYPE (init) = cv_unqualified (itype);
       stmt_expr = build_vec_init (exp, NULL_TREE, init,
-                                 /*explicit_default_init_p=*/false,
-                                 itype && same_type_p (itype,
+                                 /*explicit_value_init_p=*/false,
+                                 itype && same_type_p (TREE_TYPE (init),
                                                        TREE_TYPE (exp)),
                                   complain);
       TREE_READONLY (exp) = was_const;
@@ -1320,7 +1305,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
      followed by initialization by X.  If neither of these work
      out, then look hard.  */
   tree rval;
-  tree parms;
+  VEC(tree,gc) *parms;
 
   if (init && TREE_CODE (init) != TREE_LIST
       && (flags & LOOKUP_ONLYCONVERTING))
@@ -1360,23 +1345,28 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
       return;
     }
 
-  if (init == NULL_TREE
-      || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))
+  if (init == NULL_TREE)
+    parms = NULL;
+  else if (TREE_CODE (init) == TREE_LIST && !TREE_TYPE (init))
     {
-      parms = init;
-      if (parms)
-       init = TREE_VALUE (parms);
+      parms = make_tree_vector ();
+      for (; init != NULL_TREE; init = TREE_CHAIN (init))
+       VEC_safe_push (tree, gc, parms, TREE_VALUE (init));
     }
   else
-    parms = build_tree_list (NULL_TREE, init);
+    parms = make_tree_vector_single (init);
 
   if (true_exp == exp)
     ctor_name = complete_ctor_identifier;
   else
     ctor_name = base_ctor_identifier;
 
-  rval = build_special_member_call (exp, ctor_name, parms, binfo, flags,
+  rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
                                     complain);
+
+  if (parms != NULL)
+    release_tree_vector (parms);
+
   if (TREE_SIDE_EFFECTS (rval))
     finish_expr_stmt (convert_to_void (rval, NULL, complain));
 }
@@ -1422,12 +1412,39 @@ 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
         recorded as the DECL_INITIAL for EXP.  That means there's
         nothing more we have to do.  */
-      init = store_init_value (exp, init);
+      init = store_init_value (exp, init, flags);
       if (init)
        finish_expr_stmt (init);
       return;
     }
 
+  /* If an explicit -- but empty -- initializer list was present,
+     that's value-initialization.  */
+  if (init == void_type_node)
+    {
+      /* If there's a user-provided constructor, we just call that.  */
+      if (type_has_user_provided_constructor (type))
+       /* Fall through.  */;
+      /* If there isn't, but we still need to call the constructor,
+        zero out the object first.  */
+      else if (TYPE_NEEDS_CONSTRUCTING (type))
+       {
+         init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
+         init = build2 (INIT_EXPR, type, exp, init);
+         finish_expr_stmt (init);
+         /* And then call the constructor.  */
+       }
+      /* If we don't need to mess with the constructor at all,
+        then just zero out the object and we're done.  */
+      else
+       {
+         init = build2 (INIT_EXPR, type, exp, build_value_init_noctor (type));
+         finish_expr_stmt (init);
+         return;
+       }
+      init = NULL_TREE;
+    }
+
   /* We know that expand_default_init can handle everything we want
      at this point.  */
   expand_default_init (binfo, true_exp, exp, init, flags, complain);
@@ -1578,7 +1595,7 @@ build_offset_ref (tree type, tree member, bool address_p)
           a class derived from that class (_class.base.init_).  */
       if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
        {
-         /* Build a representation of the qualified name suitable
+         /* Build a representation of the qualified name suitable
             for use as the operand to "&" -- even though the "&" is
             not actually present.  */
          member = build2 (OFFSET_REF, TREE_TYPE (member), decl, member);
@@ -1649,7 +1666,23 @@ constant_value_1 (tree decl, bool integral_p)
          init = DECL_INITIAL (decl);
        }
       if (init == error_mark_node)
-       return decl;
+       {
+         if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+           /* Treat the error as a constant to avoid cascading errors on
+              excessively recursive template instantiation (c++/9335).  */
+           return init;
+         else
+           return decl;
+       }
+      /* Initializers in templates are generally expanded during
+        instantiation, so before that for const int i(2)
+        INIT is a TREE_LIST with the actual initializer as
+        TREE_VALUE.  */
+      if (processing_template_decl
+         && init
+         && TREE_CODE (init) == TREE_LIST
+         && TREE_CHAIN (init) == NULL_TREE)
+       init = TREE_VALUE (init);
       if (!init
          || !TREE_TYPE (init)
          || (integral_p
@@ -1705,103 +1738,116 @@ build_builtin_delete_call (tree addr)
    the type of the object being allocated; otherwise, it's just TYPE.
    INIT is the initializer, if any.  USE_GLOBAL_NEW is true if the
    user explicitly wrote "::operator new".  PLACEMENT, if non-NULL, is
-   the TREE_LIST of arguments to be provided as arguments to a
-   placement new operator.  This routine performs no semantic checks;
-   it just creates and returns a NEW_EXPR.  */
+   a vector of arguments to be provided as arguments to a placement
+   new operator.  This routine performs no semantic checks; it just
+   creates and returns a NEW_EXPR.  */
 
 static tree
-build_raw_new_expr (tree placement, tree type, tree nelts, tree init,
-                   int use_global_new)
+build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts,
+                   VEC(tree,gc) *init, int use_global_new)
 {
+  tree init_list;
   tree new_expr;
 
-  new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
-                    nelts, init);
+  /* If INIT is NULL, the we want to store NULL_TREE in the NEW_EXPR.
+     If INIT is not NULL, then we want to store VOID_ZERO_NODE.  This
+     permits us to distinguish the case of a missing initializer "new
+     int" from an empty initializer "new int()".  */
+  if (init == NULL)
+    init_list = NULL_TREE;
+  else if (VEC_empty (tree, init))
+    init_list = void_zero_node;
+  else
+    init_list = build_tree_list_vec (init);
+
+  new_expr = build4 (NEW_EXPR, build_pointer_type (type),
+                    build_tree_list_vec (placement), type, nelts,
+                    init_list);
   NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
   TREE_SIDE_EFFECTS (new_expr) = 1;
 
   return new_expr;
 }
 
-/* Make sure that there are no aliasing issues with T, a placement new
-   expression applied to PLACEMENT, by recording the change in dynamic
-   type.  If placement new is inlined, as it is with libstdc++, and if
-   the type of the placement new differs from the type of the
-   placement location itself, then alias analysis may think it is OK
-   to interchange writes to the location from before the placement new
-   and from after the placement new.  We have to prevent type-based
-   alias analysis from applying.  PLACEMENT may be NULL, which means
-   that we couldn't capture it in a temporary variable, in which case
-   we use a memory clobber.  */
+/* Diagnose uninitialized const members or reference members of type
+   TYPE. USING_NEW is used to disambiguate the diagnostic between a
+   new expression without a new-initializer and a declaration */
 
-static tree
-avoid_placement_new_aliasing (tree t, tree placement)
+static void
+diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
+                                           bool using_new)
 {
-  tree type_change;
+  tree field;
 
-  if (processing_template_decl)
-    return t;
-
-  /* If we are not using type based aliasing, we don't have to do
-     anything.  */
-  if (!flag_strict_aliasing)
-    return t;
-
-  /* If we have a pointer and a location, record the change in dynamic
-     type.  Otherwise we need a general memory clobber.  */
-  if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
-      && placement != NULL_TREE
-      && TREE_CODE (TREE_TYPE (placement)) == POINTER_TYPE)
-    type_change = build_stmt (CHANGE_DYNAMIC_TYPE_EXPR,
-                             TREE_TYPE (t),
-                             placement);
-  else
+  if (type_has_user_provided_constructor (type))
+    return;
+
+  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
     {
-      /* Build a memory clobber.  */
-      type_change = build_stmt (ASM_EXPR,
-                               build_string (0, ""),
-                               NULL_TREE,
-                               NULL_TREE,
-                               tree_cons (NULL_TREE,
-                                          build_string (6, "memory"),
-                                          NULL_TREE));
+      tree field_type;
 
-      ASM_VOLATILE_P (type_change) = 1;
+      if (TREE_CODE (field) != FIELD_DECL)
+       continue;
+
+      field_type = strip_array_types (TREE_TYPE (field));
+
+      if (TREE_CODE (field_type) == REFERENCE_TYPE)
+       {
+         if (using_new)
+           error ("uninitialized reference member in %q#T "
+                  "using %<new%> without new-initializer", origin);
+         else
+           error ("uninitialized reference member in %q#T", origin);
+         inform (DECL_SOURCE_LOCATION (field),
+                 "%qD should be initialized", field);
+       }
+
+      if (CP_TYPE_CONST_P (field_type))
+       {
+         if (using_new)
+           error ("uninitialized const member in %q#T "
+                  "using %<new%> without new-initializer", origin);
+         else
+           error ("uninitialized const member in %q#T", origin);
+         inform (DECL_SOURCE_LOCATION (field),
+                 "%qD should be initialized", field);
+       }
+
+      if (CLASS_TYPE_P (field_type))
+       diagnose_uninitialized_cst_or_ref_member_1 (field_type,
+                                                   origin, using_new);
     }
+}
 
-  return build2 (COMPOUND_EXPR, TREE_TYPE (t), type_change, t);
+void
+diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new)
+{
+  diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new);
 }
 
 /* Generate code for a new-expression, including calling the "operator
    new" function, initializing the object, and, if an exception occurs
    during construction, cleaning up.  The arguments are as for
-   build_raw_new_expr.  */
+   build_raw_new_expr.  This may change PLACEMENT and INIT.  */
 
 static tree
-build_new_1 (tree placement, tree type, tree nelts, tree init,
-            bool globally_qualified_p, tsubst_flags_t complain)
+build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
+            VEC(tree,gc) **init, bool globally_qualified_p,
+            tsubst_flags_t complain)
 {
   tree size, rval;
   /* True iff this is a call to "operator new[]" instead of just
      "operator new".  */
   bool array_p = false;
-  /* True iff ARRAY_P is true and the bound of the array type is
-     not necessarily a compile time constant.  For example, VLA_P is
-     true for "new int[f()]".  */
-  bool vla_p = false;
-  /* The type being allocated.  If ARRAY_P is true, this will be an
-     ARRAY_TYPE.  */
-  tree full_type;
-  /* If ARRAY_P is true, the element type of the array.  This is an
-     never ARRAY_TYPE; for something like "new int[3][4]", the
+  /* If ARRAY_P is true, the element type of the array.  This is never
+     an ARRAY_TYPE; for something like "new int[3][4]", the
      ELT_TYPE is "int".  If ARRAY_P is false, this is the same type as
-     FULL_TYPE.  */
+     TYPE.  */
   tree elt_type;
   /* The type of the new-expression.  (This type is always a pointer
      type.)  */
   tree pointer_type;
-  /* A pointer type pointing to the FULL_TYPE.  */
-  tree full_pointer_type;
+  tree non_const_pointer_type;
   tree outer_nelts = NULL_TREE;
   tree alloc_call, alloc_expr;
   /* The address returned by the call to "operator new".  This node is
@@ -1815,11 +1861,11 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
      beginning of the storage allocated for an array-new expression in
      order to store the number of elements.  */
   tree cookie_size = NULL_TREE;
+  tree placement_first;
   tree placement_expr = NULL_TREE;
   /* True if the function we are calling is a placement allocation
      function.  */
   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-initializer.  */
   bool is_initialized;
@@ -1832,35 +1878,15 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
   if (nelts)
     {
-      tree index;
-
       outer_nelts = nelts;
       array_p = true;
-
-      /* ??? The middle-end will error on us for building a VLA outside a
-        function context.  Methinks that's not it's purvey.  So we'll do
-        our own VLA layout later.  */
-      vla_p = true;
-      index = convert (sizetype, nelts);
-      index = size_binop (MINUS_EXPR, index, size_one_node);
-      index = build_index_type (index);
-      full_type = build_cplus_array_type (type, NULL_TREE);
-      /* We need a copy of the type as build_array_type will return a shared copy
-         of the incomplete array type.  */
-      full_type = build_distinct_type_copy (full_type);
-      TYPE_DOMAIN (full_type) = index;
-      SET_TYPE_STRUCTURAL_EQUALITY (full_type);
     }
-  else
+  else if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      full_type = type;
-      if (TREE_CODE (type) == ARRAY_TYPE)
-       {
-         array_p = true;
-         nelts = array_type_nelts_top (type);
-         outer_nelts = nelts;
-         type = TREE_TYPE (type);
-       }
+      array_p = true;
+      nelts = array_type_nelts_top (type);
+      outer_nelts = nelts;
+      type = TREE_TYPE (type);
     }
 
   /* If our base type is an array, then make sure we know how many elements
@@ -1868,7 +1894,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   for (elt_type = type;
        TREE_CODE (elt_type) == ARRAY_TYPE;
        elt_type = TREE_TYPE (elt_type))
-    nelts = cp_build_binary_op (MULT_EXPR, nelts,
+    nelts = cp_build_binary_op (input_location,
+                               MULT_EXPR, nelts,
                                array_type_nelts_top (elt_type),
                                complain);
 
@@ -1882,8 +1909,42 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   if (abstract_virtuals_error (NULL_TREE, elt_type))
     return error_mark_node;
 
-  is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init);
-  if (CP_TYPE_CONST_P (elt_type) && !is_initialized)
+  is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
+
+  if (*init == NULL && !type_has_user_provided_constructor (elt_type))
+    {
+      bool uninitialized_error = false;
+      /* A program that calls for default-initialization [...] of an
+        entity of reference type is ill-formed. */
+      if (CLASSTYPE_REF_FIELDS_NEED_INIT (elt_type))
+       uninitialized_error = true;
+
+      /* A new-expression that creates an object of type T initializes
+        that object as follows:
+      - If the new-initializer is omitted:
+        -- If T is a (possibly cv-qualified) non-POD class type
+          (or array thereof), the object is default-initialized (8.5).
+          [...]
+        -- Otherwise, the object created has indeterminate
+          value. If T is a const-qualified type, or a (possibly
+          cv-qualified) POD class type (or array thereof)
+          containing (directly or indirectly) a member of
+          const-qualified type, the program is ill-formed; */
+
+      if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type))
+       uninitialized_error = true;
+
+      if (uninitialized_error)
+       {
+         if (complain & tf_error)
+           diagnose_uninitialized_cst_or_ref_member (elt_type,
+                                                     /*using_new*/true);
+         return error_mark_node;
+       }
+    }
+
+  if (CP_TYPE_CONST_P (elt_type) && *init == NULL
+      && !type_has_user_provided_default_constructor (elt_type))
     {
       if (complain & tf_error)
         error ("uninitialized const in %<new%> of %q#T", elt_type);
@@ -1892,26 +1953,21 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
   size = size_in_bytes (elt_type);
   if (array_p)
-    {
-      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
-      if (vla_p)
-       {
-         tree n, bitsize;
-
-         /* Do our own VLA layout.  Setting TYPE_SIZE/_UNIT is
-            necessary in order for the <INIT_EXPR <*foo> <CONSTRUCTOR
-            ...>> to be valid.  */
-         TYPE_SIZE_UNIT (full_type) = size;
-         n = convert (bitsizetype, nelts);
-         bitsize = size_binop (MULT_EXPR, TYPE_SIZE (elt_type), n);
-         TYPE_SIZE (full_type) = bitsize;
-       }
-    }
+    size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
 
   alloc_fn = NULL_TREE;
 
+  /* If PLACEMENT is a single simple pointer type not passed by
+     reference, prepare to capture it in a temporary variable.  Do
+     this now, since PLACEMENT will change in the calls below.  */
+  placement_first = NULL_TREE;
+  if (VEC_length (tree, *placement) == 1
+      && (TREE_CODE (TREE_TYPE (VEC_index (tree, *placement, 0)))
+         == POINTER_TYPE))
+    placement_first = VEC_index (tree, *placement, 0);
+
   /* Allocate the object.  */
-  if (! placement && TYPE_FOR_JAVA (elt_type))
+  if (VEC_empty (tree, *placement) && TYPE_FOR_JAVA (elt_type))
     {
       tree class_addr;
       tree class_decl = build_java_class_ref (elt_type);
@@ -1967,7 +2023,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
              size = size_binop (PLUS_EXPR, size, cookie_size);
            }
          /* Create the argument list.  */
-         args = tree_cons (NULL_TREE, size, placement);
+         VEC_safe_insert (tree, gc, *placement, 0, size);
          /* Do name-lookup to find the appropriate operator.  */
          fns = lookup_fnfields (elt_type, fnname, /*protect=*/2);
          if (fns == NULL_TREE)
@@ -1986,7 +2042,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
              return error_mark_node;
            }
          alloc_call = build_new_method_call (build_dummy_object (elt_type),
-                                             fns, args,
+                                             fns, placement,
                                              /*conversion_path=*/NULL_TREE,
                                              LOOKUP_NORMAL,
                                              &alloc_fn,
@@ -2012,12 +2068,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
   gcc_assert (alloc_fn != NULL_TREE);
 
-  /* If PLACEMENT is a simple pointer type and is not passed by reference,
-     then copy it into PLACEMENT_EXPR.  */
+  /* If we found a simple case of PLACEMENT_EXPR above, then copy it
+     into a temporary variable.  */
   if (!processing_template_decl
-      && placement != NULL_TREE
-      && TREE_CHAIN (placement) == NULL_TREE
-      && TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) == POINTER_TYPE
+      && placement_first != NULL_TREE
       && TREE_CODE (alloc_call) == CALL_EXPR
       && call_expr_nargs (alloc_call) == 2
       && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 0))) == INTEGER_TYPE
@@ -2025,10 +2079,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
     {
       tree placement_arg = CALL_EXPR_ARG (alloc_call, 1);
 
-      if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))
+      if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))
          || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg))))
        {
-         placement_expr = get_target_expr (TREE_VALUE (placement));
+         placement_expr = get_target_expr (placement_first);
          CALL_EXPR_ARG (alloc_call, 1)
            = convert (TREE_TYPE (placement_arg), placement_expr);
        }
@@ -2037,18 +2091,11 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   /* In the simple case, we can stop now.  */
   pointer_type = build_pointer_type (type);
   if (!cookie_size && !is_initialized)
-    {
-      rval = build_nop (pointer_type, alloc_call);
-      if (placement != NULL)
-       rval = avoid_placement_new_aliasing (rval, placement_expr);
-      return rval;
-    }
+    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));
+  /* Store the result of the allocation call in a variable so that we can
+     use it more than once.  */
+  alloc_expr = get_target_expr (alloc_call);
   alloc_node = TARGET_EXPR_SLOT (alloc_expr);
 
   /* Strip any COMPOUND_EXPRs from ALLOC_CALL.  */
@@ -2100,17 +2147,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
       tree size_ptr_type;
 
       /* Adjust so we're pointing to the start of the object.  */
-      data_addr = get_target_expr (build2 (POINTER_PLUS_EXPR, full_pointer_type,
-                                          alloc_node, cookie_size));
+      data_addr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (alloc_node),
+                         alloc_node, cookie_size);
 
       /* Store the number of bytes allocated so that we can know how
         many elements to destroy later.  We use the last sizeof
         (size_t) bytes to store the number of elements.  */
-      cookie_ptr = fold_build1 (NEGATE_EXPR, sizetype, size_in_bytes (sizetype));
+      cookie_ptr = size_binop (MINUS_EXPR, cookie_size, size_in_bytes (sizetype));
+      cookie_ptr = fold_build2_loc (input_location,
+                               POINTER_PLUS_EXPR, TREE_TYPE (alloc_node),
+                               alloc_node, cookie_ptr);
       size_ptr_type = build_pointer_type (sizetype);
-      cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type,
-                          fold_convert (size_ptr_type, data_addr), cookie_ptr);
-      cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+      cookie_ptr = fold_convert (size_ptr_type, cookie_ptr);
+      cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
 
       cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
 
@@ -2118,16 +2167,16 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
        {
          /* Also store the element size.  */
          cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, cookie_ptr,
-                              fold_build1 (NEGATE_EXPR, sizetype,
+                              fold_build1_loc (input_location,
+                                           NEGATE_EXPR, sizetype,
                                            size_in_bytes (sizetype)));
 
-         cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+         cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
          cookie = build2 (MODIFY_EXPR, sizetype, cookie,
-                          size_in_bytes(elt_type));
+                          size_in_bytes (elt_type));
          cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
                                cookie, cookie_expr);
        }
-      data_addr = TARGET_EXPR_SLOT (data_addr);
     }
   else
     {
@@ -2135,6 +2184,17 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
       data_addr = alloc_node;
     }
 
+  /* Now use a pointer to the type we've actually allocated.  */
+
+  /* But we want to operate on a non-const version to start with,
+     since we'll be modifying the elements.  */
+  non_const_pointer_type = build_pointer_type
+    (cp_build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_CONST));
+
+  data_addr = fold_convert (non_const_pointer_type, data_addr);
+  /* Any further uses of alloc_node will want this type, too.  */
+  alloc_node = fold_convert (non_const_pointer_type, alloc_node);
+
   /* 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
@@ -2143,32 +2203,51 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   if (is_initialized)
     {
       bool stable;
+      bool explicit_value_init_p = false;
 
-      init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
+      if (*init != NULL && VEC_empty (tree, *init))
+       {
+         *init = NULL;
+         explicit_value_init_p = true;
+       }
 
       if (array_p)
        {
-         bool explicit_default_init_p = false;
-
-         if (init == void_zero_node)
+         tree vecinit = NULL_TREE;
+         if (*init && VEC_length (tree, *init) == 1
+             && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *init, 0))
+             && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *init, 0)))
            {
-             init = NULL_TREE;
-             explicit_default_init_p = true;
+             tree arraytype, domain;
+             vecinit = VEC_index (tree, *init, 0);
+             if (TREE_CONSTANT (nelts))
+               domain = compute_array_index_type (NULL_TREE, nelts);
+             else
+               {
+                 domain = NULL_TREE;
+                 if (CONSTRUCTOR_NELTS (vecinit) > 0)
+                   warning (0, "non-constant array size in new, unable to "
+                            "verify length of initializer-list");
+               }
+             arraytype = build_cplus_array_type (type, domain);
+             vecinit = digest_init (arraytype, vecinit);
            }
-         else if (init)
+         else if (*init)
             {
               if (complain & tf_error)
-                permerror ("ISO C++ forbids initialization in array new");
+                permerror (input_location, "ISO C++ forbids initialization in array new");
               else
                 return error_mark_node;
+             vecinit = build_tree_list_vec (*init);
             }
          init_expr
-           = build_vec_init (init_expr,
-                             cp_build_binary_op (MINUS_EXPR, outer_nelts,
+           = build_vec_init (data_addr,
+                             cp_build_binary_op (input_location,
+                                                 MINUS_EXPR, outer_nelts,
                                                  integer_one_node,
                                                  complain),
-                             init,
-                             explicit_default_init_p,
+                             vecinit,
+                             explicit_value_init_p,
                              /*from_array=*/0,
                               complain);
 
@@ -2179,34 +2258,34 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
        }
       else
        {
-         if (init == void_zero_node)
-           init = build_default_init (full_type, nelts);
+         init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
 
-         if (TYPE_NEEDS_CONSTRUCTING (type))
+         if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
            {
              init_expr = build_special_member_call (init_expr,
                                                     complete_ctor_identifier,
                                                     init, elt_type,
                                                     LOOKUP_NORMAL,
                                                      complain);
-             stable = stabilize_init (init_expr, &init_preeval_expr);
+           }
+         else if (explicit_value_init_p)
+           {
+             /* Something like `new int()'.  */
+             init_expr = build2 (INIT_EXPR, type,
+                                 init_expr, build_value_init (type));
            }
          else
            {
+             tree ie;
+
              /* We are processing something like `new int (10)', which
                 means allocate an int, and initialize it with 10.  */
 
-             if (TREE_CODE (init) == TREE_LIST)
-               init = build_x_compound_expr_from_list (init,
-                                                       "new initializer");
-             else
-               gcc_assert (TREE_CODE (init) != CONSTRUCTOR
-                           || TREE_TYPE (init) != NULL_TREE);
-
-             init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init,
+             ie = build_x_compound_expr_from_vec (*init, "new initializer");
+             init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, ie,
                                                complain);
-             stable = stabilize_init (init_expr, &init_preeval_expr);
            }
+         stable = stabilize_init (init_expr, &init_preeval_expr);
        }
 
       if (init_expr == error_mark_node)
@@ -2228,19 +2307,27 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
          /* 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.  */
-         cleanup = build_op_delete_call (dcode, alloc_node, size,
-                                         globally_qualified_p,
-                                         (placement_allocation_fn_p
-                                          ? alloc_call : NULL_TREE),
-                                         alloc_fn);
+         cleanup = (build_op_delete_call
+                    (dcode,
+                     alloc_node,
+                     size,
+                     globally_qualified_p,
+                     placement_allocation_fn_p ? alloc_call : NULL_TREE,
+                     alloc_fn));
 
          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 = build2 (TRY_CATCH_EXPR, void_type_node,
-                               init_expr, cleanup);
+           {
+             /* CLEANUP is compiler-generated, so no diagnostics.  */
+             TREE_NO_WARNING (cleanup) = true;
+             init_expr = build2 (TRY_CATCH_EXPR, void_type_node,
+                                 init_expr, cleanup);
+             /* Likewise, this try-catch is compiler-generated.  */
+             TREE_NO_WARNING (init_expr) = true;
+           }
          else
            /* Ack!  First we allocate the memory.  Then we set our sentry
               variable to true, and expand a cleanup that deletes the
@@ -2260,6 +2347,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
              sentry = TARGET_EXPR_SLOT (begin);
 
+             /* CLEANUP is compiler-generated, so no diagnostics.  */
+             TREE_NO_WARNING (cleanup) = true;
+
              TARGET_EXPR_CLEANUP (begin)
                = build3 (COND_EXPR, void_type_node, sentry,
                          cleanup, void_zero_node);
@@ -2271,8 +2361,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
                = build2 (COMPOUND_EXPR, void_type_node, begin,
                          build2 (COMPOUND_EXPR, void_type_node, init_expr,
                                  end));
+             /* Likewise, this is compiler-generated.  */
+             TREE_NO_WARNING (init_expr) = true;
            }
-
        }
     }
   else
@@ -2287,7 +2378,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   if (cookie_expr)
     rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval);
 
-  if (rval == alloc_node)
+  if (rval == data_addr)
     /* If we don't have an initializer or a cookie, strip the TARGET_EXPR
        and return the call (which doesn't need to be adjusted).  */
     rval = TARGET_EXPR_INITIAL (alloc_expr);
@@ -2295,7 +2386,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
     {
       if (check_new)
        {
-         tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node,
+         tree ifexp = cp_build_binary_op (input_location,
+                                          NE_EXPR, alloc_node,
                                           integer_zero_node,
                                           complain);
          rval = build_conditional_expr (ifexp, rval, alloc_node, 
@@ -2310,59 +2402,58 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   if (init_preeval_expr)
     rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval);
 
-  /* Convert to the final type.  */
-  rval = build_nop (pointer_type, rval);
-
   /* A new-expression is never an lvalue.  */
   gcc_assert (!lvalue_p (rval));
 
-  if (placement != NULL)
-    rval = avoid_placement_new_aliasing (rval, placement_expr);
-
-  return rval;
+  return convert (pointer_type, rval);
 }
 
-/* Generate a representation for a C++ "new" expression.  PLACEMENT is
-   a TREE_LIST of placement-new arguments (or NULL_TREE if none).  If
-   NELTS is NULL, TYPE is the type of the storage to be allocated.  If
-   NELTS is not NULL, then this is an array-new allocation; TYPE is
-   the type of the elements in the array and NELTS is the number of
-   elements in the array.  INIT, if non-NULL, is the initializer for
-   the new object, or void_zero_node to indicate an initializer of
-   "()".  If USE_GLOBAL_NEW is true, then the user explicitly wrote
-   "::new" rather than just "new".  */
+/* Generate a representation for a C++ "new" expression.  *PLACEMENT
+   is a vector of placement-new arguments (or NULL if none).  If NELTS
+   is NULL, TYPE is the type of the storage to be allocated.  If NELTS
+   is not NULL, then this is an array-new allocation; TYPE is the type
+   of the elements in the array and NELTS is the number of elements in
+   the array.  *INIT, if non-NULL, is the initializer for the new
+   object, or an empty vector to indicate an initializer of "()".  If
+   USE_GLOBAL_NEW is true, then the user explicitly wrote "::new"
+   rather than just "new".  This may change PLACEMENT and INIT.  */
 
 tree
-build_new (tree placement, tree type, tree nelts, tree init,
-          int use_global_new, tsubst_flags_t complain)
+build_new (VEC(tree,gc) **placement, tree type, tree nelts,
+          VEC(tree,gc) **init, int use_global_new, tsubst_flags_t complain)
 {
   tree rval;
-  tree orig_placement;
-  tree orig_nelts;
-  tree orig_init;
+  VEC(tree,gc) *orig_placement = NULL;
+  tree orig_nelts = NULL_TREE;
+  VEC(tree,gc) *orig_init = NULL;
 
-  if (placement == error_mark_node || type == error_mark_node
-      || init == error_mark_node)
+  if (type == error_mark_node)
     return error_mark_node;
 
-  orig_placement = placement;
-  orig_nelts = nelts;
-  orig_init = init;
+  if (nelts == NULL_TREE && VEC_length (tree, *init) == 1)
+    {
+      tree auto_node = type_uses_auto (type);
+      if (auto_node && describable_type (VEC_index (tree, *init, 0)))
+       type = do_auto_deduction (type, VEC_index (tree, *init, 0), auto_node);
+    }
 
   if (processing_template_decl)
     {
       if (dependent_type_p (type)
-         || any_type_dependent_arguments_p (placement)
+         || any_type_dependent_arguments_p (*placement)
          || (nelts && type_dependent_expression_p (nelts))
-         || (init != void_zero_node
-             && any_type_dependent_arguments_p (init)))
-       return build_raw_new_expr (placement, type, nelts, init,
+         || any_type_dependent_arguments_p (*init))
+       return build_raw_new_expr (*placement, type, nelts, *init,
                                   use_global_new);
-      placement = build_non_dependent_args (placement);
+
+      orig_placement = make_tree_vector_copy (*placement);
+      orig_nelts = nelts;
+      orig_init = make_tree_vector_copy (*init);
+
+      make_args_non_dependent (*placement);
       if (nelts)
        nelts = build_non_dependent_expr (nelts);
-      if (init != void_zero_node)
-       init = build_non_dependent_args (init);
+      make_args_non_dependent (*init);
     }
 
   if (nelts)
@@ -2370,7 +2461,7 @@ build_new (tree placement, tree type, tree nelts, tree init,
       if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
         {
           if (complain & tf_error)
-            permerror ("size in array new must have integral type");
+            permerror (input_location, "size in array new must have integral type");
           else
             return error_mark_node;
         }
@@ -2407,8 +2498,13 @@ build_new (tree placement, tree type, tree nelts, tree init,
     return error_mark_node;
 
   if (processing_template_decl)
-    return build_raw_new_expr (orig_placement, type, orig_nelts, orig_init,
-                              use_global_new);
+    {
+      tree ret = build_raw_new_expr (orig_placement, type, orig_nelts,
+                                    orig_init, use_global_new);
+      release_tree_vector (orig_placement);
+      release_tree_vector (orig_init);
+      return ret;
+    }
 
   /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
   rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
@@ -2457,7 +2553,8 @@ build_java_class_ref (tree type)
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
   if (class_decl == NULL_TREE)
     {
-      class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
+      class_decl = build_decl (input_location,
+                              VAR_DECL, name, TREE_TYPE (jclass_node));
       TREE_STATIC (class_decl) = 1;
       DECL_EXTERNAL (class_decl) = 1;
       TREE_PUBLIC (class_decl) = 1;
@@ -2509,11 +2606,11 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
   tbase = create_temporary_var (ptype);
   tbase_init = cp_build_modify_expr (tbase, NOP_EXPR,
-                                    fold_build2 (POINTER_PLUS_EXPR, ptype,
+                                    fold_build2_loc (input_location,
+                                                 POINTER_PLUS_EXPR, ptype,
                                                  fold_convert (ptype, base),
                                                  virtual_size),
                                     tf_warning_or_error);
-  DECL_REGISTER (tbase) = 1;
   controller = build3 (BIND_EXPR, void_type_node, tbase,
                       NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (controller) = 1;
@@ -2521,17 +2618,19 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   body = build1 (EXIT_EXPR, void_type_node,
                 build2 (EQ_EXPR, boolean_type_node, tbase,
                         fold_convert (ptype, base)));
-  tmp = fold_build1 (NEGATE_EXPR, sizetype, size_exp);
+  tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp);
   body = build_compound_expr
-    (body, cp_build_modify_expr (tbase, NOP_EXPR,
+    (input_location, 
+     body, cp_build_modify_expr (tbase, NOP_EXPR,
                                 build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp),
                                 tf_warning_or_error));
   body = build_compound_expr
-    (body, build_delete (ptype, tbase, sfk_complete_destructor,
+    (input_location,
+     body, build_delete (ptype, tbase, sfk_complete_destructor,
                         LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1));
 
   loop = build1 (LOOP_EXPR, void_type_node, body);
-  loop = build_compound_expr (tbase_init, loop);
+  loop = build_compound_expr (input_location, tbase_init, loop);
 
  no_destructor:
   /* If the delete flag is one, or anything else with the low bit set,
@@ -2554,7 +2653,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
          cookie_size = targetm.cxx.get_cookie_size (type);
          base_tbd
            = cp_convert (ptype,
-                         cp_build_binary_op (MINUS_EXPR,
+                         cp_build_binary_op (input_location,
+                                             MINUS_EXPR,
                                              cp_convert (string_type_node,
                                                          base),
                                              cookie_size,
@@ -2577,14 +2677,15 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   else if (!body)
     body = deallocate_expr;
   else
-    body = build_compound_expr (body, deallocate_expr);
+    body = build_compound_expr (input_location, body, deallocate_expr);
 
   if (!body)
     body = integer_zero_node;
 
   /* Outermost wrapper: If pointer is null, punt.  */
-  body = fold_build3 (COND_EXPR, void_type_node,
-                     fold_build2 (NE_EXPR, boolean_type_node, base,
+  body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
+                     fold_build2_loc (input_location,
+                                  NE_EXPR, boolean_type_node, base,
                                   convert (TREE_TYPE (base),
                                            integer_zero_node)),
                      body, integer_zero_node);
@@ -2610,11 +2711,11 @@ create_temporary_var (tree type)
 {
   tree decl;
 
-  decl = build_decl (VAR_DECL, NULL_TREE, type);
+  decl = build_decl (input_location,
+                    VAR_DECL, NULL_TREE, type);
   TREE_USED (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   DECL_IGNORED_P (decl) = 1;
-  DECL_SOURCE_LOCATION (decl) = input_location;
   DECL_CONTEXT (decl) = current_function_decl;
 
   return decl;
@@ -2644,15 +2745,16 @@ get_temp_regvar (tree type, tree init)
 /* `build_vec_init' returns tree structure that performs
    initialization of a vector of aggregate types.
 
-   BASE is a reference to the vector, of ARRAY_TYPE.
+   BASE is a reference to the vector, of ARRAY_TYPE, or a pointer
+     to the first element, of POINTER_TYPE.
    MAXINDEX is the maximum index of the array (one less than the
-     number of elements).  It is only used if
+     number of elements).  It is only used if BASE is a pointer or
      TYPE_DOMAIN (TREE_TYPE (BASE)) == NULL_TREE.
 
    INIT is the (possibly NULL) initializer.
 
-   If EXPLICIT_DEFAULT_INIT_P is true, then INIT must be NULL.  All
-   elements in the array are default-initialized.
+   If EXPLICIT_VALUE_INIT_P is true, then INIT must be NULL.  All
+   elements in the array are value-initialized.
 
    FROM_ARRAY is 0 if we should init everything with INIT
    (i.e., every element initialized from INIT).
@@ -2663,15 +2765,14 @@ get_temp_regvar (tree type, tree init)
 
 tree
 build_vec_init (tree base, tree maxindex, tree init,
-               bool explicit_default_init_p,
+               bool explicit_value_init_p,
                int from_array, tsubst_flags_t complain)
 {
   tree rval;
   tree base2 = NULL_TREE;
-  tree size;
   tree itype = NULL_TREE;
   tree iterator;
-  /* The type of the array.  */
+  /* The type of BASE.  */
   tree atype = TREE_TYPE (base);
   /* The type of an element in the array.  */
   tree type = TREE_TYPE (atype);
@@ -2687,17 +2788,25 @@ build_vec_init (tree base, tree maxindex, tree init,
   int num_initialized_elts = 0;
   bool is_global;
 
-  if (TYPE_DOMAIN (atype))
+  if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
     maxindex = array_type_nelts (atype);
 
   if (maxindex == NULL_TREE || maxindex == error_mark_node)
     return error_mark_node;
 
-  if (explicit_default_init_p)
+  if (explicit_value_init_p)
     gcc_assert (!init);
 
-  inner_elt_type = strip_array_types (atype);
+  inner_elt_type = strip_array_types (type);
+
+  /* Look through the TARGET_EXPR around a compound literal.  */
+  if (init && TREE_CODE (init) == TARGET_EXPR
+      && TREE_CODE (TARGET_EXPR_INITIAL (init)) == CONSTRUCTOR
+      && from_array != 2)
+    init = TARGET_EXPR_INITIAL (init);
+
   if (init
+      && TREE_CODE (atype) == ARRAY_TYPE
       && (from_array == 2
          ? (!CLASS_TYPE_P (inner_elt_type)
             || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
@@ -2709,7 +2818,7 @@ build_vec_init (tree base, tree maxindex, tree init,
               || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
          || from_array))
     {
-      /* Do non-default initialization of POD arrays resulting from
+      /* Do non-default initialization of trivial arrays resulting from
         brace-enclosed initializers.  In this case, digest_init and
         store_constructor will handle the semantics for us.  */
 
@@ -2718,10 +2827,13 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
 
   maxindex = cp_convert (ptrdiff_type_node, maxindex);
-  ptype = build_pointer_type (type);
-  size = size_in_bytes (type);
-  if (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
-    base = cp_convert (ptype, decay_conversion (base));
+  if (TREE_CODE (atype) == ARRAY_TYPE)
+    {
+      ptype = build_pointer_type (type);
+      base = cp_convert (ptype, decay_conversion (base));
+    }
+  else
+    ptype = atype;
 
   /* The code we are generating looks like:
      ({
@@ -2760,6 +2872,17 @@ build_vec_init (tree base, tree maxindex, tree init,
   base = get_temp_regvar (ptype, rval);
   iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
 
+  /* If initializing one array from another, initialize element by
+     element.  We rely upon the below calls to do the argument
+     checking.  Evaluate the initializer before entering the try block.  */
+  if (from_array && init && TREE_CODE (init) != CONSTRUCTOR)
+    {
+      base2 = decay_conversion (init);
+      itype = TREE_TYPE (base2);
+      base2 = get_temp_regvar (itype, base2);
+      itype = TREE_TYPE (itype);
+    }
+
   /* Protect the entire array initialization so that we can destroy
      the partially constructed array if an exception is thrown.
      But don't do this if we're assigning.  */
@@ -2771,7 +2894,7 @@ build_vec_init (tree base, tree maxindex, tree init,
 
   if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
     {
-      /* Do non-default initialization of non-POD arrays resulting from
+      /* Do non-default initialization of non-trivial arrays resulting from
         brace-enclosed initializers.  */
       unsigned HOST_WIDE_INT idx;
       tree elt;
@@ -2802,16 +2925,8 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
   else if (from_array)
     {
-      /* If initializing one array from another, initialize element by
-        element.  We rely upon the below calls the do argument
-        checking.  */
       if (init)
-       {
-         base2 = decay_conversion (init);
-         itype = TREE_TYPE (base2);
-         base2 = get_temp_regvar (itype, base2);
-         itype = TREE_TYPE (itype);
-       }
+       /* OK, we set base2 above.  */;
       else if (TYPE_LANG_SPECIFIC (type)
               && TYPE_NEEDS_CONSTRUCTING (type)
               && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
@@ -2829,7 +2944,7 @@ build_vec_init (tree base, tree maxindex, tree init,
      We do need to keep going if we're copying an array.  */
 
   if (from_array
-      || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_default_init_p)
+      || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p)
          && ! (host_integerp (maxindex, 0)
                && (num_initialized_elts
                    == tree_low_cst (maxindex, 0) + 1))))
@@ -2878,17 +2993,17 @@ build_vec_init (tree base, tree maxindex, tree init,
              ("cannot initialize multi-dimensional array with initializer");
          elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
                                     0, 0,
-                                    /*explicit_default_init_p=*/false,
+                                    explicit_value_init_p,
                                     0, complain);
        }
-      else if (!TYPE_NEEDS_CONSTRUCTING (type))
-       elt_init = (cp_build_modify_expr
-                   (to, INIT_EXPR,
-                    build_zero_init (type, size_one_node,
-                                     /*static_storage_p=*/false),
-                    complain));
+      else if (explicit_value_init_p)
+       elt_init = build2 (INIT_EXPR, type, to,
+                          build_value_init (type));
       else
-       elt_init = build_aggr_init (to, init, 0, complain);
+       {
+         gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
+         elt_init = build_aggr_init (to, init, 0, complain);
+       }
 
       current_stmt_tree ()->stmts_are_full_exprs_p = 1;
       finish_expr_stmt (elt_init);
@@ -2908,13 +3023,15 @@ build_vec_init (tree base, tree maxindex, tree init,
       && from_array != 2)
     {
       tree e;
-      tree m = cp_build_binary_op (MINUS_EXPR, maxindex, iterator,
+      tree m = cp_build_binary_op (input_location,
+                                  MINUS_EXPR, maxindex, iterator,
                                   complain);
 
       /* Flatten multi-dimensional array since build_vec_delete only
         expects one-dimensional array.  */
       if (TREE_CODE (type) == ARRAY_TYPE)
-       m = cp_build_binary_op (MULT_EXPR, m,
+       m = cp_build_binary_op (input_location,
+                               MULT_EXPR, m,
                                array_type_nelts_total (type),
                                complain);
 
@@ -2931,10 +3048,14 @@ build_vec_init (tree base, tree maxindex, tree init,
 
   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 = cp_build_indirect_ref (stmt_expr, NULL, complain);
+  /* Now make the result have the correct type.  */
+  if (TREE_CODE (atype) == ARRAY_TYPE)
+    {
+      atype = build_pointer_type (atype);
+      stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
+      stmt_expr = cp_build_indirect_ref (stmt_expr, RO_NULL, complain);
+      TREE_NO_WARNING (stmt_expr) = 1;
+    }
 
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
   return stmt_expr;
@@ -2967,7 +3088,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
     }
   fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2);
   return build_new_method_call (exp, fn,
-                               /*args=*/NULL_TREE,
+                               /*args=*/NULL,
                                /*conversion_path=*/NULL_TREE,
                                flags,
                                /*fn_p=*/NULL,
@@ -3018,12 +3139,14 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          complete_type (type);
          if (!COMPLETE_TYPE_P (type))
            {
-             warning (0, "possible problem detected in invocation of "
-                      "delete operator:");
-             cxx_incomplete_type_diagnostic (addr, type, 1);
-             inform ("neither the destructor nor the class-specific "
-                     "operator delete will be called, even if they are "
-                     "declared when the class is defined.");
+             if (warning (0, "possible problem detected in invocation of "
+                          "delete operator:"))
+               {
+                 cxx_incomplete_type_diagnostic (addr, type, DK_WARNING);
+                 inform (input_location, "neither the destructor nor the class-specific "
+                         "operator delete will be called, even if they are "
+                         "declared when the class is defined.");
+               }
              complete_p = false;
            }
        }
@@ -3125,7 +3248,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
                                /*alloc_fn=*/NULL_TREE);
        }
 
-      expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, 
+      expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, 
                                                      tf_warning_or_error),
                              auto_delete, flags);
       if (do_delete)
@@ -3140,7 +3263,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
        ifexp = integer_one_node;
       else
        /* Handle deleting a null pointer.  */
-       ifexp = fold (cp_build_binary_op (NE_EXPR, addr, integer_zero_node,
+       ifexp = fold (cp_build_binary_op (input_location,
+                                         NE_EXPR, addr, integer_zero_node,
                                          tf_warning_or_error));
 
       if (ifexp != integer_one_node)
@@ -3182,7 +3306,7 @@ push_base_cleanups (void)
            {
              expr = build_special_member_call (current_class_ref,
                                                base_dtor_identifier,
-                                               NULL_TREE,
+                                               NULL,
                                                base_binfo,
                                                (LOOKUP_NORMAL
                                                 | LOOKUP_NONVIRTUAL),
@@ -3204,7 +3328,7 @@ push_base_cleanups (void)
 
       expr = build_special_member_call (current_class_ref,
                                        base_dtor_identifier,
-                                       NULL_TREE, base_binfo,
+                                       NULL, base_binfo,
                                        LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                         tf_warning_or_error);
       finish_decl_cleanup (NULL_TREE, expr);
@@ -3264,6 +3388,7 @@ build_vec_delete (tree base, tree maxindex,
     {
       /* Step back one from start of vector, and read dimension.  */
       tree cookie_addr;
+      tree size_ptr_type = build_pointer_type (sizetype);
 
       if (TREE_SIDE_EFFECTS (base))
        {
@@ -3271,12 +3396,13 @@ build_vec_delete (tree base, tree maxindex,
          base = TARGET_EXPR_SLOT (base_init);
        }
       type = strip_array_types (TREE_TYPE (type));
-      cookie_addr = fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (sizetype));
+      cookie_addr = fold_build1_loc (input_location, NEGATE_EXPR,
+                                sizetype, TYPE_SIZE_UNIT (sizetype));
       cookie_addr = build2 (POINTER_PLUS_EXPR,
-                           build_pointer_type (sizetype),
-                           base,
+                           size_ptr_type,
+                           fold_convert (size_ptr_type, base),
                            cookie_addr);
-      maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error);
+      maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {