OSDN Git Service

PR c++/25811
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index 0439e92..c1f1cbf 100644 (file)
@@ -1,13 +1,14 @@
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -16,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* High-level class interface.  */
 
 
 /* High-level class interface.  */
 
@@ -39,8 +39,8 @@ Boston, MA 02110-1301, USA.  */
 static bool begin_init_stmts (tree *, tree *);
 static tree finish_init_stmts (bool, tree, tree);
 static void construct_virtual_base (tree, tree);
 static bool begin_init_stmts (tree *, tree *);
 static tree finish_init_stmts (bool, tree, tree);
 static void construct_virtual_base (tree, tree);
-static void expand_aggr_init_1 (tree, tree, tree, tree, int);
-static void expand_default_init (tree, tree, tree, tree, int);
+static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t);
+static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t);
 static tree build_vec_delete_1 (tree, tree, tree, special_function_kind, int);
 static void perform_member_init (tree, tree);
 static tree build_builtin_delete_call (tree);
 static tree build_vec_delete_1 (tree, tree, tree, special_function_kind, int);
 static void perform_member_init (tree, tree);
 static tree build_builtin_delete_call (tree);
@@ -51,10 +51,10 @@ static tree initializing_context (tree);
 static void expand_cleanup_for_base (tree, tree);
 static tree get_temp_regvar (tree, tree);
 static tree dfs_initialize_vtbl_ptrs (tree, void *);
 static void expand_cleanup_for_base (tree, tree);
 static tree get_temp_regvar (tree, tree);
 static tree dfs_initialize_vtbl_ptrs (tree, void *);
-static tree build_default_init (tree, tree);
 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 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
 
 /* We are about to generate some complex initialization code.
    Conceptually, it is all a single expression.  However, we may want
@@ -137,11 +137,12 @@ initialize_vtbl_ptrs (tree addr)
 /* Return an expression for the zero-initialization of an object with
    type T.  This expression will either be a constant (in the case
    that T is a scalar), or a CONSTRUCTOR (in the case that T is an
 /* Return an expression for the zero-initialization of an object with
    type T.  This expression will either be a constant (in the case
    that T is a scalar), or a CONSTRUCTOR (in the case that T is an
-   aggregate).  In either case, the value can be used as DECL_INITIAL
-   for a decl of the indicated TYPE; it is a valid static initializer.
-   If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS is the
-   number of elements in the array.  If STATIC_STORAGE_P is TRUE,
-   initializers are only generated for entities for which
+   aggregate), or NULL (in the case that T does not require
+   initialization).  In either case, the value can be used as
+   DECL_INITIAL for a decl of the indicated TYPE; it is a valid static
+   initializer. If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS
+   is the number of elements in the array.  If STATIC_STORAGE_P is
+   TRUE, initializers are only generated for entities for which
    zero-initialization does not simply mean filling the storage with
    zero bytes.  */
 
    zero-initialization does not simply mean filling the storage with
    zero bytes.  */
 
@@ -152,7 +153,7 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
 
   /* [dcl.init]
 
 
   /* [dcl.init]
 
-     To zero-initialization storage for an object of type T means:
+     To zero-initialize an object of type T means:
 
      -- if T is a scalar type, the storage is set to the value of zero
        converted to T.
 
      -- if T is a scalar type, the storage is set to the value of zero
        converted to T.
@@ -195,12 +196,13 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
             corresponding to base classes as well.  Thus, iterating
             over TYPE_FIELDs will result in correct initialization of
             all of the subobjects.  */
             corresponding to base classes as well.  Thus, iterating
             over TYPE_FIELDs will result in correct initialization of
             all of the subobjects.  */
-         if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
+         if (!static_storage_p || !zero_init_p (TREE_TYPE (field)))
            {
              tree value = build_zero_init (TREE_TYPE (field),
                                            /*nelts=*/NULL_TREE,
                                            static_storage_p);
            {
              tree value = build_zero_init (TREE_TYPE (field),
                                            /*nelts=*/NULL_TREE,
                                            static_storage_p);
-             CONSTRUCTOR_APPEND_ELT(v, field, value);
+             if (value)
+               CONSTRUCTOR_APPEND_ELT(v, field, value);
            }
 
          /* For unions, only the first field is initialized.  */
            }
 
          /* For unions, only the first field is initialized.  */
@@ -208,8 +210,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
            break;
        }
 
            break;
        }
 
-       /* Build a constructor to contain the initializations.  */
-       init = build_constructor (type, v);
+      /* Build a constructor to contain the initializations.  */
+      init = build_constructor (type, v);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -218,10 +220,16 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
 
       /* Iterate over the array elements, building initializations.  */
       if (nelts)
 
       /* 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);
                                 nelts, integer_one_node);
       else
        max_index = array_type_nelts (type);
+
+      /* If we have an error_mark here, we should just return error mark
+        as we don't know the size of the array yet.  */
+      if (max_index == error_mark_node)
+       return error_mark_node;
       gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
 
       /* A zero-sized array, which is accepted as an extension, will
       gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
 
       /* A zero-sized array, which is accepted as an extension, will
@@ -248,63 +256,163 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
       /* Build a constructor to contain the initializations.  */
       init = build_constructor (type, v);
     }
       /* Build a constructor to contain the initializations.  */
       init = build_constructor (type, v);
     }
+  else if (TREE_CODE (type) == VECTOR_TYPE)
+    init = fold_convert (type, integer_zero_node);
   else
     gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
 
   /* In all cases, the initializer is a constant.  */
   if (init)
   else
     gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
 
   /* In all cases, the initializer is a constant.  */
   if (init)
-    {
-      TREE_CONSTANT (init) = 1;
-      TREE_INVARIANT (init) = 1;
-    }
+    TREE_CONSTANT (init) = 1;
 
   return init;
 }
 
 
   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.  */
+/* Return a suitable initializer for value-initializing an object of type
+   TYPE, as described in [dcl.init].  */
 
 
-static tree
-build_default_init (tree type, tree nelts)
+tree
+build_value_init (tree type)
 {
 {
-  /* [dcl.init]:
+  /* [dcl.init]
 
 
-    To default-initialize an object of type T means:
+     To value-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 a class type (clause 9) with a user-provided constructor
+       (12.1), then the default constructor 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;
+     - if T is a non-union class type without a user-provided constructor,
+       then every non-static data member and base-class component of T is
+       value-initialized;92)
 
 
-    --otherwise, the storage for the object is zero-initialized.
+     - if T is an array type, then each element is value-initialized;
 
 
-    A program that calls for default-initialization of an entity of refer-
-    ence type is ill-formed.  */
+     - otherwise, the object is zero-initialized.
 
 
-  /* 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].
+     A program that calls for default-initialization or
+     value-initialization of an entity of reference type is ill-formed.
 
 
-     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;
+     92) Value-initialization for such a class object may be implemented by
+     zero-initializing the object and then calling the default
+     constructor.  */
 
 
-  /* 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);
+  if (CLASS_TYPE_P (type))
+    {
+      if (type_has_user_provided_constructor (type))
+       return build_aggr_init_expr
+         (type,
+          build_special_member_call (NULL_TREE, complete_ctor_identifier,
+                                     NULL, type, LOOKUP_NORMAL,
+                                     tf_warning_or_error));
+      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;
+         VEC(constructor_elt,gc) *v = NULL;
+
+         /* Iterate over the fields, building initializations.  */
+         for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+           {
+             tree ftype, value;
+
+             if (TREE_CODE (field) != FIELD_DECL)
+               continue;
+
+             ftype = TREE_TYPE (field);
+
+             if (TREE_CODE (ftype) == REFERENCE_TYPE)
+               error ("value-initialization of reference");
+
+             /* We could skip vfields and fields of types with
+                user-defined constructors, but I think that won't improve
+                performance at all; it should be simpler in general just
+                to zero out the entire object than try to only zero the
+                bits that actually need it.  */
+
+             /* Note that for class types there will be FIELD_DECLs
+                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 (ftype);
+
+             if (value)
+               CONSTRUCTOR_APPEND_ELT(v, field, value);
+           }
+
+         /* Build a constructor to contain the zero- initializations.  */
+         return build_constructor (type, v);
+       }
+    }
+  else if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      VEC(constructor_elt,gc) *v = NULL;
+
+      /* Iterate over the array elements, building initializations.  */
+      tree max_index = array_type_nelts (type);
+
+      /* If we have an error_mark here, we should just return error mark
+        as we don't know the size of the array yet.  */
+      if (max_index == error_mark_node)
+       return error_mark_node;
+      gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
+
+      /* A zero-sized array, which is accepted as an extension, will
+        have an upper bound of -1.  */
+      if (!tree_int_cst_equal (max_index, integer_minus_one_node))
+       {
+         constructor_elt *ce;
+
+         v = VEC_alloc (constructor_elt, gc, 1);
+         ce = VEC_quick_push (constructor_elt, v, NULL);
+
+         /* If this is a one element array, we just use a regular init.  */
+         if (tree_int_cst_equal (size_zero_node, max_index))
+           ce->index = size_zero_node;
+         else
+           ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
+                               max_index);
+
+         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.  */
+      return build_constructor (type, v);
+    }
+
+  return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
 }
 
 /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
 }
 
 /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
