OSDN Git Service

PR c++/54652
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index d9e475e..bb0e618 100644 (file)
@@ -100,7 +100,8 @@ dfs_initialize_vtbl_ptrs (tree binfo, void *data)
     {
       tree base_ptr = TREE_VALUE ((tree) data);
 
-      base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1);
+      base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1,
+                                 tf_warning_or_error);
 
       expand_virtual_init (binfo, base_ptr);
     }
@@ -139,7 +140,9 @@ initialize_vtbl_ptrs (tree addr)
    zero-initialization does not simply mean filling the storage with
    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.  */
+   be added.  Note that this only works when the result is assigned
+   to a base COMPONENT_REF; if we only have a pointer to the base subobject,
+   expand_assignment will end up clearing the full size of TYPE.  */
 
 static tree
 build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
@@ -175,9 +178,11 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
        items with static storage duration that are not otherwise
        initialized are initialized to zero.  */
     ;
+  else if (TYPE_PTR_P (type) || TYPE_PTR_TO_MEMBER_P (type))
+    init = convert (type, nullptr_node);
   else if (SCALAR_TYPE_P (type))
     init = convert (type, integer_zero_node);
-  else if (CLASS_TYPE_P (type))
+  else if (RECORD_OR_UNION_CODE_P (TREE_CODE (type)))
     {
       tree field;
       VEC(constructor_elt,gc) *v = NULL;
@@ -249,21 +254,23 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
         have an upper bound of -1.  */
       if (!tree_int_cst_equal (max_index, integer_minus_one_node))
        {
-         constructor_elt *ce;
-
-         v = VEC_alloc (constructor_elt, gc, 1);
-         ce = VEC_quick_push (constructor_elt, v, NULL);
+         constructor_elt ce;
 
          /* If this is a one element array, we just use a regular init.  */
          if (tree_int_cst_equal (size_zero_node, max_index))
-           ce->index = size_zero_node;
+           ce.index = size_zero_node;
          else
-           ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
-                               max_index);
+           ce.index = build2 (RANGE_EXPR, sizetype, size_zero_node,
+                              max_index);
 
-         ce->value = build_zero_init_1 (TREE_TYPE (type),
-                                        /*nelts=*/NULL_TREE,
-                                        static_storage_p, NULL_TREE);
+         ce.value = build_zero_init_1 (TREE_TYPE (type),
+                                       /*nelts=*/NULL_TREE,
+                                       static_storage_p, NULL_TREE);
+         if (ce.value)
+           {
+             v = VEC_alloc (constructor_elt, gc, 1);
+             *VEC_quick_push (constructor_elt, v, NULL) = ce;
+           }
        }
 
       /* Build a constructor to contain the initializations.  */
@@ -330,7 +337,8 @@ build_value_init (tree type, tsubst_flags_t complain)
      constructor.  */
 
   /* The AGGR_INIT_EXPR tweaking below breaks in templates.  */
-  gcc_assert (!processing_template_decl);
+  gcc_assert (!processing_template_decl
+             || (SCALAR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE));
 
   if (CLASS_TYPE_P (type))
     {
@@ -356,11 +364,9 @@ build_value_init (tree type, tsubst_flags_t complain)
          tree ctor = build_special_member_call
            (NULL_TREE, complete_ctor_identifier,
             NULL, type, LOOKUP_NORMAL, complain);
+         ctor = build_aggr_init_expr (type, ctor, complain);
          if (ctor != error_mark_node)
-           {
-             ctor = build_aggr_init_expr (type, ctor, complain);
-             AGGR_INIT_ZERO_FIRST (ctor) = 1;
-           }
+           AGGR_INIT_ZERO_FIRST (ctor) = 1;
          return ctor;
        }
     }
