re PR c++/54341 (ICE (segfault) in cx_check_missing_mem_inits, at cp/semantics.c...
[gcc.git] / gcc / cp / init.c
index 52b948441f2781fbbb0640e8230ddb8ceb4d95ee..561477ace5787f8182a93af7d944079f435e246a 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, 2010,
-   2011 Free Software Foundation, Inc.
+   2011, 2012 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -29,7 +29,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "cp-tree.h"
 #include "flags.h"
-#include "output.h"
 #include "target.h"
 
 static bool begin_init_stmts (tree *, tree *);
@@ -100,7 +99,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 +139,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,6 +177,8 @@ 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_OR_PTRMEM_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))
@@ -330,7 +334,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 +361,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 +376,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))
@@ -482,6 +491,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 +525,38 @@ 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);
+         if (init && TREE_CODE (init) == DEFAULT_ARG)
+           {
+             error ("constructor required before non-static data member "
+                    "for %qD has been parsed", member);
+             init = NULL_TREE;
+           }
+         /* 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,14 +612,55 @@ perform_member_init (tree member, tree init)
          finish_expr_stmt (init);
        }
     }
-  else if (type_build_ctor_call (type))
+  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))))
     {
       if (TREE_CODE (type) == ARRAY_TYPE)
        {
          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);
            }
@@ -576,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),
@@ -603,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)))
@@ -655,8 +752,6 @@ build_field_list (tree t, tree list, int *uses_unions_p)
 {
   tree fields;
 
-  *uses_unions_p = 0;
-
   /* Note whether or not T is a union.  */
   if (TREE_CODE (t) == UNION_TYPE)
     *uses_unions_p = 1;
@@ -710,7 +805,7 @@ sort_mem_initializers (tree t, tree mem_inits)
   tree next_subobject;
   VEC(tree,gc) *vbases;
   int i;
-  int uses_unions_p;
+  int uses_unions_p = 0;
 
   /* Build up a list of initializations.  The TREE_PURPOSE of entry
      will be the subobject (a FIELD_DECL or BINFO) to initialize.  The
@@ -932,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;
 
@@ -961,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.  */
@@ -981,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),
@@ -1085,7 +1180,7 @@ expand_virtual_init (tree binfo, tree decl)
   gcc_assert (vtbl_ptr != error_mark_node);
 
   /* Assign the vtable to the vptr.  */
-  vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
+  vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0, tf_warning_or_error);
   finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl,
                                          tf_warning_or_error));
 }
@@ -1155,7 +1250,7 @@ construct_virtual_base (tree vbase, tree arguments)
   exp = convert_to_base_statically (current_class_ref, vbase);
 
   expand_aggr_init_1 (vbase, current_class_ref, exp, arguments,
-                     LOOKUP_COMPLAIN, tf_warning_or_error);
+                     0, tf_warning_or_error);
   finish_then_clause (inner_if_stmt);
   finish_if_stmt (inner_if_stmt);
 
@@ -1272,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;
@@ -1377,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;
@@ -1459,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);
@@ -1482,7 +1598,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
           have already built up the constructor call so we could wrap it
           in an exception region.  */;
       else
-       init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
+       init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP,
+                           flags, complain);
 
       if (TREE_CODE (init) == MUST_NOT_THROW_EXPR)
        /* We need to protect the initialization of a catch parm with a
@@ -1512,13 +1629,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);
@@ -1577,12 +1727,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;
     }
 
@@ -1590,27 +1742,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;
     }
 
@@ -1726,9 +1878,11 @@ build_offset_ref (tree type, tree member, bool address_p)
               (or any class derived from that class).  */
          if (address_p && DECL_P (t)
              && DECL_NONSTATIC_MEMBER_P (t))
-           perform_or_defer_access_check (TYPE_BINFO (type), t, t);
+           perform_or_defer_access_check (TYPE_BINFO (type), t, t,
+                                          tf_warning_or_error);
          else
-           perform_or_defer_access_check (basebinfo, t, t);
+           perform_or_defer_access_check (basebinfo, t, t,
+                                          tf_warning_or_error);
 
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
@@ -1741,7 +1895,8 @@ build_offset_ref (tree type, tree member, bool address_p)
     /* We need additional test besides the one in
        check_accessibility_of_qualified_id in case it is
        a pointer to non-static member.  */