@@ -316,30 +424,50 @@ perform_member_init (tree member, tree init)
 {
   tree decl;
   tree type = TREE_TYPE (member);
 {
   tree decl;
   tree type = TREE_TYPE (member);
-  bool explicit;
-
-  explicit = (init != NULL_TREE);
 
   /* Effective C++ rule 12 requires that all data members be
      initialized.  */
 
   /* 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,
                                         /*access_path=*/NULL_TREE,
 
   /* Get an lvalue for the data member.  */
   decl = build_class_member_access_expr (current_class_ref, member,
                                         /*access_path=*/NULL_TREE,
-                                        /*preserve_reference=*/true);
+                                        /*preserve_reference=*/true,
+                                        tf_warning_or_error);
   if (decl == error_mark_node)
     return;
 
   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.  */
   /* 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)
        {
     {
       if (init)
        {
@@ -349,39 +477,44 @@ perform_member_init (tree member, tree init)
     }
   else if (TYPE_NEEDS_CONSTRUCTING (type))
     {
     }
   else if (TYPE_NEEDS_CONSTRUCTING (type))
     {
-      if (explicit
+      if (init != NULL_TREE
          && TREE_CODE (type) == ARRAY_TYPE
          && 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),
          && 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,
-                                           /* from_array=*/1));
+                                           /*explicit_value_init_p=*/false,
+                                           /* from_array=*/1,
+                                            tf_warning_or_error));
        }
       else
        }
       else
-       finish_expr_stmt (build_aggr_init (decl, init, 0));
+       {
+         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)
        {
     }
   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);
-           }
          /* member traversal: note it leaves init NULL */
          /* member traversal: note it leaves init NULL */
-         else if (TREE_CODE (type) == REFERENCE_TYPE)
-           pedwarn ("%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))
          else if (CP_TYPE_CONST_P (type))
-           pedwarn ("%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);
        }
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
        }
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
@@ -389,7 +522,8 @@ perform_member_init (tree member, tree init)
        init = build_x_compound_expr_from_list (init, "member initializer");
 
       if (init)
        init = build_x_compound_expr_from_list (init, "member initializer");
 
       if (init)
-       finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
+       finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init,
+                                               tf_warning_or_error));
     }
 
   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
     }
 
   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
@@ -398,7 +532,8 @@ perform_member_init (tree member, tree init)
 
       expr = build_class_member_access_expr (current_class_ref, member,
                                             /*access_path=*/NULL_TREE,
 
       expr = build_class_member_access_expr (current_class_ref, member,
                                             /*access_path=*/NULL_TREE,
-                                            /*preserve_reference=*/false);
+                                            /*preserve_reference=*/false,
+                                            tf_warning_or_error);
       expr = build_delete (type, expr, sfk_complete_destructor,
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
 
       expr = build_delete (type, expr, sfk_complete_destructor,
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
 
@@ -532,7 +667,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, "  %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.  */
        }
 
       /* Look again, from the beginning of the list.  */
@@ -548,11 +684,13 @@ sort_mem_initializers (tree t, tree mem_inits)
       if (TREE_VALUE (subobject_init))
        {
          if (TREE_CODE (subobject) == FIELD_DECL)
       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
          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.  */
        }
 
       /* Record the initialization.  */
@@ -618,8 +756,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)
                  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;
                    }
                      done = 1;
                      break;
                    }
@@ -674,20 +813,17 @@ emit_mem_initializers (tree mem_inits)
       tree subobject = TREE_PURPOSE (mem_inits);
       tree arguments = TREE_VALUE (mem_inits);
 
       tree subobject = TREE_PURPOSE (mem_inits);
       tree arguments = TREE_VALUE (mem_inits);
 
-      /* If these initializations are taking place in a copy
-        constructor, the base class should probably be explicitly
-        initialized.  */
+      /* If these initializations are taking place in a copy constructor,
+        the base class should probably be explicitly initialized if there
+        is a user-defined constructor in the base class (other than the
+        default constructor, which will be called anyway).  */
       if (extra_warnings && !arguments
          && DECL_COPY_CONSTRUCTOR_P (current_function_decl)
       if (extra_warnings && !arguments
          && DECL_COPY_CONSTRUCTOR_P (current_function_decl)
-         && TYPE_NEEDS_CONSTRUCTING (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;
+         && type_has_user_nondefault_constructor (BINFO_TYPE (subobject)))
+       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))
 
       /* Initialize the base.  */
       if (BINFO_VIRTUAL_P (subobject))
@@ -699,9 +835,11 @@ 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,
          base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
                                       subobject, 1);
          expand_aggr_init_1 (subobject, NULL_TREE,
-                             build_indirect_ref (base_addr, NULL),
+                             cp_build_indirect_ref (base_addr, RO_NULL,
+                                                     tf_warning_or_error),
                              arguments,
                              arguments,
-                             LOOKUP_NORMAL);
+                             LOOKUP_NORMAL,
+                              tf_warning_or_error);
          expand_cleanup_for_base (subobject, NULL_TREE);
        }
 
          expand_cleanup_for_base (subobject, NULL_TREE);
        }
 
@@ -742,7 +880,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);
   /* 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.  */
   TREE_USED (vtbl) = 1;
 
   /* Now compute the address to use when initializing the vptr.  */
@@ -778,11 +915,11 @@ expand_virtual_init (tree binfo, tree decl)
 
       /* Compute the value to use, when there's a VTT.  */
       vtt_parm = current_vtt_parm;
 
       /* Compute the value to use, when there's a VTT.  */
       vtt_parm = current_vtt_parm;
-      vtbl2 = build2 (PLUS_EXPR,
+      vtbl2 = build2 (POINTER_PLUS_EXPR,
                      TREE_TYPE (vtt_parm),
                      vtt_parm,
                      vtt_index);
                      TREE_TYPE (vtt_parm),
                      vtt_parm,
                      vtt_index);
-      vtbl2 = build_indirect_ref (vtbl2, NULL);
+      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
       vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
 
       /* The actual initializer is the VTT value only in the subobject
@@ -797,13 +934,15 @@ expand_virtual_init (tree binfo, tree decl)
     }
 
   /* Compute the location of the vtpr.  */
     }
 
   /* Compute the location of the vtpr.  */
-  vtbl_ptr = build_vfield_ref (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);
 
   /* Assign the vtable to the vptr.  */
   vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
                               TREE_TYPE (binfo));
   gcc_assert (vtbl_ptr != error_mark_node);
 
   /* Assign the vtable to the vptr.  */
   vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
-  finish_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
+  finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl,
+                                         tf_warning_or_error));
 }
 
 /* If an exception is thrown in a constructor, those base classes already
 }
 
 /* If an exception is thrown in a constructor, those base classes already
@@ -823,12 +962,14 @@ expand_cleanup_for_base (tree binfo, tree flag)
   /* Call the destructor.  */
   expr = build_special_member_call (current_class_ref,
                                    base_dtor_identifier,
   /* Call the destructor.  */
   expr = build_special_member_call (current_class_ref,
                                    base_dtor_identifier,
-                                   NULL_TREE,
+                                   NULL,
                                    binfo,
                                    binfo,
-                                   LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
+                                   LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
+                                    tf_warning_or_error);
   if (flag)
   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);
                        expr, integer_zero_node);
 
   finish_eh_cleanup (expr);
@@ -855,7 +996,7 @@ construct_virtual_base (tree vbase, tree arguments)
      confuses the sjlj exception-handling code.  Therefore, we do not
      create a single conditional block, but one for each
      initialization.  (That way the cleanup regions always begin
      confuses the sjlj exception-handling code.  Therefore, we do not
      create a single conditional block, but one for each
      initialization.  (That way the cleanup regions always begin
-     in the outer block.)  We trust the back-end to figure out
+     in the outer block.)  We trust the back end to figure out
      that the FLAG will not change across initializations, and
      avoid doing multiple tests.  */
   flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
      that the FLAG will not change across initializations, and
      avoid doing multiple tests.  */
   flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
@@ -869,7 +1010,7 @@ construct_virtual_base (tree vbase, tree arguments)
   exp = convert_to_base_statically (current_class_ref, vbase);
 
   expand_aggr_init_1 (vbase, current_class_ref, exp, arguments,
   exp = convert_to_base_statically (current_class_ref, vbase);
 
   expand_aggr_init_1 (vbase, current_class_ref, exp, arguments,
-                     LOOKUP_COMPLAIN);
+                     LOOKUP_COMPLAIN, tf_warning_or_error);
   finish_then_clause (inner_if_stmt);
   finish_if_stmt (inner_if_stmt);
 
   finish_then_clause (inner_if_stmt);
   finish_if_stmt (inner_if_stmt);
 
