OSDN Git Service

2011-05-23 Jonathan Wakely <jwakely.gcc@gmail.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index a99983e..5f30275 100644 (file)
@@ -1,7 +1,7 @@
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -27,13 +27,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
-#include "expr.h"
 #include "cp-tree.h"
 #include "flags.h"
 #include "output.h"
-#include "except.h"
-#include "toplev.h"
 #include "target.h"
 
 static bool begin_init_stmts (tree *, tree *);
@@ -41,7 +37,6 @@ 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, 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 int member_init_ok_or_else (tree, tree, tree);
@@ -49,11 +44,10 @@ static void expand_virtual_init (tree, tree);
 static tree sort_mem_initializers (tree, tree);
 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 tree build_dtor_call (tree, special_function_kind, int);
 static tree build_field_list (tree, tree, int *);
 static tree build_vtbl_address (tree);
+static int diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool, bool);
 
 /* We are about to generate some complex initialization code.
    Conceptually, it is all a single expression.  However, we may want
@@ -143,10 +137,13 @@ initialize_vtbl_ptrs (tree addr)
    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 bytes.  FIELD_SIZE, if non-NULL, is the bit size of the field,
+   subfields with bit positions at or above that bit size shouldn't
+   be added.  */
 
-tree
-build_zero_init (tree type, tree nelts, bool static_storage_p)
+static tree
+build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
+                  tree field_size)
 {
   tree init = NULL_TREE;
 
@@ -186,20 +183,37 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
       VEC(constructor_elt,gc) *v = NULL;
 
       /* Iterate over the fields, building initializations.  */
-      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        {
          if (TREE_CODE (field) != FIELD_DECL)
            continue;
 
+         /* Don't add virtual bases for base classes if they are beyond
+            the size of the current field, that means it is present
+            somewhere else in the object.  */
+         if (field_size)
+           {
+             tree bitpos = bit_position (field);
+             if (TREE_CODE (bitpos) == INTEGER_CST
+                 && !tree_int_cst_lt (bitpos, field_size))
+               continue;
+           }
+
          /* 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.  */
          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 new_field_size
+               = (DECL_FIELD_IS_BASE (field)
+                  && DECL_SIZE (field)
+                  && TREE_CODE (DECL_SIZE (field)) == INTEGER_CST)
+                 ? DECL_SIZE (field) : NULL_TREE;
+             tree value = build_zero_init_1 (TREE_TYPE (field),
+                                             /*nelts=*/NULL_TREE,
+                                             static_storage_p,
+                                             new_field_size);
              if (value)
                CONSTRUCTOR_APPEND_ELT(v, field, value);
            }
@@ -219,7 +233,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
 
       /* Iterate over the array elements, building initializations.  */
       if (nelts)
-       max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts),
+       max_index = fold_build2_loc (input_location,
+                                MINUS_EXPR, TREE_TYPE (nelts),
                                 nelts, integer_one_node);
       else
        max_index = array_type_nelts (type);
@@ -246,16 +261,16 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
            ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
                                max_index);
 
-         ce->value = build_zero_init (TREE_TYPE (type),
-                                      /*nelts=*/NULL_TREE,
-                                      static_storage_p);
+         ce->value = build_zero_init_1 (TREE_TYPE (type),
+                                        /*nelts=*/NULL_TREE,
+                                        static_storage_p, NULL_TREE);
        }
 
       /* 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);
+    init = build_zero_cst (type);
   else
     gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
 
@@ -266,11 +281,29 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
   return init;
 }
 
+/* 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), 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.  */
+
+tree
+build_zero_init (tree type, tree nelts, bool static_storage_p)
+{
+  return build_zero_init_1 (type, nelts, static_storage_p, NULL_TREE);
+}
+
 /* Return a suitable initializer for value-initializing an object of type
    TYPE, as described in [dcl.init].  */
 
 tree
-build_value_init (tree type)
+build_value_init (tree type, tsubst_flags_t complain)
 {
   /* [dcl.init]
 
@@ -296,6 +329,9 @@ build_value_init (tree type)
      zero-initializing the object and then calling the default
      constructor.  */
 
+  /* The AGGR_INIT_EXPR tweaking below breaks in templates.  */
+  gcc_assert (!processing_template_decl);
+
   if (CLASS_TYPE_P (type))
     {
       if (type_has_user_provided_constructor (type))
@@ -303,8 +339,9 @@ build_value_init (tree type)
          (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))
+                                     complain),
+          complain);
+      else if (type_build_ctor_call (type))
        {
          /* This is a class that needs constructing, but doesn't have
             a user-provided constructor.  So we need to zero-initialize
@@ -312,25 +349,29 @@ build_value_init (tree type)
             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;
+            NULL, type, LOOKUP_NORMAL, complain);
+         if (ctor != error_mark_node)
+           {
+             ctor = build_aggr_init_expr (type, ctor, complain);
+             AGGR_INIT_ZERO_FIRST (ctor) = 1;
+           }
          return ctor;
        }
     }
-  return build_value_init_noctor (type);
+  return build_value_init_noctor (type, complain);
 }
 
 /* Like build_value_init, but don't call the constructor for TYPE.  Used
    for base initializers.  */
 
 tree
-build_value_init_noctor (tree type)
+build_value_init_noctor (tree type, tsubst_flags_t complain)
 {
+  /* FIXME the class and array cases should just use digest_init once it is
+     SFINAE-enabled.  */
   if (CLASS_TYPE_P (type))
     {
-      gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type));
+      gcc_assert (!type_build_ctor_call (type));
        
       if (TREE_CODE (type) != UNION_TYPE)
        {
@@ -338,7 +379,7 @@ build_value_init_noctor (tree type)
          VEC(constructor_elt,gc) *v = NULL;
 
          /* Iterate over the fields, building initializations.  */
-         for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+         for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
            {
              tree ftype, value;
 
@@ -347,9 +388,6 @@ build_value_init_noctor (tree type)
 
              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
@@ -360,7 +398,10 @@ build_value_init_noctor (tree type)
                 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);
+             value = build_value_init (ftype, complain);
+
+             if (value == error_mark_node)
+               return error_mark_node;
 
              if (value)
                CONSTRUCTOR_APPEND_ELT(v, field, value);
@@ -380,7 +421,12 @@ build_value_init_noctor (tree 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;
+       {
+         if (complain & tf_error)
+           error ("cannot value-initialize array of unknown bound %qT",
+                  type);
+         return error_mark_node;
+       }
       gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
 
       /* A zero-sized array, which is accepted as an extension, will
@@ -399,9 +445,14 @@ build_value_init_noctor (tree type)
            ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
                                max_index);
 
-         ce->value = build_value_init (TREE_TYPE (type));
+         ce->value = build_value_init (TREE_TYPE (type), complain);
+
+         if (ce->value == error_mark_node)
+           return error_mark_node;
 
-         /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs.  */
+         /* We shouldn't have gotten here for anything that would need
+            non-trivial initialization, and gimplify_init_ctor_preeval
+            would need to be fixed to allow it.  */
          gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR
                      && TREE_CODE (ce->value) != AGGR_INIT_EXPR);
        }
@@ -409,6 +460,18 @@ build_value_init_noctor (tree type)
       /* Build a constructor to contain the initializations.  */
       return build_constructor (type, v);
     }
+  else if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      if (complain & tf_error)
+       error ("value-initialization of function type %qT", type);
+      return error_mark_node;
+    }
+  else if (TREE_CODE (type) == REFERENCE_TYPE)
+    {
+      if (complain & tf_error)
+       error ("value-initialization of reference type %qT", type);
+      return error_mark_node;
+    }
 
   return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
 }
@@ -426,8 +489,9 @@ perform_member_init (tree member, tree init)
   /* Effective C++ rule 12 requires that all data members be
      initialized.  */
   if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE)
-    warning (OPT_Weffc__, "%J%qD should be initialized in the member initialization "
-            "list", current_function_decl, member);
+    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,
@@ -437,28 +501,33 @@ perform_member_init (tree member, tree init)
   if (decl == error_mark_node)
     return;
 
+  if (warn_init_self && init && TREE_CODE (init) == TREE_LIST
+      && TREE_CHAIN (init) == NULL_TREE)
+    {
+      tree val = TREE_VALUE (init);
+      if (TREE_CODE (val) == COMPONENT_REF && TREE_OPERAND (val, 1) == member
+         && TREE_OPERAND (val, 0) == current_class_ref)
+       warning_at (DECL_SOURCE_LOCATION (current_function_decl),
+                   OPT_Wuninitialized, "%qD is initialized with itself",
+                   member);
+    }
+
   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);
+         init = build_vec_init_expr (type, init, tf_warning_or_error);
+         init = build2 (INIT_EXPR, type, decl, init);
          finish_expr_stmt (init);
        }
       else
        {
-         if (TREE_CODE (type) == REFERENCE_TYPE)
-           permerror (input_location, "%Jvalue-initialization of %q#D, "
-                                      "which has reference type",
-                      current_function_decl, member);
-         else
-           {
-             init = build2 (INIT_EXPR, type, decl, build_value_init (type));
-             finish_expr_stmt (init);
-           }
+         tree value = build_value_init (type, tf_warning_or_error);
+         if (value == error_mark_node)
+           return;
+         init = build2 (INIT_EXPR, type, decl, value);
+         finish_expr_stmt (init);
        }
     }
   /* Deal with this here, as we will get confused if we try to call the
@@ -472,29 +541,40 @@ perform_member_init (tree member, tree init)
          finish_expr_stmt (init);
        }
     }
-  else if (TYPE_NEEDS_CONSTRUCTING (type))
+  else if (type_build_ctor_call (type))
     {
-      if (init != NULL_TREE
-         && TREE_CODE (type) == ARRAY_TYPE
-         && TREE_CHAIN (init) == NULL_TREE
-         && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
+      if (TREE_CODE (type) == ARRAY_TYPE)
        {
-         /* Initialization of one array from another.  */
-         finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
-                                           /*explicit_value_init_p=*/false,
-                                           /* from_array=*/1,
-                                            tf_warning_or_error));
+         if (init)
+           {
+             gcc_assert (TREE_CHAIN (init) == NULL_TREE);
+             init = TREE_VALUE (init);
+           }
+         if (init == NULL_TREE
+             || same_type_ignoring_top_level_qualifiers_p (type,
+                                                           TREE_TYPE (init)))
+           {
+             init = build_vec_init_expr (type, init, tf_warning_or_error);
+             init = build2 (INIT_EXPR, type, decl, init);
+             finish_expr_stmt (init);
+           }
+         else
+           error ("invalid initializer for array member %q#D", member);
        }
       else
        {
+         int flags = LOOKUP_NORMAL;
+         if (DECL_DEFAULTED_FN (current_function_decl))
+           flags |= LOOKUP_DEFAULTED;
          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 (input_location, "%Juninitialized member %qD with %<const%> type %qT",
-                      current_function_decl, member, type);
-         finish_expr_stmt (build_aggr_init (decl, init, 0, 
+           permerror (DECL_SOURCE_LOCATION (current_function_decl),
+                      "uninitialized member %qD with %<const%> type %qT",
+                      member, type);
+         finish_expr_stmt (build_aggr_init (decl, init, flags,
                                             tf_warning_or_error));
        }
     }
@@ -502,18 +582,40 @@ perform_member_init (tree member, tree init)
     {
       if (init == NULL_TREE)
        {
+         tree core_type;
          /* member traversal: note it leaves init NULL */
          if (TREE_CODE (type) == REFERENCE_TYPE)
-           permerror (input_location, "%Juninitialized reference member %qD",
-                      current_function_decl, member);
+           permerror (DECL_SOURCE_LOCATION (current_function_decl),
+                      "uninitialized reference member %qD",
+                      member);
          else if (CP_TYPE_CONST_P (type))
-           permerror (input_location, "%Juninitialized member %qD with %<const%> type %qT",
-                      current_function_decl, member, type);
+           permerror (DECL_SOURCE_LOCATION (current_function_decl),
+                      "uninitialized member %qD with %<const%> type %qT",
+                      member, type);
+
+         core_type = strip_array_types (type);
+
+         if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+             && !type_has_constexpr_default_constructor (core_type))
+           {
+             if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl))
+               error ("uninitialized member %qD in %<constexpr%> constructor",
+                      member);
+             DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
+           }
+
+         if (CLASS_TYPE_P (core_type)
+             && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+                 || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
+           diagnose_uninitialized_cst_or_ref_member (core_type,
+                                                     /*using_new=*/false,
+                                                     /*complain=*/true);
        }
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
           in that case.  */
-       init = build_x_compound_expr_from_list (init, "member initializer");
+       init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
+                                               tf_warning_or_error);
 
       if (init)
        finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init,
@@ -529,7 +631,8 @@ perform_member_init (tree member, tree init)
                                             /*preserve_reference=*/false,
                                             tf_warning_or_error);
       expr = build_delete (type, expr, sfk_complete_destructor,
-                          LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+                          LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
+                          tf_warning_or_error);
 
       if (expr != error_mark_node)
        finish_eh_cleanup (expr);
@@ -550,27 +653,29 @@ build_field_list (tree t, tree list, int *uses_unions_p)
   if (TREE_CODE (t) == UNION_TYPE)
     *uses_unions_p = 1;
 