-    perform_or_defer_access_check (TYPE_BINFO (type), member, member);
+    perform_or_defer_access_check (TYPE_BINFO (type), member, member,
+                                  tf_warning_or_error);
 
   if (!address_p)
     {
@@ -1796,10 +1951,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
@@ -1836,12 +1992,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;
@@ -1858,18 +2015,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.  */
@@ -2013,6 +2180,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
   tree pointer_type;
   tree non_const_pointer_type;
   tree outer_nelts = NULL_TREE;
+  /* For arrays, a bounds checks on the NELTS parameter. */
+  tree outer_nelts_check = NULL_TREE;
+  bool outer_nelts_from_type = false;
+  double_int inner_nelts_count = double_int_one;
   tree alloc_call, alloc_expr;
   /* The address returned by the call to "operator new".  This node is
      a VAR_DECL and is therefore reusable.  */
@@ -2047,10 +2218,14 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
+      /* Transforms new (T[N]) to new T[N].  The former is a GNU
+        extension for variable N.  (This also covers new T where T is
+        a VLA typedef.)  */
       array_p = true;
       nelts = array_type_nelts_top (type);
       outer_nelts = nelts;
       type = TREE_TYPE (type);
+      outer_nelts_from_type = true;
     }
 
   /* If our base type is an array, then make sure we know how many elements
@@ -2058,10 +2233,61 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
   for (elt_type = type;
        TREE_CODE (elt_type) == ARRAY_TYPE;
        elt_type = TREE_TYPE (elt_type))
-    nelts = cp_build_binary_op (input_location,
-                               MULT_EXPR, nelts,
-                               array_type_nelts_top (elt_type),
-                               complain);
+    {
+      tree inner_nelts = array_type_nelts_top (elt_type);
+      tree inner_nelts_cst = maybe_constant_value (inner_nelts);
+      if (TREE_CONSTANT (inner_nelts_cst)
+         && TREE_CODE (inner_nelts_cst) == INTEGER_CST)
+       {
+         double_int result;
+         if (mul_double (TREE_INT_CST_LOW (inner_nelts_cst),
+                         TREE_INT_CST_HIGH (inner_nelts_cst),
+                         inner_nelts_count.low, inner_nelts_count.high,
+                         &result.low, &result.high))
+           {
+             if (complain & tf_error)
+               error ("integer overflow in array size");
+             nelts = error_mark_node;
+           }
+         inner_nelts_count = result;
+       }
+      else
+       {
+         if (complain & tf_error)
+           {
+             error_at (EXPR_LOC_OR_HERE (inner_nelts),
+                       "array size in operator new must be constant");
+             cxx_constant_value(inner_nelts);
+           }
+         nelts = error_mark_node;
+       }
+      if (nelts != error_mark_node)
+       nelts = cp_build_binary_op (input_location,
+                                   MULT_EXPR, nelts,
+                                   inner_nelts_cst,
+                                   complain);
+    }
+
+  if (variably_modified_type_p (elt_type, NULL_TREE) && (complain & tf_error))
+    {
+      error ("variably modified type not allowed in operator new");
+      return error_mark_node;
+    }
+
+  if (nelts == error_mark_node)
+    return error_mark_node;
+
+  /* Warn if we performed the (T[N]) to T[N] transformation and N is
+     variable.  */
+  if (outer_nelts_from_type
+      && !TREE_CONSTANT (maybe_constant_value (outer_nelts)))
+    {
+      if (complain & tf_warning_or_error)
+       pedwarn(EXPR_LOC_OR_HERE (outer_nelts), OPT_Wvla,
+               "ISO C++ does not support variable-length array types");
+      else
+       return error_mark_node;
+    }
 
   if (TREE_CODE (elt_type) == VOID_TYPE)
     {
@@ -2106,7 +2332,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);
@@ -2115,7 +2341,56 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
 
   size = size_in_bytes (elt_type);
   if (array_p)