@@ -1074,7 +1215,7 @@ expand_member_init (tree name)
    perform the initialization, but not both, as it would be ambiguous.  */
 
 tree
    perform the initialization, but not both, as it would be ambiguous.  */
 
 tree
-build_aggr_init (tree exp, tree init, int flags)
+build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
 {
   tree stmt_expr;
   tree compound_stmt;
 {
   tree stmt_expr;
   tree compound_stmt;
@@ -1101,20 +1242,22 @@ build_aggr_init (tree exp, tree init, int flags)
         initialization form -- unless the initializer is "()".  */
       if (init && TREE_CODE (init) == TREE_LIST)
        {
         initialization form -- unless the initializer is "()".  */
       if (init && TREE_CODE (init) == TREE_LIST)
        {
-         error ("bad array initializer");
+          if (complain & tf_error)
+            error ("bad array initializer");
          return error_mark_node;
        }
       /* Must arrange to initialize each element of EXP
         from elements of INIT.  */
       itype = init ? TREE_TYPE (init) : NULL_TREE;
          return error_mark_node;
        }
       /* Must arrange to initialize each element of EXP
         from elements of INIT.  */
       itype = init ? TREE_TYPE (init) : NULL_TREE;
-      if (cp_type_quals (type) != TYPE_UNQUALIFIED)
-       TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
-      if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
-       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,
       stmt_expr = build_vec_init (exp, NULL_TREE, init,
-                                 /*explicit_default_init_p=*/false,
-                                 itype && same_type_p (itype,
-                                                       TREE_TYPE (exp)));
+                                 /*explicit_value_init_p=*/false,
+                                 itype && same_type_p (TREE_TYPE (init),
+                                                       TREE_TYPE (exp)),
+                                  complain);
       TREE_READONLY (exp) = was_const;
       TREE_THIS_VOLATILE (exp) = was_volatile;
       TREE_TYPE (exp) = type;
       TREE_READONLY (exp) = was_const;
       TREE_THIS_VOLATILE (exp) = was_volatile;
       TREE_TYPE (exp) = type;
@@ -1127,43 +1270,22 @@ build_aggr_init (tree exp, tree init, int flags)
     /* Just know that we've seen something for this node.  */
     TREE_USED (exp) = 1;
 
     /* Just know that we've seen something for this node.  */
     TREE_USED (exp) = 1;
 
-  TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
   is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
   destroy_temps = stmts_are_full_exprs_p ();
   current_stmt_tree ()->stmts_are_full_exprs_p = 0;
   expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
   is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
   destroy_temps = stmts_are_full_exprs_p ();
   current_stmt_tree ()->stmts_are_full_exprs_p = 0;
   expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
-                     init, LOOKUP_NORMAL|flags);
+                     init, LOOKUP_NORMAL|flags, complain);
   stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
   stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
-  TREE_TYPE (exp) = type;
   TREE_READONLY (exp) = was_const;
   TREE_THIS_VOLATILE (exp) = was_volatile;
 
   return stmt_expr;
 }
 
   TREE_READONLY (exp) = was_const;
   TREE_THIS_VOLATILE (exp) = was_volatile;
 
   return stmt_expr;
 }
 
-/* Like build_aggr_init, but not just for aggregates.  */
-
-tree
-build_init (tree decl, tree init, int flags)
-{
-  tree expr;
-
-  if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
-    expr = build_aggr_init (decl, init, flags);
-  else if (CLASS_TYPE_P (TREE_TYPE (decl)))
-    expr = build_special_member_call (decl, complete_ctor_identifier,
-                                     build_tree_list (NULL_TREE, init),
-                                     TREE_TYPE (decl),
-                                     LOOKUP_NORMAL|flags);
-  else
-    expr = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init);
-
-  return expr;
-}
-
 static void
 static void
-expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
+expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
+                     tsubst_flags_t complain)
 {
   tree type = TREE_TYPE (exp);
   tree ctor_name;
 {
   tree type = TREE_TYPE (exp);
   tree ctor_name;
@@ -1175,7 +1297,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;
      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))
 
   if (init && TREE_CODE (init) != TREE_LIST
       && (flags & LOOKUP_ONLYCONVERTING))
@@ -1189,10 +1311,10 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
           to run a new constructor; and catching an exception, where we
           have already built up the constructor call so we could wrap it
           in an exception region.  */;
           to run a new constructor; and catching an exception, where we
           have already built up the constructor call so we could wrap it
           in an exception region.  */;
-      else if (BRACE_ENCLOSED_INITIALIZER_P (init))
+      else if (BRACE_ENCLOSED_INITIALIZER_P (init)
+              && CP_AGGREGATE_TYPE_P (type))
        {
          /* A brace-enclosed initializer for an aggregate.  */
        {
          /* A brace-enclosed initializer for an aggregate.  */
-         gcc_assert (CP_AGGREGATE_TYPE_P (type));
          init = digest_init (type, init);
        }
       else
          init = digest_init (type, init);
        }
       else
@@ -1215,24 +1337,30 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
       return;
     }
 
       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
     }
   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;
 
 
   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))
   if (TREE_SIDE_EFFECTS (rval))
-    finish_expr_stmt (convert_to_void (rval, NULL));
+    finish_expr_stmt (convert_to_void (rval, NULL, complain));
 }
 
 /* This function is responsible for initializing EXP with INIT
 }
 
 /* This function is responsible for initializing EXP with INIT
@@ -1256,7 +1384,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
    for its description.  */
 
 static void
    for its description.  */
 
 static void
-expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags)
+expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
+                    tsubst_flags_t complain)
 {
   tree type = TREE_TYPE (exp);
 
 {
   tree type = TREE_TYPE (exp);
 
@@ -1275,32 +1404,57 @@ 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.  */
       /* 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 (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.  */
   /* We know that expand_default_init can handle everything we want
      at this point.  */
-  expand_default_init (binfo, true_exp, exp, init, flags);
+  expand_default_init (binfo, true_exp, exp, init, flags, complain);
 }
 
 }
 
-/* Report an error if TYPE is not a user-defined, aggregate type.  If
+/* Report an error if TYPE is not a user-defined, class type.  If
    OR_ELSE is nonzero, give an error message.  */
 
 int
    OR_ELSE is nonzero, give an error message.  */
 
 int