@@ -373,6 +379,12 @@ build_value_init (tree type, tsubst_flags_t complain)
 tree
 build_value_init_noctor (tree type, tsubst_flags_t complain)
 {
+  if (!COMPLETE_TYPE_P (type))
+    {
+      if (complain & tf_error)
+       error ("value-initialization of incomplete type %qT", type);
+      return error_mark_node;
+    }
   /* FIXME the class and array cases should just use digest_init once it is
      SFINAE-enabled.  */
   if (CLASS_TYPE_P (type))
@@ -439,28 +451,31 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
         have an upper bound of -1.  */
       if (!tree_int_cst_equal (max_index, integer_minus_one_node))
        {
-         constructor_elt *ce;
-
-         v = VEC_alloc (constructor_elt, gc, 1);
-         ce = VEC_quick_push (constructor_elt, v, NULL);
+         constructor_elt ce;
 
          /* If this is a one element array, we just use a regular init.  */
          if (tree_int_cst_equal (size_zero_node, max_index))
-           ce->index = size_zero_node;
+           ce.index = size_zero_node;
          else
-           ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
-                               max_index);
+           ce.index = build2 (RANGE_EXPR, sizetype, size_zero_node,
+                              max_index);
 
-         ce->value = build_value_init (TREE_TYPE (type), complain);
+         ce.value = build_value_init (TREE_TYPE (type), complain);
 
-         if (ce->value == error_mark_node)
-           return error_mark_node;
+         if (ce.value)
+           {
+             if (ce.value == error_mark_node)
+               return error_mark_node;
+
+             v = VEC_alloc (constructor_elt, gc, 1);
+             *VEC_quick_push (constructor_elt, v, NULL) = ce;
 
-         /* 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);
+             /* 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);
+           }
        }
 
       /* Build a constructor to contain the initializations.  */
@@ -482,6 +497,30 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
   return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
 }
 
+/* Initialize current class with INIT, a TREE_LIST of
+   arguments for a target constructor. If TREE_LIST is void_type_node,
+   an empty initializer list was given.  */
+
+static void
+perform_target_ctor (tree init)
+{
+  tree decl = current_class_ref;
+  tree type = current_class_type;
+
+  finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL,
+                                     tf_warning_or_error));
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+    {
+      tree expr = build_delete (type, decl, sfk_complete_destructor,
+                               LOOKUP_NORMAL
+                               |LOOKUP_NONVIRTUAL
+                               |LOOKUP_DESTRUCTOR,
+                               0, tf_warning_or_error);
+      if (expr != error_mark_node)
+       finish_eh_cleanup (expr);
+    }
+}
+
 /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
    arguments.  If TREE_LIST is void_type_node, an empty initializer
    list was given; if NULL_TREE no initializer was given.  */
@@ -492,6 +531,32 @@ perform_member_init (tree member, tree init)
   tree decl;
   tree type = TREE_TYPE (member);
 
+  /* Use the non-static data member initializer if there was no
+     mem-initializer for this field.  */
+  if (init == NULL_TREE)
+    {
+      if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member))
+       /* Do deferred instantiation of the NSDMI.  */
+       init = (tsubst_copy_and_build
+               (DECL_INITIAL (DECL_TI_TEMPLATE (member)),
+                DECL_TI_ARGS (member),
+                tf_warning_or_error, member, /*function_p=*/false,
+                /*integral_constant_expression_p=*/false));
+      else
+       {
+         init = DECL_INITIAL (member);
+         /* Strip redundant TARGET_EXPR so we don't need to remap it, and
+            so the aggregate init code below will see a CONSTRUCTOR.  */
+         if (init && TREE_CODE (init) == TARGET_EXPR
+             && !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (init))))
+           init = TARGET_EXPR_INITIAL (init);
+         init = break_out_target_exprs (init);
+       }
+    }
+
+  if (init == error_mark_node)
+    return;
+
   /* Effective C++ rule 12 requires that all data members be
      initialized.  */
   if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE)
@@ -547,6 +612,44 @@ perform_member_init (tree member, tree init)
          finish_expr_stmt (init);
        }
     }