-    size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
+    {
+      /* Maximum available size in bytes.  Half of the address space
+        minus the cookie size.  */
+      double_int max_size
+       = double_int_lshift (double_int_one, TYPE_PRECISION (sizetype) - 1,
+                            HOST_BITS_PER_DOUBLE_INT, false);
+      /* Size of the inner array elements. */
+      double_int inner_size;
+      /* Maximum number of outer elements which can be allocated. */
+      double_int max_outer_nelts;
+      tree max_outer_nelts_tree;
+
+      gcc_assert (TREE_CODE (size) == INTEGER_CST);
+      cookie_size = targetm.cxx.get_cookie_size (elt_type);
+      gcc_assert (TREE_CODE (cookie_size) == INTEGER_CST);
+      gcc_checking_assert (double_int_ucmp
+                          (TREE_INT_CST (cookie_size), max_size) < 0);
+      /* Unconditionally substract the cookie size.  This decreases the
+        maximum object size and is safe even if we choose not to use
+        a cookie after all.  */
+      max_size = double_int_sub (max_size, TREE_INT_CST (cookie_size));
+      if (mul_double (TREE_INT_CST_LOW (size), TREE_INT_CST_HIGH (size),
+                     inner_nelts_count.low, inner_nelts_count.high,
+                     &inner_size.low, &inner_size.high)
+         || double_int_ucmp (inner_size, max_size) > 0)
+       {
+         if (complain & tf_error)
+           error ("size of array is too large");
+         return error_mark_node;
+       }
+      max_outer_nelts = double_int_udiv (max_size, inner_size, TRUNC_DIV_EXPR);
+      /* Only keep the top-most seven bits, to simplify encoding the
+        constant in the instruction stream.  */
+      {
+       unsigned shift = HOST_BITS_PER_DOUBLE_INT - 7
+         - (max_outer_nelts.high ? clz_hwi (max_outer_nelts.high)
+            : (HOST_BITS_PER_WIDE_INT + clz_hwi (max_outer_nelts.low)));
+       max_outer_nelts
+         = double_int_lshift (double_int_rshift
+                              (max_outer_nelts, shift,
+                               HOST_BITS_PER_DOUBLE_INT, false),
+                              shift, HOST_BITS_PER_DOUBLE_INT, false);
+      }
+      max_outer_nelts_tree = double_int_to_tree (sizetype, max_outer_nelts);
+
+      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
+      outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
+                                      outer_nelts,
+                                      max_outer_nelts_tree);
+    }
 
   alloc_fn = NULL_TREE;
 
@@ -2178,10 +2453,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
          /* Use a class-specific operator new.  */
          /* If a cookie is required, add some extra space.  */
          if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))
-           {
-             cookie_size = targetm.cxx.get_cookie_size (elt_type);
-             size = size_binop (PLUS_EXPR, size, cookie_size);
-           }
+           size = size_binop (PLUS_EXPR, size, cookie_size);
+         else
+           cookie_size = NULL_TREE;
+         /* Perform the overflow check.  */
+         if (outer_nelts_check != NULL_TREE)
+            size = fold_build3 (COND_EXPR, sizetype, outer_nelts_check,
+                                size, TYPE_MAX_VALUE (sizetype));
          /* Create the argument list.  */
          VEC_safe_insert (tree, gc, *placement, 0, size);
          /* Do name-lookup to find the appropriate operator.  */
@@ -2212,14 +2490,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
        {
          /* Use a global operator new.  */
          /* See if a cookie might be required.  */
-         if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))
-           cookie_size = targetm.cxx.get_cookie_size (elt_type);
-         else
+         if (!(array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type)))
            cookie_size = NULL_TREE;
 
          alloc_call = build_operator_new_call (fnname, placement,
                                                &size, &cookie_size,
-                                               &alloc_fn);
+                                               outer_nelts_check,
+                                               &alloc_fn, complain);
        }
     }
 
@@ -2495,7 +2772,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
                      size,
                      globally_qualified_p,
                      placement_allocation_fn_p ? alloc_call : NULL_TREE,
-                     alloc_fn));
+                     alloc_fn,
+                     complain));
 
          if (!cleanup)
            /* We're done.  */;
@@ -2570,7 +2848,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);
@@ -2612,7 +2890,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)
@@ -2652,7 +2932,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
             return error_mark_node;
         }
       nelts = mark_rvalue_use (nelts);