-is_aggr_type (tree type, int or_else)
+is_class_type (tree type, int or_else)
 {
   if (type == error_mark_node)
     return 0;
 
 {
   if (type == error_mark_node)
     return 0;
 
-  if (! IS_AGGR_TYPE (type)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
-      && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (! CLASS_TYPE_P (type))
     {
       if (or_else)
     {
       if (or_else)
-       error ("%qT is not an aggregate type", type);
+       error ("%qT is not a class type", type);
       return 0;
     }
   return 1;
       return 0;
     }
   return 1;
@@ -1340,11 +1494,11 @@ build_offset_ref (tree type, tree member, bool address_p)
     return member;
 
   if (dependent_type_p (type) || type_dependent_expression_p (member))
     return member;
 
   if (dependent_type_p (type) || type_dependent_expression_p (member))
-    return build_qualified_name (NULL_TREE, type, member, 
+    return build_qualified_name (NULL_TREE, type, member,
                                 /*template_p=*/false);
 
   gcc_assert (TYPE_P (type));
                                 /*template_p=*/false);
 
   gcc_assert (TYPE_P (type));
-  if (! is_aggr_type (type, 1))
+  if (! is_class_type (type, 1))
     return error_mark_node;
 
   gcc_assert (DECL_P (member) || BASELINK_P (member));
     return error_mark_node;
 
   gcc_assert (DECL_P (member) || BASELINK_P (member));
@@ -1359,7 +1513,7 @@ build_offset_ref (tree type, tree member, bool address_p)
     }
 
   /* Entities other than non-static members need no further
     }
 
   /* Entities other than non-static members need no further
-     processing.  */ 
+     processing.  */
   if (TREE_CODE (member) == TYPE_DECL)
     return member;
   if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
   if (TREE_CODE (member) == TYPE_DECL)
     return member;
   if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
@@ -1378,8 +1532,7 @@ build_offset_ref (tree type, tree member, bool address_p)
   if (BASELINK_P (member))
     {
       /* Go from the TREE_BASELINK to the member function info.  */
   if (BASELINK_P (member))
     {
       /* Go from the TREE_BASELINK to the member function info.  */
-      tree fnfields = member;
-      tree t = BASELINK_FUNCTIONS (fnfields);
+      tree t = BASELINK_FUNCTIONS (member);
 
       if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
        {
 
       if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
        {
@@ -1396,25 +1549,22 @@ build_offset_ref (tree type, tree member, bool address_p)
               (or any class derived from that class).  */
          if (address_p && DECL_P (t)
              && DECL_NONSTATIC_MEMBER_P (t))
               (or any class derived from that class).  */
          if (address_p && DECL_P (t)
              && DECL_NONSTATIC_MEMBER_P (t))
-           perform_or_defer_access_check (TYPE_BINFO (type), t);
+           perform_or_defer_access_check (TYPE_BINFO (type), t, t);
          else
          else
-           perform_or_defer_access_check (basebinfo, t);
+           perform_or_defer_access_check (basebinfo, t, t);
 
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
          member = t;
        }
       else
 
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
          member = t;
        }
       else
-       {
-         TREE_TYPE (fnfields) = unknown_type_node;
-         member = fnfields;
-       }
+       TREE_TYPE (member) = unknown_type_node;
     }
   else if (address_p && TREE_CODE (member) == FIELD_DECL)
     /* We need additional test besides the one in
        check_accessibility_of_qualified_id in case it is
        a pointer to non-static member.  */
     }
   else if (address_p && TREE_CODE (member) == FIELD_DECL)
     /* We need additional test besides the one in
        check_accessibility_of_qualified_id in case it is
        a pointer to non-static member.  */
-    perform_or_defer_access_check (TYPE_BINFO (type), member);
+    perform_or_defer_access_check (TYPE_BINFO (type), member, member);
 
   if (!address_p)
     {
 
   if (!address_p)
     {
@@ -1437,7 +1587,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))
        {
           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);
             for use as the operand to "&" -- even though the "&" is
             not actually present.  */
          member = build2 (OFFSET_REF, TREE_TYPE (member), decl, member);
@@ -1446,11 +1596,12 @@ build_offset_ref (tree type, tree member, bool address_p)
          if (flag_ms_extensions)
            {
              PTRMEM_OK_P (member) = 1;
          if (flag_ms_extensions)
            {
              PTRMEM_OK_P (member) = 1;
-             return build_unary_op (ADDR_EXPR, member, 0);
+             return cp_build_unary_op (ADDR_EXPR, member, 0, 
+                                        tf_warning_or_error);
            }
          error ("invalid use of non-static member function %qD",
                 TREE_OPERAND (member, 1));
            }
          error ("invalid use of non-static member function %qD",
                 TREE_OPERAND (member, 1));
-         return member;
+         return error_mark_node;
        }
       else if (TREE_CODE (member) == FIELD_DECL)
        {
        }
       else if (TREE_CODE (member) == FIELD_DECL)
        {
@@ -1475,7 +1626,7 @@ static tree
 constant_value_1 (tree decl, bool integral_p)
 {
   while (TREE_CODE (decl) == CONST_DECL
 constant_value_1 (tree decl, bool integral_p)
 {
   while (TREE_CODE (decl) == CONST_DECL
-        || (integral_p 
+        || (integral_p
             ? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
             : (TREE_CODE (decl) == VAR_DECL
                && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
             ? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
             : (TREE_CODE (decl) == VAR_DECL
                && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
@@ -1490,7 +1641,7 @@ constant_value_1 (tree decl, bool integral_p)
         instantiation time.  */
       if (DECL_CLASS_SCOPE_P (decl)
          && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
         instantiation time.  */
       if (DECL_CLASS_SCOPE_P (decl)
          && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
-         && uses_template_parms (CLASSTYPE_TI_ARGS 
+         && uses_template_parms (CLASSTYPE_TI_ARGS
                                  (DECL_CONTEXT (decl))))
        {
          ++processing_template_decl;
                                  (DECL_CONTEXT (decl))))
        {
          ++processing_template_decl;
@@ -1507,7 +1658,16 @@ constant_value_1 (tree decl, bool integral_p)
          init = DECL_INITIAL (decl);
        }
       if (init == error_mark_node)
          init = DECL_INITIAL (decl);
        }
       if (init == error_mark_node)
-       return error_mark_node;
+       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
       if (!init
          || !TREE_TYPE (init)
          || (integral_p
@@ -1538,13 +1698,13 @@ integral_constant_value (tree decl)
 }
 
 /* A more relaxed version of integral_constant_value, used by the
 }
 
 /* A more relaxed version of integral_constant_value, used by the
-   common C/C++ code and by the C++ front-end for optimization
+   common C/C++ code and by the C++ front end for optimization
    purposes.  */
 
 tree
 decl_constant_value (tree decl)
 {
    purposes.  */
 
 tree
 decl_constant_value (tree decl)
 {
-  return constant_value_1 (decl, 
+  return constant_value_1 (decl,
                           /*integral_p=*/processing_template_decl);
 }
 \f
                           /*integral_p=*/processing_template_decl);
 }
 \f
@@ -1556,62 +1716,120 @@ static tree
 build_builtin_delete_call (tree addr)
 {
   mark_used (global_delete_fndecl);
 build_builtin_delete_call (tree addr)
 {
   mark_used (global_delete_fndecl);
-  return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
+  return build_call_n (global_delete_fndecl, 1, addr);
 }
 \f
 /* Build and return a NEW_EXPR.  If NELTS is non-NULL, TYPE[NELTS] is
    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
 }
 \f
 /* Build and return a NEW_EXPR.  If NELTS is non-NULL, TYPE[NELTS] is
    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
 
 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;
   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;
 }
 
   NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
   TREE_SIDE_EFFECTS (new_expr) = 1;
 
   return new_expr;
 }
 
+/* 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 void
+diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
+                                           bool using_new)
+{
+  tree field;
+
+  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+    {
+      tree field_type;
+
+      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%>",
+                  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%>",
+                  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);
+    }
+}
+
+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
 /* 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
 
 static tree
-build_new_1 (tree placement, tree type, tree nelts, tree init,
-            bool globally_qualified_p)
-            
+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;
 {
   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
      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;
   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
   tree outer_nelts = NULL_TREE;
   tree alloc_call, alloc_expr;
   /* The address returned by the call to "operator new".  This node is
@@ -1625,10 +1843,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;
      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;
   /* 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;
   /* True if the storage must be initialized, either by a constructor
      or due to an explicit new-initializer.  */
   bool is_initialized;
@@ -1641,103 +1860,129 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
   if (nelts)
     {
 
   if (nelts)
     {
-      tree index;
-
       outer_nelts = nelts;
       array_p = true;
       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;
-      full_type = build_cplus_array_type (type, NULL_TREE);
-      index = convert (sizetype, nelts);
-      index = size_binop (MINUS_EXPR, index, size_one_node);
-      TYPE_DOMAIN (full_type) = build_index_type (index);
     }
     }
-  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 (!complete_type_or_else (type, NULL_TREE))
-    return error_mark_node;
-
   /* If our base type is an array, then make sure we know how many elements
      it has.  */
   for (elt_type = type;
        TREE_CODE (elt_type) == ARRAY_TYPE;
        elt_type = TREE_TYPE (elt_type))
   /* If our base type is an array, then make sure we know how many elements
      it has.  */
   for (elt_type = type;
        TREE_CODE (elt_type) == ARRAY_TYPE;
        elt_type = TREE_TYPE (elt_type))
-    nelts = cp_build_binary_op (MULT_EXPR, nelts,
-                               array_type_nelts_top (elt_type));
+    nelts = cp_build_binary_op (input_location,
+                               MULT_EXPR, nelts,
+                               array_type_nelts_top (elt_type),
+                               complain);
 
   if (TREE_CODE (elt_type) == VOID_TYPE)
     {
 
   if (TREE_CODE (elt_type) == VOID_TYPE)
     {
-      error ("invalid type %<void%> for new");
+      if (complain & tf_error)
+        error ("invalid type %<void%> for new");
       return error_mark_node;
     }
 
   if (abstract_virtuals_error (NULL_TREE, elt_type))
     return error_mark_node;
 
       return error_mark_node;
     }
 
   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))
     {
     {
-      error ("uninitialized const in %<new%> of %q#T", elt_type);
+      if (complain & tf_error)
+        error ("uninitialized const in %<new%> of %q#T", elt_type);
       return error_mark_node;
     }
 
   size = size_in_bytes (elt_type);
   if (array_p)
       return error_mark_node;
     }
 
   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;
 
 
   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.  */
   /* 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);
       static const char alloc_name[] = "_Jv_AllocObject";
 
     {
       tree class_addr;
       tree class_decl = build_java_class_ref (elt_type);
       static const char alloc_name[] = "_Jv_AllocObject";
 
+      if (class_decl == error_mark_node)
+       return error_mark_node;
+
       use_java_new = 1;
       if (!get_global_value_if_present (get_identifier (alloc_name),
                                        &alloc_fn))
        {
       use_java_new = 1;
       if (!get_global_value_if_present (get_identifier (alloc_name),
                                        &alloc_fn))
        {
-         error ("call to Java constructor with %qs undefined", alloc_name);
+          if (complain & tf_error)
+            error ("call to Java constructor with %qs undefined", alloc_name);
          return error_mark_node;
        }
       else if (really_overloaded_fn (alloc_fn))
        {
          return error_mark_node;
        }
       else if (really_overloaded_fn (alloc_fn))
        {
-         error ("%qD should never be overloaded", alloc_fn);
+          if (complain & tf_error)
+            error ("%qD should never be overloaded", alloc_fn);
          return error_mark_node;
        }
       alloc_fn = OVL_CURRENT (alloc_fn);
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
          return error_mark_node;
        }
       alloc_fn = OVL_CURRENT (alloc_fn);
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
-      alloc_call = (build_function_call
+      alloc_call = (cp_build_function_call
                    (alloc_fn,
                    (alloc_fn,
-                    build_tree_list (NULL_TREE, class_addr)));
+                    build_tree_list (NULL_TREE, class_addr),
+                    complain));
+    }
+  else if (TYPE_FOR_JAVA (elt_type) && MAYBE_CLASS_TYPE_P (elt_type))
+    {
+      error ("Java class %q#T object allocated using placement new", elt_type);
+      return error_mark_node;
     }
   else
     {
     }
   else
     {
@@ -1760,25 +2005,30 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
              size = size_binop (PLUS_EXPR, size, cookie_size);
            }
          /* Create the argument list.  */
              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)
            {
          /* Do name-lookup to find the appropriate operator.  */
          fns = lookup_fnfields (elt_type, fnname, /*protect=*/2);
          if (fns == NULL_TREE)
            {
-             error ("no suitable %qD found in class %qT", fnname, elt_type);
+              if (complain & tf_error)
+                error ("no suitable %qD found in class %qT", fnname, elt_type);
              return error_mark_node;
            }
          if (TREE_CODE (fns) == TREE_LIST)
            {
              return error_mark_node;
            }
          if (TREE_CODE (fns) == TREE_LIST)
            {
-             error ("request for member %qD is ambiguous", fnname);
-             print_candidates (fns);
+              if (complain & tf_error)
+                {
+                  error ("request for member %qD is ambiguous", fnname);
+                  print_candidates (fns);
+                }
              return error_mark_node;
            }
          alloc_call = build_new_method_call (build_dummy_object (elt_type),
              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,
                                              /*conversion_path=*/NULL_TREE,
                                              LOOKUP_NORMAL,
-                                             &alloc_fn);
+                                             &alloc_fn,
+                                             complain);
        }
       else
        {
        }
       else
        {
@@ -1800,16 +2050,34 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
   gcc_assert (alloc_fn != NULL_TREE);
 
 
   gcc_assert (alloc_fn != NULL_TREE);
 
+  /* If we found a simple case of PLACEMENT_EXPR above, then copy it
+     into a temporary variable.  */
+  if (!processing_template_decl
+      && 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
+      && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 1))) == POINTER_TYPE)
+    {
+      tree placement_arg = CALL_EXPR_ARG (alloc_call, 1);
+
+      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 (placement_first);
+         CALL_EXPR_ARG (alloc_call, 1)
+           = convert (TREE_TYPE (placement_arg), placement_expr);
+       }
+    }
+
   /* In the simple case, we can stop now.  */
   pointer_type = build_pointer_type (type);
   if (!cookie_size && !is_initialized)
     return build_nop (pointer_type, alloc_call);
 
   /* In the simple case, we can stop now.  */
   pointer_type = build_pointer_type (type);
   if (!cookie_size && !is_initialized)
     return build_nop (pointer_type, alloc_call);
 
-  /* While we're working, use a pointer to the type we've actually
-     allocated. Store the result of the call in a variable so that we
-     can use it more than once.  */
-  full_pointer_type = build_pointer_type (full_type);
-  alloc_expr = get_target_expr (build_nop (full_pointer_type, alloc_call));
+  /* 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.  */
   alloc_node = TARGET_EXPR_SLOT (alloc_expr);
 
   /* Strip any COMPOUND_EXPRs from ALLOC_CALL.  */
@@ -1858,32 +2126,39 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
     {
       tree cookie;
       tree cookie_ptr;
     {
       tree cookie;
       tree cookie_ptr;
+      tree size_ptr_type;
 
       /* Adjust so we're pointing to the start of the object.  */
 
       /* Adjust so we're pointing to the start of the object.  */
-      data_addr = get_target_expr (build2 (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.  */
 
       /* 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 = build2 (MINUS_EXPR, build_pointer_type (sizetype),
-                          data_addr, size_in_bytes (sizetype));
-      cookie = build_indirect_ref (cookie_ptr, NULL);
+      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 = 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);
 
       if (targetm.cxx.cookie_has_size ())
        {
          /* Also store the element size.  */
 
       cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
 
       if (targetm.cxx.cookie_has_size ())
        {
          /* Also store the element size.  */
-         cookie_ptr = build2 (MINUS_EXPR, build_pointer_type (sizetype),
-                              cookie_ptr, size_in_bytes (sizetype));
-         cookie = build_indirect_ref (cookie_ptr, NULL);
+         cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, cookie_ptr,
+                              fold_build1_loc (input_location,
+                                           NEGATE_EXPR, sizetype,
+                                           size_in_bytes (sizetype)));
+
+         cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
          cookie = build2 (MODIFY_EXPR, sizetype, cookie,
          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);
        }
          cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
                                cookie, cookie_expr);
        }
-      data_addr = TARGET_EXPR_SLOT (data_addr);
     }
   else
     {
     }
   else
     {
@@ -1891,6 +2166,17 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
       data_addr = alloc_node;
     }
 
       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
   /* 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
@@ -1899,28 +2185,53 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   if (is_initialized)
     {
       bool stable;
   if (is_initialized)
     {
       bool stable;
+      bool explicit_value_init_p = false;
 
 
-      init_expr = build_indirect_ref (data_addr, NULL);
+      if (*init != NULL && VEC_empty (tree, *init))
+       {
+         *init = NULL;
+         explicit_value_init_p = true;
+       }
 
       if (array_p)
        {
 
       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)
-           pedwarn ("ISO C++ forbids initialization in array new");
-
+         else if (*init)
+            {
+              if (complain & tf_error)
+                permerror (input_location, "ISO C++ forbids initialization in array new");
+              else
+                return error_mark_node;
+             vecinit = build_tree_list_vec (*init);
+            }
          init_expr
          init_expr
-           = build_vec_init (init_expr,
-                             cp_build_binary_op (MINUS_EXPR, outer_nelts,
-                                                 integer_one_node),
-                             init, 
-                             explicit_default_init_p,
-                             /*from_array=*/0);
+           = build_vec_init (data_addr,
+                             cp_build_binary_op (input_location,
+                                                 MINUS_EXPR, outer_nelts,
+                                                 integer_one_node,
+                                                 complain),
+                             vecinit,
+                             explicit_value_init_p,
+                             /*from_array=*/0,
+                              complain);
 
          /* An array initialization is stable because the initialization
             of each element is a full-expression, so the temporaries don't
 
          /* An array initialization is stable because the initialization
             of each element is a full-expression, so the temporaries don't
@@ -1929,32 +2240,34 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
        }
       else
        {
        }
       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,
            {
              init_expr = build_special_member_call (init_expr,
                                                     complete_ctor_identifier,
                                                     init, elt_type,
-                                                    LOOKUP_NORMAL);
-             stable = stabilize_init (init_expr, &init_preeval_expr);
+                                                    LOOKUP_NORMAL,
+                                                     complain);
+           }
+         else if (explicit_value_init_p)
+           {
+             /* Something like `new int()'.  */
+             init_expr = build2 (INIT_EXPR, type,
+                                 init_expr, build_value_init (type));
            }
          else
            {
            }
          else
            {
+             tree ie;
+
              /* We are processing something like `new int (10)', which
                 means allocate an int, and initialize it with 10.  */
              /* We are processing something like `new int (10)', which
                 means allocate an int, and initialize it with 10.  */
-             
-             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 = build_modify_expr (init_expr, INIT_EXPR, init);
-             stable = stabilize_init (init_expr, &init_preeval_expr);
+
+             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);
        }
 
       if (init_expr == error_mark_node)
        }
 
       if (init_expr == error_mark_node)
@@ -1976,20 +2289,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.  */
          /* 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),
-                                         (placement_allocation_fn_p
-                                          ? alloc_fn : NULL_TREE));
+         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.  */
 
          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
          else
            /* Ack!  First we allocate the memory.  Then we set our sentry
               variable to true, and expand a cleanup that deletes the
@@ -2009,6 +2329,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
              sentry = TARGET_EXPR_SLOT (begin);
 
 
              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);
              TARGET_EXPR_CLEANUP (begin)
                = build3 (COND_EXPR, void_type_node, sentry,
                          cleanup, void_zero_node);
@@ -2020,8 +2343,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));
                = 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
        }
     }
   else
@@ -2036,7 +2360,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 (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);
     /* 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);
@@ -2044,9 +2368,12 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
     {
       if (check_new)
        {
     {
       if (check_new)
        {
-         tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node,
-                                          integer_zero_node);
-         rval = build_conditional_expr (ifexp, rval, 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, 
+                                         complain);
        }
 
       /* Perform the allocation before anything else, so that ALLOC_NODE
        }
 
       /* Perform the allocation before anything else, so that ALLOC_NODE
@@ -2057,64 +2384,70 @@ 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);
 
   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.  */
   /* A new-expression is never an lvalue.  */
-  rval = rvalue (rval);
+  gcc_assert (!lvalue_p (rval));
 
 
-  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
 
 tree
-build_new (tree placement, tree type, tree nelts, tree init,
-          int use_global_new)
+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 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 (type == error_mark_node)
     return 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)
 
   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))
          || (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);
                                   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 (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)
     {
       if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
     }
 
   if (nelts)
     {
       if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
-       pedwarn ("size in array new must have integral type");
-      nelts = save_expr (cp_convert (sizetype, nelts));
-      if (nelts == integer_zero_node)
-       warning (0, "zero size array reserves no space");
+        {
+          if (complain & tf_error)
+            permerror (input_location, "size in array new must have integral type");
+          else
+            return error_mark_node;
+        }
+      nelts = cp_save_expr (cp_convert (sizetype, nelts));
     }
 
   /* ``A reference cannot be created by the new operator.  A reference
     }
 
   /* ``A reference cannot be created by the new operator.  A reference
@@ -2122,23 +2455,38 @@ build_new (tree placement, tree type, tree nelts, tree init,
      returned by new.'' ARM 5.3.3 */
   if (TREE_CODE (type) == REFERENCE_TYPE)
     {
      returned by new.'' ARM 5.3.3 */
   if (TREE_CODE (type) == REFERENCE_TYPE)
     {
-      error ("new cannot be applied to a reference type");
+      if (complain & tf_error)
+        error ("new cannot be applied to a reference type");
+      else
+        return error_mark_node;
       type = TREE_TYPE (type);
     }
 
   if (TREE_CODE (type) == FUNCTION_TYPE)
     {
       type = TREE_TYPE (type);
     }
 
   if (TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error ("new cannot be applied to a function type");
+      if (complain & tf_error)
+        error ("new cannot be applied to a function type");
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
-  rval = build_new_1 (placement, type, nelts, init, use_global_new);
+  /* The type allocated must be complete.  If the new-type-id was
+     "T[N]" then we are just checking that "T" is complete here, but
+     that is equivalent, since the value of "N" doesn't matter.  */
+  if (!complete_type_or_else (type, NULL_TREE))
+    return error_mark_node;
+
+  rval = build_new_1 (placement, type, nelts, init, use_global_new, complain);
   if (rval == error_mark_node)
     return error_mark_node;
 
   if (processing_template_decl)
   if (rval == error_mark_node)
     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);
 
   /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
   rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
@@ -2160,8 +2508,10 @@ build_java_class_ref (tree type)
     {
       jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
       if (jclass_node == NULL_TREE)
     {
       jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
       if (jclass_node == NULL_TREE)
-       fatal_error ("call to Java constructor, while %<jclass%> undefined");
-
+       {
+         error ("call to Java constructor, while %<jclass%> undefined");
+         return error_mark_node;
+       }
       jclass_node = TREE_TYPE (jclass_node);
     }
 
       jclass_node = TREE_TYPE (jclass_node);
     }
 
@@ -2176,13 +2526,17 @@ build_java_class_ref (tree type)
          break;
        }
     if (!field)
          break;
        }
     if (!field)