+  else if (init
+          && (TREE_CODE (type) == REFERENCE_TYPE
+              /* Pre-digested NSDMI.  */
+              || (((TREE_CODE (init) == CONSTRUCTOR
+                    && TREE_TYPE (init) == type)
+                   /* { } mem-initializer.  */
+                   || (TREE_CODE (init) == TREE_LIST
+                       && TREE_CODE (TREE_VALUE (init)) == CONSTRUCTOR
+                       && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init))))
+                  && (CP_AGGREGATE_TYPE_P (type)
+                      || is_std_init_list (type)))))
+    {
+      /* With references and list-initialization, we need to deal with
+        extending temporary lifetimes.  12.2p5: "A temporary bound to a
+        reference member in a constructor’s ctor-initializer (12.6.2)
+        persists until the constructor exits."  */
+      unsigned i; tree t;
+      VEC(tree,gc) *cleanups = make_tree_vector ();
+      if (TREE_CODE (init) == TREE_LIST)
+       init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
+                                               tf_warning_or_error);
+      if (TREE_TYPE (init) != type)
+       init = digest_init (type, init, tf_warning_or_error);
+      if (init == error_mark_node)
+       return;
+      /* A FIELD_DECL doesn't really have a suitable lifetime, but
+        make_temporary_var_for_ref_to_temp will treat it as automatic and
+        set_up_extended_ref_temp wants to use the decl in a warning.  */
+      init = extend_ref_init_temps (member, init, &cleanups);
+      if (TREE_CODE (type) == ARRAY_TYPE
+         && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type)))
+       init = build_vec_init_expr (type, init, tf_warning_or_error);
+      init = build2 (INIT_EXPR, type, decl, init);
+      finish_expr_stmt (init);
+      FOR_EACH_VEC_ELT (tree, cleanups, i, t)
+       push_cleanup (decl, t, false);
+      release_tree_vector (cleanups);
+    }
   else if (type_build_ctor_call (type)
           || (init && CLASS_TYPE_P (strip_array_types (type))))
     {
@@ -554,8 +657,10 @@ perform_member_init (tree member, tree init)
        {
          if (init)
            {
-             gcc_assert (TREE_CHAIN (init) == NULL_TREE);
-             init = TREE_VALUE (init);
+             if (TREE_CHAIN (init))
+               init = error_mark_node;
+             else
+               init = TREE_VALUE (init);
              if (BRACE_ENCLOSED_INITIALIZER_P (init))
                init = digest_init (type, init, tf_warning_or_error);
            }
@@ -577,7 +682,7 @@ perform_member_init (tree member, tree init)
            flags |= LOOKUP_DEFAULTED;
          if (CP_TYPE_CONST_P (type)
              && init == NULL_TREE
-             && !type_has_user_provided_default_constructor (type))
+             && default_init_uninitialized_part (type))
            /* TYPE_NEEDS_CONSTRUCTING can be set just because we have a
               vtable; still give this diagnostic.  */
            permerror (DECL_SOURCE_LOCATION (current_function_decl),
@@ -604,15 +709,6 @@ perform_member_init (tree member, tree init)
 
          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)))
@@ -931,6 +1027,16 @@ emit_mem_initializers (tree mem_inits)
   if (!COMPLETE_TYPE_P (current_class_type))
     return;
 
+  if (mem_inits
+      && TYPE_P (TREE_PURPOSE (mem_inits))
+      && same_type_p (TREE_PURPOSE (mem_inits), current_class_type))
+    {
+      /* Delegating constructor. */
+      gcc_assert (TREE_CHAIN (mem_inits) == NULL_TREE);
+      perform_target_ctor (TREE_VALUE (mem_inits));
+      return;
+    }
+
   if (DECL_DEFAULTED_FN (current_function_decl))
     flags |= LOOKUP_DEFAULTED;
 
@@ -960,16 +1066,6 @@ emit_mem_initializers (tree mem_inits)
                        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.  */
@@ -980,7 +1076,7 @@ emit_mem_initializers (tree mem_inits)
          tree base_addr;
 
          base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