-  for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
+  for (fields = TYPE_FIELDS (t); fields; fields = DECL_CHAIN (fields))
     {
+      tree fieldtype;
+
       /* Skip CONST_DECLs for enumeration constants and so forth.  */
       if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
        continue;
 
+      fieldtype = TREE_TYPE (fields);
       /* Keep track of whether or not any fields are unions.  */
-      if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
+      if (TREE_CODE (fieldtype) == UNION_TYPE)
        *uses_unions_p = 1;
 
       /* For an anonymous struct or union, we must recursively
         consider the fields of the anonymous type.  They can be
         directly initialized from the constructor.  */
-      if (ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
+      if (ANON_AGGR_TYPE_P (fieldtype))
        {
          /* Add this field itself.  Synthesized copy constructors
             initialize the entire aggregate.  */
          list = tree_cons (fields, NULL_TREE, list);
          /* And now add the fields in the anonymous aggregate.  */
-         list = build_field_list (TREE_TYPE (fields), list,
-                                  uses_unions_p);
+         list = build_field_list (fieldtype, list, uses_unions_p);
        }
       /* Add this field.  */
       else if (DECL_NAME (fields))
@@ -661,7 +766,8 @@ sort_mem_initializers (tree t, tree mem_inits)
            warning (OPT_Wreorder, "  %q+#D", subobject);
          else
            warning (OPT_Wreorder, "  base %qT", subobject);
-         warning (OPT_Wreorder, "%J  when initialized here", current_function_decl);
+         warning_at (DECL_SOURCE_LOCATION (current_function_decl),
+                     OPT_Wreorder, "  when initialized here");
        }
 
       /* Look again, from the beginning of the list.  */
@@ -677,11 +783,13 @@ sort_mem_initializers (tree t, tree mem_inits)
       if (TREE_VALUE (subobject_init))
        {
          if (TREE_CODE (subobject) == FIELD_DECL)
-           error ("%Jmultiple initializations given for %qD",
-                  current_function_decl, subobject);
+           error_at (DECL_SOURCE_LOCATION (current_function_decl),
+                     "multiple initializations given for %qD",
+                     subobject);
          else
-           error ("%Jmultiple initializations given for base %qT",
-                  current_function_decl, subobject);
+           error_at (DECL_SOURCE_LOCATION (current_function_decl),
+                     "multiple initializations given for base %qT",
+                     subobject);
        }
 
       /* Record the initialization.  */
@@ -693,38 +801,54 @@ sort_mem_initializers (tree t, tree mem_inits)
 
      If a ctor-initializer specifies more than one mem-initializer for
      multiple members of the same union (including members of
-     anonymous unions), the ctor-initializer is ill-formed.  */
+     anonymous unions), the ctor-initializer is ill-formed.
+
+     Here we also splice out uninitialized union members.  */
   if (uses_unions_p)
     {
       tree last_field = NULL_TREE;
-      for (init = sorted_inits; init; init = TREE_CHAIN (init))
+      tree *p;
+      for (p = &sorted_inits; *p; )
        {
          tree field;
-         tree field_type;
+         tree ctx;
          int done;
 
-         /* Skip uninitialized members and base classes.  */
-         if (!TREE_VALUE (init)
-             || TREE_CODE (TREE_PURPOSE (init)) != FIELD_DECL)
-           continue;
+         init = *p;
+
+         field = TREE_PURPOSE (init);
+
+         /* Skip base classes.  */
+         if (TREE_CODE (field) != FIELD_DECL)
+           goto next;
+
+         /* If this is an anonymous union with no explicit initializer,
+            splice it out.  */
+         if (!TREE_VALUE (init) && ANON_UNION_TYPE_P (TREE_TYPE (field)))
+           goto splice;
+
          /* See if this field is a member of a union, or a member of a
             structure contained in a union, etc.  */
-         field = TREE_PURPOSE (init);
-         for (field_type = DECL_CONTEXT (field);
-              !same_type_p (field_type, t);
-              field_type = TYPE_CONTEXT (field_type))
-           if (TREE_CODE (field_type) == UNION_TYPE)
+         for (ctx = DECL_CONTEXT (field);
+              !same_type_p (ctx, t);
+              ctx = TYPE_CONTEXT (ctx))
+           if (TREE_CODE (ctx) == UNION_TYPE)
              break;
          /* If this field is not a member of a union, skip it.  */
-         if (TREE_CODE (field_type) != UNION_TYPE)
-           continue;
+         if (TREE_CODE (ctx) != UNION_TYPE)
+           goto next;
+
+         /* If this union member has no explicit initializer, splice
+            it out.  */
+         if (!TREE_VALUE (init))
+           goto splice;
 
          /* It's only an error if we have two initializers for the same
             union type.  */
          if (!last_field)
            {
              last_field = field;
-             continue;
+             goto next;
            }
 
          /* See if LAST_FIELD and the field initialized by INIT are
@@ -735,40 +859,48 @@ sort_mem_initializers (tree t, tree mem_inits)
               union { struct { int i; int j; }; };
 
             initializing both `i' and `j' makes sense.  */
-         field_type = DECL_CONTEXT (field);
+         ctx = DECL_CONTEXT (field);
          done = 0;
          do
            {
-             tree last_field_type;
+             tree last_ctx;
 
-             last_field_type = DECL_CONTEXT (last_field);
+             last_ctx = DECL_CONTEXT (last_field);
              while (1)
                {
-                 if (same_type_p (last_field_type, field_type))
+                 if (same_type_p (last_ctx, ctx))
                    {
-                     if (TREE_CODE (field_type) == UNION_TYPE)
-                       error ("%Jinitializations for multiple members of %qT",
-                              current_function_decl, last_field_type);
+                     if (TREE_CODE (ctx) == UNION_TYPE)
+                       error_at (DECL_SOURCE_LOCATION (current_function_decl),
+                                 "initializations for multiple members of %qT",
+                                 last_ctx);
                      done = 1;
                      break;
                    }
 
-                 if (same_type_p (last_field_type, t))
+                 if (same_type_p (last_ctx, t))
                    break;
 
-                 last_field_type = TYPE_CONTEXT (last_field_type);
+                 last_ctx = TYPE_CONTEXT (last_ctx);
                }
 
              /* If we've reached the outermost class, then we're
                 done.  */
-             if (same_type_p (field_type, t))
+             if (same_type_p (ctx, t))
                break;
 
-             field_type = TYPE_CONTEXT (field_type);
+             ctx = TYPE_CONTEXT (ctx);
            }
          while (!done);
 
          last_field = field;
+
+       next:
+         p = &TREE_CHAIN (*p);
+         continue;
+       splice:
+         *p = TREE_CHAIN (*p);
+         continue;
        }
     }
 
@@ -785,11 +917,16 @@ sort_mem_initializers (tree t, tree mem_inits)
 void
 emit_mem_initializers (tree mem_inits)
 {
+  int flags = LOOKUP_NORMAL;
+
   /* We will already have issued an error message about the fact that
      the type is incomplete.  */
   if (!COMPLETE_TYPE_P (current_class_type))
     return;
 
+  if (DECL_DEFAULTED_FN (current_function_decl))
+    flags |= LOOKUP_DEFAULTED;
+
   /* Sort the mem-initializers into the order in which the
      initializations should be performed.  */
   mem_inits = sort_mem_initializers (current_class_type, mem_inits);
@@ -803,16 +940,30 @@ emit_mem_initializers (tree 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 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)
-         && type_has_user_nondefault_constructor (BINFO_TYPE (subobject)))
-       warning (OPT_Wextra, "%Jbase class %q#T should be explicitly initialized in the "
-                "copy constructor",
-                current_function_decl, BINFO_TYPE (subobject));
+      if (arguments == NULL_TREE)
+       {
+         /* 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
+             && DECL_COPY_CONSTRUCTOR_P (current_function_decl)
+             && 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));
+
+         if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+             && !(type_has_constexpr_default_constructor
+                  (BINFO_TYPE (subobject))))
+           {
+             if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl))
+               error ("uninitialized base %qT in %<constexpr%> constructor",
+                      BINFO_TYPE (subobject));
+             DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
+           }
+       }
 
       /* Initialize the base.  */
       if (BINFO_VIRTUAL_P (subobject))
@@ -824,10 +975,10 @@ emit_mem_initializers (tree mem_inits)
          base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
                                       subobject, 1);
          expand_aggr_init_1 (subobject, NULL_TREE,
-                             cp_build_indirect_ref (base_addr, NULL,
+                             cp_build_indirect_ref (base_addr, RO_NULL,
                                                      tf_warning_or_error),
                              arguments,
-                             LOOKUP_NORMAL,
+                             flags,
                               tf_warning_or_error);
          expand_cleanup_for_base (subobject, NULL_TREE);
        }
@@ -908,7 +1059,7 @@ expand_virtual_init (tree binfo, tree decl)
                      TREE_TYPE (vtt_parm),
                      vtt_parm,
                      vtt_index);
-      vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error);
+      vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error);
       vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
 
       /* The actual initializer is the VTT value only in the subobject
@@ -923,7 +1074,7 @@ expand_virtual_init (tree binfo, tree decl)
     }
 
   /* Compute the location of the vtpr.  */
-  vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL, 
+  vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL, 
                                                       tf_warning_or_error),
                               TREE_TYPE (binfo));
   gcc_assert (vtbl_ptr != error_mark_node);
@@ -956,7 +1107,8 @@ expand_cleanup_for_base (tree binfo, tree flag)
                                    LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                     tf_warning_or_error);
   if (flag)
-    expr = fold_build3 (COND_EXPR, void_type_node,
+    expr = fold_build3_loc (input_location,
+                       COND_EXPR, void_type_node,
                        c_common_truthvalue_conversion (input_location, flag),
                        expr, integer_zero_node);
 
@@ -987,7 +1139,7 @@ construct_virtual_base (tree vbase, tree arguments)
      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));
+  flag = DECL_CHAIN (DECL_ARGUMENTS (current_function_decl));
   inner_if_stmt = begin_if_stmt ();
   finish_if_stmt_cond (flag, inner_if_stmt);
 
@@ -1219,7 +1371,9 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
   TREE_READONLY (exp) = 0;
   TREE_THIS_VOLATILE (exp) = 0;
 
-  if (init && TREE_CODE (init) != TREE_LIST)
+  if (init && TREE_CODE (init) != TREE_LIST
+      && !(BRACE_ENCLOSED_INITIALIZER_P (init)
+          && CONSTRUCTOR_IS_DIRECT_INIT (init)))
     flags |= LOOKUP_ONLYCONVERTING;
 
   if (TREE_CODE (type) == ARRAY_TYPE)
@@ -1237,13 +1391,13 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
       /* Must arrange to initialize each element of EXP
         from elements of INIT.  */
       itype = init ? TREE_TYPE (init) : NULL_TREE;
-      if (cp_type_quals (type) != TYPE_UNQUALIFIED)
-       TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
-      if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
-       itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
+      if (cv_qualified_p (type))
+       TREE_TYPE (exp) = cv_unqualified (type);
+      if (itype && cv_qualified_p (itype))
+       TREE_TYPE (init) = cv_unqualified (itype);
       stmt_expr = build_vec_init (exp, NULL_TREE, init,
                                  /*explicit_value_init_p=*/false,
-                                 itype && same_type_p (itype,
+                                 itype && same_type_p (TREE_TYPE (init),
                                                        TREE_TYPE (exp)),
                                   complain);
       TREE_READONLY (exp) = was_const;
@@ -1287,6 +1441,18 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
   tree rval;
   VEC(tree,gc) *parms;
 
+  if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
+      && CP_AGGREGATE_TYPE_P (type))
+    {
+      /* A brace-enclosed initializer for an aggregate.  In C++0x this can
+        happen for direct-initialization, too.  */
+      init = digest_init (type, init, complain);
+      init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init);
+      TREE_SIDE_EFFECTS (init) = 1;
+      finish_expr_stmt (init);
+      return;
+    }
+
   if (init && TREE_CODE (init) != TREE_LIST
       && (flags & LOOKUP_ONLYCONVERTING))
     {
@@ -1299,12 +1465,6 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
           to run a new constructor; and catching an exception, where we
           have already built up the constructor call so we could wrap it
           in an exception region.  */;
-      else if (BRACE_ENCLOSED_INITIALIZER_P (init)
-              && CP_AGGREGATE_TYPE_P (type))
-       {
-         /* A brace-enclosed initializer for an aggregate.  */
-         init = digest_init (type, init);
-       }
       else
        init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
 
@@ -1347,8 +1507,20 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
   if (parms != NULL)
     release_tree_vector (parms);
 
+  if (exp == true_exp && TREE_CODE (rval) == CALL_EXPR)
+    {
+      tree fn = get_callee_fndecl (rval);
+      if (fn && DECL_DECLARED_CONSTEXPR_P (fn))
+       {
+         tree e = maybe_constant_value (rval);
+         if (TREE_CONSTANT (e))
+           rval = build2 (INIT_EXPR, type, exp, e);
+       }
+    }
+
+  /* FIXME put back convert_to_void?  */
   if (TREE_SIDE_EFFECTS (rval))
-    finish_expr_stmt (convert_to_void (rval, NULL, complain));
+    finish_expr_stmt (rval);
 }
 
 /* This function is responsible for initializing EXP with INIT
@@ -1407,7 +1579,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
        /* 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))
+      else if (type_build_ctor_call (type))
        {
          init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
          init = build2 (INIT_EXPR, type, exp, init);
@@ -1418,7 +1590,8 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
         then just zero out the object and we're done.  */
       else
        {
-         init = build2 (INIT_EXPR, type, exp, build_value_init_noctor (type));
+         init = build2 (INIT_EXPR, type, exp,
+                        build_value_init_noctor (type, complain));
          finish_expr_stmt (init);
          return;
        }
@@ -1481,9 +1654,9 @@ build_offset_ref (tree type, tree member, bool address_p)
   if (TREE_CODE (member) == TEMPLATE_DECL)
     return member;
 
-  if (dependent_type_p (type) || type_dependent_expression_p (member))
+  if (dependent_scope_p (type) || type_dependent_expression_p (member))
     return build_qualified_name (NULL_TREE, type, member,
-                                /*template_p=*/false);
+                                 /*template_p=*/false);
 
   gcc_assert (TYPE_P (type));
   if (! is_class_type (type, 1))
@@ -1493,8 +1666,8 @@ build_offset_ref (tree type, tree member, bool address_p)
   /* Callers should call mark_used before this point.  */
   gcc_assert (!DECL_P (member) || TREE_USED (member));
 
-  if (!COMPLETE_TYPE_P (complete_type (type))
-      && !TYPE_BEING_DEFINED (type))
+  type = TYPE_MAIN_VARIANT (type);
+  if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type)))
     {
       error ("incomplete type %qT does not have member %qD", type, member);
       return error_mark_node;
@@ -1584,8 +1757,7 @@ build_offset_ref (tree type, tree member, bool address_p)
          if (flag_ms_extensions)
            {
              PTRMEM_OK_P (member) = 1;
-             return cp_build_unary_op (ADDR_EXPR, member, 0, 
-                                        tf_warning_or_error);
+             return cp_build_addr_expr (member, tf_warning_or_error);
            }
          error ("invalid use of non-static member function %qD",
                 TREE_OPERAND (member, 1));
@@ -1615,38 +1787,27 @@ constant_value_1 (tree decl, bool integral_p)
 {
   while (TREE_CODE (decl) == CONST_DECL
         || (integral_p
-            ? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+            ? decl_constant_var_p (decl)
             : (TREE_CODE (decl) == VAR_DECL
                && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
     {
       tree init;
-      /* Static data members in template classes may have
-        non-dependent initializers.  References to such non-static
-        data members are not value-dependent, so we must retrieve the
-        initializer here.  The DECL_INITIAL will have the right type,
-        but will not have been folded because that would prevent us
-        from performing all appropriate semantic checks at
-        instantiation time.  */
-      if (DECL_CLASS_SCOPE_P (decl)
-         && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
-         && uses_template_parms (CLASSTYPE_TI_ARGS
-                                 (DECL_CONTEXT (decl))))
-       {
-         ++processing_template_decl;
-         init = fold_non_dependent_expr (DECL_INITIAL (decl));
-         --processing_template_decl;
-       }
-      else
+      /* If DECL is a static data member in a template
+        specialization, we must instantiate it here.  The
+        initializer for the static data member is not processed
+        until needed; we need it now.  */
+      mark_used (decl);
+      mark_rvalue_use (decl);
+      init = DECL_INITIAL (decl);
+      if (init == error_mark_node)
        {
-         /* If DECL is a static data member in a template
-            specialization, we must instantiate it here.  The
-            initializer for the static data member is not processed
-            until needed; we need it now.  */
-         mark_used (decl);
-         init = DECL_INITIAL (decl);
+         if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+           /* Treat the error as a constant to avoid cascading errors on
+              excessively recursive template instantiation (c++/9335).  */
+           return init;
+         else
+           return decl;
        }
-      if (init == 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
@@ -1658,16 +1819,15 @@ constant_value_1 (tree decl, bool integral_p)
        init = TREE_VALUE (init);
       if (!init
          || !TREE_TYPE (init)
-         || (integral_p
-             ? !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init))
-             : (!TREE_CONSTANT (init)
-                /* Do not return an aggregate constant (of which
-                   string literals are a special case), as we do not
-                   want to make inadvertent copies of such entities,
-                   and we must be sure that their addresses are the
-                   same everywhere.  */
-                || TREE_CODE (init) == CONSTRUCTOR
-                || TREE_CODE (init) == STRING_CST)))
+         || !TREE_CONSTANT (init)
+         || (!integral_p
+             /* Do not return an aggregate constant (of which
+                string literals are a special case), as we do not
+                want to make inadvertent copies of such entities,
+                and we must be sure that their addresses are the
+                same everywhere.  */
+             && (TREE_CODE (init) == CONSTRUCTOR
+                 || TREE_CODE (init) == STRING_CST)))
        break;
       decl = unshare_expr (init);
     }
@@ -1742,6 +1902,77 @@ build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts,
   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. Returns
+   the error count. */
+
+static int
+diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
+                                           bool using_new, bool complain)
+{
+  tree field;
+  int error_count = 0;
+
+  if (type_has_user_provided_constructor (type))
+    return 0;
+
+  for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+    {
+      tree field_type;
+
+      if (TREE_CODE (field) != FIELD_DECL)
+       continue;
+
+      field_type = strip_array_types (TREE_TYPE (field));
+
+      if (type_has_user_provided_constructor (field_type))
+       continue;
+
+      if (TREE_CODE (field_type) == REFERENCE_TYPE)
+       {
+         ++ error_count;
+         if (complain)
+           {
+             if (using_new)
+               error ("uninitialized reference member in %q#T "
+                      "using %<new%> without new-initializer", origin);
+             else
+               error ("uninitialized reference member in %q#T", origin);
+             inform (DECL_SOURCE_LOCATION (field),
+                     "%qD should be initialized", field);
+           }
+       }
+
+      if (CP_TYPE_CONST_P (field_type))
+       {
+         ++ error_count;
+         if (complain)
+           {
+             if (using_new)
+               error ("uninitialized const member in %q#T "
+                      "using %<new%> without new-initializer", origin);
+             else
+               error ("uninitialized const member in %q#T", origin);
+             inform (DECL_SOURCE_LOCATION (field),
+                     "%qD should be initialized", field);
+           }
+       }
+
+      if (CLASS_TYPE_P (field_type))
+       error_count
+         += diagnose_uninitialized_cst_or_ref_member_1 (field_type, origin,
+                                                        using_new, complain);
+    }
+  return error_count;
+}
+
+int
+diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new, bool complain)
+{
+  return diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new, complain);
+}
+
 /* 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
@@ -1764,6 +1995,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
   /* The type of the new-expression.  (This type is always a pointer
      type.)  */
   tree 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