-      internal_error ("can't find class$");
-    }
+      {
+       error ("can't find %<class$%> in %qT", type);
+       return error_mark_node;
+      }
+  }
 
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
   if (class_decl == NULL_TREE)
     {
 
   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;
       TREE_STATIC (class_decl) = 1;
       DECL_EXTERNAL (class_decl) = 1;
       TREE_PUBLIC (class_decl) = 1;
@@ -2220,11 +2574,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
      executing any other code in the loop.
      This is also the containing expression returned by this function.  */
   tree controller = NULL_TREE;
      executing any other code in the loop.
      This is also the containing expression returned by this function.  */
   tree controller = NULL_TREE;
+  tree tmp;
 
   /* We should only have 1-D arrays here.  */
   gcc_assert (TREE_CODE (type) != ARRAY_TYPE);
 
 
   /* We should only have 1-D arrays here.  */
   gcc_assert (TREE_CODE (type) != ARRAY_TYPE);
 
-  if (! IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+  if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     goto no_destructor;
 
   /* The below is short by the cookie size.  */
     goto no_destructor;
 
   /* The below is short by the cookie size.  */
@@ -2232,11 +2587,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
                             convert (sizetype, maxindex));
 
   tbase = create_temporary_var (ptype);
                             convert (sizetype, maxindex));
 
   tbase = create_temporary_var (ptype);
