+ if (CLASS_TYPE_P (type))
+ {
+ if (type_has_user_provided_constructor (type))
+ return build_aggr_init_expr
+ (type,
+ build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ NULL, type, LOOKUP_NORMAL,
+ tf_warning_or_error));
+ else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
+ {
+ /* This is a class that needs constructing, but doesn't have
+ a user-provided constructor. So we need to zero-initialize
+ the object and then call the implicitly defined ctor.
+ This will be handled in simplify_aggr_init_expr. */
+ tree ctor = build_special_member_call
+ (NULL_TREE, complete_ctor_identifier,
+ NULL, type, LOOKUP_NORMAL, tf_warning_or_error);
+
+ ctor = build_aggr_init_expr (type, ctor);
+ AGGR_INIT_ZERO_FIRST (ctor) = 1;
+ return ctor;
+ }
+ }
+ return build_value_init_noctor (type);
+}
+
+/* Like build_value_init, but don't call the constructor for TYPE. Used
+ for base initializers. */
+
+tree
+build_value_init_noctor (tree type)
+{
+ if (CLASS_TYPE_P (type))
+ {
+ gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type));
+
+ if (TREE_CODE (type) != UNION_TYPE)
+ {
+ tree field;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* Iterate over the fields, building initializations. */
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ tree ftype, value;
+
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ ftype = TREE_TYPE (field);
+
+ if (TREE_CODE (ftype) == REFERENCE_TYPE)
+ error ("value-initialization of reference");
+
+ /* We could skip vfields and fields of types with
+ user-defined constructors, but I think that won't improve
+ performance at all; it should be simpler in general just
+ to zero out the entire object than try to only zero the
+ bits that actually need it. */
+
+ /* Note that for class types there will be FIELD_DECLs
+ corresponding to base classes as well. Thus, iterating
+ over TYPE_FIELDs will result in correct initialization of
+ all of the subobjects. */
+ value = build_value_init (ftype);
+
+ if (value)
+ CONSTRUCTOR_APPEND_ELT(v, field, value);
+ }
+
+ /* Build a constructor to contain the zero- initializations. */
+ return build_constructor (type, v);
+ }
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* Iterate over the array elements, building initializations. */
+ tree max_index = array_type_nelts (type);
+
+ /* If we have an error_mark here, we should just return error mark
+ as we don't know the size of the array yet. */
+ if (max_index == error_mark_node)
+ return error_mark_node;
+ gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
+
+ /* A zero-sized array, which is accepted as an extension, will
+ 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);
+
+ /* 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;
+ else
+ ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
+ max_index);
+
+ ce->value = build_value_init (TREE_TYPE (type));
+
+ /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */
+ gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR
+ && TREE_CODE (ce->value) != AGGR_INIT_EXPR);
+ }
+
+ /* Build a constructor to contain the initializations. */
+ return build_constructor (type, v);
+ }
+
+ return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);