@@ -1822,10 +2054,40 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
       return error_mark_node;
     }
 
-  if (abstract_virtuals_error (NULL_TREE, elt_type))
+  if (abstract_virtuals_error_sfinae (NULL_TREE, elt_type, complain))
     return error_mark_node;
 
-  is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
+  is_initialized = (type_build_ctor_call (elt_type) || *init != NULL);
+
+  if (*init == NULL)
+    {
+      bool maybe_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))
+       maybe_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))
+       maybe_uninitialized_error = true;
+
+      if (maybe_uninitialized_error
+         && diagnose_uninitialized_cst_or_ref_member (elt_type,
+                                                      /*using_new=*/true,
+                                                      complain & tf_error))
+       return error_mark_node;
+    }
 
   if (CP_TYPE_CONST_P (elt_type) && *init == NULL
       && !type_has_user_provided_default_constructor (elt_type))
@@ -1876,10 +2138,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
        }
       alloc_fn = OVL_CURRENT (alloc_fn);
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
-      alloc_call = (cp_build_function_call
-                   (alloc_fn,
-                    build_tree_list (NULL_TREE, class_addr),
-                    complain));
+      alloc_call = cp_build_function_call_nary (alloc_fn, complain,
+                                               class_addr, NULL_TREE);
     }
   else if (TYPE_FOR_JAVA (elt_type) && MAYBE_CLASS_TYPE_P (elt_type))
     {
@@ -2038,11 +2298,12 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
         many elements to destroy later.  We use the last sizeof
         (size_t) bytes to store the number of elements.  */
       cookie_ptr = size_binop (MINUS_EXPR, cookie_size, size_in_bytes (sizetype));
-      cookie_ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (alloc_node),
+      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, NULL, complain);
+      cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
 
       cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
 
@@ -2050,10 +2311,11 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
        {
          /* Also store the element size.  */
          cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, cookie_ptr,
-                              fold_build1 (NEGATE_EXPR, sizetype,
+                              fold_build1_loc (input_location,
+                                           NEGATE_EXPR, sizetype,
                                            size_in_bytes (sizetype)));
 
-         cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+         cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
          cookie = build2 (MODIFY_EXPR, sizetype, cookie,
                           size_in_bytes (elt_type));
          cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
@@ -2067,9 +2329,15 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
     }
 
   /* Now use a pointer to the type we've actually allocated.  */
-  data_addr = fold_convert (pointer_type, data_addr);
+
+  /* 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, cp_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 (pointer_type, alloc_node);
+  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
@@ -2087,14 +2355,49 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
          explicit_value_init_p = true;
        }
 
-      if (array_p)
+      if (processing_template_decl && explicit_value_init_p)
+       {
+         /* build_value_init doesn't work in templates, and we don't need
+            the initializer anyway since we're going to throw it away and
+            rebuild it at instantiation time, so just build up a single
+            constructor call to get any appropriate diagnostics.  */
+         init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
+         if (type_build_ctor_call (elt_type))
+           init_expr = build_special_member_call (init_expr,
+                                                  complete_ctor_identifier,
+                                                  init, elt_type,
+                                                  LOOKUP_NORMAL,
+                                                  complain);
+         stable = stabilize_init (init_expr, &init_preeval_expr);
+       }
+      else if (array_p)
        {
-         if (*init)
+         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)))
+           {
+             tree arraytype, domain;
+             vecinit = VEC_index (tree, *init, 0);
+             if (TREE_CONSTANT (nelts))
+               domain = compute_array_index_type (NULL_TREE, nelts, complain);
+             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, complain);
+           }
+         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
            = build_vec_init (data_addr,
@@ -2102,7 +2405,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
                                                  MINUS_EXPR, outer_nelts,
                                                  integer_one_node,
                                                  complain),
-                             build_tree_list_vec (*init),
+                             vecinit,
                              explicit_value_init_p,
                              /*from_array=*/0,
                               complain);