-  tbase_init = build_modify_expr (tbase, NOP_EXPR,
-                                 fold_build2 (PLUS_EXPR, ptype,
-                                              base,
-                                              virtual_size));
-  DECL_REGISTER (tbase) = 1;
+  tbase_init = cp_build_modify_expr (tbase, NOP_EXPR,
+                                    fold_build2_loc (input_location,
+                                                 POINTER_PLUS_EXPR, ptype,
+                                                 fold_convert (ptype, base),
+                                                 virtual_size),
+                                    tf_warning_or_error);
   controller = build3 (BIND_EXPR, void_type_node, tbase,
                       NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (controller) = 1;
   controller = build3 (BIND_EXPR, void_type_node, tbase,
                       NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (controller) = 1;
@@ -2244,15 +2600,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)));
   body = build1 (EXIT_EXPR, void_type_node,
                 build2 (EQ_EXPR, boolean_type_node, tbase,
                         fold_convert (ptype, base)));
+  tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp);
   body = build_compound_expr
   body = build_compound_expr
-    (body, build_modify_expr (tbase, NOP_EXPR,
-                             build2 (MINUS_EXPR, ptype, tbase, size_exp)));
+    (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_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);
                         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,
 
  no_destructor:
   /* If the delete flag is one, or anything else with the low bit set,
@@ -2275,10 +2635,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
          cookie_size = targetm.cxx.get_cookie_size (type);
          base_tbd
            = cp_convert (ptype,
          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),
                                              cp_convert (string_type_node,
                                                          base),
-                                             cookie_size));
+                                             cookie_size,
+                                             tf_warning_or_error));
          /* True size with header.  */
          virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size);
        }
          /* True size with header.  */
          virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size);
        }
@@ -2287,7 +2649,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
        deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
                                                base_tbd, virtual_size,
                                                use_global_delete & 1,
        deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
                                                base_tbd, virtual_size,
                                                use_global_delete & 1,
-                                               /*placement=*/NULL_TREE, 
+                                               /*placement=*/NULL_TREE,
                                                /*alloc_fn=*/NULL_TREE);
     }
 
                                                /*alloc_fn=*/NULL_TREE);
     }
 
@@ -2297,14 +2659,15 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   else if (!body)
     body = deallocate_expr;
   else
   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.  */
 
   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);
                                   convert (TREE_TYPE (base),
                                            integer_zero_node)),
                      body, integer_zero_node);
@@ -2320,7 +2683,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
     /* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR.  */
     body = build2 (COMPOUND_EXPR, void_type_node, base, body);
 
     /* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR.  */
     body = build2 (COMPOUND_EXPR, void_type_node, base, body);
 
-  return convert_to_void (body, /*implicit=*/NULL);
+  return convert_to_void (body, /*implicit=*/NULL, tf_warning_or_error);
 }
 
 /* Create an unnamed variable of the indicated TYPE.  */
 }
 
 /* Create an unnamed variable of the indicated TYPE.  */
@@ -2330,11 +2693,11 @@ create_temporary_var (tree type)
 {
   tree decl;
 
 {
   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;
   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;
   DECL_CONTEXT (decl) = current_function_decl;
 
   return decl;
@@ -2355,7 +2718,8 @@ get_temp_regvar (tree type, tree init)
   decl = create_temporary_var (type);
   add_decl_expr (decl);
 
   decl = create_temporary_var (type);
   add_decl_expr (decl);
 
-  finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
+  finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init, 
+                                         tf_warning_or_error));
 
   return decl;
 }
 
   return decl;
 }
@@ -2363,15 +2727,16 @@ get_temp_regvar (tree type, tree init)
 /* `build_vec_init' returns tree structure that performs
    initialization of a vector of aggregate types.
 
 /* `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
    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.
 
      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).
 
    FROM_ARRAY is 0 if we should init everything with INIT
    (i.e., every element initialized from INIT).
@@ -2381,16 +2746,15 @@ get_temp_regvar (tree type, tree init)
    but use assignment instead of initialization.  */
 
 tree
    but use assignment instead of initialization.  */
 
 tree