-                                      subobject, 1);
+                                      subobject, 1, tf_warning_or_error);
          expand_aggr_init_1 (subobject, NULL_TREE,
                              cp_build_indirect_ref (base_addr, RO_NULL,
                                                      tf_warning_or_error),
@@ -1271,8 +1367,9 @@ expand_member_init (tree name)
       tree virtual_binfo;
       int i;
 
-      if (current_template_parms)
-       return basetype;
+      if (same_type_p (basetype, current_class_type)
+         || current_template_parms)
+         return basetype;
 
       class_binfo = TYPE_BINFO (current_class_type);
       direct_binfo = NULL_TREE;
@@ -1376,6 +1473,8 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
   TREE_THIS_VOLATILE (exp) = 0;
 
   if (init && TREE_CODE (init) != TREE_LIST
+      && !(TREE_CODE (init) == TARGET_EXPR
+          && TARGET_EXPR_DIRECT_INIT_P (init))
       && !(BRACE_ENCLOSED_INITIALIZER_P (init)
           && CONSTRUCTOR_IS_DIRECT_INIT (init)))
     flags |= LOOKUP_ONLYCONVERTING;
@@ -1458,10 +1557,28 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
 
   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);
+
+  /* A CONSTRUCTOR of the target's type is a previously digested
+     initializer, whether that happened just above or in
+     cp_parser_late_parsing_nsdmi.
+
+     A TARGET_EXPR with TARGET_EXPR_DIRECT_INIT_P or TARGET_EXPR_LIST_INIT_P
+     set represents the whole initialization, so we shouldn't build up
+     another ctor call.  */
+  if (init
+      && (TREE_CODE (init) == CONSTRUCTOR
+         || (TREE_CODE (init) == TARGET_EXPR
+             && (TARGET_EXPR_DIRECT_INIT_P (init)
+                 || TARGET_EXPR_LIST_INIT_P (init))))
+      && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init), type))
     {
-      /* A brace-enclosed initializer for an aggregate.  In C++0x this can
-        happen for direct-initialization, too.  */
-      init = digest_init (type, init, complain);
+      /* Early initialization via a TARGET_EXPR only works for
+        complete objects.  */
+      gcc_assert (TREE_CODE (init) == CONSTRUCTOR || true_exp == exp);
+
       init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init);
       TREE_SIDE_EFFECTS (init) = 1;
       finish_expr_stmt (init);
@@ -1511,13 +1628,46 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
   else
     parms = make_tree_vector_single (init);
 
-  if (true_exp == exp)
-    ctor_name = complete_ctor_identifier;
-  else
-    ctor_name = base_ctor_identifier;
+  if (exp == current_class_ref && current_function_decl
+      && DECL_HAS_IN_CHARGE_PARM_P (current_function_decl))
+    {
+      /* Delegating constructor. */
+      tree complete;
+      tree base;
+      tree elt; unsigned i;
 
-  rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
-                                    complain);
+      /* Unshare the arguments for the second call.  */
+      VEC(tree,gc) *parms2 = make_tree_vector ();
+      FOR_EACH_VEC_ELT (tree, parms, i, elt)
+       {
+         elt = break_out_target_exprs (elt);
+         VEC_safe_push (tree, gc, parms2, elt);
+       }
+      complete = build_special_member_call (exp, complete_ctor_identifier,
+                                           &parms2, binfo, flags,
+                                           complain);
+      complete = fold_build_cleanup_point_expr (void_type_node, complete);
+      release_tree_vector (parms2);
+
+      base = build_special_member_call (exp, base_ctor_identifier,
+                                       &parms, binfo, flags,
+                                       complain);
+      base = fold_build_cleanup_point_expr (void_type_node, base);
+      rval = build3 (COND_EXPR, void_type_node,
+                    build2 (EQ_EXPR, boolean_type_node,
+                            current_in_charge_parm, integer_zero_node),
+                    base,
+                    complete);
+    }
+   else
+    {
+      if (true_exp == exp)
+       ctor_name = complete_ctor_identifier;
+      else
+       ctor_name = base_ctor_identifier;
+      rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
+                                       complain);
+  }
 
   if (parms != NULL)
     release_tree_vector (parms);
@@ -1576,12 +1726,14 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
   if (init && TREE_CODE (exp) == VAR_DECL
       && COMPOUND_LITERAL_P (init))
     {
+      VEC(tree,gc)* cleanups = NULL;
       /* If store_init_value returns NULL_TREE, the INIT has been
         recorded as the DECL_INITIAL for EXP.  That means there's
         nothing more we have to do.  */
-      init = store_init_value (exp, init, flags);
+      init = store_init_value (exp, init, &cleanups, flags);
       if (init)
        finish_expr_stmt (init);
+      gcc_assert (!cleanups);
       return;
     }
 
