OSDN Git Service

PR c++/29043
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index 2608996..57b874d 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -54,6 +54,7 @@ static tree dfs_initialize_vtbl_ptrs (tree, void *);
 static tree build_dtor_call (tree, special_function_kind, int);
 static tree build_field_list (tree, tree, int *);
 static tree build_vtbl_address (tree);
+static void diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool);
 
 /* We are about to generate some complex initialization code.
    Conceptually, it is all a single expression.  However, we may want
@@ -219,7 +220,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
 
       /* Iterate over the array elements, building initializations.  */
       if (nelts)
-       max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts),
+       max_index = fold_build2_loc (input_location,
+                                MINUS_EXPR, TREE_TYPE (nelts),
                                 nelts, integer_one_node);
       else
        max_index = array_type_nelts (type);
@@ -426,8 +428,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,
@@ -451,9 +454,9 @@ perform_member_init (tree member, tree init)
       else
        {
          if (TREE_CODE (type) == REFERENCE_TYPE)
-           permerror (input_location, "%Jvalue-initialization of %q#D, "
-                                      "which has reference type",
-                      current_function_decl, member);
+           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));
@@ -492,8 +495,9 @@ perform_member_init (tree member, tree init)
              && !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);
+           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));
        }
@@ -502,13 +506,21 @@ 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 (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+             || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+           diagnose_uninitialized_cst_or_ref_member (core_type, /*using_new=*/false);
        }
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
@@ -661,7 +673,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 +690,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.  */
@@ -747,8 +762,9 @@ sort_mem_initializers (tree t, tree mem_inits)
                  if (same_type_p (last_field_type, field_type))
                    {
                      if (TREE_CODE (field_type) == UNION_TYPE)
-                       error ("%Jinitializations for multiple members of %qT",
-                              current_function_decl, last_field_type);
+                       error_at (DECL_SOURCE_LOCATION (current_function_decl),
+                                 "initializations for multiple members of %qT",
+                                 last_field_type);
                      done = 1;
                      break;
                    }
@@ -810,9 +826,10 @@ emit_mem_initializers (tree mem_inits)
       if (extra_warnings && !arguments
          && DECL_COPY_CONSTRUCTOR_P (current_function_decl)
          && type_has_user_nondefault_constructor (BINFO_TYPE (subobject)))
-       warning (OPT_Wextra, "%Jbase class %q#T should be explicitly initialized in the "
-                "copy constructor",
-                current_function_decl, BINFO_TYPE (subobject));
+       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))
@@ -824,7 +841,7 @@ emit_mem_initializers (tree mem_inits)
          base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
                                       subobject, 1);
          expand_aggr_init_1 (subobject, NULL_TREE,
-                             cp_build_indirect_ref (base_addr, NULL,
+                             cp_build_indirect_ref (base_addr, RO_NULL,
                                                      tf_warning_or_error),
                              arguments,
                              LOOKUP_NORMAL,
@@ -908,7 +925,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 +940,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 +973,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);
 
@@ -1237,13 +1255,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;
@@ -1646,7 +1664,14 @@ constant_value_1 (tree decl, bool integral_p)
          init = DECL_INITIAL (decl);
        }
       if (init == error_mark_node)
-       return decl;
+       {
+         if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+           /* Treat the error as a constant to avoid cascading errors on
+              excessively recursive template instantiation (c++/9335).  */
+           return init;
+         else
+           return decl;
+       }
       /* Initializers in templates are generally expanded during
         instantiation, so before that for const int i(2)
         INIT is a TREE_LIST with the actual initializer as
@@ -1742,6 +1767,59 @@ 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 */
+
+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
@@ -1764,6 +1842,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
@@ -1827,6 +1906,38 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 
   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))
     {
@@ -2038,11 +2149,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 +2162,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 +2180,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, 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
@@ -2089,12 +2208,32 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 
       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);
+             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)
             {
               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 +2241,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,7 +2253,7 @@ 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)
            {
@@ -2176,8 +2315,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 +2342,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 +2356,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 +2400,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
@@ -2452,11 +2601,11 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
   tbase = create_temporary_var (ptype);
   tbase_init = cp_build_modify_expr (tbase, NOP_EXPR,
-                                    fold_build2 (POINTER_PLUS_EXPR, ptype,
+                                    fold_build2_loc (input_location,
+                                                 POINTER_PLUS_EXPR, ptype,
                                                  fold_convert (ptype, base),
                                                  virtual_size),
                                     tf_warning_or_error);
-  DECL_REGISTER (tbase) = 1;
   controller = build3 (BIND_EXPR, void_type_node, tbase,
                       NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (controller) = 1;
@@ -2464,7 +2613,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   body = build1 (EXIT_EXPR, void_type_node,
                 build2 (EQ_EXPR, boolean_type_node, tbase,
                         fold_convert (ptype, base)));
-  tmp = fold_build1 (NEGATE_EXPR, sizetype, size_exp);
+  tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp);
   body = build_compound_expr
     (input_location, 
      body, cp_build_modify_expr (tbase, NOP_EXPR,
@@ -2529,8 +2678,9 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
     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);
@@ -2615,7 +2765,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.  */
@@ -2644,7 +2793,15 @@ 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))
@@ -2656,17 +2813,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);
@@ -2712,6 +2867,17 @@ build_vec_init (tree base, tree maxindex, tree init,
   base = get_temp_regvar (ptype, rval);
   iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
 
+  /* If initializing one array from another, initialize element by
+     element.  We rely upon the below calls to do the argument
+     checking.  Evaluate the initializer before entering the try block.  */
+  if (from_array && init && TREE_CODE (init) != CONSTRUCTOR)
+    {
+      base2 = decay_conversion (init);
+      itype = TREE_TYPE (base2);
+      base2 = get_temp_regvar (itype, base2);
+      itype = TREE_TYPE (itype);
+    }
+
   /* Protect the entire array initialization so that we can destroy
      the partially constructed array if an exception is thrown.
      But don't do this if we're assigning.  */
@@ -2723,7 +2889,7 @@ build_vec_init (tree base, tree maxindex, tree init,
 
   if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
     {
-      /* Do non-default initialization of non-POD arrays resulting from
+      /* Do non-default initialization of non-trivial arrays resulting from
         brace-enclosed initializers.  */
       unsigned HOST_WIDE_INT idx;
       tree elt;
@@ -2754,16 +2920,8 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
   else if (from_array)
     {
-      /* If initializing one array from another, initialize element by
-        element.  We rely upon the below calls the do argument
-        checking.  */
       if (init)
-       {
-         base2 = decay_conversion (init);
-         itype = TREE_TYPE (base2);
-         base2 = get_temp_regvar (itype, base2);
-         itype = TREE_TYPE (itype);
-       }
+       /* OK, we set base2 above.  */;
       else if (TYPE_LANG_SPECIFIC (type)
               && TYPE_NEEDS_CONSTRUCTING (type)
               && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
@@ -2890,7 +3048,7 @@ 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;
     }
 
@@ -3085,7 +3243,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
                                /*alloc_fn=*/NULL_TREE);
        }
 
-      expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, 
+      expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, 
                                                      tf_warning_or_error),
                              auto_delete, flags);
       if (do_delete)
@@ -3233,12 +3391,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, tf_warning_or_error);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {