OSDN Git Service

PR c++/54652
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index 8e28e3b..bb0e618 100644 (file)
@@ -140,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,
@@ -180,7 +182,7 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
     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;
@@ -252,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.  */
@@ -333,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 || SCALAR_TYPE_P (type));
+  gcc_assert (!processing_template_decl
+             || (SCALAR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE));
 
   if (CLASS_TYPE_P (type))
     {
@@ -359,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;
        }
     }
@@ -376,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))
@@ -442,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;
 
-         /* 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);
+             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);
+           }
        }
 
       /* Build a constructor to contain the initializations.  */
@@ -1729,8 +1741,10 @@ 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 no user-provided ctor, we need to zero out the object.  */
-      if (!type_has_user_provided_constructor (type))
+      /* 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)
@@ -2761,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)
@@ -2783,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)
@@ -3139,8 +3156,7 @@ 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
-      || integer_all_onesp (maxindex))
+  if (maxindex == NULL_TREE || maxindex == error_mark_node)
     return error_mark_node;
 
   if (explicit_value_init_p)
@@ -3324,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;
                }
            }
@@ -3490,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);