@@ -2114,9 +2417,9 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
        }
       else
        {
-         init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
+         init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
 
-         if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
+         if (type_build_ctor_call (type) && !explicit_value_init_p)
            {
              init_expr = build_special_member_call (init_expr,
                                                     complete_ctor_identifier,
@@ -2127,8 +2430,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
          else if (explicit_value_init_p)
            {
              /* Something like `new int()'.  */
-             init_expr = build2 (INIT_EXPR, type,
-                                 init_expr, build_value_init (type));
+             tree val = build_value_init (type, complain);
+             if (val == error_mark_node)
+               return error_mark_node;
+             init_expr = build2 (INIT_EXPR, type, init_expr, val);
            }
          else
            {
@@ -2176,8 +2481,14 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
          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
@@ -2197,6 +2508,9 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 
              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);
@@ -2208,8 +2522,9 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
                = 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
@@ -2251,7 +2566,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
   /* A new-expression is never an lvalue.  */
   gcc_assert (!lvalue_p (rval));
 
-  return rval;
+  return convert (pointer_type, rval);
 }
 
 /* Generate a representation for a C++ "new" expression.  *PLACEMENT
@@ -2279,8 +2594,13 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
   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 (auto_node)
+       {
+         tree d_init = VEC_index (tree, *init, 0);
+         d_init = resolve_nondeduced_context (d_init);
+         if (describable_type (d_init))
+           type = do_auto_deduction (type, d_init, auto_node);
+       }
     }
 
   if (processing_template_decl)
@@ -2311,6 +2631,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
           else
             return error_mark_node;
         }
+      nelts = mark_rvalue_use (nelts);
       nelts = cp_save_expr (cp_convert (sizetype, nelts));
     }
 
@@ -2336,7 +2657,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
   /* 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))
+  if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
     return error_mark_node;
 
   rval = build_new_1 (placement, type, nelts, init, use_global_new, complain);
@@ -2382,7 +2703,7 @@ build_java_class_ref (tree type)
   /* Mangle the class$ field.  */
   {
     tree field;
-    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+    for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
       if (DECL_NAME (field) == CL_suffix)
        {
          mangle_decl (field);
@@ -2391,7 +2712,7 @@ build_java_class_ref (tree type)
        }
     if (!field)
       {
-       error ("can't find %<class$%> in %qT", type);
+       error ("can%'t find %<class$%> in %qT", type);
        return error_mark_node;
       }
   }
@@ -2399,7 +2720,8 @@ build_java_class_ref (tree type)
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
   if (class_decl == NULL_TREE)
     {
-      class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
+      class_decl = build_decl (input_location,
+                              VAR_DECL, name, TREE_TYPE (jclass_node));
       TREE_STATIC (class_decl) = 1;
       DECL_EXTERNAL (class_decl) = 1;
       TREE_PUBLIC (class_decl) = 1;
@@ -2413,7 +2735,8 @@ build_java_class_ref (tree type)
 \f
 static tree
 build_vec_delete_1 (tree base, tree maxindex, tree type,
-    special_function_kind auto_delete_vec, int use_global_delete)
+                   special_function_kind auto_delete_vec,
+                   int use_global_delete, tsubst_flags_t complain)
 {
   tree virtual_size;
   tree ptype = build_pointer_type (type = complete_type (type));
@@ -2442,6 +2765,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   /* We should only have 1-D arrays here.  */
   gcc_assert (TREE_CODE (type) != ARRAY_TYPE);
 
+  if (base == error_mark_node || maxindex == error_mark_node)
+    return error_mark_node;
+
   if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     goto no_destructor;
 
@@ -2451,11 +2777,13 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
   tbase = create_temporary_var (ptype);
   tbase_init = cp_build_modify_expr (tbase, NOP_EXPR,
-                                    fold_build2 (POINTER_PLUS_EXPR, ptype,
+                                    fold_build2_loc (input_location,
+                                                 POINTER_PLUS_EXPR, ptype,
                                                  fold_convert (ptype, base),
                                                  virtual_size),
-                                    tf_warning_or_error);
-  DECL_REGISTER (tbase) = 1;
+                                    complain);
+  if (tbase_init == error_mark_node)
+    return error_mark_node;
   controller = build3 (BIND_EXPR, void_type_node, tbase,
                       NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (controller) = 1;
@@ -2463,22 +2791,25 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   body = build1 (EXIT_EXPR, void_type_node,
                 build2 (EQ_EXPR, boolean_type_node, tbase,
                         fold_convert (ptype, base)));
-  tmp = fold_build1 (NEGATE_EXPR, sizetype, size_exp);
-  body = build_compound_expr
-    (body, cp_build_modify_expr (tbase, NOP_EXPR,
-                                build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp),
-                                tf_warning_or_error));
-  body = build_compound_expr
-    (body, build_delete (ptype, tbase, sfk_complete_destructor,
-                        LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1));
+  tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp);
+  tmp = build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp);
+  tmp = cp_build_modify_expr (tbase, NOP_EXPR, tmp, complain);
+  if (tmp == error_mark_node)
+    return error_mark_node;
+  body = build_compound_expr (input_location, body, tmp);
+  tmp = build_delete (ptype, tbase, sfk_complete_destructor,
+                     LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1,
+                     complain);
+  if (tmp == error_mark_node)
+    return error_mark_node;
+  body = build_compound_expr (input_location, body, tmp);
 
   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,
-     delete the storage.  */
-  if (auto_delete_vec != sfk_base_destructor)
+  /* Delete the storage if appropriate.  */
+  if (auto_delete_vec == sfk_deleting_destructor)
     {
       tree base_tbd;
 
@@ -2494,24 +2825,24 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
          tree cookie_size;
 
          cookie_size = targetm.cxx.get_cookie_size (type);
-         base_tbd
-           = cp_convert (ptype,
-                         cp_build_binary_op (input_location,
-                                             MINUS_EXPR,
-                                             cp_convert (string_type_node,
-                                                         base),
-                                             cookie_size,
-                                             tf_warning_or_error));
+         base_tbd = cp_build_binary_op (input_location,
+                                        MINUS_EXPR,
+                                        cp_convert (string_type_node,
+                                                    base),
+                                        cookie_size,
+                                        complain);
+         if (base_tbd == error_mark_node)
+           return error_mark_node;
+         base_tbd = cp_convert (ptype, base_tbd);
          /* True size with header.  */
          virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size);
        }
 
-      if (auto_delete_vec == sfk_deleting_destructor)
-       deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
-                                               base_tbd, virtual_size,
-                                               use_global_delete & 1,
-                                               /*placement=*/NULL_TREE,
-                                               /*alloc_fn=*/NULL_TREE);
+      deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
+                                             base_tbd, virtual_size,
+                                             use_global_delete & 1,
+                                             /*placement=*/NULL_TREE,
+                                             /*alloc_fn=*/NULL_TREE);
     }
 
   body = loop;
@@ -2520,14 +2851,15 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   else if (!body)
     body = deallocate_expr;
   else
-    body = build_compound_expr (body, deallocate_expr);
+    body = build_compound_expr (input_location, body, deallocate_expr);
 
   if (!body)
     body = integer_zero_node;
 
   /* Outermost wrapper: If pointer is null, punt.  */
-  body = fold_build3 (COND_EXPR, void_type_node,
-                     fold_build2 (NE_EXPR, boolean_type_node, base,
+  body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
+                     fold_build2_loc (input_location,
+                                  NE_EXPR, boolean_type_node, base,
                                   convert (TREE_TYPE (base),
                                            integer_zero_node)),
                      body, integer_zero_node);
@@ -2543,7 +2875,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);
 
-  return convert_to_void (body, /*implicit=*/NULL, tf_warning_or_error);
+  return convert_to_void (body, ICV_CAST, complain);
 }
 
 /* Create an unnamed variable of the indicated TYPE.  */
