diff options
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r-- | gcc/cp/tree.c | 95 |
1 files changed, 70 insertions, 25 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 8fe8832..2f082a6 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -473,45 +473,80 @@ build_cplus_new (tree type, tree init, tsubst_flags_t complain) another array to copy. */ static tree -build_vec_init_elt (tree type, tree init) +build_vec_init_elt (tree type, tree init, tsubst_flags_t complain) { - tree inner_type = strip_array_types (type); + tree inner_type = strip_array_types (TREE_TYPE (type)); VEC(tree,gc) *argvec; - if (integer_zerop (array_type_nelts_total (type)) - || !CLASS_TYPE_P (inner_type)) + if (!CLASS_TYPE_P (inner_type)) /* No interesting initialization to do. */ return integer_zero_node; else if (init == void_type_node) return build_value_init (inner_type, tf_warning_or_error); - gcc_assert (init == NULL_TREE - || (same_type_ignoring_top_level_qualifiers_p - (type, TREE_TYPE (init)))); - - argvec = make_tree_vector (); - if (init) + if (init == NULL_TREE) + argvec = make_tree_vector (); + else if (TREE_CODE (init) == TREE_LIST) + /* Array init extension, i.e. g++.robertl/eb58.C. */ + argvec = make_tree_vector_from_list (init); + else if (same_type_ignoring_top_level_qualifiers_p + (inner_type, strip_array_types (TREE_TYPE (init)))) { + /* Array copy or list-initialization. */ tree dummy = build_dummy_object (inner_type); if (!real_lvalue_p (init)) dummy = move (dummy); - VEC_quick_push (tree, argvec, dummy); + argvec = make_tree_vector_single (dummy); } - return build_special_member_call (NULL_TREE, complete_ctor_identifier, + else + gcc_unreachable (); + init = build_special_member_call (NULL_TREE, complete_ctor_identifier, &argvec, inner_type, LOOKUP_NORMAL, - tf_warning_or_error); + complain); + release_tree_vector (argvec); + + /* For array new, also mark the destructor as used. */ + if (TREE_CODE (type) == POINTER_TYPE + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_type)) + { + tree dtor = get_dtor_sfinae (inner_type, complain); + if (dtor == error_mark_node) + return error_mark_node; + else if (dtor) + mark_used (dtor); + } + return init; } -/* Return a TARGET_EXPR which expresses the initialization of an array to - be named later, either default-initialization or copy-initialization - from another array of the same type. */ +/* Return a TARGET_EXPR which expresses the initialization of an array. If + TARGET is an array type, the initialization is of an array to be named + later, and the initialization will be wrapped in a TARGET_EXPR. If + TARGET is an expression, it is the array to be initialized. INIT is the + initializer, or void_type_node for value-initialization. If TARGET is + an expression, NELTS is the number of elements to initialize. */ tree -build_vec_init_expr (tree type, tree init) +build_vec_init_expr (tree target, tree init, tree nelts, + tsubst_flags_t complain) { - tree slot; + tree slot, type; bool value_init = false; - tree elt_init = build_vec_init_elt (type, init); + tree elt_init; + tree real_nelts; + + if (TYPE_P (target)) + { + gcc_assert (TREE_CODE (target) == ARRAY_TYPE && nelts == NULL_TREE); + type = target; + slot = build_local_temp (type); + } + else + { + gcc_assert (EXPR_P (target)); + slot = target; + type = TREE_TYPE (slot); + gcc_assert (TREE_CODE (type) == POINTER_TYPE && nelts != NULL_TREE); + } if (init == void_type_node) { @@ -519,8 +554,14 @@ build_vec_init_expr (tree type, tree init) init = NULL_TREE; } - slot = build_local_temp (type); - init = build2 (VEC_INIT_EXPR, type, slot, init); + real_nelts = nelts ? nelts : array_type_nelts_total (type); + if (integer_zerop (real_nelts)) + /* No elements to initialize. */ + elt_init = integer_zero_node; + else + elt_init = build_vec_init_elt (type, init, complain); + + init = build3 (VEC_INIT_EXPR, type, slot, init, nelts); SET_EXPR_LOCATION (init, input_location); if (cxx_dialect >= cxx0x @@ -528,8 +569,11 @@ build_vec_init_expr (tree type, tree init) VEC_INIT_EXPR_IS_CONSTEXPR (init) = true; VEC_INIT_EXPR_VALUE_INIT (init) = value_init; - init = build_target_expr (slot, init, tf_warning_or_error); - TARGET_EXPR_IMPLICIT_P (init) = 1; + if (slot != target) + { + init = build_target_expr (slot, init, complain); + TARGET_EXPR_IMPLICIT_P (init) = 1; + } return init; } @@ -547,14 +591,15 @@ diagnose_non_constexpr_vec_init (tree expr) else init = VEC_INIT_EXPR_INIT (expr); - elt_init = build_vec_init_elt (type, init); + elt_init = build_vec_init_elt (type, init, tf_warning_or_error); require_potential_constant_expression (elt_init); } tree build_array_copy (tree init) { - return build_vec_init_expr (TREE_TYPE (init), init); + return build_vec_init_expr (TREE_TYPE (init), init, NULL_TREE, + tf_warning_or_error); } /* Build a TARGET_EXPR using INIT to initialize a new temporary of the |