-build_vec_init (tree base, tree maxindex, tree init, 
-               bool explicit_default_init_p,
-               int from_array)
+build_vec_init (tree base, tree maxindex, tree init,
+               bool explicit_value_init_p,
+               int from_array, tsubst_flags_t complain)
 {
   tree rval;
   tree base2 = NULL_TREE;
 {
   tree rval;
   tree base2 = NULL_TREE;
-  tree size;
   tree itype = NULL_TREE;
   tree iterator;
   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);
   tree atype = TREE_TYPE (base);
   /* The type of an element in the array.  */
   tree type = TREE_TYPE (atype);
@@ -2406,17 +2770,25 @@ build_vec_init (tree base, tree maxindex, tree init,
   int num_initialized_elts = 0;
   bool is_global;
 
   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;
 
     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);
 
     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
   if (init
+      && TREE_CODE (atype) == ARRAY_TYPE
       && (from_array == 2
          ? (!CLASS_TYPE_P (inner_elt_type)
             || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
       && (from_array == 2
          ? (!CLASS_TYPE_P (inner_elt_type)
             || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
@@ -2428,7 +2800,7 @@ build_vec_init (tree base, tree maxindex, tree init,
               || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
          || from_array))
     {
               || ! 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.  */
 
         brace-enclosed initializers.  In this case, digest_init and
         store_constructor will handle the semantics for us.  */
 
@@ -2437,10 +2809,13 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
 
   maxindex = cp_convert (ptrdiff_type_node, maxindex);
     }
 
   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:
      ({
 
   /* The code we are generating looks like:
      ({
@@ -2469,7 +2844,7 @@ build_vec_init (tree base, tree maxindex, tree init,
      When copying from array to another, when the array elements have
      only trivial copy constructors, we should use __builtin_memcpy
      rather than generating a loop.  That way, we could take advantage
      When copying from array to another, when the array elements have
      only trivial copy constructors, we should use __builtin_memcpy
      rather than generating a loop.  That way, we could take advantage
-     of whatever cleverness the back-end has for dealing with copies
+     of whatever cleverness the back end has for dealing with copies
      of blocks of memory.  */
 
   is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
      of blocks of memory.  */
 
   is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
@@ -2479,6 +2854,17 @@ build_vec_init (tree base, tree maxindex, tree init,
   base = get_temp_regvar (ptype, rval);
   iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
 
   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.  */
   /* 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.  */
@@ -2490,7 +2876,7 @@ build_vec_init (tree base, tree maxindex, tree init,
 
   if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
     {
 
   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;
         brace-enclosed initializers.  */
       unsigned HOST_WIDE_INT idx;
       tree elt;
@@ -2503,15 +2889,17 @@ build_vec_init (tree base, tree maxindex, tree init,
          num_initialized_elts++;
 
          current_stmt_tree ()->stmts_are_full_exprs_p = 1;
          num_initialized_elts++;
 
          current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-         if (IS_AGGR_TYPE (type) || TREE_CODE (type) == ARRAY_TYPE)
-           finish_expr_stmt (build_aggr_init (baseref, elt, 0));
+         if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
+           finish_expr_stmt (build_aggr_init (baseref, elt, 0, complain));
          else
          else
-           finish_expr_stmt (build_modify_expr (baseref, NOP_EXPR,
-                                                elt));
+           finish_expr_stmt (cp_build_modify_expr (baseref, NOP_EXPR,
+                                                    elt, complain));
          current_stmt_tree ()->stmts_are_full_exprs_p = 0;
 
          current_stmt_tree ()->stmts_are_full_exprs_p = 0;
 
-         finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base, 0));
-         finish_expr_stmt (build_unary_op (PREDECREMENT_EXPR, iterator, 0));
+         finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base, 0,
+                                               complain));
+         finish_expr_stmt (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
+                                               complain));
        }
 
       /* Clear out INIT so that we don't get confused below.  */
        }
 
       /* Clear out INIT so that we don't get confused below.  */
@@ -2519,21 +2907,14 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
   else if (from_array)
     {
     }
   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)
       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))
        {
       else if (TYPE_LANG_SPECIFIC (type)
               && TYPE_NEEDS_CONSTRUCTING (type)
               && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
        {
-         error ("initializer ends prematurely");
+          if (complain & tf_error)
+            error ("initializer ends prematurely");
          return error_mark_node;
        }
     }
          return error_mark_node;
        }
     }
@@ -2545,7 +2926,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
      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))))
          && ! (host_integerp (maxindex, 0)
                && (num_initialized_elts
                    == tree_low_cst (maxindex, 0) + 1))))
@@ -2561,7 +2942,8 @@ build_vec_init (tree base, tree maxindex, tree init,
       finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
                               build_int_cst (TREE_TYPE (iterator), -1)),
                       for_stmt);
       finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
                               build_int_cst (TREE_TYPE (iterator), -1)),
                       for_stmt);
-      finish_for_expr (build_unary_op (PREDECREMENT_EXPR, iterator, 0),
+      finish_for_expr (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
+                                          complain),
                       for_stmt);
 
       to = build1 (INDIRECT_REF, type, base);
                       for_stmt);
 
       to = build1 (INDIRECT_REF, type, base);
@@ -2576,11 +2958,13 @@ build_vec_init (tree base, tree maxindex, tree init,
            from = NULL_TREE;
 
          if (from_array == 2)
            from = NULL_TREE;
 
          if (from_array == 2)
-           elt_init = build_modify_expr (to, NOP_EXPR, from);
+           elt_init = cp_build_modify_expr (to, NOP_EXPR, from, 
+                                            complain);
          else if (TYPE_NEEDS_CONSTRUCTING (type))
          else if (TYPE_NEEDS_CONSTRUCTING (type))
-           elt_init = build_aggr_init (to, from, 0);
+           elt_init = build_aggr_init (to, from, 0, complain);
          else if (from)
          else if (from)
-           elt_init = build_modify_expr (to, NOP_EXPR, from);
+           elt_init = cp_build_modify_expr (to, NOP_EXPR, from,
+                                            complain);
          else
            gcc_unreachable ();
        }
          else
            gcc_unreachable ();
        }
@@ -2590,25 +2974,28 @@ build_vec_init (tree base, tree maxindex, tree init,
            sorry
              ("cannot initialize multi-dimensional array with initializer");
          elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
            sorry
              ("cannot initialize multi-dimensional array with initializer");
          elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
-                                    0, 0, 
-                                    /*explicit_default_init_p=*/false,
-                                    0);
+                                    0, 0,
+                                    explicit_value_init_p,
+                                    0, complain);
        }
        }
-      else if (!TYPE_NEEDS_CONSTRUCTING (type))
-       elt_init = (build_modify_expr 
-                   (to, INIT_EXPR,
-                    build_zero_init (type, size_one_node,
-                                     /*static_storage_p=*/false)));
+      else if (explicit_value_init_p)
+       elt_init = build2 (INIT_EXPR, type, to,
+                          build_value_init (type));
       else
       else
-       elt_init = build_aggr_init (to, init, 0);
+       {
+         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);
       current_stmt_tree ()->stmts_are_full_exprs_p = 0;
 
 
       current_stmt_tree ()->stmts_are_full_exprs_p = 1;
       finish_expr_stmt (elt_init);
       current_stmt_tree ()->stmts_are_full_exprs_p = 0;
 
-      finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base, 0));
+      finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base, 0,
+                                           complain));
       if (base2)
       if (base2)
-       finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base2, 0));
+       finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base2, 0,
+                                             complain));
 
       finish_for_stmt (for_stmt);
     }
 
       finish_for_stmt (for_stmt);
     }
@@ -2618,13 +3005,17 @@ build_vec_init (tree base, tree maxindex, tree init,
       && from_array != 2)
     {
       tree e;
       && 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)
 
       /* 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,
-                               array_type_nelts_total (type));
+       m = cp_build_binary_op (input_location,
+                               MULT_EXPR, m,
+                               array_type_nelts_total (type),
+                               complain);
 
       finish_cleanup_try_block (try_block);
       e = build_vec_delete_1 (rval, m,
 
       finish_cleanup_try_block (try_block);
       e = build_vec_delete_1 (rval, m,
@@ -2639,10 +3030,14 @@ build_vec_init (tree base, tree maxindex, tree init,
 
   stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
 
 
   stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
 
-  /* Now convert make the result have the correct type.  */
-  atype = build_pointer_type (atype);
-  stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
-  stmt_expr = build_indirect_ref (stmt_expr, NULL);
+  /* 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;
 
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
   return stmt_expr;
@@ -2675,10 +3070,11 @@ 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,
     }
   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,
                                /*conversion_path=*/NULL_TREE,
                                flags,
-                               /*fn_p=*/NULL);
+                               /*fn_p=*/NULL,
+                               tf_warning_or_error);
 }
 
 /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
 }
 
 /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -2725,16 +3121,18 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          complete_type (type);
          if (!COMPLETE_TYPE_P (type))
            {
          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;
            }
        }
              complete_p = false;
            }
        }