-      nelts = cp_save_expr (cp_convert (sizetype, nelts));
+      nelts = cp_save_expr (cp_convert (sizetype, nelts, complain));
     }
 
   /* ``A reference cannot be created by the new operator.  A reference
@@ -2849,12 +3129,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
          base_tbd = cp_build_binary_op (input_location,
                                         MINUS_EXPR,
                                         cp_convert (string_type_node,
-                                                    base),
+                                                    base, complain),
                                         cookie_size,
                                         complain);
          if (base_tbd == error_mark_node)
            return error_mark_node;
-         base_tbd = cp_convert (ptype, base_tbd);
+         base_tbd = cp_convert (ptype, base_tbd, complain);
          /* True size with header.  */
          virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size);
        }
@@ -2863,7 +3143,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
                                              base_tbd, virtual_size,
                                              use_global_delete & 1,
                                              /*placement=*/NULL_TREE,
-                                             /*alloc_fn=*/NULL_TREE);
+                                             /*alloc_fn=*/NULL_TREE,
+                                             complain);
     }
 
   body = loop;
@@ -2882,7 +3163,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);
 
@@ -2990,7 +3271,8 @@ build_vec_init (tree base, tree maxindex, tree init,
   if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
     maxindex = array_type_nelts (atype);
 
-  if (maxindex == NULL_TREE || maxindex == error_mark_node)
+  if (maxindex == NULL_TREE || maxindex == error_mark_node
+      || integer_all_onesp (maxindex))
     return error_mark_node;
 
   if (explicit_value_init_p)
@@ -3025,11 +3307,14 @@ build_vec_init (tree base, tree maxindex, tree init,
       return stmt_expr;
     }
 
-  maxindex = cp_convert (ptrdiff_type_node, maxindex);
+  maxindex = cp_convert (ptrdiff_type_node, maxindex, complain);
   if (TREE_CODE (atype) == ARRAY_TYPE)
     {
       ptype = build_pointer_type (type);
-      base = cp_convert (ptype, decay_conversion (base));
+      base = decay_conversion (base, complain);
+      if (base == error_mark_node)
+       return error_mark_node;
+      base = cp_convert (ptype, base, complain);
     }
   else
     ptype = atype;
@@ -3078,7 +3363,9 @@ build_vec_init (tree base, tree maxindex, tree init,
     {
       if (lvalue_kind (init) & clk_rvalueref)
        xvalue = true;
-      base2 = decay_conversion (init);
+      base2 = decay_conversion (init, complain);
+      if (base2 == error_mark_node)
+       return error_mark_node;
       itype = TREE_TYPE (base2);
       base2 = get_temp_regvar (itype, base2);
       itype = TREE_TYPE (itype);
@@ -3119,6 +3406,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
@@ -3141,7 +3431,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,
@@ -3491,7 +3783,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
        addr = save_expr (addr);
 
       /* Throw away const and volatile on target type of addr.  */
-      addr = convert_force (build_pointer_type (type), addr, 0);
+      addr = convert_force (build_pointer_type (type), addr, 0, complain);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -3517,7 +3809,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
       if (TREE_SIDE_EFFECTS (addr))
        addr = save_expr (addr);
 
-      addr = convert_force (build_pointer_type (type), addr, 0);
+      addr = convert_force (build_pointer_type (type), addr, 0, complain);
     }
 
   gcc_assert (MAYBE_CLASS_TYPE_P (type));
@@ -3531,7 +3823,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
                                   cxx_sizeof_nowarn (type),
                                   use_global_delete,
                                   /*placement=*/NULL_TREE,
-                                  /*alloc_fn=*/NULL_TREE);
+                                  /*alloc_fn=*/NULL_TREE,
+                                  complain);
     }
   else
     {
@@ -3570,7 +3863,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
                                            cxx_sizeof_nowarn (type),
                                            /*global_p=*/false,
                                            /*placement=*/NULL_TREE,
-                                           /*alloc_fn=*/NULL_TREE);
+                                           /*alloc_fn=*/NULL_TREE,
+                                           complain);
          /* Call the complete object destructor.  */
          auto_delete = sfk_complete_destructor;
        }
@@ -3582,7 +3876,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
                                /*global_p=*/false,
                                /*placement=*/NULL_TREE,
-                               /*alloc_fn=*/NULL_TREE);
+                               /*alloc_fn=*/NULL_TREE,
+                               complain);
        }
 
       expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain),
@@ -3603,7 +3898,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;