@@ -2553,11 +2885,11 @@ create_temporary_var (tree type)
 {
   tree decl;
 
-  decl = build_decl (VAR_DECL, NULL_TREE, type);
+  decl = build_decl (input_location,
+                    VAR_DECL, NULL_TREE, type);
   TREE_USED (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   DECL_IGNORED_P (decl) = 1;
-  DECL_SOURCE_LOCATION (decl) = input_location;
   DECL_CONTEXT (decl) = current_function_decl;
 
   return decl;
@@ -2570,7 +2902,7 @@ create_temporary_var (tree type)
    things when it comes time to do final cleanups (which take place
    "outside" the binding contour of the function).  */
 
-static tree
+tree
 get_temp_regvar (tree type, tree init)
 {
   tree decl;
@@ -2612,7 +2944,6 @@ build_vec_init (tree base, tree maxindex, tree init,
 {
   tree rval;
   tree base2 = NULL_TREE;
-  tree size;
   tree itype = NULL_TREE;
   tree iterator;
   /* The type of BASE.  */
@@ -2630,6 +2961,10 @@ build_vec_init (tree base, tree maxindex, tree init,
   tree try_block = NULL_TREE;
   int num_initialized_elts = 0;
   bool is_global;
+  tree const_init = NULL_TREE;
+  tree obase = base;
+  bool xvalue = false;
+  bool errors = false;
 
   if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
     maxindex = array_type_nelts (atype);
@@ -2641,10 +2976,18 @@ build_vec_init (tree base, tree maxindex, tree init,
     gcc_assert (!init);
 
   inner_elt_type = strip_array_types (type);
+
+  /* Look through the TARGET_EXPR around a compound literal.  */
+  if (init && TREE_CODE (init) == TARGET_EXPR
+      && TREE_CODE (TARGET_EXPR_INITIAL (init)) == CONSTRUCTOR
+      && from_array != 2)
+    init = TARGET_EXPR_INITIAL (init);
+
   if (init
+      && TREE_CODE (atype) == ARRAY_TYPE
       && (from_array == 2
          ? (!CLASS_TYPE_P (inner_elt_type)
-            || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
+            || !TYPE_HAS_COMPLEX_COPY_ASSIGN (inner_elt_type))
          : !TYPE_NEEDS_CONSTRUCTING (type))
       && ((TREE_CODE (init) == CONSTRUCTOR
           /* Don't do this if the CONSTRUCTOR might contain something
@@ -2653,17 +2996,15 @@ build_vec_init (tree base, tree maxindex, tree init,
               || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
          || from_array))
     {
-      /* Do non-default initialization of POD arrays resulting from
+      /* Do non-default initialization of trivial arrays resulting from
         brace-enclosed initializers.  In this case, digest_init and
         store_constructor will handle the semantics for us.  */
 
-      gcc_assert (TREE_CODE (atype) == ARRAY_TYPE);
       stmt_expr = build2 (INIT_EXPR, atype, base, init);
       return stmt_expr;
     }
 
   maxindex = cp_convert (ptrdiff_type_node, maxindex);
-  size = size_in_bytes (type);
   if (TREE_CODE (atype) == ARRAY_TYPE)
     {
       ptype = build_pointer_type (type);
@@ -2709,6 +3050,19 @@ build_vec_init (tree base, tree maxindex, tree init,
   base = get_temp_regvar (ptype, rval);
   iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
 
+  /* If initializing one array from another, initialize element by
+     element.  We rely upon the below calls to do the argument
+     checking.  Evaluate the initializer before entering the try block.  */
+  if (from_array && init && TREE_CODE (init) != CONSTRUCTOR)
+    {
+      if (lvalue_kind (init) & clk_rvalueref)
+       xvalue = true;
+      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.  */
@@ -2718,32 +3072,100 @@ build_vec_init (tree base, tree maxindex, tree init,
       try_block = begin_try_block ();
     }
 
+  /* Maybe pull out constant value when from_array? */
+
   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;
+      tree field, elt;
+      /* Should we try to create a constant initializer?  */
+      bool try_const = (literal_type_p (inner_elt_type)
+                       || TYPE_HAS_CONSTEXPR_CTOR (inner_elt_type));
+      bool saw_non_const = false;
+      bool saw_const = false;
+      /* If we're initializing a static array, we want to do static
+        initialization of any elements with constant initializers even if
+        some are non-constant.  */
+      bool do_static_init = (DECL_P (obase) && TREE_STATIC (obase));
+      VEC(constructor_elt,gc) *new_vec;
       from_array = 0;
 
-      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt)
+      if (try_const)
+       new_vec = VEC_alloc (constructor_elt, gc, CONSTRUCTOR_NELTS (init));
+      else
+       new_vec = NULL;
+
+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, field, elt)
        {
          tree baseref = build1 (INDIRECT_REF, type, base);
+         tree one_init;
 
          num_initialized_elts++;
 
          current_stmt_tree ()->stmts_are_full_exprs_p = 1;
          if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
-           finish_expr_stmt (build_aggr_init (baseref, elt, 0, complain));
+           one_init = build_aggr_init (baseref, elt, 0, complain);
          else
-           finish_expr_stmt (cp_build_modify_expr (baseref, NOP_EXPR,
-                                                    elt, complain));
+           one_init = cp_build_modify_expr (baseref, NOP_EXPR,
+                                            elt, complain);
+         if (one_init == error_mark_node)
+           errors = true;
+         if (try_const)
+           {
+             tree e = one_init;
+             if (TREE_CODE (e) == EXPR_STMT)
+               e = TREE_OPERAND (e, 0);
+             if (TREE_CODE (e) == CONVERT_EXPR
+                 && VOID_TYPE_P (TREE_TYPE (e)))
+               e = TREE_OPERAND (e, 0);
+             e = maybe_constant_init (e);
+             if (reduced_constant_expression_p (e))
+               {
+                 CONSTRUCTOR_APPEND_ELT (new_vec, field, e);
+                 if (do_static_init)
+                   one_init = NULL_TREE;
+                 else
+                   one_init = build2 (INIT_EXPR, type, baseref, e);
+                 saw_const = true;
+               }
+             else
+               {
+                 if (do_static_init)
+                   CONSTRUCTOR_APPEND_ELT (new_vec, field,
+                                           build_zero_init (TREE_TYPE (e),
+                                                            NULL_TREE, true));
+                 saw_non_const = true;
+               }
+           }
+
+         if (one_init)
+           finish_expr_stmt (one_init);
          current_stmt_tree ()->stmts_are_full_exprs_p = 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));
+         one_init = cp_build_unary_op (PREINCREMENT_EXPR, base, 0, complain);
+         if (one_init == error_mark_node)
+           errors = true;
+         else
+           finish_expr_stmt (one_init);
+
+         one_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
+                                       complain);
+         if (one_init == error_mark_node)
+           errors = true;
+         else
+           finish_expr_stmt (one_init);
+       }
+
+      if (try_const)
+       {
+         if (!saw_non_const)
+           const_init = build_constructor (atype, new_vec);
+         else if (do_static_init && saw_const)
+           DECL_INITIAL (obase) = build_constructor (atype, new_vec);
+         else
+           VEC_free (constructor_elt, gc, new_vec);
        }
 
       /* Clear out INIT so that we don't get confused below.  */
@@ -2751,23 +3173,14 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
   else if (from_array)
     {
-      /* If initializing one array from another, initialize element by
-        element.  We rely upon the below calls the do argument
-        checking.  */
       if (init)
-       {
-         base2 = decay_conversion (init);
-         itype = TREE_TYPE (base2);
-         base2 = get_temp_regvar (itype, base2);
-         itype = TREE_TYPE (itype);
-       }
-      else if (TYPE_LANG_SPECIFIC (type)
-              && TYPE_NEEDS_CONSTRUCTING (type)
+       /* OK, we set base2 above.  */;
+      else if (CLASS_TYPE_P (type)
               && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
        {
           if (complain & tf_error)
             error ("initializer ends prematurely");
-         return error_mark_node;
+         errors = true;
        }
     }
 
@@ -2778,7 +3191,7 @@ build_vec_init (tree base, tree maxindex, tree init,
      We do need to keep going if we're copying an array.  */
 
   if (from_array
-      || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p)
+      || ((type_build_ctor_call (type) || explicit_value_init_p)
          && ! (host_integerp (maxindex, 0)
                && (num_initialized_elts
                    == tree_low_cst (maxindex, 0) + 1))))
@@ -2789,14 +3202,16 @@ build_vec_init (tree base, tree maxindex, tree init,
       tree elt_init;
       tree to;
 
-      for_stmt = begin_for_stmt ();
+      for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
       finish_for_init_stmt (for_stmt);
       finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
                               build_int_cst (TREE_TYPE (iterator), -1)),
                       for_stmt);
-      finish_for_expr (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
-                                          complain),
-                      for_stmt);
+      elt_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
+                                   complain);
+      if (elt_init == error_mark_node)
+       errors = true;
+      finish_for_expr (elt_init, for_stmt);
 
       to = build1 (INDIRECT_REF, type, base);
 
@@ -2805,14 +3220,18 @@ build_vec_init (tree base, tree maxindex, tree init,
          tree from;
 
          if (base2)
-           from = build1 (INDIRECT_REF, itype, base2);
+           {
+             from = build1 (INDIRECT_REF, itype, base2);
+             if (xvalue)
+               from = move (from);
+           }
          else
            from = NULL_TREE;
 
          if (from_array == 2)
            elt_init = cp_build_modify_expr (to, NOP_EXPR, from, 
                                             complain);
-         else if (TYPE_NEEDS_CONSTRUCTING (type))
+         else if (type_build_ctor_call (type))
            elt_init = build_aggr_init (to, from, 0, complain);
          else if (from)
            elt_init = cp_build_modify_expr (to, NOP_EXPR, from,
@@ -2831,14 +3250,20 @@ build_vec_init (tree base, tree maxindex, tree init,
                                     0, complain);
        }
       else if (explicit_value_init_p)
-       elt_init = build2 (INIT_EXPR, type, to,
-                          build_value_init (type));
+       {
+         elt_init = build_value_init (type, complain);
+         if (elt_init != error_mark_node)
+           elt_init = build2 (INIT_EXPR, type, to, elt_init);
+       }
       else
        {
-         gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
+         gcc_assert (type_build_ctor_call (type));
          elt_init = build_aggr_init (to, init, 0, complain);
        }
 
+      if (elt_init == error_mark_node)
+       errors = true;
+
       current_stmt_tree ()->stmts_are_full_exprs_p = 1;
       finish_expr_stmt (elt_init);
       current_stmt_tree ()->stmts_are_full_exprs_p = 0;
@@ -2871,8 +3296,10 @@ build_vec_init (tree base, tree maxindex, tree init,
 
       finish_cleanup_try_block (try_block);
       e = build_vec_delete_1 (rval, m,
-                             inner_elt_type, sfk_base_destructor,
-                             /*use_global_delete=*/0);
+                             inner_elt_type, sfk_complete_destructor,
+                             /*use_global_delete=*/0, complain);
+      if (e == error_mark_node)
+       errors = true;
       finish_cleanup (e, try_block);
     }
 
@@ -2887,11 +3314,16 @@ build_vec_init (tree base, tree maxindex, tree init,
     {
       atype = build_pointer_type (atype);
       stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
-      stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain);
+      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;
+
+  if (const_init)
+    return build2 (INIT_EXPR, atype, obase, const_init);
+  if (errors)
+    return error_mark_node;
   return stmt_expr;
 }
 
@@ -2899,7 +3331,8 @@ build_vec_init (tree base, tree maxindex, tree init,
    build_delete.  */
 
 static tree
-build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
+build_dtor_call (tree exp, special_function_kind dtor_kind, int flags,
+                tsubst_flags_t complain)
 {
   tree name;
   tree fn;
@@ -2926,7 +3359,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
                                /*conversion_path=*/NULL_TREE,
                                flags,
                                /*fn_p=*/NULL,
-                               tf_warning_or_error);
+                               complain);
 }
 
 /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -2940,7 +3373,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
 
 tree
 build_delete (tree type, tree addr, special_function_kind auto_delete,
-    int flags, int use_global_delete)
+             int flags, int use_global_delete, tsubst_flags_t complain)
 {
   tree expr;
 
@@ -2954,6 +3387,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
 
   type = TYPE_MAIN_VARIANT (type);
 
+  addr = mark_rvalue_use (addr);
+
   if (TREE_CODE (type) == POINTER_TYPE)
     {
       bool complete_p = true;
@@ -2973,13 +3408,14 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          complete_type (type);
          if (!COMPLETE_TYPE_P (type))
            {
-             if (warning (0, "possible problem detected in invocation of "
-                          "delete operator:"))
+             if ((complain & tf_warning)
+                 && 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.");
+                         "declared when the class is defined");
                }
              complete_p = false;
            }
@@ -2999,18 +3435,21 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
 
       if (TYPE_DOMAIN (type) == NULL_TREE)
        {
-         error ("unknown array size in delete");
+         if (complain & tf_error)
+           error ("unknown array size in delete");
          return error_mark_node;
        }
       return build_vec_delete (addr, array_type_nelts (type),
-                              auto_delete, use_global_delete);
+                              auto_delete, use_global_delete, complain);
     }
   else
     {
       /* Don't check PROTECT here; leave that decision to the
         destructor.  If the destructor is accessible, call it,
         else report error.  */
-      addr = cp_build_unary_op (ADDR_EXPR, addr, 0, tf_warning_or_error);
+      addr = cp_build_addr_expr (addr, complain);
+      if (addr == error_mark_node)
+       return error_mark_node;
       if (TREE_SIDE_EFFECTS (addr))
        addr = save_expr (addr);
 
@@ -3082,9 +3521,10 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
                                /*alloc_fn=*/NULL_TREE);
        }
 
-      expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, 
-                                                     tf_warning_or_error),
-                             auto_delete, flags);
+      expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain),
+                             auto_delete, flags, complain);
+      if (expr == error_mark_node)
+       return error_mark_node;
       if (do_delete)
        expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete);
 