@@ -1589,27 +1741,27 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
      that's value-initialization.  */
   if (init == void_type_node)
     {
-      /* If there's a user-provided constructor, we just call that.  */
-      if (type_has_user_provided_constructor (type))
-       /* Fall through.  */;
-      /* If there isn't, but we still need to call the constructor,
-        zero out the object first.  */
-      else if (type_build_ctor_call (type))
-       {
-         init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
+      /* If the type has data but no user-provided ctor, we need to zero
+        out the object.  */
+      if (!type_has_user_provided_constructor (type)
+         && !is_really_empty_class (type))
+       {
+         tree field_size = NULL_TREE;
+         if (exp != true_exp && CLASSTYPE_AS_BASE (type) != type)
+           /* Don't clobber already initialized virtual bases.  */
+           field_size = TYPE_SIZE (CLASSTYPE_AS_BASE (type));
+         init = build_zero_init_1 (type, NULL_TREE, /*static_storage_p=*/false,
+                                   field_size);
          init = build2 (INIT_EXPR, type, exp, init);
          finish_expr_stmt (init);
-         /* And then call the constructor.  */
        }
+
       /* If we don't need to mess with the constructor at all,
-        then just zero out the object and we're done.  */
-      else
-       {
-         init = build2 (INIT_EXPR, type, exp,
-                        build_value_init_noctor (type, complain));
-         finish_expr_stmt (init);
-         return;
-       }
+        then we're done.  */
+      if (! type_build_ctor_call (type))
+       return;
+
+      /* Otherwise fall through and call the constructor.  */
       init = NULL_TREE;
     }
 
@@ -1795,10 +1947,11 @@ build_offset_ref (tree type, tree member, bool address_p)
    constant initializer, return the initializer (or, its initializers,
    recursively); otherwise, return DECL.  If INTEGRAL_P, the
    initializer is only returned if DECL is an integral
-   constant-expression.  */
+   constant-expression.  If RETURN_AGGREGATE_CST_OK_P, it is ok to
+   return an aggregate constant.  */
 
 static tree
-constant_value_1 (tree decl, bool integral_p)
+constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p)
 {
   while (TREE_CODE (decl) == CONST_DECL
         || (integral_p
@@ -1835,12 +1988,13 @@ constant_value_1 (tree decl, bool integral_p)
       if (!init
          || !TREE_TYPE (init)
          || !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.  */
+         || (!integral_p && !return_aggregate_cst_ok_p
+             /* Unless RETURN_AGGREGATE_CST_OK_P is true, 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;
@@ -1857,18 +2011,28 @@ constant_value_1 (tree decl, bool integral_p)
 tree
 integral_constant_value (tree decl)
 {
-  return constant_value_1 (decl, /*integral_p=*/true);
+  return constant_value_1 (decl, /*integral_p=*/true,
+                          /*return_aggregate_cst_ok_p=*/false);
 }
 
 /* A more relaxed version of integral_constant_value, used by the
-   common C/C++ code and by the C++ front end for optimization
-   purposes.  */
+   common C/C++ code.  */
 
 tree
 decl_constant_value (tree decl)
 {
-  return constant_value_1 (decl,
-                          /*integral_p=*/processing_template_decl);
+  return constant_value_1 (decl, /*integral_p=*/processing_template_decl,
+                          /*return_aggregate_cst_ok_p=*/true);
+}
+
+/* A version of integral_constant_value used by the C++ front end for
+   optimization purposes.  */
+
+tree
+decl_constant_value_safe (tree decl)
+{
+  return constant_value_1 (decl, /*integral_p=*/processing_template_decl,
+                          /*return_aggregate_cst_ok_p=*/false);
 }
 \f
 /* Common subroutines of build_new and build_vec_delete.  */
@@ -2105,7 +2269,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
     }
 
   if (CP_TYPE_CONST_P (elt_type) && *init == NULL
-      && !type_has_user_provided_default_constructor (elt_type))
+      && default_init_uninitialized_part (elt_type))
     {
       if (complain & tf_error)
         error ("uninitialized const in %<new%> of %q#T", elt_type);
@@ -2569,7 +2733,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
        {
          tree ifexp = cp_build_binary_op (input_location,
                                           NE_EXPR, alloc_node,
-                                          integer_zero_node,
+                                          nullptr_node,
                                           complain);
          rval = build_conditional_expr (ifexp, rval, alloc_node, 
                                          complain);
@@ -2611,7 +2775,9 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (nelts == NULL_TREE && VEC_length (tree, *init) == 1)
+  if (nelts == NULL_TREE && VEC_length (tree, *init) == 1
+      /* Don't do auto deduction where it might affect mangling.  */
+      && (!processing_template_decl || at_function_scope_p ()))
     {
       tree auto_node = type_uses_auto (type);
       if (auto_node)
@@ -2633,7 +2799,8 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
 
       orig_placement = make_tree_vector_copy (*placement);
       orig_nelts = nelts;
-      orig_init = make_tree_vector_copy (*init);
+      if (*init)
+       orig_init = make_tree_vector_copy (*init);
 
       make_args_non_dependent (*placement);
       if (nelts)
@@ -2881,7 +3048,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
                      fold_build2_loc (input_location,
                                   NE_EXPR, boolean_type_node, base,
                                   convert (TREE_TYPE (base),
-                                           integer_zero_node)),
+                                           nullptr_node)),
                      body, integer_zero_node);
   body = build1 (NOP_EXPR, void_type_node, body);
 
@@ -3118,6 +3285,9 @@ build_vec_init (tree base, tree maxindex, tree init,
       bool try_const = (TREE_CODE (atype) == ARRAY_TYPE
                        && (literal_type_p (inner_elt_type)
                            || TYPE_HAS_CONSTEXPR_CTOR (inner_elt_type)));
+      /* If the constructor already has the array type, it's been through
+        digest_init, so we shouldn't try to do anything more.  */
+      bool digested = same_type_p (atype, TREE_TYPE (init));
       bool saw_non_const = false;
       bool saw_const = false;
       /* If we're initializing a static array, we want to do static
@@ -3140,7 +3310,9 @@ build_vec_init (tree base, tree maxindex, tree init,
          num_initialized_elts++;
 
          current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-         if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
+         if (digested)
+           one_init = build2 (INIT_EXPR, type, baseref, elt);
+         else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
            one_init = build_aggr_init (baseref, elt, 0, complain);
          else
            one_init = cp_build_modify_expr (baseref, NOP_EXPR,
@@ -3168,9 +3340,12 @@ build_vec_init (tree base, tree maxindex, tree init,
              else
                {
                  if (do_static_init)
-                   CONSTRUCTOR_APPEND_ELT (new_vec, field,
-                                           build_zero_init (TREE_TYPE (e),
-                                                            NULL_TREE, true));
+                   {
+                     tree value = build_zero_init (TREE_TYPE (e), NULL_TREE,
+                                                   true);
+                     if (value)
+                       CONSTRUCTOR_APPEND_ELT (new_vec, field, value);
+                   }
                  saw_non_const = true;
                }
            }
@@ -3334,7 +3509,9 @@ build_vec_init (tree base, tree maxindex, tree init,
       if (TREE_CODE (type) == ARRAY_TYPE)
        m = cp_build_binary_op (input_location,
                                MULT_EXPR, m,
-                               array_type_nelts_total (type),
+                               /* Force signed arithmetic.  */
+                               convert (TREE_TYPE (m),
+                                        array_type_nelts_total (type)),
                                complain);
 
       finish_cleanup_try_block (try_block);
@@ -3602,7 +3779,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
        {
          /* Handle deleting a null pointer.  */
          ifexp = fold (cp_build_binary_op (input_location,
-                                           NE_EXPR, addr, integer_zero_node,
+                                           NE_EXPR, addr, nullptr_node,
                                            complain));
          if (ifexp == error_mark_node)
            return error_mark_node;