-      if (VOID_TYPE_P (type) || !complete_p || !IS_AGGR_TYPE (type))
+      if (VOID_TYPE_P (type) || !complete_p || !MAYBE_CLASS_TYPE_P (type))
        /* Call the builtin operator delete.  */
        return build_builtin_delete_call (addr);
       if (TREE_SIDE_EFFECTS (addr))
        /* Call the builtin operator delete.  */
        return build_builtin_delete_call (addr);
       if (TREE_SIDE_EFFECTS (addr))
@@ -2760,28 +3158,29 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
       /* Don't check PROTECT here; leave that decision to the
         destructor.  If the destructor is accessible, call it,
         else report error.  */
       /* Don't check PROTECT here; leave that decision to the
         destructor.  If the destructor is accessible, call it,
         else report error.  */
-      addr = build_unary_op (ADDR_EXPR, addr, 0);
+      addr = cp_build_unary_op (ADDR_EXPR, addr, 0, tf_warning_or_error);
       if (TREE_SIDE_EFFECTS (addr))
        addr = save_expr (addr);
 
       addr = convert_force (build_pointer_type (type), addr, 0);
     }
 
       if (TREE_SIDE_EFFECTS (addr))
        addr = save_expr (addr);
 
       addr = convert_force (build_pointer_type (type), addr, 0);
     }
 
-  gcc_assert (IS_AGGR_TYPE (type));
+  gcc_assert (MAYBE_CLASS_TYPE_P (type));
 
   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     {
       if (auto_delete != sfk_deleting_destructor)
        return void_zero_node;
 
 
   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     {
       if (auto_delete != sfk_deleting_destructor)
        return void_zero_node;
 
-      return build_op_delete_call (DELETE_EXPR, addr, 
-                                  cxx_sizeof_nowarn (type), 
+      return build_op_delete_call (DELETE_EXPR, addr,
+                                  cxx_sizeof_nowarn (type),
                                   use_global_delete,
                                   /*placement=*/NULL_TREE,
                                   /*alloc_fn=*/NULL_TREE);
     }
   else
     {
                                   use_global_delete,
                                   /*placement=*/NULL_TREE,
                                   /*alloc_fn=*/NULL_TREE);
     }
   else
     {
+      tree head = NULL_TREE;
       tree do_delete = NULL_TREE;
       tree ifexp;
 
       tree do_delete = NULL_TREE;
       tree ifexp;
 
@@ -2795,8 +3194,9 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
        {
          /* We will use ADDR multiple times so we must save it.  */
          addr = save_expr (addr);
        {
          /* We will use ADDR multiple times so we must save it.  */
          addr = save_expr (addr);
+         head = get_target_expr (build_headof (addr));
          /* Delete the object.  */
          /* Delete the object.  */
-         do_delete = build_builtin_delete_call (addr);
+         do_delete = build_builtin_delete_call (head);
          /* Otherwise, treat this like a complete object destructor
             call.  */
          auto_delete = sfk_complete_destructor;
          /* Otherwise, treat this like a complete object destructor
             call.  */
          auto_delete = sfk_complete_destructor;
@@ -2825,22 +3225,29 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          /* Make sure we have access to the member op delete, even though
             we'll actually be calling it from the destructor.  */
          build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
          /* Make sure we have access to the member op delete, even though
             we'll actually be calling it from the destructor.  */
          build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
-                               /*global_p=*/false, 
+                               /*global_p=*/false,
                                /*placement=*/NULL_TREE,
                                /*alloc_fn=*/NULL_TREE);
        }
 
                                /*placement=*/NULL_TREE,
                                /*alloc_fn=*/NULL_TREE);
        }
 
-      expr = build_dtor_call (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)
        expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete);
 
                              auto_delete, flags);
       if (do_delete)
        expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete);
 
+      /* We need to calculate this before the dtor changes the vptr.  */
+      if (head)
+       expr = build2 (COMPOUND_EXPR, void_type_node, head, expr);
+
       if (flags & LOOKUP_DESTRUCTOR)
        /* Explicit destructor call; don't check for null pointer.  */
        ifexp = integer_one_node;
       else
        /* Handle deleting a null pointer.  */
       if (flags & LOOKUP_DESTRUCTOR)
        /* Explicit destructor call; don't check for null pointer.  */
        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)
        expr = build3 (COND_EXPR, void_type_node,
 
       if (ifexp != integer_one_node)
        expr = build3 (COND_EXPR, void_type_node,
@@ -2881,10 +3288,11 @@ push_base_cleanups (void)
            {
              expr = build_special_member_call (current_class_ref,
                                                base_dtor_identifier,
            {
              expr = build_special_member_call (current_class_ref,
                                                base_dtor_identifier,
-                                               NULL_TREE,
+                                               NULL,
                                                base_binfo,
                                                (LOOKUP_NORMAL
                                                base_binfo,
                                                (LOOKUP_NORMAL
-                                                | LOOKUP_NONVIRTUAL));
+                                                | LOOKUP_NONVIRTUAL),
+                                                tf_warning_or_error);
              expr = build3 (COND_EXPR, void_type_node, cond,
                             expr, void_zero_node);
              finish_decl_cleanup (NULL_TREE, expr);
              expr = build3 (COND_EXPR, void_type_node, cond,
                             expr, void_zero_node);
              finish_decl_cleanup (NULL_TREE, expr);
@@ -2902,22 +3310,26 @@ push_base_cleanups (void)
 
       expr = build_special_member_call (current_class_ref,
                                        base_dtor_identifier,
 
       expr = build_special_member_call (current_class_ref,
                                        base_dtor_identifier,
-                                       NULL_TREE, base_binfo,
-                                       LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
+                                       NULL, base_binfo,
+                                       LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
+                                        tf_warning_or_error);
       finish_decl_cleanup (NULL_TREE, expr);
     }
 
   for (member = TYPE_FIELDS (current_class_type); member;
        member = TREE_CHAIN (member))
     {
       finish_decl_cleanup (NULL_TREE, expr);
     }
 
   for (member = TYPE_FIELDS (current_class_type); member;
        member = TREE_CHAIN (member))
     {
-      if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
+      if (TREE_TYPE (member) == error_mark_node
+         || TREE_CODE (member) != FIELD_DECL
+         || DECL_ARTIFICIAL (member))
        continue;
       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
        {
          tree this_member = (build_class_member_access_expr
                              (current_class_ref, member,
                               /*access_path=*/NULL_TREE,
        continue;
       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
        {
          tree this_member = (build_class_member_access_expr
                              (current_class_ref, member,
                               /*access_path=*/NULL_TREE,
-                              /*preserve_reference=*/false));
+                              /*preserve_reference=*/false,
+                              tf_warning_or_error));
          tree this_type = TREE_TYPE (member);
          expr = build_delete (this_type, this_member,
                               sfk_complete_destructor,
          tree this_type = TREE_TYPE (member);
          expr = build_delete (this_type, this_member,
                               sfk_complete_destructor,
@@ -2958,6 +3370,7 @@ build_vec_delete (tree base, tree maxindex,
     {
       /* Step back one from start of vector, and read dimension.  */
       tree cookie_addr;
     {
       /* 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))
        {
 
       if (TREE_SIDE_EFFECTS (base))
        {
@@ -2965,11 +3378,13 @@ build_vec_delete (tree base, tree maxindex,
          base = TARGET_EXPR_SLOT (base_init);
        }
       type = strip_array_types (TREE_TYPE (type));
          base = TARGET_EXPR_SLOT (base_init);
        }
       type = strip_array_types (TREE_TYPE (type));
-      cookie_addr = build2 (MINUS_EXPR,
-                           build_pointer_type (sizetype),
-                           base,
-                           TYPE_SIZE_UNIT (sizetype));
-      maxindex = build_indirect_ref (cookie_addr, NULL);
+      cookie_addr = fold_build1_loc (input_location, NEGATE_EXPR,
+                                sizetype, TYPE_SIZE_UNIT (sizetype));
+      cookie_addr = build2 (POINTER_PLUS_EXPR,
+                           size_ptr_type,
+                           fold_convert (size_ptr_type, base),
+                           cookie_addr);
+      maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -2977,7 +3392,7 @@ build_vec_delete (tree base, tree maxindex,
         bad name.  */
       maxindex = array_type_nelts_total (type);
       type = strip_array_types (type);
         bad name.  */
       maxindex = array_type_nelts_total (type);
       type = strip_array_types (type);
-      base = build_unary_op (ADDR_EXPR, base, 1);
+      base = cp_build_unary_op (ADDR_EXPR, base, 1, tf_warning_or_error);
       if (TREE_SIDE_EFFECTS (base))
        {
          base_init = get_target_expr (base);
       if (TREE_SIDE_EFFECTS (base))
        {
          base_init = get_target_expr (base);