@@ -3096,10 +3536,14 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
        /* 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 (input_location,
-                                         NE_EXPR, addr, integer_zero_node,
-                                         tf_warning_or_error));
+       {
+         /* Handle deleting a null pointer.  */
+         ifexp = fold (cp_build_binary_op (input_location,
+                                           NE_EXPR, addr, integer_zero_node,
+                                           complain));
+         if (ifexp == error_mark_node)
+           return error_mark_node;
+       }
 
       if (ifexp != integer_one_node)
        expr = build3 (COND_EXPR, void_type_node,
@@ -3168,25 +3612,31 @@ push_base_cleanups (void)
       finish_decl_cleanup (NULL_TREE, expr);
     }
 
+  /* Don't automatically destroy union members.  */
+  if (TREE_CODE (current_class_type) == UNION_TYPE)
+    return;
+
   for (member = TYPE_FIELDS (current_class_type); member;
-       member = TREE_CHAIN (member))
+       member = DECL_CHAIN (member))
     {
-      if (TREE_TYPE (member) == error_mark_node
+      tree this_type = TREE_TYPE (member);
+      if (this_type == error_mark_node
          || TREE_CODE (member) != FIELD_DECL
          || DECL_ARTIFICIAL (member))
        continue;
-      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+      if (ANON_UNION_TYPE_P (this_type))
+       continue;
+      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
        {
          tree this_member = (build_class_member_access_expr
                              (current_class_ref, member,
                               /*access_path=*/NULL_TREE,
                               /*preserve_reference=*/false,
                               tf_warning_or_error));
-         tree this_type = TREE_TYPE (member);
          expr = build_delete (this_type, this_member,
                               sfk_complete_destructor,
                               LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
-                              0);
+                              0, tf_warning_or_error);
          finish_decl_cleanup (NULL_TREE, expr);
        }
     }
@@ -3210,7 +3660,8 @@ push_base_cleanups (void)
 
 tree
 build_vec_delete (tree base, tree maxindex,
-    special_function_kind auto_delete_vec, int use_global_delete)
+                 special_function_kind auto_delete_vec,
+                 int use_global_delete, tsubst_flags_t complain)
 {
   tree type;
   tree rval;
@@ -3230,12 +3681,13 @@ build_vec_delete (tree base, tree maxindex,
          base = TARGET_EXPR_SLOT (base_init);
        }
       type = strip_array_types (TREE_TYPE (type));
-      cookie_addr = fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (sizetype));
+      cookie_addr = fold_build1_loc (input_location, NEGATE_EXPR,
+                                sizetype, TYPE_SIZE_UNIT (sizetype));
       cookie_addr = build2 (POINTER_PLUS_EXPR,
                            size_ptr_type,
                            fold_convert (size_ptr_type, base),
                            cookie_addr);
-      maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error);
+      maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, complain);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -3243,7 +3695,9 @@ build_vec_delete (tree base, tree maxindex,
         bad name.  */
       maxindex = array_type_nelts_total (type);
       type = strip_array_types (type);
-      base = cp_build_unary_op (ADDR_EXPR, base, 1, tf_warning_or_error);
+      base = cp_build_addr_expr (base, complain);
+      if (base == error_mark_node)
+       return error_mark_node;
       if (TREE_SIDE_EFFECTS (base))
        {
          base_init = get_target_expr (base);
@@ -3252,14 +3706,14 @@ build_vec_delete (tree base, tree maxindex,
     }
   else
     {
-      if (base != error_mark_node)
+      if (base != error_mark_node && !(complain & tf_error))
        error ("type to vector delete is neither pointer or array type");
       return error_mark_node;
     }
 
   rval = build_vec_delete_1 (base, maxindex, type, auto_delete_vec,
-                            use_global_delete);
-  if (base_init)
+                            use_global_delete, complain);
+  if (base_init && rval != error_mark_node)
     rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), base_init, rval);
 
   return rval;