diff options
author | giovannibajo <giovannibajo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-20 01:19:59 +0000 |
---|---|---|
committer | giovannibajo <giovannibajo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-20 01:19:59 +0000 |
commit | c75b4594282e6b33803b8332acba704d057f8d97 (patch) | |
tree | cee4baf52782472c6ce30e28249d2a5df154551f | |
parent | 9e564f0b63c843a988f0bc8859c8d6879fc7a22d (diff) | |
download | gcc-c75b4594282e6b33803b8332acba704d057f8d97.tar.gz |
Make CONSTRUCTOR use VEC to store initializers.
* c-common.c (complete_array_type): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* c-pretty-print.c (pp_c_initializer_list): Use pp_c_constructor_elts.
(pp_c_constructor_elts): New function.
* c-pretty-print.h (pp_c_constructor_elts): Declare.
* c-typeck.c (build_function_call, build_c_cast, digest_init,
struct constructor_stack, struct initializer_stack,
constructor_elements, push_init_level, pop_init_level,
add_pending_init, find_init_member, output_init_element): Update to
cope with VEC in CONSTRUCTOR_ELTS.
* coverage.c (build_fn_info_value, build_ctr_info_value,
build_gcov_info): Likewise.
* expr.c (categorize_ctor_elements_1, store_constructor,
expand_expr_real_1): Likewise.
* fold-const.c (fold_ternary): Likewise.
* gimplify.c (gimplify_init_ctor_preeval, zero_sized_field_decl,
gimplify_init_constructor, gimplify_expr): Likewise.
* tree-dump.c (dequeue_and_dump): Likewise.
* tree-inline.c (copy_tree_r): Add code to duplicate a CONSTRUCTOR
node.
* tree-pretty-print.c (dump_generic_node): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* tree-sra.c (generate_element_init_1): Likewise.
* tree-ssa-ccp.c (fold_const_aggregate_ref): Likewise.
* tree-ssa-operands.c (get_expr_operands): Likewise.
* tree-vect-generic.c (expand_vector_piecewise): Likewise.
* tree-vect-transform.c (vect_get_vec_def_for_operand):
(get_initial_def_for_reduction): Likewise.
* tree-vn.c (set_value_handle, get_value_handle): CONSTURCTOR uses
value handle in annotations.
* tree.c (tree_node_kind, tree_code_size, make_node_stat,
tree_node_structure): Add support for constr_kind.
(build_vector_from_ctor, build_constructor_single,
build_constructor_from_list): New functions.
(build_constructor): Update to take a VEC instead of a TREE_LIST.
(simple_cst_equal, iterative_hash_expr, initializer_zerop, walk_tree):
Update to cope with VEC in CONSTRUCTOR_ELTS.
* tree.def (CONSTRUCTOR): Make it a tcc_exceptional node.
* tree.h (FOR_EACH_CONSTRUCTOR_VALUE, FOR_EACH_CONSTRUCTOR_ELT,
CONSTRUCTOR_APPEND_ELT): New macros.
(struct constructor_elt, struct tree_constructor): New data types.
(union tree_node): Add tree_constructor field.
* treestruct.def: Define TS_CONSTRUCTOR.
* varasm.c (const_hash_1, compare_constant, copy_constant,
compute_reloc_for_constant, output_addressed_constants,
initializer_constant_valid_p, output_constant,
array_size_for_constructor, output_constructor): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* vec.h (VEC_empty, VEC_copy): New macros.
ada/
Make CONSTRUCTOR use VEC to store initializers.
* decl.c (gnat_to_gnu_entity): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* trans.c (extract_values): Likewise.
* utils.c (convert, remove_conversions): Likewise.
* utils2.c (contains_save_expr_p, build_binary_op, build_unary_op,
gnat_build_constructor): Likewise.
cp/
Make CONSTRUCTOR use VEC to store initializers.
* call.c (convert_default_arg): Update call to digest_init.
* class.c (dump_class_hierarchy, dump_array): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* cp-tree.h (EMPTY_CONSTRUCTOR_P): Likewise.
(finish_compound_literal, digest_init): Update declaration.
* decl.c (struct reshape_iter): New data type.
(reshape_init_array): Rename to...
(reshape_init_array_1): Update to cope with VEC in CONSTRUCTOR_ELTS.
(reshape_init): Rewrite from scratch. Split parts into...
(reshape_init_array, reshape_init_vector, reshape_init_class,
reshape_init_r): New functions.
(check_initializer): Update call to reshape_init. Remove obsolete
code.
(initialize_artificial_var, cp_complete_array_type): Update to cope
with VEC in CONSTRUCTOR_ELTS.
* decl2.c (grokfield): Update calls to digest_init.
(mark_vtable_entries): Update to cope with VEC in CONSTRUCTOR_ELTS.
* error.c (dump_expr_init_vec): New function.
(dump_expr): Use dump_expr_init_vec.
* init.c (build_zero_init, build_vec_init): Update to cope with VEC
in CONSTRUCTOR_ELTS.
(expand_default_init): Update call to digest_init.
* parser.c (cp_parser_postfix_expression): Use a VEC for the
initializers.
(cp_parser_initializer_list): Build a VEC of initializers.
* pt.c (tsubst_copy, tsubst_copy_and_build): Update to cope with VEC
in CONSTRUCTOR_ELTS.
* rtti.c (tinfo_base_init, generic_initializer, ptr_initializer,
ptm_initializer, class_initializer, get_pseudo_ti_init): Use
build_constructor_from_list instead of build_constructor.
* semantics.c (finish_compound_literal): Update call to digest_init.
* tree.c (stabilize_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* typeck.c (build_ptrmemfunc1): Likewise.
* typeck2.c: (cxx_incomplete_type_error, split_nonconstant_init_1):
Likewise.
(store_init_value): Use build_constructor_from_list and update call
to digest_init.
(digest_init): Rewrite.
(process_init_constructor): Rewrite from scratch. Split into...
(process_init_constructor_array, picflag_from_initializer,
process_init_constructor_record, process_init_constructor_union):
New functions.
(PICFLAG_ERRONEOUS, PICFLAG_NOT_ALL_CONSTANT, PICFLAG_NOT_ALL_SIMPLE):
New macros.
(build_functional_cast): Use build_constructor_from_list instead of
build_constructor.
fortran/
Make CONSTRUCTOR use VEC to store initializers.
* trans-array.c (gfc_build_null_descriptor,
gfc_trans_array_constructor_value, gfc_conv_array_initializer):
Update to cope with VEC in CONSTRUCTOR_ELTS.
* trans-common.c (create_common): Likewise.
* trans-expr.c (gfc_conv_structure): Likewise.
* trans-stmt.c (gfc_trans_character_select): Use
build_constructor_from_list instead of build_constructor.
java/
Make CONSTRUCTOR use VEC to store initializers.
* check-init.c (check_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* class.c (make_field_value, make_method_value, get_dispatch_table,
make_class_data, emit_symbol_table, emit_catch_table,
emit_assertion_table): Use build_constructor_from_list instead of
build_constructor.
* constants.c (build_constants_constructor): Likewise.
* java-gimplify.c (java_gimplify_new_array_init): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* java-tree.h (START_RECORD_CONSTRUCTOR, PUSH_SUPER_VALUE,
PUSH_FIELD_VALUE, FINISH_RECORD_CONSTRUCTOR): Create a VEC instead
of a TREE_LIST.
* jcf-write.c (generate_bytecode_insns): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* parse.y (build_new_array_init): Use build_constructor_from_list
instead of build_constructor.
(patch_new_array_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
(array_constructor_check_entry): Likewise.
objc/
Make CONSTRUCTOR use VEC to store initializers.
* objc-act.c (objc_build_constructor): Use build_constructor_from_list
instead of build_constructor.
testsuite/
Make CONSTRUCTOR use VEC to store initializers.
* g++.dg/ext/complit3.C: Check for specific error messages.
* g++.dg/init/brace2.C: Update error message.
* g++.dg/warn/Wbraces2.C: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102182 138bc75d-0d04-0410-961f-82ee72b054a4
63 files changed, 1664 insertions, 1198 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 45251cbfc49..88073eb9e1a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,56 @@ +2005-07-20 Giovanni Bajo <giovannibajo@libero.it> + + Make CONSTRUCTOR use VEC to store initializers. + * c-common.c (complete_array_type): Update to cope with VEC in + CONSTRUCTOR_ELTS. + * c-pretty-print.c (pp_c_initializer_list): Use pp_c_constructor_elts. + (pp_c_constructor_elts): New function. + * c-pretty-print.h (pp_c_constructor_elts): Declare. + * c-typeck.c (build_function_call, build_c_cast, digest_init, + struct constructor_stack, struct initializer_stack, + constructor_elements, push_init_level, pop_init_level, + add_pending_init, find_init_member, output_init_element): Update to + cope with VEC in CONSTRUCTOR_ELTS. + * coverage.c (build_fn_info_value, build_ctr_info_value, + build_gcov_info): Likewise. + * expr.c (categorize_ctor_elements_1, store_constructor, + expand_expr_real_1): Likewise. + * fold-const.c (fold_ternary): Likewise. + * gimplify.c (gimplify_init_ctor_preeval, zero_sized_field_decl, + gimplify_init_constructor, gimplify_expr): Likewise. + * tree-dump.c (dequeue_and_dump): Likewise. + * tree-inline.c (copy_tree_r): Add code to duplicate a CONSTRUCTOR + node. + * tree-pretty-print.c (dump_generic_node): Update to cope with VEC in + CONSTRUCTOR_ELTS. + * tree-sra.c (generate_element_init_1): Likewise. + * tree-ssa-ccp.c (fold_const_aggregate_ref): Likewise. + * tree-ssa-operands.c (get_expr_operands): Likewise. + * tree-vect-generic.c (expand_vector_piecewise): Likewise. + * tree-vect-transform.c (vect_get_vec_def_for_operand): + (get_initial_def_for_reduction): Likewise. + * tree-vn.c (set_value_handle, get_value_handle): CONSTURCTOR uses + value handle in annotations. + * tree.c (tree_node_kind, tree_code_size, make_node_stat, + tree_node_structure): Add support for constr_kind. + (build_vector_from_ctor, build_constructor_single, + build_constructor_from_list): New functions. + (build_constructor): Update to take a VEC instead of a TREE_LIST. + (simple_cst_equal, iterative_hash_expr, initializer_zerop, walk_tree): + Update to cope with VEC in CONSTRUCTOR_ELTS. + * tree.def (CONSTRUCTOR): Make it a tcc_exceptional node. + * tree.h (FOR_EACH_CONSTRUCTOR_VALUE, FOR_EACH_CONSTRUCTOR_ELT, + CONSTRUCTOR_APPEND_ELT): New macros. + (struct constructor_elt, struct tree_constructor): New data types. + (union tree_node): Add tree_constructor field. + * treestruct.def: Define TS_CONSTRUCTOR. + * varasm.c (const_hash_1, compare_constant, copy_constant, + compute_reloc_for_constant, output_addressed_constants, + initializer_constant_valid_p, output_constant, + array_size_for_constructor, output_constructor): Update to cope with + VEC in CONSTRUCTOR_ELTS. + * vec.h (VEC_empty, VEC_copy): New macros. + 2005-07-19 Devang Patel <dpatel@apple.com> * dbxout.c (dbxout_type): Check Objective-C++ lang. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 48c60073c3d..47e24b140c0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2005-07-20 Giovanni Bajo <giovannibajo@libero.it> + + Make CONSTRUCTOR use VEC to store initializers. + * decl.c (gnat_to_gnu_entity): Update to cope with VEC in + CONSTRUCTOR_ELTS. + * trans.c (extract_values): Likewise. + * utils.c (convert, remove_conversions): Likewise. + * utils2.c (contains_save_expr_p, build_binary_op, build_unary_op, + gnat_build_constructor): Likewise. + 2005-07-09 Andrew Pinski <pinskia@physics.uc.edu> * decl.c (components_to_record): Use DECL_FCONTEXT instead of diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c index f21a6990444..145ece8ae8e 100644 --- a/gcc/ada/decl.c +++ b/gcc/ada/decl.c @@ -940,16 +940,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_alloc_type = TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_alloc_type))); - if (TREE_CODE (gnu_expr) == CONSTRUCTOR - && - TREE_CHAIN (CONSTRUCTOR_ELTS (gnu_expr)) == NULL_TREE) - gnu_expr = 0; - else - gnu_expr - = build_component_ref - (gnu_expr, NULL_TREE, - TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr))), - false); + if (TREE_CODE (gnu_expr) == CONSTRUCTOR + && VEC_length (constructor_elt, + CONSTRUCTOR_ELTS (gnu_expr)) == 1) + gnu_expr = 0; + else + gnu_expr + = build_component_ref + (gnu_expr, NULL_TREE, + TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr))), + false); } if (TREE_CODE (TYPE_SIZE_UNIT (gnu_alloc_type)) == INTEGER_CST diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index 3a3327ab63f..961425224e8 100644 --- a/gcc/ada/trans.c +++ b/gcc/ada/trans.c @@ -5625,7 +5625,8 @@ extract_values (tree values, tree record_type) else if (DECL_INTERNAL_P (field)) { value = extract_values (values, TREE_TYPE (field)); - if (TREE_CODE (value) == CONSTRUCTOR && !CONSTRUCTOR_ELTS (value)) + if (TREE_CODE (value) == CONSTRUCTOR + && VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (value))) value = 0; } else diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c index edd17067ab4..baec9ff82cb 100644 --- a/gcc/ada/utils.c +++ b/gcc/ada/utils.c @@ -2703,9 +2703,10 @@ convert (tree type, tree expr) /* If we have just converted to this padded type, just get the inner expression. */ if (TREE_CODE (expr) == CONSTRUCTOR - && CONSTRUCTOR_ELTS (expr) - && TREE_PURPOSE (CONSTRUCTOR_ELTS (expr)) == TYPE_FIELDS (etype)) - return TREE_VALUE (CONSTRUCTOR_ELTS (expr)); + && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (expr)) + && VEC_index (constructor_elt, CONSTRUCTOR_ELTS (expr), 0)->index + == TYPE_FIELDS (etype)) + return VEC_index (constructor_elt, CONSTRUCTOR_ELTS (expr), 0)->value; else return convert (type, build_component_ref (expr, NULL_TREE, @@ -3025,7 +3026,9 @@ remove_conversions (tree exp, bool true_address) if (true_address && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE && TYPE_JUSTIFIED_MODULAR_P (TREE_TYPE (exp))) - return remove_conversions (TREE_VALUE (CONSTRUCTOR_ELTS (exp)), true); + return remove_conversions (VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (exp), 0)->value, + true); break; case COMPONENT_REF: diff --git a/gcc/ada/utils2.c b/gcc/ada/utils2.c index 4b0369b76dc..5847910d2e6 100644 --- a/gcc/ada/utils2.c +++ b/gcc/ada/utils2.c @@ -263,13 +263,15 @@ contains_save_expr_p (tree exp) return contains_save_expr_p (TREE_OPERAND (exp, 0)); case CONSTRUCTOR: - return (CONSTRUCTOR_ELTS (exp) - && contains_save_expr_p (CONSTRUCTOR_ELTS (exp))); + { + tree value; + unsigned HOST_WIDE_INT ix; - case TREE_LIST: - return (contains_save_expr_p (TREE_VALUE (exp)) - || (TREE_CHAIN (exp) - && contains_save_expr_p (TREE_CHAIN (exp)))); + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), ix, value) + if (contains_save_expr_p (value)) + return true; + return false; + } default: return false; @@ -884,8 +886,9 @@ build_binary_op (enum tree_code op_code, tree result_type, just compare the data pointer. */ else if (TYPE_FAT_POINTER_P (left_base_type) && TREE_CODE (right_operand) == CONSTRUCTOR - && integer_zerop (TREE_VALUE - (CONSTRUCTOR_ELTS (right_operand)))) + && integer_zerop (VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (right_operand), + 0)->value)) { right_operand = build_component_ref (left_operand, NULL_TREE, TYPE_FIELDS (left_base_type), @@ -1138,9 +1141,11 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand) a pointer to our type. */ if (TREE_CODE (type) == RECORD_TYPE && TYPE_IS_PADDING_P (type)) { + result = VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (operand), + 0)->value; result - = build_unary_op (ADDR_EXPR, NULL_TREE, - TREE_VALUE (CONSTRUCTOR_ELTS (operand))); + = build_unary_op (ADDR_EXPR, NULL_TREE, result); result = convert (build_pointer_type (TREE_TYPE (operand)), result); break; @@ -1501,7 +1506,7 @@ gnat_build_constructor (tree type, tree list) } } - result = build_constructor (type, list); + result = build_constructor_from_list (type, list); TREE_CONSTANT (result) = TREE_INVARIANT (result) = TREE_STATIC (result) = allconstant; TREE_SIDE_EFFECTS (result) = side_effects; diff --git a/gcc/c-common.c b/gcc/c-common.c index 90a373cfa66..3c341d87b0c 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -5938,9 +5938,9 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) } else if (TREE_CODE (initial_value) == CONSTRUCTOR) { - tree elts = CONSTRUCTOR_ELTS (initial_value); + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value); - if (elts == NULL) + if (VEC_empty (constructor_elt, v)) { if (pedantic) failure = 3; @@ -5949,15 +5949,21 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) else { tree curindex; + unsigned HOST_WIDE_INT cnt; + constructor_elt *ce; - if (TREE_PURPOSE (elts)) - maxindex = fold_convert (sizetype, TREE_PURPOSE (elts)); + if (VEC_index (constructor_elt, v, 0)->index) + maxindex = fold_convert (sizetype, + VEC_index (constructor_elt, + v, 0)->index); curindex = maxindex; - for (elts = TREE_CHAIN (elts); elts; elts = TREE_CHAIN (elts)) + for (cnt = 1; + VEC_iterate (constructor_elt, v, cnt, ce); + cnt++) { - if (TREE_PURPOSE (elts)) - curindex = fold_convert (sizetype, TREE_PURPOSE (elts)); + if (ce->index) + curindex = fold_convert (sizetype, ce->index); else curindex = size_binop (PLUS_EXPR, curindex, size_one_node); diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index 6276923e794..bbc19be9fd4 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -1137,14 +1137,14 @@ pp_c_initializer_list (c_pretty_printer *pp, tree e) if (TREE_CODE (e) == VECTOR_CST) pp_c_expression_list (pp, TREE_VECTOR_CST_ELTS (e)); else if (TREE_CODE (e) == CONSTRUCTOR) - pp_c_expression_list (pp, CONSTRUCTOR_ELTS (e)); + pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e)); else break; return; case COMPLEX_TYPE: if (TREE_CODE (e) == CONSTRUCTOR) - pp_c_expression_list (pp, CONSTRUCTOR_ELTS (e)); + pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e)); else if (TREE_CODE (e) == COMPLEX_CST || TREE_CODE (e) == COMPLEX_EXPR) { const bool cst = TREE_CODE (e) == COMPLEX_CST; @@ -1369,6 +1369,22 @@ pp_c_expression_list (c_pretty_printer *pp, tree e) } } +/* Print out V, which contains the elements of a constructor. */ + +void +pp_c_constructor_elts (c_pretty_printer *pp, VEC(constructor_elt,gc) *v) +{ + unsigned HOST_WIDE_INT ix; + tree value; + + FOR_EACH_CONSTRUCTOR_VALUE (v, ix, value) + { + pp_expression (pp, value); + if (ix != VEC_length (constructor_elt, v) - 1) + pp_separate_with (pp, ','); + } +} + /* Print out an expression-list in parens, as in a function call. */ void diff --git a/gcc/c-pretty-print.h b/gcc/c-pretty-print.h index 1291203d197..0f9d46a86e7 100644 --- a/gcc/c-pretty-print.h +++ b/gcc/c-pretty-print.h @@ -192,6 +192,7 @@ void pp_c_statement (c_pretty_printer *, tree); void pp_c_expression (c_pretty_printer *, tree); void pp_c_logical_or_expression (c_pretty_printer *, tree); void pp_c_expression_list (c_pretty_printer *, tree); +void pp_c_constructor_elts (c_pretty_printer *, VEC(constructor_elt,gc) *); void pp_c_call_argument_list (c_pretty_printer *, tree); void pp_c_unary_expression (c_pretty_printer *, tree); void pp_c_cast_expression (c_pretty_printer *, tree); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 928084f4397..d9c994983ae 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2061,8 +2061,7 @@ build_function_call (tree function, tree params) if (AGGREGATE_TYPE_P (return_type)) rhs = build_compound_literal (return_type, - build_constructor (return_type, - NULL_TREE)); + build_constructor (return_type, 0)); else rhs = fold_build1 (NOP_EXPR, return_type, integer_zero_node); @@ -3210,8 +3209,7 @@ build_c_cast (tree type, tree expr) if (pedantic) pedwarn ("ISO C forbids casts to union type"); t = digest_init (type, - build_constructor (type, - build_tree_list (field, value)), + build_constructor_single (type, field, value), true, 0); TREE_CONSTANT (t) = TREE_CONSTANT (value); TREE_INVARIANT (t) = TREE_INVARIANT (value); @@ -4397,18 +4395,22 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) if (TREE_CODE (inside_init) == CONSTRUCTOR) { - tree link; + unsigned HOST_WIDE_INT ix; + tree value; + bool constant_p = true; /* Iterate through elements and check if all constructor elements are *_CSTs. */ - for (link = CONSTRUCTOR_ELTS (inside_init); - link; - link = TREE_CHAIN (link)) - if (! CONSTANT_CLASS_P (TREE_VALUE (link))) - break; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value) + if (!CONSTANT_CLASS_P (value)) + { + constant_p = false; + break; + } - if (link == NULL) - return build_vector (type, CONSTRUCTOR_ELTS (inside_init)); + if (constant_p) + return build_vector_from_ctor (type, + CONSTRUCTOR_ELTS (inside_init)); } } @@ -4574,7 +4576,7 @@ static tree constructor_bit_index; /* If we are saving up the elements rather than allocating them, this is the list of elements so far (in reverse order, most recent first). */ -static tree constructor_elements; +static VEC(constructor_elt,gc) *constructor_elements; /* 1 if constructor should be incrementally stored into a constructor chain, 0 if all the elements should be kept in AVL tree. */ @@ -4645,7 +4647,7 @@ struct constructor_stack tree unfilled_index; tree unfilled_fields; tree bit_index; - tree elements; + VEC(constructor_elt,gc) *elements; struct init_node *pending_elts; int offset; int depth; @@ -4689,7 +4691,7 @@ struct initializer_stack tree decl; struct constructor_stack *constructor_stack; struct constructor_range_stack *constructor_range_stack; - tree elements; + VEC(constructor_elt,gc) *elements; struct spelling *spelling; struct spelling *spelling_base; int spelling_size; @@ -5024,7 +5026,7 @@ push_init_level (int implicit) constructor_constant = TREE_CONSTANT (value); constructor_simple = TREE_STATIC (value); constructor_elements = CONSTRUCTOR_ELTS (value); - if (constructor_elements + if (!VEC_empty (constructor_elt, constructor_elements) && (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == ARRAY_TYPE)) set_nonincremental_init (); @@ -5199,19 +5201,19 @@ pop_init_level (int implicit) { /* A nonincremental scalar initializer--just return the element, after verifying there is just one. */ - if (constructor_elements == 0) + if (VEC_empty (constructor_elt,constructor_elements)) { if (!constructor_erroneous) error_init ("empty scalar initializer"); ret.value = error_mark_node; } - else if (TREE_CHAIN (constructor_elements) != 0) + else if (VEC_length (constructor_elt,constructor_elements) != 1) { error_init ("extra elements in scalar initializer"); - ret.value = TREE_VALUE (constructor_elements); + ret.value = VEC_index (constructor_elt,constructor_elements,0)->value; } else - ret.value = TREE_VALUE (constructor_elements); + ret.value = VEC_index (constructor_elt,constructor_elements,0)->value; } else { @@ -5220,7 +5222,7 @@ pop_init_level (int implicit) else { ret.value = build_constructor (constructor_type, - nreverse (constructor_elements)); + constructor_elements); if (constructor_constant) TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1; if (constructor_constant && constructor_simple) @@ -5669,14 +5671,15 @@ add_pending_init (tree purpose, tree value) static void set_nonincremental_init (void) { - tree chain; + unsigned HOST_WIDE_INT ix; + tree index, value; if (TREE_CODE (constructor_type) != RECORD_TYPE && TREE_CODE (constructor_type) != ARRAY_TYPE) return; - for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain)) - add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain)); + FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value) + add_pending_init (index, value); constructor_elements = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE) { @@ -5828,9 +5831,10 @@ find_init_member (tree field) } else if (TREE_CODE (constructor_type) == UNION_TYPE) { - if (constructor_elements - && TREE_PURPOSE (constructor_elements) == field) - return TREE_VALUE (constructor_elements); + if (!VEC_empty (constructor_elt, constructor_elements) + && (VEC_last (constructor_elt, constructor_elements)->index + == field)) + return VEC_last (constructor_elt, constructor_elements)->value; } return 0; } @@ -5852,6 +5856,8 @@ static void output_init_element (tree value, bool strict_string, tree type, tree field, int pending) { + constructor_elt *celt; + if (type == error_mark_node || value == error_mark_node) { constructor_erroneous = 1; @@ -5956,9 +5962,10 @@ output_init_element (tree value, bool strict_string, tree type, tree field, return; } else if (TREE_CODE (constructor_type) == UNION_TYPE - && constructor_elements) + && !VEC_empty (constructor_elt, constructor_elements)) { - if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements))) + if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt, + constructor_elements)->value)) warning_init ("initialized field with side-effects overwritten"); /* We can have just one union field set. */ @@ -5970,8 +5977,9 @@ output_init_element (tree value, bool strict_string, tree type, tree field, if (field && TREE_CODE (field) == INTEGER_CST) field = copy_node (field); - constructor_elements - = tree_cons (field, value, constructor_elements); + celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL); + celt->index = field; + celt->value = value; /* Advance the variable that indicates sequential elements output. */ if (TREE_CODE (constructor_type) == ARRAY_TYPE) diff --git a/gcc/coverage.c b/gcc/coverage.c index b1e2e5121b2..5c1d0922aa5 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -672,10 +672,13 @@ build_fn_info_value (const struct function_list *function, tree type) array_value = tree_cons (NULL_TREE, counters, array_value); } - array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value)); + /* FIXME: use build_constructor directly. */ + array_value = build_constructor_from_list (TREE_TYPE (fields), + nreverse (array_value)); value = tree_cons (fields, array_value, value); - value = build_constructor (type, nreverse (value)); + /* FIXME: use build_constructor directly. */ + value = build_constructor_from_list (type, nreverse (value)); return value; } @@ -768,7 +771,8 @@ build_ctr_info_value (unsigned int counter, tree type) build1 (ADDR_EXPR, TREE_TYPE (fields), fn), value); - value = build_constructor (type, nreverse (value)); + /* FIXME: use build_constructor directly. */ + value = build_constructor_from_list (type, nreverse (value)); return value; } @@ -856,7 +860,9 @@ build_gcov_info (void) array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1)); array_type = build_array_type (fn_info_type, array_type); - fn_info_value = build_constructor (array_type, nreverse (fn_info_value)); + /* FIXME: use build_constructor directly. */ + fn_info_value = build_constructor_from_list (array_type, + nreverse (fn_info_value)); fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value); } else @@ -894,8 +900,9 @@ build_gcov_info (void) ctr_info_value = tree_cons (NULL_TREE, build_ctr_info_value (ix, ctr_info_type), ctr_info_value); - ctr_info_value = build_constructor (ctr_info_ary_type, - nreverse (ctr_info_value)); + /* FIXME: use build_constructor directly. */ + ctr_info_value = build_constructor_from_list (ctr_info_ary_type, + nreverse (ctr_info_value)); field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type); TREE_CHAIN (field) = fields; @@ -904,7 +911,8 @@ build_gcov_info (void) finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE); - value = build_constructor (type, nreverse (value)); + /* FIXME: use build_constructor directly. */ + value = build_constructor_from_list (type, nreverse (value)); return value; } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b30aabc1f9a..0704146cfff 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,54 @@ +2005-07-20 Giovanni Bajo <giovannibajo@libero.it> + + Make CONSTRUCTOR use VEC to store initializers. + * call.c (convert_default_arg): Update call to digest_init. + * class.c (dump_class_hierarchy, dump_array): Update to cope with + VEC in CONSTRUCTOR_ELTS. + * cp-tree.h (EMPTY_CONSTRUCTOR_P): Likewise. + (finish_compound_literal, digest_init): Update declaration. + * decl.c (struct reshape_iter): New data type. + (reshape_init_array): Rename to... + (reshape_init_array_1): Update to cope with VEC in CONSTRUCTOR_ELTS. + (reshape_init): Rewrite from scratch. Split parts into... + (reshape_init_array, reshape_init_vector, reshape_init_class, + reshape_init_r): New functions. + (check_initializer): Update call to reshape_init. Remove obsolete + code. + (initialize_artificial_var, cp_complete_array_type): Update to cope + with VEC in CONSTRUCTOR_ELTS. + * decl2.c (grokfield): Update calls to digest_init. + (mark_vtable_entries): Update to cope with VEC in CONSTRUCTOR_ELTS. + * error.c (dump_expr_init_vec): New function. + (dump_expr): Use dump_expr_init_vec. + * init.c (build_zero_init, build_vec_init): Update to cope with VEC + in CONSTRUCTOR_ELTS. + (expand_default_init): Update call to digest_init. + * parser.c (cp_parser_postfix_expression): Use a VEC for the + initializers. + (cp_parser_initializer_list): Build a VEC of initializers. + * pt.c (tsubst_copy, tsubst_copy_and_build): Update to cope with VEC + in CONSTRUCTOR_ELTS. + * rtti.c (tinfo_base_init, generic_initializer, ptr_initializer, + ptm_initializer, class_initializer, get_pseudo_ti_init): Use + build_constructor_from_list instead of build_constructor. + * semantics.c (finish_compound_literal): Update call to digest_init. + * tree.c (stabilize_init): Update to cope with VEC in + CONSTRUCTOR_ELTS. + * typeck.c (build_ptrmemfunc1): Likewise. + * typeck2.c: (cxx_incomplete_type_error, split_nonconstant_init_1): + Likewise. + (store_init_value): Use build_constructor_from_list and update call + to digest_init. + (digest_init): Rewrite. + (process_init_constructor): Rewrite from scratch. Split into... + (process_init_constructor_array, picflag_from_initializer, + process_init_constructor_record, process_init_constructor_union): + New functions. + (PICFLAG_ERRONEOUS, PICFLAG_NOT_ALL_CONSTANT, PICFLAG_NOT_ALL_SIMPLE): + New macros. + (build_functional_cast): Use build_constructor_from_list instead of + build_constructor. + 2005-07-18 Mark Mitchell <mark@codesourcery.com> PR c++/22263 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 21201cf7f0a..6e887088401 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4544,7 +4544,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum) if (TREE_CODE (arg) == CONSTRUCTOR) { - arg = digest_init (type, arg, 0); + arg = digest_init (type, arg); arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, "default argument", fn, parmnum); } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 5dbec4602a4..9b85a4df2e9 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6437,8 +6437,8 @@ dump_class_hierarchy (tree t) static void dump_array (FILE * stream, tree decl) { - tree inits; - int ix; + tree value; + unsigned HOST_WIDE_INT ix; HOST_WIDE_INT elt; tree size = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (decl))); @@ -6450,10 +6450,10 @@ dump_array (FILE * stream, tree decl) TFF_PLAIN_IDENTIFIER)); fprintf (stream, "\n"); - for (ix = 0, inits = CONSTRUCTOR_ELTS (DECL_INITIAL (decl)); - inits; ix++, inits = TREE_CHAIN (inits)) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)), + ix, value) fprintf (stream, "%-4ld %s\n", (long)(ix * elt), - expr_as_string (TREE_VALUE (inits), TFF_PLAIN_IDENTIFIER)); + expr_as_string (value, TFF_PLAIN_IDENTIFIER)); } static void diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d9d053d6dfb..0ac7bbab433 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2417,9 +2417,10 @@ extern void decl_shadowed_for_var_insert (tree, tree); #define BRACE_ENCLOSED_INITIALIZER_P(NODE) \ (TREE_CODE (NODE) == CONSTRUCTOR && !TREE_TYPE (NODE)) -#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ - && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \ - && ! TREE_HAS_CONSTRUCTOR (NODE)) +#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ + && VEC_empty (constructor_elt, \ + CONSTRUCTOR_ELTS (NODE)) \ + && !TREE_HAS_CONSTRUCTOR (NODE)) /* Nonzero means that an object of this type can not be initialized using an initializer list. */ @@ -4168,7 +4169,7 @@ extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree); extern tree finish_unary_op_expr (enum tree_code, tree); -extern tree finish_compound_literal (tree, tree); +extern tree finish_compound_literal (tree, VEC(constructor_elt,gc) *); extern tree finish_fname (tree); extern void finish_translation_unit (void); extern tree finish_template_type_parm (tree, tree); @@ -4348,7 +4349,7 @@ extern void complete_type_check_abstract (tree); extern int abstract_virtuals_error (tree, tree); extern tree store_init_value (tree, tree); -extern tree digest_init (tree, tree, tree *); +extern tree digest_init (tree, tree); extern tree build_scoped_ref (tree, tree, tree *); extern tree build_x_arrow (tree); extern tree build_m_component_ref (tree, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 855906a0188..ddcab2e0fed 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -114,7 +114,7 @@ static void store_parm_decls (tree); static void initialize_local_var (tree, tree); static void expand_static_init (tree, tree); static tree next_initializable_field (tree); -static tree reshape_init (tree, tree *); +static tree reshape_init (tree, tree); /* Erroneous argument lists can use this *IFF* they do not modify it. */ tree error_mark_list; @@ -4103,6 +4103,18 @@ check_for_uninitialized_const_var (tree decl) error ("uninitialized const %qD", decl); } + +/* Structure holding the current initializer being processed by reshape_init. + CUR is a pointer to the current element being processed, END is a pointer + after the last element present in the initializer. */ +typedef struct reshape_iterator_t +{ + constructor_elt *cur; + constructor_elt *end; +} reshape_iter; + +static tree reshape_init_r (tree, reshape_iter *, bool); + /* FIELD is a FIELD_DECL or NULL. In the former case, the value returned is the next FIELD_DECL (possibly FIELD itself) that can be initialized. If there are no more such fields, the return value @@ -4120,22 +4132,23 @@ next_initializable_field (tree field) return field; } -/* Subroutine of reshape_init. Reshape the constructor for an array. INITP - is the pointer to the old constructor list (to the CONSTRUCTOR_ELTS of - the CONSTRUCTOR we are processing), while NEW_INIT is the CONSTRUCTOR we - are building. - ELT_TYPE is the element type of the array. MAX_INDEX is an INTEGER_CST - representing the size of the array minus one (the maximum index), or - NULL_TREE if the array was declared without specifying the size. */ +/* Subroutine of reshape_init_array and reshape_init_vector, which does + the actual work. ELT_TYPE is the element type of the array. MAX_INDEX is an + INTEGER_CST representing the size of the array minus one (the maximum index), + or NULL_TREE if the array was declared without specifying the size. D is + the iterator within the constructor. */ -static bool -reshape_init_array (tree elt_type, tree max_index, - tree *initp, tree new_init) +static tree +reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d) { + tree new_init; bool sized_array_p = (max_index != NULL_TREE); unsigned HOST_WIDE_INT max_index_cst = 0; unsigned HOST_WIDE_INT index; + /* The initializer for an array is always a CONSTRUCTOR. */ + new_init = build_constructor (NULL_TREE, NULL); + if (sized_array_p) { if (host_integerp (max_index, 1)) @@ -4148,104 +4161,181 @@ reshape_init_array (tree elt_type, tree max_index, /* Loop until there are no more initializers. */ for (index = 0; - *initp && (!sized_array_p || index <= max_index_cst); + d->cur != d->end && (!sized_array_p || index <= max_index_cst); ++index) { - tree element_init; - tree designated_index; + tree elt_init; - element_init = reshape_init (elt_type, initp); - if (element_init == error_mark_node) - return false; - TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init); - CONSTRUCTOR_ELTS (new_init) = element_init; - designated_index = TREE_PURPOSE (element_init); - if (designated_index) + if (d->cur->index) { /* Handle array designated initializers (GNU extension). */ - if (TREE_CODE (designated_index) == IDENTIFIER_NODE) + if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE) { error ("name %qD used in a GNU-style designated " - "initializer for an array", designated_index); - TREE_PURPOSE (element_init) = NULL_TREE; + "initializer for an array", d->cur->index); } else gcc_unreachable (); } + + elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false); + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), NULL_TREE, elt_init); } - return true; + return new_init; } -/* Undo the brace-elision allowed by [dcl.init.aggr] in a - brace-enclosed aggregate initializer. +/* Subroutine of reshape_init_r, processes the initializers for arrays. + Parameters are the same of reshape_init_r. */ - *INITP is one of a list of initializers describing a brace-enclosed - initializer for an entity of the indicated aggregate TYPE. It may - not presently match the shape of the TYPE; for example: +static tree +reshape_init_array (tree type, reshape_iter *d) +{ + tree max_index = NULL_TREE; - struct S { int a; int b; }; - struct S a[] = { 1, 2, 3, 4 }; + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); - Here *INITP will point to TREE_LIST of four elements, rather than a - list of two elements, each itself a list of two elements. This - routine transforms INIT from the former form into the latter. The - revised initializer is returned. */ + if (TYPE_DOMAIN (type)) + max_index = array_type_nelts (type); + + return reshape_init_array_1 (TREE_TYPE (type), max_index, d); +} + +/* Subroutine of reshape_init_r, processes the initializers for vectors. + Parameters are the same of reshape_init_r. */ + +static tree +reshape_init_vector (tree type, reshape_iter *d) +{ + tree max_index = NULL_TREE; + tree rtype; + + gcc_assert (TREE_CODE (type) == VECTOR_TYPE); + + if (TREE_CODE (d->cur->value) == CONSTRUCTOR + && TREE_HAS_CONSTRUCTOR (d->cur->value)) + { + tree value = d->cur->value; + if (!same_type_p (TREE_TYPE (value), type)) + { + error ("invalid type %qT as initializer for a vector of type %qT", + TREE_TYPE (d->cur->value), type); + value = error_mark_node; + } + ++d->cur; + return value; + } + + /* For a vector, the representation type is a struct + containing a single member which is an array of the + appropriate size. */ + rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type); + if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype)))) + max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS (rtype))); + + return reshape_init_array_1 (TREE_TYPE (type), max_index, d); +} + +/* Subroutine of reshape_init_r, processes the initializers for classes + or union. Parameters are the same of reshape_init_r. */ static tree -reshape_init (tree type, tree *initp) +reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p) { - tree inits; - tree old_init; - tree old_init_value; + tree field; tree new_init; - bool brace_enclosed_p; - bool string_init_p; - old_init = *initp; - old_init_value = (TREE_CODE (*initp) == TREE_LIST - ? TREE_VALUE (*initp) : old_init); + gcc_assert (CLASS_TYPE_P (type)); - gcc_assert (old_init_value); + /* The initializer for a class is always a CONSTRUCTOR. */ + new_init = build_constructor (NULL_TREE, NULL); + field = next_initializable_field (TYPE_FIELDS (type)); - /* If the initializer is brace-enclosed, pull initializers from the - enclosed elements. Advance past the brace-enclosed initializer - now. */ - if (TREE_CODE (old_init_value) == CONSTRUCTOR - && BRACE_ENCLOSED_INITIALIZER_P (old_init_value)) + if (!field) { - *initp = TREE_CHAIN (old_init); - TREE_CHAIN (old_init) = NULL_TREE; - inits = CONSTRUCTOR_ELTS (old_init_value); - initp = &inits; - brace_enclosed_p = true; + /* [dcl.init.aggr] + + An initializer for an aggregate member that is an + empty class shall have the form of an empty + initializer-list {}. */ + if (!first_initializer_p) + { + error ("initializer for %qT must be brace-enclosed", type); + return error_mark_node; + } + return new_init; } - else + + /* Loop through the initializable fields, gathering initializers. */ + while (d->cur != d->end) { - inits = NULL_TREE; - brace_enclosed_p = false; + tree field_init; + + /* Handle designated initializers, as an extension. */ + if (d->cur->index) + { + if (pedantic) + pedwarn ("ISO C++ does not allow designated initializers"); + + field = lookup_field_1 (type, d->cur->index, /*want_type=*/false); + + if (!field || TREE_CODE (field) != FIELD_DECL) + error ("%qT has no non-static data member named %qD", type, + d->cur->index); + } + + /* If we processed all the member of the class, we are done. */ + if (!field) + break; + + field_init = reshape_init_r (TREE_TYPE (field), d, + /*first_initializer_p=*/false); + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), field, field_init); + + /* [dcl.init.aggr] + + When a union is initialized with a brace-enclosed + initializer, the braces shall only contain an + initializer for the first member of the union. */ + if (TREE_CODE (type) == UNION_TYPE) + break; + + field = next_initializable_field (TREE_CHAIN (field)); } + return new_init; +} + +/* Subroutine of reshape_init, which processes a single initializer (part of + a CONSTRUCTOR). TYPE is the type of the variable being initialized, D is the + iterator within the CONSTRUCTOR which points to the initializer to process. + FIRST_INITIALIZER_P is true if this is the first initializer of the + CONSTRUCTOR node. */ + +static tree +reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) +{ + tree init = d->cur->value; + /* A non-aggregate type is always initialized with a single initializer. */ if (!CP_AGGREGATE_TYPE_P (type)) - { - *initp = TREE_CHAIN (old_init); - TREE_CHAIN (old_init) = NULL_TREE; - /* It is invalid to initialize a non-aggregate type with a - brace-enclosed initializer. */ - if (brace_enclosed_p) - { - error ("brace-enclosed initializer used to initialize %qT", - type); - if (TREE_CODE (old_init) == TREE_LIST) - TREE_VALUE (old_init) = error_mark_node; - else - old_init = error_mark_node; - } - - return old_init; - } + { + /* It is invalid to initialize a non-aggregate type with a + brace-enclosed initializer. + We need to check for BRACE_ENCLOSED_INITIALIZER_P here because + of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is + a CONSTRUCTOR (with a record type). */ + if (TREE_CODE (init) == CONSTRUCTOR + && BRACE_ENCLOSED_INITIALIZER_P (init)) /* p7626.C */ + { + error ("braces around scalar initializer for type %qT", type); + init = error_mark_node; + } + + d->cur++; + return init; + } /* [dcl.init.aggr] @@ -4256,139 +4346,124 @@ reshape_init (tree type, tree *initp) non-empty subaggregate, brace elision is assumed and the initializer is considered for the initialization of the first member of the subaggregate. */ - if (!brace_enclosed_p - && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value)) + if (TREE_CODE (init) != CONSTRUCTOR + && can_convert_arg (type, TREE_TYPE (init), init)) { - *initp = TREE_CHAIN (old_init); - TREE_CHAIN (old_init) = NULL_TREE; - return old_init; + d->cur++; + return init; } - string_init_p = false; - if (TREE_CODE (old_init_value) == STRING_CST - && TREE_CODE (type) == ARRAY_TYPE + /* [dcl.init.string] + + A char array (whether plain char, signed char, or unsigned char) + can be initialized by a string-literal (optionally enclosed in + braces); a wchar_t array can be initialized by a wide + string-literal (optionally enclosed in braces). */ + if (TREE_CODE (type) == ARRAY_TYPE && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))) { - /* [dcl.init.string] + tree str_init = init; - A char array (whether plain char, signed char, or unsigned char) - can be initialized by a string-literal (optionally enclosed in - braces); a wchar_t array can be initialized by a wide - string-literal (optionally enclosed in braces). */ - new_init = old_init; - /* Move past the initializer. */ - *initp = TREE_CHAIN (old_init); - TREE_CHAIN (old_init) = NULL_TREE; - string_init_p = true; + /* Strip one level of braces if and only if they enclose a single + element (as allowed by [dcl.init.string]). */ + if (!first_initializer_p + && TREE_CODE (str_init) == CONSTRUCTOR + && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (str_init)) == 1) + { + str_init = VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (str_init), 0)->value; + } + + /* If it's a string literal, then it's the initializer for the array + as a whole. Otherwise, continue with normal initialization for + array types (one value per array element). */ + if (TREE_CODE (str_init) == STRING_CST) + { + d->cur++; + return str_init; + } } - else - { - /* Build a CONSTRUCTOR to hold the contents of the aggregate. */ - new_init = build_constructor (NULL_TREE, NULL_TREE); - if (CLASS_TYPE_P (type)) + /* The following cases are about aggregates. If we are not within a full + initializer already, and there is not a CONSTRUCTOR, it means that there + is a missing set of braces (that is, we are processing the case for + which reshape_init exists). */ + if (!first_initializer_p) + { + if (TREE_CODE (init) == CONSTRUCTOR) { - tree field; - - field = next_initializable_field (TYPE_FIELDS (type)); - - if (!field) + /* For a nested compound literal, there is no need to reshape since + brace elision is not allowed. Even if we decided to allow it, + we should add a call to reshape_init in finish_compound_literal, + before calling digest_init, so changing this code would still + not be necessary. */ + if (!TREE_HAS_CONSTRUCTOR (init)) { - /* [dcl.init.aggr] - - An initializer for an aggregate member that is an - empty class shall have the form of an empty - initializer-list {}. */ - if (!brace_enclosed_p) - { - error ("initializer for %qT must be brace-enclosed", type); - return error_mark_node; - } + ++d->cur; + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); + return reshape_init (type, init); } else - { - /* Loop through the initializable fields, gathering - initializers. */ - while (*initp) - { - tree field_init; + gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init)); + } - /* Handle designated initializers, as an extension. */ - if (TREE_PURPOSE (*initp)) - { - if (pedantic) - pedwarn ("ISO C++ does not allow designated initializers"); - field = lookup_field_1 (type, TREE_PURPOSE (*initp), - /*want_type=*/false); - if (!field || TREE_CODE (field) != FIELD_DECL) - error ("%qT has no non-static data member named %qD", - type, TREE_PURPOSE (*initp)); - } - if (!field) - break; + warning (OPT_Wmissing_braces, "missing braces around initializer for %qT", + type); + } - field_init = reshape_init (TREE_TYPE (field), initp); - if (field_init == error_mark_node) - return error_mark_node; - TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init); - CONSTRUCTOR_ELTS (new_init) = field_init; - /* [dcl.init.aggr] - - When a union is initialized with a brace-enclosed - initializer, the braces shall only contain an - initializer for the first member of the union. */ - if (TREE_CODE (type) == UNION_TYPE) - break; - field = next_initializable_field (TREE_CHAIN (field)); - } - } - } - else if (TREE_CODE (type) == ARRAY_TYPE - || TREE_CODE (type) == VECTOR_TYPE) - { - /* If the bound of the array is known, take no more initializers - than are allowed. */ - tree max_index = NULL_TREE; - if (TREE_CODE (type) == ARRAY_TYPE) - { - if (TYPE_DOMAIN (type)) - max_index = array_type_nelts (type); - } - else - { - /* For a vector, the representation type is a struct - containing a single member which is an array of the - appropriate size. */ - tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type); - if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype)))) - max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS - (rtype))); - } + /* Dispatch to specialized routines. */ + if (CLASS_TYPE_P (type)) + return reshape_init_class (type, d, first_initializer_p); + else if (TREE_CODE (type) == ARRAY_TYPE) + return reshape_init_array (type, d); + else if (TREE_CODE (type) == VECTOR_TYPE) + return reshape_init_vector (type, d); + else + gcc_unreachable(); +} - if (!reshape_init_array (TREE_TYPE (type), max_index, - initp, new_init)) - return error_mark_node; - } - else - gcc_unreachable (); +/* Undo the brace-elision allowed by [dcl.init.aggr] in a + brace-enclosed aggregate initializer. - /* The initializers were placed in reverse order in the - CONSTRUCTOR. */ - CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init)); + INIT is the CONSTRUCTOR containing the list of initializers describing + a brace-enclosed initializer for an entity of the indicated aggregate TYPE. + It may not presently match the shape of the TYPE; for example: - if (TREE_CODE (old_init) == TREE_LIST) - new_init = build_tree_list (TREE_PURPOSE (old_init), new_init); - } + struct S { int a; int b; }; + struct S a[] = { 1, 2, 3, 4 }; - /* If there are more initializers than necessary, issue a - diagnostic. */ - if (*initp) - { - if (brace_enclosed_p) - error ("too many initializers for %qT", type); - else if (warn_missing_braces && !string_init_p) - warning (0, "missing braces around initializer"); - } + Here INIT will hold a VEC of four elements, rather than a + VEC of two elements, each itself a VEC of two elements. This + routine transforms INIT from the former form into the latter. The + revised CONSTRUCTOR node is returned. */ + +static tree +reshape_init (tree type, tree init) +{ + VEC(constructor_elt, gc) *v; + reshape_iter d; + tree new_init; + + gcc_assert (TREE_CODE (init) == CONSTRUCTOR); + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); + + v = CONSTRUCTOR_ELTS (init); + + /* An empty constructor does not need reshaping, and it is always a valid + initializer. */ + if (VEC_empty (constructor_elt, v)) + return init; + + /* Recurse on this CONSTRUCTOR. */ + d.cur = VEC_index (constructor_elt, v, 0); + d.end = d.cur + VEC_length (constructor_elt, v); + + new_init = reshape_init_r (type, &d, true); + + /* Make sure all the element of the constructor were used. Otherwise, + issue an error about exceeding initializers. */ + if (d.cur != d.end) + error ("too many initializers for %qT", type); return new_init; } @@ -4455,20 +4530,13 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) init = grok_reference_init (decl, type, init, cleanup); else if (init) { + /* Do not reshape constructors of vectors (they don't need to be + reshaped. */ if (TREE_CODE (init) == CONSTRUCTOR - && BRACE_ENCLOSED_INITIALIZER_P (init)) + && !TREE_HAS_CONSTRUCTOR (init) + && !TREE_TYPE (init)) /* ptrmemfunc */ { - /* [dcl.init] paragraph 13, - If T is a scalar type, then a declaration of the form - T x = { a }; - is equivalent to - T x = a; - - reshape_init will complain about the extra braces, - and doesn't do anything useful in the case where TYPE is - scalar, so just don't call it. */ - if (CP_AGGREGATE_TYPE_P (type)) - init = reshape_init (type, &init); + init = reshape_init (type, init); if ((*targetm.vector_opaque_p) (type)) { @@ -4486,9 +4554,9 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) { if (TREE_CODE (type) == ARRAY_TYPE) goto initialize_aggr; - else if (TREE_CODE (init) == CONSTRUCTOR - && BRACE_ENCLOSED_INITIALIZER_P (init)) + else if (TREE_CODE (init) == CONSTRUCTOR) { + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); if (TYPE_NON_AGGREGATE_CLASS (type)) { error ("%qD must be initialized by constructor, " @@ -4713,7 +4781,7 @@ initialize_local_var (tree decl, tree init) void initialize_artificial_var (tree decl, tree init) { - DECL_INITIAL (decl) = build_constructor (NULL_TREE, init); + DECL_INITIAL (decl) = build_constructor_from_list (NULL_TREE, init); DECL_INITIALIZED_P (decl) = 1; determine_visibility (decl); layout_var_decl (decl); @@ -5401,14 +5469,21 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default) if (initial_value) { /* An array of character type can be initialized from a - brace-enclosed string constant. */ + brace-enclosed string constant. + + FIXME: this code is duplicated from reshape_init. Probably + we should just call reshape_init here? */ if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype))) && TREE_CODE (initial_value) == CONSTRUCTOR - && CONSTRUCTOR_ELTS (initial_value) - && (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value))) - == STRING_CST) - && TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE) - initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)); + && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (initial_value))) + { + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value); + tree value = VEC_index (constructor_elt, v, 0)->value; + + if (TREE_CODE (value) == STRING_CST + && VEC_length (constructor_elt, v) == 1) + initial_value = value; + } } failure = complete_array_type (ptype, initial_value, do_default); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 5afcd896cc1..e7db5525961 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -903,37 +903,24 @@ grokfield (const cp_declarator *declarator, else if (pedantic && TREE_CODE (value) != VAR_DECL) /* Already complained in grokdeclarator. */ init = NULL_TREE; - else + else if (!processing_template_decl) { - /* We allow initializers to become parameters to base - initializers. */ - if (TREE_CODE (init) == TREE_LIST) - { - if (TREE_CHAIN (init) == NULL_TREE) - init = TREE_VALUE (init); - else - init = digest_init (TREE_TYPE (value), init, (tree *)0); - } + if (TREE_CODE (init) == CONSTRUCTOR) + init = digest_init (TREE_TYPE (value), init); + else + init = integral_constant_value (init); - if (!processing_template_decl) + if (init != error_mark_node && !TREE_CONSTANT (init)) { - if (TREE_CODE (init) == CONSTRUCTOR) - init = digest_init (TREE_TYPE (value), init, (tree *)0); - else - init = integral_constant_value (init); - - if (init != error_mark_node && ! TREE_CONSTANT (init)) + /* We can allow references to things that are effectively + static, since references are initialized with the + address. */ + if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE + || (TREE_STATIC (init) == 0 + && (!DECL_P (init) || DECL_EXTERNAL (init) == 0))) { - /* We can allow references to things that are effectively - static, since references are initialized with the - address. */ - if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE - || (TREE_STATIC (init) == 0 - && (!DECL_P (init) || DECL_EXTERNAL (init) == 0))) - { - error ("field initializer is not constant"); - init = error_mark_node; - } + error ("field initializer is not constant"); + init = error_mark_node; } } } @@ -1262,11 +1249,12 @@ coerce_delete_type (tree type) static void mark_vtable_entries (tree decl) { - tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl)); + tree fnaddr; + unsigned HOST_WIDE_INT idx; - for (; entries; entries = TREE_CHAIN (entries)) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)), + idx, fnaddr) { - tree fnaddr = TREE_VALUE (entries); tree fn; STRIP_NOPS (fnaddr); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 6d80fc6b290..9905e253aa1 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1266,6 +1266,23 @@ dump_expr_list (tree l, int flags) } } +/* Print out a vector of initializers (subr of dump_expr). */ + +static void +dump_expr_init_vec (VEC(constructor_elt,gc) *v, int flags) +{ + unsigned HOST_WIDE_INT idx; + tree value; + + FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) + { + dump_expr (value, flags | TFF_EXPR_IN_PARENS); + if (idx != VEC_length (constructor_elt, v) - 1) + pp_separate_with_comma (cxx_pp); + } +} + + /* Print out an expression E under control of FLAGS. */ static void @@ -1659,7 +1676,7 @@ dump_expr (tree t, int flags) } } } - if (TREE_TYPE (t) && !CONSTRUCTOR_ELTS (t)) + if (TREE_TYPE (t) && EMPTY_CONSTRUCTOR_P (t)) { dump_type (TREE_TYPE (t), 0); pp_cxx_left_paren (cxx_pp); @@ -1668,7 +1685,7 @@ dump_expr (tree t, int flags) else { pp_cxx_left_brace (cxx_pp); - dump_expr_list (CONSTRUCTOR_ELTS (t), flags); + dump_expr_init_vec (CONSTRUCTOR_ELTS (t), flags); pp_cxx_right_brace (cxx_pp); } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 05491c44a2d..9383e928fa5 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -184,12 +184,9 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) else if (CLASS_TYPE_P (type)) { tree field; - tree inits; + VEC(constructor_elt,gc) *v = NULL; - /* Build a constructor to contain the initializations. */ - init = build_constructor (type, NULL_TREE); /* Iterate over the fields, building initializations. */ - inits = NULL_TREE; for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { if (TREE_CODE (field) != FIELD_DECL) @@ -200,27 +197,27 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) over TYPE_FIELDs will result in correct initialization of all of the subobjects. */ if (static_storage_p && !zero_init_p (TREE_TYPE (field))) - inits = tree_cons (field, - build_zero_init (TREE_TYPE (field), - /*nelts=*/NULL_TREE, - static_storage_p), - inits); + { + tree value = build_zero_init (TREE_TYPE (field), + /*nelts=*/NULL_TREE, + static_storage_p); + CONSTRUCTOR_APPEND_ELT(v, field, value); + } /* For unions, only the first field is initialized. */ if (TREE_CODE (type) == UNION_TYPE) break; } - CONSTRUCTOR_ELTS (init) = nreverse (inits); + + /* Build a constructor to contain the initializations. */ + init = build_constructor (type, v); } else if (TREE_CODE (type) == ARRAY_TYPE) { tree max_index; - tree inits; + VEC(constructor_elt,gc) *v = NULL; - /* Build a constructor to contain the initializations. */ - init = build_constructor (type, NULL_TREE); /* Iterate over the array elements, building initializations. */ - inits = NULL_TREE; if (nelts) max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts), nelts, integer_one_node); @@ -232,21 +229,25 @@ build_zero_init (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)) { - tree elt_init = build_zero_init (TREE_TYPE (type), - /*nelts=*/NULL_TREE, - static_storage_p); - tree range; + 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)) - range = size_zero_node; + ce->index = size_zero_node; else - range = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index); + ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node, + max_index); - inits = tree_cons (range, elt_init, inits); + ce->value = build_zero_init (TREE_TYPE (type), + /*nelts=*/NULL_TREE, + static_storage_p); } - CONSTRUCTOR_ELTS (init) = nreverse (inits); + /* Build a constructor to contain the initializations. */ + init = build_constructor (type, v); } else gcc_assert (TREE_CODE (type) == REFERENCE_TYPE); @@ -1191,7 +1192,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags) { /* A brace-enclosed initializer for an aggregate. */ gcc_assert (CP_AGGREGATE_TYPE_P (type)); - init = digest_init (type, init, (tree *)NULL); + init = digest_init (type, init); } else init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); @@ -2417,7 +2418,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) && ((TREE_CODE (init) == CONSTRUCTOR /* Don't do this if the CONSTRUCTOR might contain something that might throw and require us to clean up. */ - && (CONSTRUCTOR_ELTS (init) == NULL_TREE + && (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init)) || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type))) || from_array)) { @@ -2485,13 +2486,12 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) { /* Do non-default initialization of non-POD arrays resulting from brace-enclosed initializers. */ - - tree elts; + unsigned HOST_WIDE_INT idx; + tree elt; from_array = 0; - for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts)) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt) { - tree elt = TREE_VALUE (elts); tree baseref = build1 (INDIRECT_REF, type, base); num_initialized_elts++; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bd39a674c86..082727e5901 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1546,7 +1546,7 @@ static tree cp_parser_initializer (cp_parser *, bool *, bool *); static tree cp_parser_initializer_clause (cp_parser *, bool *); -static tree cp_parser_initializer_list +static VEC(constructor_elt,gc) *cp_parser_initializer_list (cp_parser *, bool *); static bool cp_parser_ctor_initializer_opt_and_function_body @@ -4027,7 +4027,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) if (cp_parser_allow_gnu_extensions_p (parser) && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - tree initializer_list = NULL_TREE; + VEC(constructor_elt,gc) *initializer_list = NULL; bool saved_in_type_id_in_expr_p; cp_parser_parse_tentatively (parser); @@ -12298,7 +12298,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, returned is simply a representation for the expression. Otherwise, a CONSTRUCTOR is returned. The CONSTRUCTOR_ELTS will be - the elements of the initializer-list (or NULL_TREE, if the last + the elements of the initializer-list (or NULL, if the last production is used). The TREE_TYPE for the CONSTRUCTOR will be NULL_TREE. There is no way to detect whether or not the optional trailing `,' was provided. NON_CONSTANT_P is as for @@ -12358,15 +12358,15 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) identifier : initializer-clause initializer-list, identifier : initializer-clause - Returns a TREE_LIST. The TREE_VALUE of each node is an expression - for the initializer. If the TREE_PURPOSE is non-NULL, it is the + Returns a VEC of constructor_elt. The VALUE of each elt is an expression + for the initializer. If the INDEX of the elt is non-NULL, it is the IDENTIFIER_NODE naming the field to initialize. NON_CONSTANT_P is as for cp_parser_initializer. */ -static tree +static VEC(constructor_elt,gc) * cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) { - tree initializers = NULL_TREE; + VEC(constructor_elt,gc) *v = NULL; /* Assume all of the expressions are constant. */ *non_constant_p = false; @@ -12400,8 +12400,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) /* If any clause is non-constant, so is the entire initializer. */ if (clause_non_constant_p) *non_constant_p = true; - /* Add it to the list. */ - initializers = tree_cons (identifier, initializer, initializers); + + /* Add it to the vector. */ + CONSTRUCTOR_APPEND_ELT(v, identifier, initializer); /* If the next token is not a comma, we have reached the end of the list. */ @@ -12420,9 +12421,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) cp_lexer_consume_token (parser->lexer); } - /* The initializers were built up in reverse order, so we need to - reverse them now. */ - return nreverse (initializers); + return v; } /* Classes [gram.class] */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 619cdc11752..2ab89b2eae3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8006,13 +8006,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) return t; case CONSTRUCTOR: - { - r = build_constructor - (tsubst (TREE_TYPE (t), args, complain, in_decl), - tsubst_copy (CONSTRUCTOR_ELTS (t), args, complain, in_decl)); - TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t); - return r; - } + /* This is handled by tsubst_copy_and_build. */ + gcc_unreachable (); case VA_ARG_EXPR: return build_x_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain, @@ -8814,38 +8809,35 @@ tsubst_copy_and_build (tree t, case CONSTRUCTOR: { + VEC(constructor_elt,gc) *n; + constructor_elt *ce; + unsigned HOST_WIDE_INT idx; tree r; - tree elts; tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); - bool purpose_p; + bool process_index_p; /* digest_init will do the wrong thing if we let it. */ if (type && TYPE_PTRMEMFUNC_P (type)) return t; - r = NULL_TREE; - /* We do not want to process the purpose of aggregate + /* We do not want to process the index of aggregate initializers as they are identifier nodes which will be looked up by digest_init. */ - purpose_p = !(type && IS_AGGR_TYPE (type)); - for (elts = CONSTRUCTOR_ELTS (t); - elts; - elts = TREE_CHAIN (elts)) - { - tree purpose = TREE_PURPOSE (elts); - tree value = TREE_VALUE (elts); + process_index_p = !(type && IS_AGGR_TYPE (type)); - if (purpose && purpose_p) - purpose = RECUR (purpose); - value = RECUR (value); - r = tree_cons (purpose, value, r); + n = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t)); + for (idx = 0; VEC_iterate (constructor_elt, n, idx, ce); idx++) + { + if (ce->index && process_index_p) + ce->index = RECUR (ce->index); + ce->value = RECUR (ce->value); } - r = build_constructor (NULL_TREE, nreverse (r)); + r = build_constructor (NULL_TREE, n); TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t); if (type) - return digest_init (type, r, 0); + return digest_init (type, r); return r; } diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index dd59f693c87..e0069388dd7 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -861,7 +861,7 @@ tinfo_base_init (tinfo_s *ti, tree target) init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); - init = build_constructor (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -879,7 +879,7 @@ generic_initializer (tinfo_s *ti, tree target) { tree init = tinfo_base_init (ti, target); - init = build_constructor (NULL_TREE, init); + init = build_constructor_from_list (NULL_TREE, init); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -905,7 +905,7 @@ ptr_initializer (tinfo_s *ti, tree target) get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), init); - init = build_constructor (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -937,8 +937,8 @@ ptm_initializer (tinfo_s *ti, tree target) init = tree_cons (NULL_TREE, get_tinfo_ptr (klass), init); - - init = build_constructor (NULL_TREE, nreverse (init)); + + init = build_constructor_from_list (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -955,7 +955,7 @@ class_initializer (tinfo_s *ti, tree target, tree trail) tree init = tinfo_base_init (ti, target); TREE_CHAIN (init) = trail; - init = build_constructor (NULL_TREE, init); + init = build_constructor_from_list (NULL_TREE, init); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -1066,10 +1066,10 @@ get_pseudo_ti_init (tree type, unsigned tk_index) build_int_cst (NULL_TREE, flags)); base_init = tree_cons (NULL_TREE, offset, base_init); base_init = tree_cons (NULL_TREE, tinfo, base_init); - base_init = build_constructor (NULL_TREE, base_init); + base_init = build_constructor_from_list (NULL_TREE, base_init); base_inits = tree_cons (NULL_TREE, base_init, base_inits); } - base_inits = build_constructor (NULL_TREE, base_inits); + base_inits = build_constructor_from_list (NULL_TREE, base_inits); base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE); /* Prepend the number of bases. */ base_inits = tree_cons (NULL_TREE, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3d99c5d7ff6..e935bb985b1 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2011,20 +2011,19 @@ finish_unary_op_expr (enum tree_code code, tree expr) the INITIALIZER_LIST is being cast. */ tree -finish_compound_literal (tree type, tree initializer_list) +finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) { tree compound_literal; /* Build a CONSTRUCTOR for the INITIALIZER_LIST. */ compound_literal = build_constructor (NULL_TREE, initializer_list); /* Mark it as a compound-literal. */ - TREE_HAS_CONSTRUCTOR (compound_literal) = 1; if (processing_template_decl) TREE_TYPE (compound_literal) = type; else { /* Check the initialization. */ - compound_literal = digest_init (type, compound_literal, NULL); + compound_literal = digest_init (type, compound_literal); /* If the TYPE was an array type with an unknown bound, then we can figure out the dimension now. For example, something like: @@ -2036,6 +2035,7 @@ finish_compound_literal (tree type, tree initializer_list) compound_literal, 1); } + TREE_HAS_CONSTRUCTOR (compound_literal) = 1; return compound_literal; } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 0cf6b4ebc1a..ddc0b514c99 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2241,7 +2241,7 @@ stabilize_init (tree init, tree *initp) if (TREE_CODE (t) == COMPOUND_EXPR) t = expr_last (t); if (TREE_CODE (t) == CONSTRUCTOR - && CONSTRUCTOR_ELTS (t) == NULL_TREE) + && EMPTY_CONSTRUCTOR_P (t)) { /* Default-initialization. */ *initp = NULL_TREE; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b13c8cf6264..9a14f4854a0 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5640,6 +5640,7 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn) tree u = NULL_TREE; tree delta_field; tree pfn_field; + VEC(constructor_elt, gc) *v; /* Pull the FIELD_DECLs out of the type. */ pfn_field = TYPE_FIELDS (type); @@ -5649,9 +5650,10 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn) delta = convert_and_check (delta_type_node, delta); /* Finish creating the initializer. */ - u = tree_cons (pfn_field, pfn, - build_tree_list (delta_field, delta)); - u = build_constructor (type, u); + v = VEC_alloc(constructor_elt, gc, 2); + CONSTRUCTOR_APPEND_ELT(v, pfn_field, pfn); + CONSTRUCTOR_APPEND_ELT(v, delta_field, delta); + u = build_constructor (type, v); TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta); TREE_INVARIANT (u) = TREE_INVARIANT (pfn) & TREE_INVARIANT (delta); TREE_STATIC (u) = (TREE_CONSTANT (u) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 4244088501a..2564a054768 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -39,7 +39,9 @@ Boston, MA 02110-1301, USA. */ #include "output.h" #include "diagnostic.h" -static tree process_init_constructor (tree, tree, tree *); +static tree +process_init_constructor (tree type, tree init); + /* Print an error message stemming from an attempt to use BASETYPE as a base class for TYPE. */ @@ -435,11 +437,12 @@ cxx_incomplete_type_error (tree value, tree type) static void split_nonconstant_init_1 (tree dest, tree init) { - tree *pelt, elt, type = TREE_TYPE (dest); - tree sub, code, inner_type = NULL; + unsigned HOST_WIDE_INT idx; + tree field_index, value; + tree type = TREE_TYPE (dest); + tree inner_type = NULL; bool array_type_p = false; - pelt = &CONSTRUCTOR_ELTS (init); switch (TREE_CODE (type)) { case ARRAY_TYPE: @@ -450,16 +453,21 @@ split_nonconstant_init_1 (tree dest, tree init) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - while ((elt = *pelt)) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, + field_index, value) { - tree field_index = TREE_PURPOSE (elt); - tree value = TREE_VALUE (elt); + /* The current implementation of this algorithm assumes that + the field was set for all the elements. This is usually done + by process_init_constructor. */ + gcc_assert (field_index); if (!array_type_p) inner_type = TREE_TYPE (field_index); if (TREE_CODE (value) == CONSTRUCTOR) { + tree sub; + if (array_type_p) sub = build4 (ARRAY_REF, inner_type, dest, field_index, NULL_TREE, NULL_TREE); @@ -471,7 +479,19 @@ split_nonconstant_init_1 (tree dest, tree init) } else if (!initializer_constant_valid_p (value, inner_type)) { - *pelt = TREE_CHAIN (elt); + tree code; + tree sub; + + /* FIXME: Ordered removal is O(1) so the whole function is + worst-case quadratic. This could be fixed using an aside + bitmap to record which elements must be removed and remove + them all at the same time. Or by merging + split_non_constant_init into process_init_constructor_array, + that is separating constants from non-constants while building + the vector. */ + VEC_ordered_remove (constructor_elt, CONSTRUCTOR_ELTS (init), + idx); + --idx; if (array_type_p) sub = build4 (ARRAY_REF, inner_type, dest, field_index, @@ -485,14 +505,13 @@ split_nonconstant_init_1 (tree dest, tree init) add_stmt (code); continue; } - - pelt = &TREE_CHAIN (elt); } break; case VECTOR_TYPE: if (!initializer_constant_valid_p (init, type)) { + tree code; tree cons = copy_node (init); CONSTRUCTOR_ELTS (init) = NULL; code = build2 (MODIFY_EXPR, type, dest, cons); @@ -568,7 +587,7 @@ store_init_value (tree decl, tree init) { error ("constructor syntax used, but no constructor declared " "for type %qT", type); - init = build_constructor (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (NULL_TREE, nreverse (init)); } } else if (TREE_CODE (init) == TREE_LIST @@ -591,7 +610,7 @@ store_init_value (tree decl, tree init) /* End of special C++ code. */ /* Digest the specified initializer into an expression. */ - value = digest_init (type, init, (tree *) 0); + value = digest_init (type, init); /* If the initializer is not a constant, fill in DECL_INITIAL with the bits that are constant, and then return an expression that will perform the dynamic initialization. */ @@ -607,39 +626,22 @@ store_init_value (tree decl, tree init) } -/* Digest the parser output INIT as an initializer for type TYPE. - Return a C expression of type TYPE to represent the initial value. +/* Process the initializer INIT for a variable of type TYPE, emitting + diagnostics for invalid initializers and converting the initializer as + appropriate. - If TAIL is nonzero, it points to a variable holding a list of elements - of which INIT is the first. We update the list stored there by - removing from the head all the elements that we use. - Normally this is only one; we use more than one element only if - TYPE is an aggregate and INIT is not a constructor. */ + For aggregate types, it assumes that reshape_init has already run, thus the + initializer will have the right shape (brace elision has been undone). */ tree -digest_init (tree type, tree init, tree* tail) +digest_init (tree type, tree init) { enum tree_code code = TREE_CODE (type); - tree element = NULL_TREE; - tree old_tail_contents = NULL_TREE; - - /* By default, assume we use one element from a list. - We correct this later in the sole case where it is not true. */ - if (tail) - { - old_tail_contents = *tail; - *tail = TREE_CHAIN (*tail); - } - - if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST - && TREE_VALUE (init) == error_mark_node)) + if (init == error_mark_node) return error_mark_node; - if (TREE_CODE (init) == ERROR_MARK) - /* __PRETTY_FUNCTION__'s initializer is a bogus expression inside - a template function. This gets substituted during instantiation. */ - return init; + gcc_assert (init); /* We must strip the outermost array type when completing the type, because the its bounds might be incomplete at the moment. */ @@ -647,60 +649,38 @@ digest_init (tree type, tree init, tree* tail) ? TREE_TYPE (type) : type, NULL_TREE)) return error_mark_node; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue + (g++.old-deja/g++.law/casts2.C). */ if (TREE_CODE (init) == NON_LVALUE_EXPR) init = TREE_OPERAND (init, 0); - if (BRACE_ENCLOSED_INITIALIZER_P (init) - && CONSTRUCTOR_ELTS (init) != 0 - && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0) - { - element = TREE_VALUE (CONSTRUCTOR_ELTS (init)); - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - if (element && TREE_CODE (element) == NON_LVALUE_EXPR) - element = TREE_OPERAND (element, 0); - if (element == error_mark_node) - return element; - } - - /* Initialization of an array of chars from a string constant - optionally enclosed in braces. */ - + /* Initialization of an array of chars from a string constant. The initializer + can be optionally enclosed in braces, but reshape_init has already removed + them if they were present. */ if (code == ARRAY_TYPE) { - tree typ1; - - if (TREE_CODE (init) == TREE_LIST) - { - error ("initializing array with parameter list"); - return error_mark_node; - } - - typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); if (char_type_p (typ1) - && ((init && TREE_CODE (init) == STRING_CST) - || (element && TREE_CODE (element) == STRING_CST))) + /*&& init */ + && TREE_CODE (init) == STRING_CST) { - tree string = element ? element : init; + tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init))); - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) - != char_type_node) + if (char_type != char_type_node && TYPE_PRECISION (typ1) == BITS_PER_UNIT) { error ("char-array initialized from wide string"); return error_mark_node; } - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) - == char_type_node) + if (char_type == char_type_node && TYPE_PRECISION (typ1) != BITS_PER_UNIT) { error ("int-array initialized from non-wide string"); return error_mark_node; } - TREE_TYPE (string) = type; - if (TYPE_DOMAIN (type) != 0 - && TREE_CONSTANT (TYPE_SIZE (type))) + TREE_TYPE (init) = type; + if (TYPE_DOMAIN (type) != 0 && TREE_CONSTANT (TYPE_SIZE (type))) { int size = TREE_INT_CST_LOW (TYPE_SIZE (type)); size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; @@ -708,419 +688,372 @@ digest_init (tree type, tree init, tree* tail) because it's ok to ignore the terminating null char that is counted in the length of the constant, but in C++ this would be invalid. */ - if (size < TREE_STRING_LENGTH (string)) + if (size < TREE_STRING_LENGTH (init)) pedwarn ("initializer-string for array of chars is too long"); } - return string; + return init; } } /* Handle scalar types, including conversions, and signature pointers and references. */ - - if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE - || code == ENUMERAL_TYPE || code == REFERENCE_TYPE - || code == BOOLEAN_TYPE || code == COMPLEX_TYPE - || TYPE_PTR_TO_MEMBER_P (type)) + if (SCALAR_TYPE_P (type) + || code == REFERENCE_TYPE) + return convert_for_initialization (0, type, init, LOOKUP_NORMAL, + "initialization", NULL_TREE, 0); + + /* Come here only for aggregates: records, arrays, unions, complex numbers + and vectors. */ + gcc_assert (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == VECTOR_TYPE + || TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == COMPLEX_TYPE); + + if (BRACE_ENCLOSED_INITIALIZER_P (init)) + return process_init_constructor (type, init); + else { - if (BRACE_ENCLOSED_INITIALIZER_P (init)) + if (TREE_HAS_CONSTRUCTOR (init) + && TREE_CODE (type) == ARRAY_TYPE) { - if (element == 0) - { - error ("initializer for scalar variable requires one element"); - return error_mark_node; - } - init = element; - } - while (BRACE_ENCLOSED_INITIALIZER_P (init)) - { - pedwarn ("braces around scalar initializer for %qT", type); - init = CONSTRUCTOR_ELTS (init); - if (TREE_CHAIN (init)) - pedwarn ("ignoring extra initializers for %qT", type); - init = TREE_VALUE (init); - } + error ("cannot initialize aggregate of type %qT with " + "a compound literal", type); - return convert_for_initialization (0, type, init, LOOKUP_NORMAL, + return error_mark_node; + } + return convert_for_initialization (NULL_TREE, type, init, + LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING, "initialization", NULL_TREE, 0); } +} + + +/* Set of flags used within process_init_constructor to describe the + initializers. */ +#define PICFLAG_ERRONEOUS 1 +#define PICFLAG_NOT_ALL_CONSTANT 2 +#define PICFLAG_NOT_ALL_SIMPLE 4 + +/* Given an initializer INIT, return the flag (PICFLAG_*) which better + describe it. */ + +static int +picflag_from_initializer (tree init) +{ + if (init == error_mark_node) + return PICFLAG_ERRONEOUS; + else if (!TREE_CONSTANT (init)) + return PICFLAG_NOT_ALL_CONSTANT; + else if (!initializer_constant_valid_p (init, TREE_TYPE (init))) + return PICFLAG_NOT_ALL_SIMPLE; + return 0; +} - /* Come here only for records and arrays (and unions with constructors). */ +/* Subroutine of process_init_constructor, which will process an initializer + INIT for a array or vector of type TYPE. Returns the flags (PICFLAG_*) which + describe the initializers. */ - if (COMPLETE_TYPE_P (type) && ! TREE_CONSTANT (TYPE_SIZE (type))) +static int +process_init_constructor_array (tree type, tree init) +{ + unsigned HOST_WIDE_INT i, len = 0; + int flags = 0; + bool unbounded = false; + constructor_elt *ce; + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (init); + + gcc_assert (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == VECTOR_TYPE); + + if (TREE_CODE (type) == ARRAY_TYPE) { - error ("variable-sized object of type %qT may not be initialized", - type); - return error_mark_node; + tree domain = TYPE_DOMAIN (type); + if (domain) + len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)) + - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)) + + 1); + else + unbounded = true; /* Take as many as there are. */ } + else + /* Vectors are like simple fixed-size arrays. */ + len = TYPE_VECTOR_SUBPARTS (type); - if (code == ARRAY_TYPE || code == VECTOR_TYPE || IS_AGGR_TYPE_CODE (code)) + /* There cannot be more initializers than needed (or reshape_init would + detect this before we do. */ + if (!unbounded) + gcc_assert (VEC_length (constructor_elt, v) <= len); + + for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i) { - if (BRACE_ENCLOSED_INITIALIZER_P (init)) - { - if (TYPE_NON_AGGREGATE_CLASS (type)) - { - error ("subobject of type %qT must be initialized by " - "constructor, not by %qE", - type, init); - return error_mark_node; - } - return process_init_constructor (type, init, (tree *)0); - } - else if (can_convert_arg (type, TREE_TYPE (init), init) - || TYPE_NON_AGGREGATE_CLASS (type)) - /* These are never initialized from multiple constructor elements. */; - else if (tail != 0) + if (ce->index) { - *tail = old_tail_contents; - return process_init_constructor (type, 0, tail); + gcc_assert (TREE_CODE (ce->index) == INTEGER_CST); + if (compare_tree_int (ce->index, i) != 0) + sorry ("non-trivial designated initializers not supported"); } + else + ce->index = size_int (i); + gcc_assert (ce->value); + ce->value = digest_init (TREE_TYPE (type), ce->value); - if (code != ARRAY_TYPE) - { - int flags = LOOKUP_NORMAL; - /* Initialization from { } is copy-initialization. */ - if (tail) - flags |= LOOKUP_ONLYCONVERTING; + if (ce->value != error_mark_node) + gcc_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (type), TREE_TYPE (ce->value))); - return convert_for_initialization (NULL_TREE, type, init, flags, - "initialization", NULL_TREE, 0); - } + flags |= picflag_from_initializer (ce->value); } - error ("invalid initializer"); - return error_mark_node; -} - -/* Process a constructor for a variable of type TYPE. - The constructor elements may be specified either with INIT or with ELTS, - only one of which should be non-null. + /* No more initializers. If the array is unbounded, we are done. Otherwise, + we must add initializers ourselves. */ + if (!unbounded) + for (; i < len; ++i) + { + tree next; + + if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) + { + /* If this type needs constructors run for default-initialization, + we can't rely on the backend to do it for us, so build up + TARGET_EXPRs. If the type in question is a class, just build + one up; if it's an array, recurse. */ + if (IS_AGGR_TYPE (TREE_TYPE (type))) + next = build_functional_cast (TREE_TYPE (type), NULL_TREE); + else + next = build_constructor (NULL_TREE, NULL); + next = digest_init (TREE_TYPE (type), next); + } + else if (!zero_init_p (TREE_TYPE (type))) + next = build_zero_init (TREE_TYPE (type), + /*nelts=*/NULL_TREE, + /*static_storage_p=*/false); + else + /* The default zero-initialization is fine for us; don't + add anything to the CONSTRUCTOR. */ + break; - If INIT is specified, it is a CONSTRUCTOR node which is specifically - and solely for initializing this datum. + flags |= picflag_from_initializer (next); + CONSTRUCTOR_APPEND_ELT (v, size_int (i), next); + } - If ELTS is specified, it is the address of a variable containing - a list of expressions. We take as many elements as we need - from the head of the list and update the list. + CONSTRUCTOR_ELTS (init) = v; + return flags; +} - In the resulting constructor, TREE_CONSTANT is set if all elts are - constant, and TREE_STATIC is set if, in addition, all elts are simple enough - constants that the assembler and linker can compute them. */ +/* Subroutine of process_init_constructor, which will process an initializer + INIT for a class of type TYPE. Returns the flags (PICFLAG_*) which describe + the initializers. */ -static tree -process_init_constructor (tree type, tree init, tree* elts) +static int +process_init_constructor_record (tree type, tree init) { - tree tail; - /* List of the elements of the result constructor, - in reverse order. */ - tree members = NULL; - tree next1; - tree result; - int allconstant = 1; - int allsimple = 1; - int erroneous = 0; - - /* Make TAIL be the list of elements to use for the initialization, - no matter how the data was given to us. */ - - if (elts) - { - if (warn_missing_braces) - warning (0, "aggregate has a partly bracketed initializer"); - tail = *elts; - } - else - tail = CONSTRUCTOR_ELTS (init); - - /* Gobble as many elements as needed, and make a constructor or initial value - for each element of this aggregate. Chain them together in result. - If there are too few, use 0 for each scalar ultimate component. */ - - if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE) + VEC(constructor_elt,gc) *v = NULL; + int flags = 0; + tree field; + unsigned HOST_WIDE_INT idx = 0; + + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + gcc_assert (!CLASSTYPE_VBASECLASSES (type)); + gcc_assert (!TYPE_BINFO (type) + || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type))); + gcc_assert (!TYPE_POLYMORPHIC_P (type)); + + /* Generally, we will always have an index for each initializer (which is + a FIELD_DECL, put by reshape_init), but compound literals don't go trough + reshape_init. So we need to handle both cases. */ + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { - long len; - int i; + tree next; - if (TREE_CODE (type) == ARRAY_TYPE) + if (!DECL_NAME (field) && DECL_C_BIT_FIELD (field)) { - tree domain = TYPE_DOMAIN (type); - if (domain) - len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)) - - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)) - + 1); - else - len = -1; /* Take as many as there are. */ - } - else - { - /* Vectors are like simple fixed-size arrays. */ - len = TYPE_VECTOR_SUBPARTS (type); + flags |= picflag_from_initializer (integer_zero_node); + CONSTRUCTOR_APPEND_ELT (v, field, integer_zero_node); + continue; } - for (i = 0; len < 0 || i < len; i++) + if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) + continue; + + if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init))) { - if (tail) + constructor_elt *ce = VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (init), idx); + if (ce->index) { - if (TREE_PURPOSE (tail) - && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST - || compare_tree_int (TREE_PURPOSE (tail), i) != 0)) - sorry ("non-trivial labeled initializers"); - - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; - next1 = digest_init (TREE_TYPE (type), - TREE_VALUE (tail), &tail1); - if (next1 == error_mark_node) - return next1; - gcc_assert (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (type), TREE_TYPE (next1))); - gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST); - if (tail == tail1 && len < 0) - { - error ("non-empty initializer for array of empty elements"); - /* Just ignore what we were supposed to use. */ - tail1 = NULL_TREE; - } - tail = tail1; - } - else - { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); - } + /* We can have either a FIELD_DECL or an IDENTIFIER_NODE. The + latter case can happen in templates where lookup has to be + deferred. */ + gcc_assert (TREE_CODE (ce->index) == FIELD_DECL + || TREE_CODE (ce->index) == IDENTIFIER_NODE); + if (ce->index != field + && ce->index != DECL_NAME (field)) + sorry ("non-trivial designated initializers not supported"); } - else if (len < 0) - /* We're done. */ - break; - else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) - { - /* If this type needs constructors run for - default-initialization, we can't rely on the backend to do it - for us, so build up TARGET_EXPRs. If the type in question is - a class, just build one up; if it's an array, recurse. */ - if (IS_AGGR_TYPE (TREE_TYPE (type))) - next1 = build_functional_cast (TREE_TYPE (type), NULL_TREE); - else - next1 = build_constructor (NULL_TREE, NULL_TREE); - next1 = digest_init (TREE_TYPE (type), next1, 0); - } - else if (! zero_init_p (TREE_TYPE (type))) - next1 = build_zero_init (TREE_TYPE (type), - /*nelts=*/NULL_TREE, - /*static_storage_p=*/false); + gcc_assert (ce->value); + next = digest_init (TREE_TYPE (field), ce->value); + ++idx; + } + else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) + { + /* If this type needs constructors run for + default-initialization, we can't rely on the backend to do it + for us, so build up TARGET_EXPRs. If the type in question is + a class, just build one up; if it's an array, recurse. */ + if (IS_AGGR_TYPE (TREE_TYPE (field))) + next = build_functional_cast (TREE_TYPE (field), NULL_TREE); + else + next = build_constructor (NULL_TREE, NULL); + + next = digest_init (TREE_TYPE (field), next); + + /* Warn when some struct elements are implicitly initialized. */ + warning (OPT_Wmissing_field_initializers, + "missing initializer for member %qD", field); + } + else + { + if (TREE_READONLY (field)) + error ("uninitialized const member %qD", field); + else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field))) + error ("member %qD with uninitialized const fields", field); + else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) + error ("member %qD is uninitialized reference", field); + + /* Warn when some struct elements are implicitly initialized + to zero. */ + warning (OPT_Wmissing_field_initializers, + "missing initializer for member %qD", field); + + if (!zero_init_p (TREE_TYPE (field))) + next = build_zero_init (TREE_TYPE (field), /*nelts=*/NULL_TREE, + /*static_storage_p=*/false); else /* The default zero-initialization is fine for us; don't - add anything to the CONSTRUCTOR. */ - break; - - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) - allsimple = 0; - members = tree_cons (size_int (i), next1, members); + add anything to the CONSTRUCTOR. */ + continue; } + + flags |= picflag_from_initializer (next); + CONSTRUCTOR_APPEND_ELT (v, field, next); } - else if (TREE_CODE (type) == RECORD_TYPE) - { - tree field; - if (tail) - { - gcc_assert (!CLASSTYPE_VBASECLASSES (type)); - gcc_assert (!TYPE_BINFO (type) - || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type))); - gcc_assert (!TYPE_POLYMORPHIC_P (type)); - } + CONSTRUCTOR_ELTS (init) = v; + return flags; +} - for (field = TYPE_FIELDS (type); field; - field = TREE_CHAIN (field)) - { - if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field)) - { - members = tree_cons (field, integer_zero_node, members); - continue; - } +/* Subroutine of process_init_constructor, which will process a single + initializer INIT for an union of type TYPE. Returns the flags (PICFLAG_*) + which describe the initializer. */ - if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) - continue; +static int +process_init_constructor_union (tree type, tree init) +{ + constructor_elt *ce; - if (tail) - { - if (TREE_PURPOSE (tail) - && TREE_PURPOSE (tail) != field - && TREE_PURPOSE (tail) != DECL_NAME (field)) - sorry ("non-trivial labeled initializers"); - - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; - - next1 = digest_init (TREE_TYPE (field), - TREE_VALUE (tail), &tail1); - gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST); - tail = tail1; - } - else - { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); - } - } - else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) - { - /* If this type needs constructors run for - default-initialization, we can't rely on the backend to do it - for us, so build up TARGET_EXPRs. If the type in question is - a class, just build one up; if it's an array, recurse. */ - - if (IS_AGGR_TYPE (TREE_TYPE (field))) - next1 = build_functional_cast (TREE_TYPE (field), - NULL_TREE); - else - { - next1 = build_constructor (NULL_TREE, NULL_TREE); - if (init) - TREE_HAS_CONSTRUCTOR (next1) - = TREE_HAS_CONSTRUCTOR (init); - } - next1 = digest_init (TREE_TYPE (field), next1, 0); - - /* Warn when some struct elements are implicitly initialized. */ - if (warn_missing_field_initializers - && (!init || BRACE_ENCLOSED_INITIALIZER_P (init))) - warning (0, "missing initializer for member %qD", field); - } - else + /* If the initializer was empty, use default zero initialization. */ + if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init))) + return 0; + + gcc_assert (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) == 1); + ce = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (init), 0); + + /* If this element specifies a field, initialize via that field. */ + if (ce->index) + { + if (TREE_CODE (ce->index) == FIELD_DECL) + ; + else if (TREE_CODE (ce->index) == IDENTIFIER_NODE) + { + /* This can happen within a cast, see g++.dg/opt/cse2.C. */ + tree name = ce->index; + tree field; + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (DECL_NAME (field) == name) + break; + if (!field) { - if (TREE_READONLY (field)) - error ("uninitialized const member %qD", field); - else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field))) - error ("member %qD with uninitialized const fields", field); - else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) - error ("member %qD is uninitialized reference", field); - - /* Warn when some struct elements are implicitly initialized - to zero. */ - if (warn_missing_field_initializers - && (!init || BRACE_ENCLOSED_INITIALIZER_P (init))) - warning (0, "missing initializer for member %qD", field); - - if (! zero_init_p (TREE_TYPE (field))) - next1 = build_zero_init (TREE_TYPE (field), - /*nelts=*/NULL_TREE, - /*static_storage_p=*/false); - else - /* The default zero-initialization is fine for us; don't - add anything to the CONSTRUCTOR. */ - continue; + error ("no field %qD found in union being initialized", field); + ce->value = error_mark_node; } - - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) - allsimple = 0; - members = tree_cons (field, next1, members); + ce->index = field; + } + else + { + gcc_assert (TREE_CODE (ce->index) == INTEGER_CST + || TREE_CODE (ce->index) == RANGE_EXPR); + error ("index value instead of field name in union initializer"); + ce->value = error_mark_node; } } - else if (TREE_CODE (type) == UNION_TYPE - /* If the initializer was empty, use default zero initialization. */ - && tail) + else { - tree field = TYPE_FIELDS (type); - /* Find the first named field. ANSI decided in September 1990 that only named fields count here. */ + tree field = TYPE_FIELDS (type); while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL)) field = TREE_CHAIN (field); - - /* If this element specifies a field, initialize via that field. */ - if (TREE_PURPOSE (tail) != NULL_TREE) - { - int win = 0; - - if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL) - /* Handle the case of a call by build_c_cast. */ - field = TREE_PURPOSE (tail), win = 1; - else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE) - error ("index value instead of field name in union initializer"); - else - { - tree temp; - for (temp = TYPE_FIELDS (type); - temp; - temp = TREE_CHAIN (temp)) - if (DECL_NAME (temp) == TREE_PURPOSE (tail)) - break; - if (temp) - field = temp, win = 1; - else - error ("no field %qD in union being initialized", - TREE_PURPOSE (tail)); - } - if (!win) - TREE_VALUE (tail) = error_mark_node; - } - else if (field == 0) + if (!field) { error ("union %qT with no named members cannot be initialized", type); - TREE_VALUE (tail) = error_mark_node; + ce->value = error_mark_node; } + ce->index = field; + } - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; + if (ce->value && ce->value != error_mark_node) + ce->value = digest_init (TREE_TYPE (ce->index), ce->value); - next1 = digest_init (TREE_TYPE (field), - TREE_VALUE (tail), &tail1); - gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST); - tail = tail1; - } - else - { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); - } + return picflag_from_initializer (ce->value); +} - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) - allsimple = 0; - members = tree_cons (field, next1, members); - } +/* Process INIT, a constructor for a variable of aggregate type TYPE. The + constructor is a brace-enclosed initializer, and will be modified in-place. + + Each element is converted to the right type through digest_init, and + missing initializers are added following the language rules (zero-padding, + etc.). - /* If arguments were specified as a list, just remove the ones we used. */ - if (elts) - *elts = tail; - /* If arguments were specified as a constructor, - complain unless we used all the elements of the constructor. */ - else if (tail) - pedwarn ("excess elements in aggregate initializer"); + After the execution, the initializer will have TREE_CONSTANT if all elts are + constant, and TREE_STATIC set if, in addition, all elts are simple enough + constants that the assembler and linker can compute them. + + The function returns the initializer itself, or error_mark_node in case + of error. */ + +static tree +process_init_constructor (tree type, tree init) +{ + int flags; + + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); + + if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE) + flags = process_init_constructor_array (type, init); + else if (TREE_CODE (type) == RECORD_TYPE) + flags = process_init_constructor_record (type, init); + else if (TREE_CODE (type) == UNION_TYPE) + flags = process_init_constructor_union (type, init); + else + gcc_unreachable (); - if (erroneous) + if (flags & PICFLAG_ERRONEOUS) return error_mark_node; - result = build_constructor (type, nreverse (members)); + TREE_TYPE (init) = type; if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE) - cp_complete_array_type (&TREE_TYPE (result), result, /*do_default=*/0); - if (init) - TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init); - if (allconstant) + cp_complete_array_type (&TREE_TYPE (init), init, /*do_default=*/0); + if (!(flags & PICFLAG_NOT_ALL_CONSTANT)) { - TREE_CONSTANT (result) = 1; - TREE_INVARIANT (result) = 1; - if (allsimple) - TREE_STATIC (result) = 1; + TREE_CONSTANT (init) = 1; + TREE_INVARIANT (init) = 1; + if (!(flags & PICFLAG_NOT_ALL_SIMPLE)) + TREE_STATIC (init) = 1; } - return result; + return init; } /* Given a structure or union value DATUM, construct and return @@ -1396,7 +1329,7 @@ build_functional_cast (tree exp, tree parms) if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type) && TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) { - exp = build_constructor (type, NULL_TREE); + exp = build_constructor (type, NULL); return get_target_expr (exp); } diff --git a/gcc/expr.c b/gcc/expr.c index 182ab2382be..60d45f3ad25 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4398,17 +4398,16 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, HOST_WIDE_INT *p_elt_count, bool *p_must_clear) { + unsigned HOST_WIDE_INT idx; HOST_WIDE_INT nz_elts, nc_elts, elt_count; - tree list; + tree value, purpose; nz_elts = 0; nc_elts = 0; elt_count = 0; - for (list = CONSTRUCTOR_ELTS (ctor); list; list = TREE_CHAIN (list)) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, purpose, value) { - tree value = TREE_VALUE (list); - tree purpose = TREE_PURPOSE (list); HOST_WIDE_INT mult; mult = 1; @@ -4482,14 +4481,16 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, tree init_sub_type; bool clear_this = true; - list = CONSTRUCTOR_ELTS (ctor); - if (list) + if (!VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor))) { /* We don't expect more than one element of the union to be initialized. Not sure what we should do otherwise... */ - gcc_assert (TREE_CHAIN (list) == NULL); + gcc_assert (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (ctor)) + == 1); - init_sub_type = TREE_TYPE (TREE_VALUE (list)); + init_sub_type = TREE_TYPE (VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (ctor), + 0)->value); /* ??? We could look at each element of the union, and find the largest element. Which would avoid comparing the size of the @@ -4699,7 +4700,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) case UNION_TYPE: case QUAL_UNION_TYPE: { - tree elt; + unsigned HOST_WIDE_INT idx; + tree field, value; /* If size is zero or the target is already cleared, do nothing. */ if (size == 0 || cleared) @@ -4731,7 +4733,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) register whose mode size isn't equal to SIZE since clear_storage can't handle this case. */ else if (size > 0 - && ((list_length (CONSTRUCTOR_ELTS (exp)) + && (((int)VEC_length (constructor_elt, CONSTRUCTOR_ELTS (exp)) != fields_length (type)) || mostly_zeros_p (exp)) && (!REG_P (target) @@ -4747,11 +4749,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) /* Store each element of the constructor into the corresponding field of TARGET. */ - - for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, field, value) { - tree field = TREE_PURPOSE (elt); - tree value = TREE_VALUE (elt); enum machine_mode mode; HOST_WIDE_INT bitsize; HOST_WIDE_INT bitpos = 0; @@ -4857,8 +4856,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) } case ARRAY_TYPE: { - tree elt; - int i; + tree value, index; + unsigned HOST_WIDE_INT i; int need_to_clear; tree domain; tree elttype = TREE_TYPE (type); @@ -4888,18 +4887,20 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) need_to_clear = 1; else { + unsigned HOST_WIDE_INT idx; + tree index, value; HOST_WIDE_INT count = 0, zero_count = 0; need_to_clear = ! const_bounds_p; /* This loop is a more accurate version of the loop in mostly_zeros_p (it handles RANGE_EXPR in an index). It is also needed to check for missing elements. */ - for (elt = CONSTRUCTOR_ELTS (exp); - elt != NULL_TREE && ! need_to_clear; - elt = TREE_CHAIN (elt)) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, index, value) { - tree index = TREE_PURPOSE (elt); HOST_WIDE_INT this_node_count; + + if (need_to_clear) + break; if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR) { @@ -4920,7 +4921,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) this_node_count = 1; count += this_node_count; - if (mostly_zeros_p (TREE_VALUE (elt))) + if (mostly_zeros_p (value)) zero_count += this_node_count; } @@ -4949,16 +4950,12 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) /* Store each element of the constructor into the corresponding element of TARGET, determined by counting the elements. */ - for (elt = CONSTRUCTOR_ELTS (exp), i = 0; - elt; - elt = TREE_CHAIN (elt), i++) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), i, index, value) { enum machine_mode mode; HOST_WIDE_INT bitsize; HOST_WIDE_INT bitpos; int unsignedp; - tree value = TREE_VALUE (elt); - tree index = TREE_PURPOSE (elt); rtx xtarget = target; if (cleared && initializer_zerop (value)) @@ -5118,7 +5115,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) case VECTOR_TYPE: { - tree elt; + unsigned HOST_WIDE_INT idx; + constructor_elt *ce; int i; int need_to_clear; int icode = 0; @@ -5158,18 +5156,17 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) else { unsigned HOST_WIDE_INT count = 0, zero_count = 0; + tree value; - for (elt = CONSTRUCTOR_ELTS (exp); - elt != NULL_TREE; - elt = TREE_CHAIN (elt)) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value) { int n_elts_here = tree_low_cst (int_const_binop (TRUNC_DIV_EXPR, - TYPE_SIZE (TREE_TYPE (TREE_VALUE (elt))), + TYPE_SIZE (TREE_TYPE (value)), TYPE_SIZE (elttype), 0), 1); count += n_elts_here; - if (mostly_zeros_p (TREE_VALUE (elt))) + if (mostly_zeros_p (value)) zero_count += n_elts_here; } @@ -5193,20 +5190,19 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) /* Store each element of the constructor into the corresponding element of TARGET, determined by counting the elements. */ - for (elt = CONSTRUCTOR_ELTS (exp), i = 0; - elt; - elt = TREE_CHAIN (elt), i += bitsize / elt_size) + for (idx = 0, i = 0; + VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), idx, ce); + idx++, i += bitsize / elt_size) { - tree value = TREE_VALUE (elt); - tree index = TREE_PURPOSE (elt); HOST_WIDE_INT eltpos; + tree value = ce->value; bitsize = tree_low_cst (TYPE_SIZE (TREE_TYPE (value)), 1); if (cleared && initializer_zerop (value)) continue; - if (index != 0) - eltpos = tree_low_cst (index, 1); + if (ce->index) + eltpos = tree_low_cst (ce->index, 1); else eltpos = i; @@ -6733,8 +6729,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_FLOAT) return const_vector_from_tree (exp); else - return expand_expr (build1 (CONSTRUCTOR, TREE_TYPE (exp), - TREE_VECTOR_CST_ELTS (exp)), + return expand_expr (build_constructor_from_list + (TREE_TYPE (exp), + TREE_VECTOR_CST_ELTS (exp)), ignore ? const0_rtx : target, tmode, modifier); case CONST_DECL: @@ -6832,10 +6829,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, subexpressions. */ if (ignore) { - tree elt; + unsigned HOST_WIDE_INT idx; + tree value; - for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) - expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0); + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value) + expand_expr (value, const0_rtx, VOIDmode, 0); return const0_rtx; } @@ -6997,16 +6995,17 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, && ! TREE_SIDE_EFFECTS (array) && TREE_CODE (index) == INTEGER_CST) { - tree elem; - - for (elem = CONSTRUCTOR_ELTS (array); - (elem && !tree_int_cst_equal (TREE_PURPOSE (elem), index)); - elem = TREE_CHAIN (elem)) - ; + unsigned HOST_WIDE_INT ix; + tree field, value; - if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem))) - return expand_expr (fold (TREE_VALUE (elem)), target, tmode, - modifier); + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (array), ix, + field, value) + if (tree_int_cst_equal (field, index)) + { + if (!TREE_SIDE_EFFECTS (value)) + return expand_expr (fold (value), target, tmode, modifier); + break; + } } else if (optimize >= 1 @@ -7024,17 +7023,18 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, if (TREE_CODE (init) == CONSTRUCTOR) { - tree elem; - - for (elem = CONSTRUCTOR_ELTS (init); - (elem - && !tree_int_cst_equal (TREE_PURPOSE (elem), index)); - elem = TREE_CHAIN (elem)) - ; - - if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem))) - return expand_expr (fold (TREE_VALUE (elem)), target, - tmode, modifier); + unsigned HOST_WIDE_INT ix; + tree field, value; + + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix, + field, value) + if (tree_int_cst_equal (field, index)) + { + if (!TREE_SIDE_EFFECTS (value)) + return expand_expr (fold (value), target, tmode, + modifier); + break; + } } else if (TREE_CODE (init) == STRING_CST && 0 > compare_tree_int (index, @@ -7058,11 +7058,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, appropriate field if it is present. */ if (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR) { - tree elt; + unsigned HOST_WIDE_INT idx; + tree field, value; - for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt; - elt = TREE_CHAIN (elt)) - if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)), + idx, field, value) + if (field == TREE_OPERAND (exp, 1) /* We can normally use the value of the field in the CONSTRUCTOR. However, if this is a bitfield in an integral mode that we can fit in a HOST_WIDE_INT, @@ -7070,24 +7071,21 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, since this is done implicitly by the constructor. If the bitfield does not meet either of those conditions, we can't do this optimization. */ - && (! DECL_BIT_FIELD (TREE_PURPOSE (elt)) - || ((GET_MODE_CLASS (DECL_MODE (TREE_PURPOSE (elt))) - == MODE_INT) - && (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt))) + && (! DECL_BIT_FIELD (field) + || ((GET_MODE_CLASS (DECL_MODE (field)) == MODE_INT) + && (GET_MODE_BITSIZE (DECL_MODE (field)) <= HOST_BITS_PER_WIDE_INT)))) { - if (DECL_BIT_FIELD (TREE_PURPOSE (elt)) + if (DECL_BIT_FIELD (field) && modifier == EXPAND_STACK_PARM) target = 0; - op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier); - if (DECL_BIT_FIELD (TREE_PURPOSE (elt))) + op0 = expand_expr (value, target, tmode, modifier); + if (DECL_BIT_FIELD (field)) { - HOST_WIDE_INT bitsize - = TREE_INT_CST_LOW (DECL_SIZE (TREE_PURPOSE (elt))); - enum machine_mode imode - = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt))); + HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)); + enum machine_mode imode = TYPE_MODE (TREE_TYPE (field)); - if (TYPE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt)))) + if (TYPE_UNSIGNED (TREE_TYPE (field))) { op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1); op0 = expand_and (imode, op0, op1, target); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0e414bc2bf1..273a912d4e4 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -9861,9 +9861,11 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2) if (TREE_CODE (arg0) == CONSTRUCTOR && ! type_contains_placeholder_p (TREE_TYPE (arg0))) { - tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0)); - if (m) - return TREE_VALUE (m); + unsigned HOST_WIDE_INT idx; + tree field, value; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg0), idx, field, value) + if (field == arg1) + return value; } return NULL_TREE; diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 12c6b2efdb9..80a1538e149 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,14 @@ +2005-07-20 Giovanni Bajo <giovannibajo@libero.it> + + Make CONSTRUCTOR use VEC to store initializers. + * trans-array.c (gfc_build_null_descriptor, + gfc_trans_array_constructor_value, gfc_conv_array_initializer): + Update to cope with VEC in CONSTRUCTOR_ELTS. + * trans-common.c (create_common): Likewise. + * trans-expr.c (gfc_conv_structure): Likewise. + * trans-stmt.c (gfc_trans_character_select): Use + build_constructor_from_list instead of build_constructor. + 2005-07-19 Paul Thomas <pault@gcc.gnu.org> PR fortran/16940 diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index d54dff3e366..e634154cc72 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -299,8 +299,7 @@ gfc_build_null_descriptor (tree type) field = TYPE_FIELDS (type); /* Set a NULL data pointer. */ - tmp = tree_cons (field, null_pointer_node, NULL_TREE); - tmp = build1 (CONSTRUCTOR, type, tmp); + tmp = build_constructor_single (type, field, null_pointer_node); TREE_CONSTANT (tmp) = 1; TREE_INVARIANT (tmp) = 1; /* All other fields are ignored. */ @@ -834,7 +833,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type, gfc_index_zero_node, bound); tmptype = build_array_type (type, tmptype); - init = build1 (CONSTRUCTOR, tmptype, nreverse (list)); + init = build_constructor_from_list (tmptype, nreverse (list)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -2833,15 +2832,14 @@ tree gfc_conv_array_initializer (tree type, gfc_expr * expr) { gfc_constructor *c; - tree list; tree tmp; mpz_t maxval; gfc_se se; HOST_WIDE_INT hi; unsigned HOST_WIDE_INT lo; tree index, range; + VEC(constructor_elt,gc) *v = NULL; - list = NULL_TREE; switch (expr->expr_type) { case EXPR_CONSTANT: @@ -2865,7 +2863,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr) /* This will probably eat buckets of memory for large arrays. */ while (hi != 0 || lo != 0) { - list = tree_cons (NULL_TREE, se.expr, list); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr); if (lo == 0) hi--; lo--; @@ -2873,7 +2871,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr) break; case EXPR_ARRAY: - /* Create a list of all the elements. */ + /* Create a vector of all the elements. */ for (c = expr->value.constructor; c; c = c->next) { if (c->iterator) @@ -2917,26 +2915,24 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr) case EXPR_CONSTANT: gfc_conv_constant (&se, c->expr); if (range == NULL_TREE) - list = tree_cons (index, se.expr, list); + CONSTRUCTOR_APPEND_ELT (v, index, se.expr); else { if (index != NULL_TREE) - list = tree_cons (index, se.expr, list); - list = tree_cons (range, se.expr, list); + CONSTRUCTOR_APPEND_ELT (v, index, se.expr); + CONSTRUCTOR_APPEND_ELT (v, range, se.expr); } break; case EXPR_STRUCTURE: gfc_conv_structure (&se, c->expr, 1); - list = tree_cons (index, se.expr, list); + CONSTRUCTOR_APPEND_ELT (v, index, se.expr); break; default: gcc_unreachable (); } } - /* We created the list in reverse order. */ - list = nreverse (list); break; default: @@ -2944,7 +2940,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr) } /* Create a constructor from the list of elements. */ - tmp = build1 (CONSTRUCTOR, type, list); + tmp = build_constructor (type, v); TREE_CONSTANT (tmp) = 1; TREE_INVARIANT (tmp) = 1; return tmp; diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c index 39b49e2c04f..4defe0f6af3 100644 --- a/gcc/fortran/trans-common.c +++ b/gcc/fortran/trans-common.c @@ -422,10 +422,10 @@ create_common (gfc_common_head *com, segment_info * head, bool saw_equiv) if (is_init) { - tree list, ctor, tmp; + tree ctor, tmp; HOST_WIDE_INT offset = 0; + VEC(constructor_elt,gc) *v = NULL; - list = NULL_TREE; for (s = head; s; s = s->next) { if (s->sym->value) @@ -442,20 +442,25 @@ create_common (gfc_common_head *com, segment_info * head, bool saw_equiv) tmp = gfc_conv_initializer (s->sym->value, &s->sym->ts, TREE_TYPE (s->field), s->sym->attr.dimension, s->sym->attr.pointer || s->sym->attr.allocatable); - list = tree_cons (s->field, tmp, list); + + CONSTRUCTOR_APPEND_ELT (v, s->field, tmp); offset = s->offset + s->length; } } - gcc_assert (list); - ctor = build1 (CONSTRUCTOR, union_type, nreverse(list)); + gcc_assert (!VEC_empty (constructor_elt, v)); + ctor = build_constructor (union_type, v); TREE_CONSTANT (ctor) = 1; TREE_INVARIANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; #ifdef ENABLE_CHECKING - for (tmp = CONSTRUCTOR_ELTS (ctor); tmp; tmp = TREE_CHAIN (tmp)) - gcc_assert (TREE_CODE (TREE_PURPOSE (tmp)) == FIELD_DECL); + { + tree field, value; + unsigned HOST_WIDE_INT idx; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, field, value) + gcc_assert (TREE_CODE (field) == FIELD_DECL); + } #endif } diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index c1863fc75e2..0cd8741758c 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -1812,11 +1812,10 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init) { gfc_constructor *c; gfc_component *cm; - tree head; - tree tail; tree val; tree type; tree tmp; + VEC(constructor_elt,gc) *v = NULL; gcc_assert (se->ss == NULL); gcc_assert (expr->expr_type == EXPR_STRUCTURE); @@ -1831,9 +1830,6 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init) return; } - head = build1 (CONSTRUCTOR, type, NULL_TREE); - tail = NULL_TREE; - cm = expr->ts.derived->components; for (c = expr->value.constructor; c; c = c->next, cm = cm->next) { @@ -1844,19 +1840,10 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init) val = gfc_conv_initializer (c->expr, &cm->ts, TREE_TYPE (cm->backend_decl), cm->dimension, cm->pointer); - /* Build a TREE_CHAIN to hold it. */ - val = tree_cons (cm->backend_decl, val, NULL_TREE); - - /* Add it to the list. */ - if (tail == NULL_TREE) - TREE_OPERAND(head, 0) = tail = val; - else - { - TREE_CHAIN (tail) = val; - tail = val; - } + /* Append it to the constructor list. */ + CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, val); } - se->expr = head; + se->expr = build_constructor (type, v); } diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 0ec029fa5dd..99467b4945f 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -1220,14 +1220,14 @@ gfc_trans_character_select (gfc_code *code) tmp = gfc_build_addr_expr (pvoid_type_node, labels[i]); node = tree_cons (ss_target, tmp, node); - tmp = build1 (CONSTRUCTOR, select_struct, nreverse (node)); + tmp = build_constructor_from_list (select_struct, nreverse (node)); init = tree_cons (NULL_TREE, tmp, init); } type = build_array_type (select_struct, build_index_type (build_int_cst (NULL_TREE, n - 1))); - init = build1 (CONSTRUCTOR, type, nreverse(init)); + init = build_constructor_from_list (type, nreverse(init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 3f06d7a0491..bb08c2b140f 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2385,9 +2385,12 @@ gimplify_init_ctor_preeval (tree *expr_p, tree *pre_p, tree *post_p, /* Recurse for nested constructors. */ if (TREE_CODE (*expr_p) == CONSTRUCTOR) { - tree list; - for (list = CONSTRUCTOR_ELTS (*expr_p); list ; list = TREE_CHAIN (list)) - gimplify_init_ctor_preeval (&TREE_VALUE (list), pre_p, post_p, data); + unsigned HOST_WIDE_INT ix; + constructor_elt *ce; + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (*expr_p); + + for (ix = 0; VEC_iterate (constructor_elt, v, ix, ce); ix++) + gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data); return; } @@ -2446,7 +2449,8 @@ gimplify_init_ctor_preeval (tree *expr_p, tree *pre_p, tree *post_p, Note that we never have to deal with SAVE_EXPRs here, because this has already been taken care of for us, in gimplify_init_ctor_preeval(). */ -static void gimplify_init_ctor_eval (tree, tree, tree *, bool); +static void gimplify_init_ctor_eval (tree, VEC(constructor_elt,gc) *, + tree *, bool); static void gimplify_init_ctor_eval_range (tree object, tree lower, tree upper, @@ -2530,24 +2534,24 @@ zero_sized_field_decl (tree fdecl) /* A subroutine of gimplify_init_constructor. Generate individual MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the - assignments should happen. LIST is the CONSTRUCTOR_ELTS of the + assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the CONSTRUCTOR. CLEARED is true if the entire LHS object has been zeroed first. */ static void -gimplify_init_ctor_eval (tree object, tree list, tree *pre_p, bool cleared) +gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts, + tree *pre_p, bool cleared) { tree array_elt_type = NULL; + unsigned HOST_WIDE_INT ix; + tree purpose, value; if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE) array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object))); - for (; list; list = TREE_CHAIN (list)) + FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value) { - tree purpose, value, cref, init; - - purpose = TREE_PURPOSE (list); - value = TREE_VALUE (list); + tree cref, init; /* NULL values are created above for gimplification errors. */ if (value == NULL) @@ -2617,7 +2621,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, tree ctor = TREE_OPERAND (*expr_p, 1); tree type = TREE_TYPE (ctor); enum gimplify_status ret; - tree elt_list; + VEC(constructor_elt,gc) *elts; if (TREE_CODE (ctor) != CONSTRUCTOR) return GS_UNHANDLED; @@ -2628,7 +2632,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, return ret; object = TREE_OPERAND (*expr_p, 0); - elt_list = CONSTRUCTOR_ELTS (ctor); + elts = CONSTRUCTOR_ELTS (ctor); ret = GS_ALL_DONE; switch (TREE_CODE (type)) @@ -2646,7 +2650,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, /* Aggregate types must lower constructors to initialization of individual elements. The exception is that a CONSTRUCTOR node with no elements indicates zero-initialization of the whole. */ - if (elt_list == NULL) + if (VEC_empty (constructor_elt, elts)) break; categorize_ctor_elements (ctor, &num_nonzero_elements, @@ -2758,7 +2762,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, /* Zap the CONSTRUCTOR element list, which simplifies this case. Note that we still have to gimplify, in order to handle the case of variable sized types. Avoid shared tree structures. */ - CONSTRUCTOR_ELTS (ctor) = NULL_TREE; + CONSTRUCTOR_ELTS (ctor) = NULL; object = unshare_expr (object); gimplify_stmt (expr_p); append_to_statement_list (*expr_p, pre_p); @@ -2776,7 +2780,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, &preeval_data); - gimplify_init_ctor_eval (object, elt_list, pre_p, cleared); + gimplify_init_ctor_eval (object, elts, pre_p, cleared); } *expr_p = NULL_TREE; @@ -2788,17 +2792,9 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, tree r, i; /* Extract the real and imaginary parts out of the ctor. */ - r = i = NULL_TREE; - if (elt_list) - { - r = TREE_VALUE (elt_list); - elt_list = TREE_CHAIN (elt_list); - if (elt_list) - { - i = TREE_VALUE (elt_list); - gcc_assert (!TREE_CHAIN (elt_list)); - } - } + gcc_assert (VEC_length (constructor_elt, elts) == 2); + r = VEC_index (constructor_elt, elts, 0)->value; + i = VEC_index (constructor_elt, elts, 1)->value; if (r == NULL || i == NULL) { tree zero = convert (TREE_TYPE (type), integer_zero_node); @@ -2827,35 +2823,44 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, break; case VECTOR_TYPE: - /* Go ahead and simplify constant constructors to VECTOR_CST. */ - if (TREE_CONSTANT (ctor)) - { - tree tem; + { + unsigned HOST_WIDE_INT ix; + constructor_elt *ce; - /* Even when ctor is constant, it might contain non-*_CST - elements (e.g. { 1.0/0.0 - 1.0/0.0, 0.0 }) and those don't - belong into VECTOR_CST nodes. */ - for (tem = elt_list; tem; tem = TREE_CHAIN (tem)) - if (! CONSTANT_CLASS_P (TREE_VALUE (tem))) - break; + /* Go ahead and simplify constant constructors to VECTOR_CST. */ + if (TREE_CONSTANT (ctor)) + { + bool constant_p = true; + tree value; + + /* Even when ctor is constant, it might contain non-*_CST + elements (e.g. { 1.0/0.0 - 1.0/0.0, 0.0 }) and those don't + belong into VECTOR_CST nodes. */ + FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value) + if (!CONSTANT_CLASS_P (value)) + { + constant_p = false; + break; + } - if (! tem) - { - TREE_OPERAND (*expr_p, 1) = build_vector (type, elt_list); - break; - } - } + if (constant_p) + { + TREE_OPERAND (*expr_p, 1) = build_vector_from_ctor (type, elts); + break; + } + } - /* Vector types use CONSTRUCTOR all the way through gimple - compilation as a general initializer. */ - for (; elt_list; elt_list = TREE_CHAIN (elt_list)) - { - enum gimplify_status tret; - tret = gimplify_expr (&TREE_VALUE (elt_list), pre_p, post_p, - is_gimple_val, fb_rvalue); - if (tret == GS_ERROR) - ret = GS_ERROR; - } + /* Vector types use CONSTRUCTOR all the way through gimple + compilation as a general initializer. */ + for (ix = 0; VEC_iterate (constructor_elt, elts, ix, ce); ix++) + { + enum gimplify_status tret; + tret = gimplify_expr (&ce->value, pre_p, post_p, + is_gimple_val, fb_rvalue); + if (tret == GS_ERROR) + ret = GS_ERROR; + } + } break; default: @@ -4159,10 +4164,14 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, gimplify any element that has side-effects. */ if (fallback == fb_none) { - for (tmp = CONSTRUCTOR_ELTS (*expr_p); tmp; - tmp = TREE_CHAIN (tmp)) - if (TREE_SIDE_EFFECTS (TREE_VALUE (tmp))) - gimplify_expr (&TREE_VALUE (tmp), pre_p, post_p, + unsigned HOST_WIDE_INT ix; + constructor_elt *ce; + for (ix = 0; + VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (*expr_p), + ix, ce); + ix++) + if (TREE_SIDE_EFFECTS (ce->value)) + gimplify_expr (&ce->value, pre_p, post_p, gimple_test_f, fallback); *expr_p = NULL_TREE; diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 26459dfabda..1b6eccf3a04 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,26 @@ +2005-07-20 Giovanni Bajo <giovannibajo@libero.it> + + Make CONSTRUCTOR use VEC to store initializers. + * check-init.c (check_init): Update to cope with VEC in + CONSTRUCTOR_ELTS. + * class.c (make_field_value, make_method_value, get_dispatch_table, + make_class_data, emit_symbol_table, emit_catch_table, + emit_assertion_table): Use build_constructor_from_list instead of + build_constructor. + * constants.c (build_constants_constructor): Likewise. + * java-gimplify.c (java_gimplify_new_array_init): Update to cope with + VEC in CONSTRUCTOR_ELTS. + * java-tree.h (START_RECORD_CONSTRUCTOR, PUSH_SUPER_VALUE, + PUSH_FIELD_VALUE, FINISH_RECORD_CONSTRUCTOR): Create a VEC instead + of a TREE_LIST. + * jcf-write.c (generate_bytecode_insns): Update to cope with VEC in + CONSTRUCTOR_ELTS. + * parse.y (build_new_array_init): Use build_constructor_from_list + instead of build_constructor. + (patch_new_array_init): Update to cope with VEC in + CONSTRUCTOR_ELTS. + (array_constructor_check_entry): Likewise. + 2005-07-12 Tom Tromey <tromey@redhat.com> * jvspec.c (lang_specific_driver): Put filelist_filename first on diff --git a/gcc/java/check-init.c b/gcc/java/check-init.c index f8b1736f2dc..377ac78630b 100644 --- a/gcc/java/check-init.c +++ b/gcc/java/check-init.c @@ -918,9 +918,11 @@ check_init (tree exp, words before) case NEW_ARRAY_INIT: { - tree x = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); - for ( ; x != NULL_TREE; x = TREE_CHAIN (x)) - check_init (TREE_VALUE (x), before); + tree value; + unsigned HOST_WIDE_INT idx; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)), + idx, value) + check_init (value, before); } break; diff --git a/gcc/java/class.c b/gcc/java/class.c index eca80178987..c2bd62f7a73 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1278,7 +1278,7 @@ make_field_value (tree fdecl) PUSH_FIELD_VALUE (finit, "info", - build_constructor (field_info_union_node, + build_constructor_from_list (field_info_union_node, build_tree_list ((FIELD_STATIC (fdecl) ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node)) @@ -1359,7 +1359,7 @@ make_method_value (tree mdecl) table = tree_cons (NULL_TREE, utf8, table); } type = build_prim_array_type (ptr_type_node, length); - table = build_constructor (type, table); + table = build_constructor_from_list (type, table); /* Compute something unique enough. */ sprintf (buf, "_methods%d", method_name_count++); array = build_decl (VAR_DECL, get_identifier (buf), type); @@ -1480,8 +1480,9 @@ get_dispatch_table (tree type, tree this_class_addr) if (TARGET_VTABLE_USES_DESCRIPTORS) arraysize *= TARGET_VTABLE_USES_DESCRIPTORS; arraysize += 2; - return build_constructor (build_prim_array_type (nativecode_ptr_type_node, - arraysize), list); + return build_constructor_from_list + (build_prim_array_type (nativecode_ptr_type_node, + arraysize), list); } @@ -1608,8 +1609,8 @@ make_class_data (tree type) field_array_type = build_prim_array_type (field_type_node, field_count); fields_decl = build_decl (VAR_DECL, mangled_classname ("_FL_", type), field_array_type); - DECL_INITIAL (fields_decl) = build_constructor (field_array_type, - static_fields); + DECL_INITIAL (fields_decl) = build_constructor_from_list + (field_array_type, static_fields); TREE_STATIC (fields_decl) = 1; DECL_ARTIFICIAL (fields_decl) = 1; DECL_IGNORED_P (fields_decl) = 1; @@ -1639,8 +1640,8 @@ make_class_data (tree type) method_array_type = build_prim_array_type (method_type_node, method_count); methods_decl = build_decl (VAR_DECL, mangled_classname ("_MT_", type), method_array_type); - DECL_INITIAL (methods_decl) = build_constructor (method_array_type, - nreverse (methods)); + DECL_INITIAL (methods_decl) = build_constructor_from_list + (method_array_type, nreverse (methods)); TREE_STATIC (methods_decl) = 1; DECL_ARTIFICIAL (methods_decl) = 1; DECL_IGNORED_P (methods_decl) = 1; @@ -1715,7 +1716,8 @@ make_class_data (tree type) } init = tree_cons (NULL_TREE, index, init); } - DECL_INITIAL (idecl) = build_constructor (interface_array_type, init); + DECL_INITIAL (idecl) = build_constructor_from_list (interface_array_type, + init); TREE_STATIC (idecl) = 1; DECL_ARTIFICIAL (idecl) = 1; DECL_IGNORED_P (idecl) = 1; @@ -2528,7 +2530,7 @@ emit_symbol_table (tree name, tree the_table, tree decl_list, /* Put the list in the right order and make it a constructor. */ list = nreverse (list); - table = build_constructor (symbols_array_type, list); + table = build_constructor_from_list (symbols_array_type, list); /* Make it the initial value for otable_syms and emit the decl. */ DECL_INITIAL (the_syms_decl) = table; @@ -2589,7 +2591,7 @@ emit_catch_table (tree this_class) table = build_decl (VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type); DECL_INITIAL (table) = - build_constructor (array_type, TYPE_CATCH_CLASSES (this_class)); + build_constructor_from_list (array_type, TYPE_CATCH_CLASSES (this_class)); TREE_STATIC (table) = 1; TREE_READONLY (table) = 1; DECL_IGNORED_P (table) = 1; @@ -2669,7 +2671,7 @@ emit_assertion_table (tree class) /* Put the list in the right order and make it a constructor. */ list = nreverse (list); - ctor = build_constructor (assertion_table_type, list); + ctor = build_constructor_from_list (assertion_table_type, list); table_decl = build_decl (VAR_DECL, mangled_classname ("_type_assert_", class), assertion_table_type); diff --git a/gcc/java/constants.c b/gcc/java/constants.c index 335f20cbafe..bba67a708eb 100644 --- a/gcc/java/constants.c +++ b/gcc/java/constants.c @@ -515,8 +515,8 @@ build_constants_constructor (void) data_decl = build_constant_data_ref (); TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type); - DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl), - data_list); + DECL_INITIAL (data_decl) = build_constructor_from_list + (TREE_TYPE (data_decl), data_list); DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl)); DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl)); rest_of_decl_compilation (data_decl, 1, 0); @@ -527,7 +527,8 @@ build_constants_constructor (void) current_class), tags_type); TREE_STATIC (tags_decl) = 1; - DECL_INITIAL (tags_decl) = build_constructor (tags_type, tags_list); + DECL_INITIAL (tags_decl) = build_constructor_from_list + (tags_type, tags_list); rest_of_decl_compilation (tags_decl, 1, 0); tags_value = build_address_of (tags_decl); } diff --git a/gcc/java/java-gimplify.c b/gcc/java/java-gimplify.c index 60713a41b09..cbc174d8f02 100644 --- a/gcc/java/java-gimplify.c +++ b/gcc/java/java-gimplify.c @@ -296,7 +296,8 @@ java_gimplify_new_array_init (tree exp) HOST_WIDE_INT ilength = java_array_type_length (array_type); tree length = build_int_cst (NULL_TREE, ilength); tree init = TREE_OPERAND (exp, 0); - tree values = CONSTRUCTOR_ELTS (init); + tree value; + unsigned HOST_WIDE_INT cnt; tree array_ptr_type = build_pointer_type (array_type); tree tmp = create_tmp_var (array_ptr_type, "array"); @@ -306,7 +307,7 @@ java_gimplify_new_array_init (tree exp) int index = 0; /* FIXME: try to allocate array statically? */ - while (values != NULL_TREE) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), cnt, value) { /* FIXME: Should use build_java_arrayaccess here, but avoid bounds checking. */ @@ -317,9 +318,8 @@ java_gimplify_new_array_init (tree exp) build4 (ARRAY_REF, element_type, lhs, build_int_cst (NULL_TREE, index++), NULL_TREE, NULL_TREE), - TREE_VALUE (values)); + value); body = build2 (COMPOUND_EXPR, element_type, body, assignment); - values = TREE_CHAIN (values); } return build2 (COMPOUND_EXPR, array_ptr_type, body, tmp); diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 5b634357879..ab6157b7c61 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -1762,41 +1762,49 @@ extern tree *type_map; #define FINISH_RECORD(RTYPE) layout_type (RTYPE) /* Start building a RECORD_TYPE constructor with a given TYPE in CONS. */ -#define START_RECORD_CONSTRUCTOR(CONS, CTYPE) \ -{ CONS = build_constructor ((CTYPE), NULL_TREE); \ - TREE_CHAIN (CONS) = TYPE_FIELDS (CTYPE); } +#define START_RECORD_CONSTRUCTOR(CONS, CTYPE) \ + do \ + { \ + CONS = build_constructor ((CTYPE), VEC_alloc (constructor_elt, gc, 0)); \ + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (CONS), TYPE_FIELDS (CTYPE), \ + NULL); \ + } \ + while (0) /* Append a field initializer to CONS for the dummy field for the inherited fields. The dummy field has the given VALUE, and the same type as the super-class. Must be specified before calls to PUSH_FIELD_VALUE. */ -#define PUSH_SUPER_VALUE(CONS, VALUE) \ -{ \ - tree _field = TREE_CHAIN (CONS); \ - if (DECL_NAME (_field) != NULL_TREE) \ - abort (); \ - CONSTRUCTOR_ELTS (CONS) \ - = tree_cons (_field, (VALUE), CONSTRUCTOR_ELTS (CONS)); \ - TREE_CHAIN (CONS) = TREE_CHAIN (_field); \ -} +#define PUSH_SUPER_VALUE(CONS, VALUE) \ + do \ + { \ + constructor_elt *_elt___ = VEC_last (constructor_elt, \ + CONSTRUCTOR_ELTS (CONS)); \ + tree _next___ = TREE_CHAIN (_elt___->index); \ + gcc_assert (!DECL_NAME (_elt___->index)); \ + _elt___->value = VALUE; \ + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (CONS), _next___, NULL); \ + } \ + while (0) /* Append a field initializer to CONS for a field with the given VALUE. NAME is a char* string used for error checking; the initializer must be specified in order. */ #define PUSH_FIELD_VALUE(CONS, NAME, VALUE) \ -do \ -{ \ - tree _field = TREE_CHAIN (CONS); \ - if (strcmp (IDENTIFIER_POINTER (DECL_NAME (_field)), NAME) != 0) \ - abort (); \ - CONSTRUCTOR_ELTS (CONS) \ - = tree_cons (_field, (VALUE), CONSTRUCTOR_ELTS (CONS)); \ - TREE_CHAIN (CONS) = TREE_CHAIN (_field); \ -} \ -while (0) + do \ + { \ + constructor_elt *_elt___ = VEC_last (constructor_elt, \ + CONSTRUCTOR_ELTS (CONS)); \ + tree _next___ = TREE_CHAIN (_elt___->index); \ + gcc_assert (strcmp (IDENTIFIER_POINTER (DECL_NAME (_elt___->index)), \ + NAME) == 0); \ + _elt___->value = VALUE; \ + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (CONS), _next___, NULL); \ + } \ + while (0) /* Finish creating a record CONSTRUCTOR CONS. */ #define FINISH_RECORD_CONSTRUCTOR(CONS) \ - CONSTRUCTOR_ELTS(CONS) = nreverse (CONSTRUCTOR_ELTS (CONS)) + VEC_pop (constructor_elt, CONSTRUCTOR_ELTS (CONS)) /* Macros on constructors invocations. */ #define CALL_CONSTRUCTOR_P(NODE) \ diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c index c27b7320eb1..45764995143 100644 --- a/gcc/java/jcf-write.c +++ b/gcc/java/jcf-write.c @@ -2461,14 +2461,16 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state) break; case NEW_ARRAY_INIT: { - tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); tree array_type = TREE_TYPE (TREE_TYPE (exp)); tree element_type = TYPE_ARRAY_ELEMENT (array_type); + unsigned HOST_WIDE_INT idx; + tree value; HOST_WIDE_INT length = java_array_type_length (array_type); if (target == IGNORE_TARGET) { - for ( ; values != NULL_TREE; values = TREE_CHAIN (values)) - generate_bytecode_insns (TREE_VALUE (values), target, state); + FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) + generate_bytecode_insns (value, target, state); break; } push_int_const (length, state); @@ -2489,16 +2491,17 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state) } offset = 0; jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7); - for ( ; values != NULL_TREE; values = TREE_CHAIN (values), offset++) + FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) { int save_SP = state->code_SP; emit_dup (1, 0, state); push_int_const (offset, state); NOTE_PUSH (1); - generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state); + generate_bytecode_insns (value, STACK_TARGET, state); RESERVE (1); OP1 (jopcode); state->code_SP = save_SP; + offset++; } } break; diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 6007b18a11d..10a37e0e449 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -274,7 +274,7 @@ static void missing_return_error (tree); static tree build_new_array_init (int, tree); static tree patch_new_array_init (tree, tree); static tree maybe_build_array_element_wfl (tree); -static int array_constructor_check_entry (tree, tree); +static int array_constructor_check_entry (tree, constructor_elt *); static const char *purify_type_name (const char *); static tree fold_constant_for_init (tree, tree); static jdeplist *reverse_jdep_list (struct parser_ctxt *); @@ -14793,7 +14793,8 @@ maybe_build_array_element_wfl (tree node) static tree build_new_array_init (int location, tree values) { - tree constructor = build_constructor (NULL_TREE, values); + tree constructor = build_constructor_from_list (NULL_TREE, + nreverse (values)); tree to_return = build1 (NEW_ARRAY_INIT, NULL_TREE, constructor); EXPR_WFL_LINECOL (to_return) = location; return to_return; @@ -14807,8 +14808,9 @@ static tree patch_new_array_init (tree type, tree node) { int error_seen = 0; - tree current, element_type; - HOST_WIDE_INT length; + tree element_type; + unsigned HOST_WIDE_INT length; + constructor_elt *current; int all_constant = 1; tree init = TREE_OPERAND (node, 0); @@ -14822,16 +14824,16 @@ patch_new_array_init (tree type, tree node) type = TREE_TYPE (type); element_type = TYPE_ARRAY_ELEMENT (type); - CONSTRUCTOR_ELTS (init) = nreverse (CONSTRUCTOR_ELTS (init)); - - for (length = 0, current = CONSTRUCTOR_ELTS (init); - current; length++, current = TREE_CHAIN (current)) + for (length = 0; + VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (init), + length, current); + length++) { - tree elt = TREE_VALUE (current); + tree elt = current->value; if (elt == NULL_TREE || TREE_CODE (elt) != NEW_ARRAY_INIT) { error_seen |= array_constructor_check_entry (element_type, current); - elt = TREE_VALUE (current); + elt = current->value; /* When compiling to native code, STRING_CST is converted to INDIRECT_REF, but still with a TREE_CONSTANT flag. */ if (! TREE_CONSTANT (elt) || TREE_CODE (elt) == INDIRECT_REF) @@ -14839,8 +14841,8 @@ patch_new_array_init (tree type, tree node) } else { - TREE_VALUE (current) = patch_new_array_init (element_type, elt); - TREE_PURPOSE (current) = NULL_TREE; + current->value = patch_new_array_init (element_type, elt); + current->index = NULL_TREE; all_constant = 0; } if (elt && TREE_CODE (elt) == TREE_LIST @@ -14869,16 +14871,16 @@ patch_new_array_init (tree type, tree node) otherwise. */ static int -array_constructor_check_entry (tree type, tree entry) +array_constructor_check_entry (tree type, constructor_elt *entry) { char *array_type_string = NULL; /* For error reports */ tree value, type_value, new_value, wfl_value, patched; int error_seen = 0; new_value = NULL_TREE; - wfl_value = TREE_VALUE (entry); + wfl_value = entry->value; - value = java_complete_tree (TREE_VALUE (entry)); + value = java_complete_tree (entry->value); /* patch_string return error_mark_node if arg is error_mark_node */ if ((patched = patch_string (value))) value = patched; @@ -14889,7 +14891,7 @@ array_constructor_check_entry (tree type, tree entry) /* At anytime, try_builtin_assignconv can report a warning on constant overflow during narrowing. */ - SET_WFL_OPERATOR (wfl_operator, TREE_PURPOSE (entry), wfl_value); + SET_WFL_OPERATOR (wfl_operator, entry->index, wfl_value); new_value = try_builtin_assignconv (wfl_operator, type, value); if (!new_value && (new_value = try_reference_assignconv (type, value))) type_value = promote_type (type); @@ -14908,12 +14910,12 @@ array_constructor_check_entry (tree type, tree entry) } if (new_value) - TREE_VALUE (entry) = new_value; + entry->value = new_value; if (array_type_string) free (array_type_string); - TREE_PURPOSE (entry) = NULL_TREE; + entry->index = NULL_TREE; return error_seen; } diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 9bd62da8e4f..31a1e8f9159 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,9 @@ +2005-07-20 Giovanni Bajo <giovannibajo@libero.it> + + Make CONSTRUCTOR use VEC to store initializers. + * objc-act.c (objc_build_constructor): Use build_constructor_from_list + instead of build_constructor. + 2005-07-08 Daniel Berlin <dberlin@dberlin.org> * objc-act.c (objc_push_parm): DECL_ARG_TYPE_AS_WRITTEN is diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index ee7b0287271..d004fb5eb04 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -2001,7 +2001,7 @@ objc_add_static_instance (tree constructor, tree class_decl) static tree objc_build_constructor (tree type, tree elts) { - tree constructor = build_constructor (type, elts); + tree constructor = build_constructor_from_list (type, elts); TREE_CONSTANT (constructor) = 1; TREE_STATIC (constructor) = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4ffcf4ca02e..5d69c6faca4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2005-07-20 Giovanni Bajo <giovannibajo@libero.it> + + Make CONSTRUCTOR use VEC to store initializers. + * g++.dg/ext/complit3.C: Check for specific error messages. + * g++.dg/init/brace2.C: Update error message. + * g++.dg/warn/Wbraces2.C: Likewise. + 2005-07-19 Paul Thomas <pault@gcc.gnu.org> PR fortran/16940 diff --git a/gcc/testsuite/g++.dg/ext/complit3.C b/gcc/testsuite/g++.dg/ext/complit3.C index 92e2033100e..1783a08bdc7 100644 --- a/gcc/testsuite/g++.dg/ext/complit3.C +++ b/gcc/testsuite/g++.dg/ext/complit3.C @@ -2,7 +2,7 @@ int Compound_Literals_0() { - static int y[] = (int []) {1, 2, 3}; // { dg-error "" } - static int z[] = (int [3]) {1}; // { dg-error "" } + static int y[] = (int []) {1, 2, 3}; // { dg-error "compound literal" } + static int z[] = (int [3]) {1}; // { dg-error "compound literal" } return y[0]+z[0]; } diff --git a/gcc/testsuite/g++.dg/init/brace2.C b/gcc/testsuite/g++.dg/init/brace2.C index 488d916aa42..5138430e5cb 100644 --- a/gcc/testsuite/g++.dg/init/brace2.C +++ b/gcc/testsuite/g++.dg/init/brace2.C @@ -3,6 +3,6 @@ int x = { 2 }; const char * y = { "hello" }; int a = 2; -int b = { 2,3 }; // { dg-error "requires one element" } +int b = { 2,3 }; // { dg-error "too many initializers" } int c = { { 2 } } ; // { dg-error "braces around scalar initializer" } diff --git a/gcc/testsuite/g++.dg/warn/Wbraces2.C b/gcc/testsuite/g++.dg/warn/Wbraces2.C index b51d5ca77b9..6d54ede9b4c 100644 --- a/gcc/testsuite/g++.dg/warn/Wbraces2.C +++ b/gcc/testsuite/g++.dg/warn/Wbraces2.C @@ -2,14 +2,14 @@ // { dg-options "-Wmissing-braces" } int a[2][2] = { 0, 1, 2, 3 }; // { dg-warning "missing braces" } int b[2][2] = { { 0, 1 }, { 2, 3 } }; -int c[2][2] = { { { 0 }, 1 }, { 2, 3 } }; // { dg-error "brace-enclosed" } +int c[2][2] = { { { 0 }, 1 }, { 2, 3 } }; // { dg-error "braces around scalar" } struct S { char s[6]; int i; }; S d = { "hello", 1 }; S e = { { "hello" }, 1 }; -S f = { { { "hello" } }, 1 }; // { dg-error "brace-enclosed" } +S f = { { { "hello" } }, 1 }; // { dg-error "braces around scalar" } S g = { 'h', 'e', 'l', 'l', 'o', '\0', 1 }; // { dg-warning "missing braces" } struct T { wchar_t s[6]; int i; }; T i = { L"hello", 1 }; T j = { { L"hello" }, 1 }; -T k = { { { L"hello" } }, 1 }; // { dg-error "brace-enclosed" } +T k = { { { L"hello" } }, 1 }; // { dg-error "braces around scalar" } T l = { L'h', L'e', L'l', L'l', L'o', L'\0', 1 };// { dg-warning "missing braces" } diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index 3f6592bd306..2beecc74456 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -583,7 +583,17 @@ dequeue_and_dump (dump_info_p di) break; case CONSTRUCTOR: - dump_child ("elts", CONSTRUCTOR_ELTS (t)); + { + unsigned HOST_WIDE_INT cnt; + tree index, value; + dump_int (di, "lngt", VEC_length (constructor_elt, + CONSTRUCTOR_ELTS (t))); + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value) + { + dump_child ("idx", index); + dump_child ("val", value); + } + } break; case BIND_EXPR: diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index fe70751cc9a..ff7ea43a105 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2395,7 +2395,22 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) if (TREE_CODE (*tp) == BIND_EXPR) BIND_EXPR_BLOCK (*tp) = NULL_TREE; } + else if (code == CONSTRUCTOR) + { + /* CONSTRUCTOR nodes need special handling because + we need to duplicate the vector of elements. */ + tree new; + + new = copy_node (*tp); + + /* Propagate mudflap marked-ness. */ + if (flag_mudflap && mf_marked_p (*tp)) + mf_mark (new); + CONSTRUCTOR_ELTS (new) = VEC_copy (constructor_elt, gc, + CONSTRUCTOR_ELTS (*tp)); + *tp = new; + } else if (TREE_CODE_CLASS (code) == tcc_type) *walk_subtrees = 0; else if (TREE_CODE_CLASS (code) == tcc_declaration) diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 1d61de214f0..d7bfe8c129c 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -778,36 +778,29 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, case CONSTRUCTOR: { - tree lnode; + unsigned HOST_WIDE_INT ix; + tree field, val; bool is_struct_init = FALSE; pp_character (buffer, '{'); - lnode = CONSTRUCTOR_ELTS (node); if (TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE || TREE_CODE (TREE_TYPE (node)) == UNION_TYPE) is_struct_init = TRUE; - while (lnode && lnode != error_mark_node) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (node), ix, field, val) { - tree val; - if (TREE_PURPOSE (lnode) && is_struct_init) + if (field && is_struct_init) { pp_character (buffer, '.'); - dump_generic_node (buffer, TREE_PURPOSE (lnode), spc, flags, false); + dump_generic_node (buffer, field, spc, flags, false); pp_string (buffer, "="); } - val = TREE_VALUE (lnode); if (val && TREE_CODE (val) == ADDR_EXPR) if (TREE_CODE (TREE_OPERAND (val, 0)) == FUNCTION_DECL) val = TREE_OPERAND (val, 0); if (val && TREE_CODE (val) == FUNCTION_DECL) - { dump_decl_name (buffer, val, flags); - } else - { - dump_generic_node (buffer, TREE_VALUE (lnode), spc, flags, false); - } - lnode = TREE_CHAIN (lnode); - if (lnode && TREE_CODE (lnode) == TREE_LIST) + dump_generic_node (buffer, val, spc, flags, false); + if (ix != VEC_length (constructor_elt, CONSTRUCTOR_ELTS (node)) - 1) { pp_character (buffer, ','); pp_space (buffer); diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index b3494af5c92..0d839d8cbb7 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -1642,6 +1642,8 @@ generate_element_init_1 (struct sra_elt *elt, tree init, tree *list_p) enum tree_code init_code; struct sra_elt *sub; tree t; + unsigned HOST_WIDE_INT idx; + tree value, purpose; /* We can be passed DECL_INITIAL of a static variable. It might have a conversion, which we strip off here. */ @@ -1675,11 +1677,8 @@ generate_element_init_1 (struct sra_elt *elt, tree init, tree *list_p) break; case CONSTRUCTOR: - for (t = CONSTRUCTOR_ELTS (init); t ; t = TREE_CHAIN (t)) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, purpose, value) { - tree purpose = TREE_PURPOSE (t); - tree value = TREE_VALUE (t); - if (TREE_CODE (purpose) == RANGE_EXPR) { tree lower = TREE_OPERAND (purpose, 0); diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 8bf824250e4..95a2fa13864 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -936,7 +936,9 @@ static tree fold_const_aggregate_ref (tree t) { prop_value_t *value; - tree base, ctor, idx, field, elt; + tree base, ctor, idx, field; + unsigned HOST_WIDE_INT cnt; + tree cfield, cval; switch (TREE_CODE (t)) { @@ -993,13 +995,9 @@ fold_const_aggregate_ref (tree t) } /* Whoo-hoo! I'll fold ya baby. Yeah! */ - for (elt = CONSTRUCTOR_ELTS (ctor); - (elt && !tree_int_cst_equal (TREE_PURPOSE (elt), idx)); - elt = TREE_CHAIN (elt)) - ; - - if (elt) - return TREE_VALUE (elt); + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval) + if (tree_int_cst_equal (cfield, idx)) + return cval; break; case COMPONENT_REF: @@ -1035,11 +1033,11 @@ fold_const_aggregate_ref (tree t) field = TREE_OPERAND (t, 1); - for (elt = CONSTRUCTOR_ELTS (ctor); elt; elt = TREE_CHAIN (elt)) - if (TREE_PURPOSE (elt) == field + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval) + if (cfield == field /* FIXME: Handle bit-fields. */ - && ! DECL_BIT_FIELD (TREE_PURPOSE (elt))) - return TREE_VALUE (elt); + && ! DECL_BIT_FIELD (cfield)) + return cval; break; default: diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 609fa0f947c..2044394337f 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1390,10 +1390,13 @@ get_expr_operands (tree stmt, tree *expr_p, int flags) { /* General aggregate CONSTRUCTORs have been decomposed, but they are still in use as the COMPLEX_EXPR equivalent for vectors. */ + constructor_elt *ce; + unsigned HOST_WIDE_INT idx; - tree t; - for (t = TREE_OPERAND (expr, 0); t ; t = TREE_CHAIN (t)) - get_expr_operands (stmt, &TREE_VALUE (t), opf_none); + for (idx = 0; + VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (expr), idx, ce); + idx++) + get_expr_operands (stmt, &ce->value, opf_none); return; } diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 015a727de3a..f9c9fda3104 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -207,7 +207,7 @@ expand_vector_piecewise (block_stmt_iterator *bsi, elem_op_func f, tree type, tree inner_type, tree a, tree b, enum tree_code code) { - tree head, *chain = &head; + VEC(constructor_elt,gc) *v; tree part_width = TYPE_SIZE (inner_type); tree index = bitsize_int (0); int nunits = TYPE_VECTOR_SUBPARTS (type); @@ -215,15 +215,17 @@ expand_vector_piecewise (block_stmt_iterator *bsi, elem_op_func f, / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1); int i; + v = VEC_alloc(constructor_elt, gc, (nunits + delta - 1) / delta); for (i = 0; i < nunits; i += delta, index = int_const_binop (PLUS_EXPR, index, part_width, 0)) { tree result = f (bsi, inner_type, a, b, index, part_width, code); - *chain = tree_cons (NULL_TREE, result, NULL_TREE); - chain = &TREE_CHAIN (*chain); + constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL); + ce->index = NULL_TREE; + ce->value = result; } - return build1 (CONSTRUCTOR, type, head); + return build_constructor (type, v); } /* Expand a vector operation to scalars with the freedom to use diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 525eef46001..c2a8f0d9dc4 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -596,7 +596,8 @@ vect_get_vec_def_for_operand (tree op, tree stmt, tree *scalar_def) t = tree_cons (NULL_TREE, def, t); } - vec_inv = build_constructor (vectype, t); + /* FIXME: use build_constructor directly. */ + vec_inv = build_constructor_from_list (vectype, t); return vect_init_vector (stmt, vec_inv); } @@ -771,7 +772,7 @@ get_initial_def_for_reduction (tree stmt, tree init_val, tree *scalar_def) if (TREE_CODE (init_val) == INTEGER_CST || TREE_CODE (init_val) == REAL_CST) vec = build_vector (vectype, t); else - vec = build_constructor (vectype, t); + vec = build_constructor_from_list (vectype, t); if (!need_epilog_adjust) { diff --git a/gcc/tree-vn.c b/gcc/tree-vn.c index 38ba39b69bb..4863cb76f36 100644 --- a/gcc/tree-vn.c +++ b/gcc/tree-vn.c @@ -182,7 +182,8 @@ set_value_handle (tree e, tree v) { if (TREE_CODE (e) == SSA_NAME) SSA_NAME_VALUE (e) = v; - else if (EXPR_P (e) || DECL_P (e) || TREE_CODE (e) == TREE_LIST) + else if (EXPR_P (e) || DECL_P (e) || TREE_CODE (e) == TREE_LIST + || TREE_CODE (e) == CONSTRUCTOR) get_tree_ann (e)->common.value_handle = v; else /* Do nothing. Constants are their own value handles. */ @@ -287,7 +288,8 @@ get_value_handle (tree expr) if (TREE_CODE (expr) == SSA_NAME) return SSA_NAME_VALUE (expr); - else if (EXPR_P (expr) || DECL_P (expr) || TREE_CODE (expr) == TREE_LIST) + else if (EXPR_P (expr) || DECL_P (expr) || TREE_CODE (expr) == TREE_LIST + || TREE_CODE (expr) == CONSTRUCTOR) { tree_ann_t ann = tree_ann (expr); return ((ann) ? ann->common.value_handle : NULL_TREE); diff --git a/gcc/tree.c b/gcc/tree.c index 20cd722ec0f..770ed313856 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -93,6 +93,7 @@ static const char * const tree_node_kind_names[] = { "binfos", "phi_nodes", "ssa names", + "constructors", "random kinds", "lang_decl kinds", "lang_type kinds" @@ -328,6 +329,7 @@ tree_code_size (enum tree_code code) case STATEMENT_LIST: return sizeof (struct tree_statement_list); case BLOCK: return sizeof (struct tree_block); case VALUE_HANDLE: return sizeof (struct tree_value_handle); + case CONSTRUCTOR: return sizeof (struct tree_constructor); default: return lang_hooks.tree_size (code); @@ -418,7 +420,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = id_kind; break; - case TREE_VEC:; + case TREE_VEC: kind = vec_kind; break; @@ -438,6 +440,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = b_kind; break; + case CONSTRUCTOR: + kind = constr_kind; + break; + default: kind = x_kind; break; @@ -904,27 +910,72 @@ build_vector (tree type, tree vals) return v; } +/* Return a new VECTOR_CST node whose type is TYPE and whose values + are extracted from V, a vector of CONSTRUCTOR_ELT. */ + +tree +build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v) +{ + tree list = NULL_TREE; + unsigned HOST_WIDE_INT idx; + tree value; + + FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) + list = tree_cons (NULL_TREE, value, list); + return build_vector (type, nreverse (list)); +} + /* Return a new CONSTRUCTOR node whose type is TYPE and whose values - are in a list pointed to by VALS. */ + are in the VEC pointed by VALS. */ tree -build_constructor (tree type, tree vals) +build_constructor (tree type, VEC(constructor_elt,gc) *vals) { tree c = make_node (CONSTRUCTOR); TREE_TYPE (c) = type; CONSTRUCTOR_ELTS (c) = vals; + return c; +} + +/* Build a CONSTRUCTOR node made of a single initializer, with the specified + INDEX and VALUE. */ +tree +build_constructor_single (tree type, tree index, tree value) +{ + VEC(constructor_elt,gc) *v; + constructor_elt *elt; + + v = VEC_alloc (constructor_elt, gc, 1); + elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = index; + elt->value = value; + + return build_constructor (type, v); +} + + +/* Return a new CONSTRUCTOR node whose type is TYPE and whose values + are in a list pointed to by VALS. */ +tree +build_constructor_from_list (tree type, tree vals) +{ + tree t; + VEC(constructor_elt,gc) *v = NULL; - /* ??? May not be necessary. Mirrors what build does. */ if (vals) { - TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals); - TREE_READONLY (c) = TREE_READONLY (vals); - TREE_CONSTANT (c) = TREE_CONSTANT (vals); - TREE_INVARIANT (c) = TREE_INVARIANT (vals); + v = VEC_alloc (constructor_elt, gc, list_length (vals)); + for (t = vals; t; t = TREE_CHAIN (t)) + { + constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = TREE_PURPOSE (t); + elt->value = TREE_VALUE (t); + } } - return c; + return build_constructor (type, v); } + /* Return a new REAL_CST node whose type is TYPE and value is D. */ tree @@ -1951,6 +2002,7 @@ tree_node_structure (tree t) case PLACEHOLDER_EXPR: return TS_COMMON; case STATEMENT_LIST: return TS_STATEMENT_LIST; case BLOCK: return TS_BLOCK; + case CONSTRUCTOR: return TS_CONSTRUCTOR; case TREE_BINFO: return TS_BINFO; case VALUE_HANDLE: return TS_VALUE_HANDLE; @@ -4321,8 +4373,21 @@ simple_cst_equal (tree t1, tree t2) TREE_STRING_LENGTH (t1))); case CONSTRUCTOR: - return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1), - CONSTRUCTOR_ELTS (t2)); + { + unsigned HOST_WIDE_INT idx; + VEC(constructor_elt, gc) *v1 = CONSTRUCTOR_ELTS (t1); + VEC(constructor_elt, gc) *v2 = CONSTRUCTOR_ELTS (t2); + + if (VEC_length (constructor_elt, v1) != VEC_length (constructor_elt, v2)) + return false; + + for (idx = 0; idx < VEC_length (constructor_elt, v1); ++idx) + /* ??? Should we handle also fields here? */ + if (!simple_cst_equal (VEC_index (constructor_elt, v1, idx)->value, + VEC_index (constructor_elt, v2, idx)->value)) + return false; + return true; + } case SAVE_EXPR: return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); @@ -4530,6 +4595,17 @@ iterative_hash_expr (tree t, hashval_t val) for (; t; t = TREE_CHAIN (t)) val = iterative_hash_expr (TREE_VALUE (t), val); return val; + case CONSTRUCTOR: + { + unsigned HOST_WIDE_INT idx; + tree field, value; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value) + { + val = iterative_hash_expr (field, val); + val = iterative_hash_expr (value, val); + } + return val; + } case FUNCTION_DECL: /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form. Otherwise nodes that compare equal @@ -6402,14 +6478,14 @@ initializer_zerop (tree init) return true; case CONSTRUCTOR: - elt = CONSTRUCTOR_ELTS (init); - if (elt == NULL_TREE) - return true; + { + unsigned HOST_WIDE_INT idx; - for (; elt ; elt = TREE_CHAIN (elt)) - if (! initializer_zerop (TREE_VALUE (elt))) - return false; - return true; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt) + if (!initializer_zerop (elt)) + return false; + return true; + } default: return false; @@ -7057,7 +7133,16 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); case CONSTRUCTOR: - WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp)); + { + unsigned HOST_WIDE_INT idx; + constructor_elt *ce; + + for (idx = 0; + VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (*tp), idx, ce); + idx++) + WALK_SUBTREE (ce->value); + } + break; case SAVE_EXPR: WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); diff --git a/gcc/tree.def b/gcc/tree.def index 43fa835fb01..00b130fbc24 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -435,19 +435,19 @@ DEFTREECODE (FILTER_EXPR, "filter_expr", tcc_expression, 0) /* Constructor: return an aggregate value made from specified components. In C, this is used only for structure and array initializers. - The operand is a list of component values made out of a chain of - TREE_LIST nodes. + The operand is a sequence of component values made out of a VEC of + struct constructor_elt. For ARRAY_TYPE: - The TREE_PURPOSE of each node is the corresponding index. - If the TREE_PURPOSE is a RANGE_EXPR, it is a short-hand for many nodes, - one for each index in the range. (If the corresponding TREE_VALUE + The field INDEX of each constructor_elt is the corresponding index. + If the index is a RANGE_EXPR, it is a short-hand for many nodes, + one for each index in the range. (If the corresponding field VALUE has side-effects, they are evaluated once for each element. Wrap the value in a SAVE_EXPR if you want to evaluate side effects only once.) For RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE: - The TREE_PURPOSE of each node is a FIELD_DECL. */ -DEFTREECODE (CONSTRUCTOR, "constructor", tcc_expression, 1) + The field INDEX of each node is a FIELD_DECL. */ +DEFTREECODE (CONSTRUCTOR, "constructor", tcc_exceptional, 0) /* The expression types are mostly straightforward, with the fourth argument of DEFTREECODE saying how many operands there are. diff --git a/gcc/tree.h b/gcc/tree.h index e1007a3caed..b9cd508edd0 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1190,6 +1190,57 @@ struct tree_vec GTY(()) tree GTY ((length ("TREE_VEC_LENGTH ((tree)&%h)"))) a[1]; }; +/* In a CONSTRUCTOR node. */ +#define CONSTRUCTOR_ELTS(NODE) (CONSTRUCTOR_CHECK (NODE)->constructor.elts) + +/* Iterate through the vector V of CONSTRUCTOR_ELT elements, yielding the + value of each element (stored within VAL). IX must be a scratch variable + of unsigned integer type. */ +#define FOR_EACH_CONSTRUCTOR_VALUE(V, IX, VAL) \ + for (IX = 0; (IX >= VEC_length (constructor_elt, V)) \ + ? false \ + : ((VAL = VEC_index (constructor_elt, V, IX)->value), \ + true); \ + (IX)++) + +/* Iterate through the vector V of CONSTRUCTOR_ELT elements, yielding both + the value of each element (stored within VAL) and its index (stored + within INDEX). IX must be a scratch variable of unsigned integer type. */ +#define FOR_EACH_CONSTRUCTOR_ELT(V, IX, INDEX, VAL) \ + for (IX = 0; (IX >= VEC_length (constructor_elt, V)) \ + ? false \ + : ((VAL = VEC_index (constructor_elt, V, IX)->value), \ + (INDEX = VEC_index (constructor_elt, V, IX)->index), \ + true); \ + (IX)++) + +/* Append a new constructor element to V, with the specified INDEX and VAL. */ +#define CONSTRUCTOR_APPEND_ELT(V, INDEX, VALUE) \ + do { \ + constructor_elt *_ce___ = VEC_safe_push (constructor_elt, gc, V, NULL); \ + _ce___->index = INDEX; \ + _ce___->value = VALUE; \ + } while (0) + +/* A single element of a CONSTRUCTOR. VALUE holds the actual value of the + element. INDEX can optionally design the position of VALUE: in arrays, + it is the index where VALUE has to be placed; in structures, it is the + FIELD_DECL of the member. */ +typedef struct constructor_elt_d GTY(()) +{ + tree index; + tree value; +} constructor_elt; + +DEF_VEC_O(constructor_elt); +DEF_VEC_ALLOC_O(constructor_elt,gc); + +struct tree_constructor GTY(()) +{ + struct tree_common common; + VEC(constructor_elt,gc) *elts; +}; + /* Define fields and accessors for some nodes that represent expressions. */ /* Nonzero if NODE is an empty statement (NOP_EXPR <0>). */ @@ -1197,9 +1248,6 @@ struct tree_vec GTY(()) && VOID_TYPE_P (TREE_TYPE (NODE)) \ && integer_zerop (TREE_OPERAND (NODE, 0))) -/* In a CONSTRUCTOR node. */ -#define CONSTRUCTOR_ELTS(NODE) TREE_OPERAND_CHECK_CODE (NODE, CONSTRUCTOR, 0) - /* In ordinary expression nodes. */ #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I) #define TREE_COMPLEXITY(NODE) (EXPR_CHECK (NODE)->exp.complexity) @@ -2725,8 +2773,6 @@ struct tree_value_handle GTY(()) unsigned int id; }; - - /* Define the overall contents of a tree node. It may be any of the structures declared above for various types of node. */ @@ -2764,6 +2810,7 @@ union tree_node GTY ((ptr_alias (union lang_tree_node), struct tree_binfo GTY ((tag ("TS_BINFO"))) binfo; struct tree_statement_list GTY ((tag ("TS_STATEMENT_LIST"))) stmt_list; struct tree_value_handle GTY ((tag ("TS_VALUE_HANDLE"))) value_handle; + struct tree_constructor GTY ((tag ("TS_CONSTRUCTOR"))) constructor; }; /* Standard named or nameless data types of the C compiler. */ @@ -3104,7 +3151,10 @@ extern tree build_int_cst_type (tree, HOST_WIDE_INT); extern tree build_int_cstu (tree, unsigned HOST_WIDE_INT); extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT); extern tree build_vector (tree, tree); -extern tree build_constructor (tree, tree); +extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *); +extern tree build_constructor (tree, VEC(constructor_elt,gc) *); +extern tree build_constructor_single (tree, tree, tree); +extern tree build_constructor_from_list (tree, tree); extern tree build_real_from_int_cst (tree, tree); extern tree build_complex (tree, tree, tree); extern tree build_string (int, const char *); @@ -4081,6 +4131,7 @@ typedef enum binfo_kind, phi_kind, ssa_name_kind, + constr_kind, x_kind, lang_decl, lang_type, diff --git a/gcc/treestruct.def b/gcc/treestruct.def index 43a465d4ea7..bdcc4461c6a 100644 --- a/gcc/treestruct.def +++ b/gcc/treestruct.def @@ -58,3 +58,4 @@ DEFTREESTRUCT(TS_BLOCK, "block") DEFTREESTRUCT(TS_BINFO, "binfo") DEFTREESTRUCT(TS_STATEMENT_LIST, "statement list") DEFTREESTRUCT(TS_VALUE_HANDLE, "value handle") +DEFTREESTRUCT(TS_CONSTRUCTOR, "constructor") diff --git a/gcc/varasm.c b/gcc/varasm.c index db54f986730..e4d30974ddc 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2400,13 +2400,14 @@ const_hash_1 (const tree exp) case CONSTRUCTOR: { - tree link; + unsigned HOST_WIDE_INT idx; + tree value; hi = 5 + int_size_in_bytes (TREE_TYPE (exp)); - for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) - if (TREE_VALUE (link)) - hi = hi * 603 + const_hash_1 (TREE_VALUE (link)); + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value) + if (value) + hi = hi * 603 + const_hash_1 (value); return hi; } @@ -2517,7 +2518,8 @@ compare_constant (const tree t1, const tree t2) case CONSTRUCTOR: { - tree l1, l2; + VEC(constructor_elt, gc) *v1, *v2; + unsigned HOST_WIDE_INT idx; typecode = TREE_CODE (TREE_TYPE (t1)); if (typecode != TREE_CODE (TREE_TYPE (t2))) @@ -2540,28 +2542,34 @@ compare_constant (const tree t1, const tree t2) return 0; } - for (l1 = CONSTRUCTOR_ELTS (t1), l2 = CONSTRUCTOR_ELTS (t2); - l1 && l2; - l1 = TREE_CHAIN (l1), l2 = TREE_CHAIN (l2)) + v1 = CONSTRUCTOR_ELTS (t1); + v2 = CONSTRUCTOR_ELTS (t2); + if (VEC_length (constructor_elt, v1) + != VEC_length (constructor_elt, v2)) + return 0; + + for (idx = 0; idx < VEC_length (constructor_elt, v1); ++idx) { + constructor_elt *c1 = VEC_index (constructor_elt, v1, idx); + constructor_elt *c2 = VEC_index (constructor_elt, v2, idx); + /* Check that each value is the same... */ - if (! compare_constant (TREE_VALUE (l1), TREE_VALUE (l2))) + if (!compare_constant (c1->value, c2->value)) return 0; /* ... and that they apply to the same fields! */ if (typecode == ARRAY_TYPE) { - if (! compare_constant (TREE_PURPOSE (l1), - TREE_PURPOSE (l2))) + if (!compare_constant (c1->index, c2->index)) return 0; } else { - if (TREE_PURPOSE (l1) != TREE_PURPOSE (l2)) + if (c1->index != c2->index) return 0; } } - return l1 == NULL_TREE && l2 == NULL_TREE; + return 1; } case ADDR_EXPR: @@ -2645,13 +2653,19 @@ copy_constant (tree exp) case CONSTRUCTOR: { tree copy = copy_node (exp); - tree list = copy_list (CONSTRUCTOR_ELTS (exp)); - tree tail; - - CONSTRUCTOR_ELTS (copy) = list; - for (tail = list; tail; tail = TREE_CHAIN (tail)) - TREE_VALUE (tail) = copy_constant (TREE_VALUE (tail)); - + VEC(constructor_elt, gc) *v; + unsigned HOST_WIDE_INT idx; + tree purpose, value; + + v = VEC_alloc(constructor_elt, gc, VEC_length(constructor_elt, + CONSTRUCTOR_ELTS (exp))); + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, purpose, value) + { + constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL); + ce->index = purpose; + ce->value = copy_constant (value); + } + CONSTRUCTOR_ELTS (copy) = v; return copy; } @@ -3476,10 +3490,12 @@ compute_reloc_for_constant (tree exp) break; case CONSTRUCTOR: - for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem)) - if (TREE_VALUE (tem) != 0) - reloc |= compute_reloc_for_constant (TREE_VALUE (tem)); - + { + unsigned HOST_WIDE_INT idx; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, tem) + if (tem != 0) + reloc |= compute_reloc_for_constant (tem); + } break; default: @@ -3533,10 +3549,12 @@ output_addressed_constants (tree exp) break; case CONSTRUCTOR: - for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem)) - if (TREE_VALUE (tem) != 0) - output_addressed_constants (TREE_VALUE (tem)); - + { + unsigned HOST_WIDE_INT idx; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, tem) + if (tem != 0) + output_addressed_constants (tem); + } break; default: @@ -3567,16 +3585,16 @@ initializer_constant_valid_p (tree value, tree endtype) if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE) && TREE_CONSTANT (value) - && CONSTRUCTOR_ELTS (value)) + && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (value))) { + unsigned HOST_WIDE_INT idx; tree elt; bool absolute = true; - for (elt = CONSTRUCTOR_ELTS (value); elt; elt = TREE_CHAIN (elt)) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt) { tree reloc; - value = TREE_VALUE (elt); - reloc = initializer_constant_valid_p (value, TREE_TYPE (value)); + reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt)); if (!reloc) return NULL_TREE; if (reloc != null_pointer_node) @@ -3832,7 +3850,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) /* Allow a constructor with no elements for any data type. This means to fill the space with zeros. */ - if (TREE_CODE (exp) == CONSTRUCTOR && CONSTRUCTOR_ELTS (exp) == 0) + if (TREE_CODE (exp) == CONSTRUCTOR + && VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (exp))) { assemble_zeros (size); return; @@ -3942,6 +3961,8 @@ static unsigned HOST_WIDE_INT array_size_for_constructor (tree val) { tree max_index, i; + unsigned HOST_WIDE_INT cnt; + tree index, value; /* This code used to attempt to handle string constants that are not arrays of single-bytes, but nothing else does, so there's no point in @@ -3950,10 +3971,8 @@ array_size_for_constructor (tree val) return TREE_STRING_LENGTH (val); max_index = NULL_TREE; - for (i = CONSTRUCTOR_ELTS (val); i; i = TREE_CHAIN (i)) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (val), cnt, index, value) { - tree index = TREE_PURPOSE (i); - if (TREE_CODE (index) == RANGE_EXPR) index = TREE_OPERAND (index, 1); if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index)) @@ -3983,7 +4002,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) { tree type = TREE_TYPE (exp); - tree link, field = 0; + tree field = 0; tree min_index = 0; /* Number of bytes output or skipped so far. In other words, current position within the constructor. */ @@ -3991,6 +4010,8 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size, /* Nonzero means BYTE contains part of a byte, to be output. */ int byte_buffer_in_use = 0; int byte = 0; + unsigned HOST_WIDE_INT cnt; + constructor_elt *ce; gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT); @@ -4010,23 +4031,22 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size, There is always a maximum of one element in the chain LINK for unions (even if the initializer in a source program incorrectly contains more one). */ - for (link = CONSTRUCTOR_ELTS (exp); - link; - link = TREE_CHAIN (link), - field = field ? TREE_CHAIN (field) : 0) + for (cnt = 0; + VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce); + cnt++, field = field ? TREE_CHAIN (field) : 0) { - tree val = TREE_VALUE (link); + tree val = ce->value; tree index = 0; /* The element in a union constructor specifies the proper field or index. */ if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE) - && TREE_PURPOSE (link) != 0) - field = TREE_PURPOSE (link); + && ce->index != 0) + field = ce->index; else if (TREE_CODE (type) == ARRAY_TYPE) - index = TREE_PURPOSE (link); + index = ce->index; #ifdef ASM_COMMENT_START if (field && flag_verbose_asm) @@ -4089,6 +4109,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size, if each element has the proper size. */ if ((field != 0 || index != 0) && pos != total_bytes) { + gcc_assert (pos >= total_bytes); assemble_zeros (pos - total_bytes); total_bytes = pos; } @@ -4164,6 +4185,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size, /* If still not at proper byte, advance to there. */ if (next_offset / BITS_PER_UNIT != total_bytes) { + gcc_assert (next_offset / BITS_PER_UNIT >= total_bytes); assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes); total_bytes = next_offset / BITS_PER_UNIT; } diff --git a/gcc/vec.h b/gcc/vec.h index 63840a1bd4a..842ac7bbaaa 100644 --- a/gcc/vec.h +++ b/gcc/vec.h @@ -147,6 +147,15 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define VEC_length(T,V) (VEC_OP(T,base,length)(VEC_BASE(V))) + +/* Check if vector is empty + int VEC_T_empty(const VEC(T) *v); + + Return non-zero if V is an empty vector (or V is NULL), zero otherwise. */ + +#define VEC_empty(T,V) (VEC_length (T,V) == 0) + + /* Get the final element of the vector. T VEC_T_last(VEC(T) *v); // Integer T VEC_T_last(VEC(T) *v); // Pointer @@ -205,6 +214,14 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define VEC_embedded_size(T,N) (VEC_OP(T,base,embedded_size)(N)) #define VEC_embedded_init(T,O,N) (VEC_OP(T,base,embedded_init)(VEC_BASE(O),N)) +/* Copy a vector. + VEC(T,A) *VEC_T_A_copy(VEC(T) *); + + Copy the live elements of a vector into a new vector. The new and + old vectors need not be allocated by the same mechanim. */ + +#define VEC_copy(T,A,V) (VEC_OP(T,A,copy)(VEC_BASE(V) MEM_STAT_INFO)) + /* Determine if a vector has additional capacity. int VEC_T_space (VEC(T) *v,int reserve) @@ -667,6 +684,23 @@ static inline void VEC_OP (T,A,free) \ *vec_ = NULL; \ } \ \ +static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \ +{ \ + size_t len_ = vec_ ? vec_->num : 0; \ + VEC (T,A) *new_vec_ = NULL; \ + \ + if (len_) \ + { \ + /* We must request exact size allocation, hence the negation. */ \ + new_vec_ = (VEC (T,A) *)(vec_##A##_p_reserve \ + (NULL, -len_ PASS_MEM_STAT)); \ + \ + new_vec_->base.num = len_; \ + memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \ + } \ + return new_vec_; \ +} \ + \ static inline int VEC_OP (T,A,reserve) \ (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \ { \ @@ -895,6 +929,25 @@ static inline VEC(T,A) *VEC_OP (T,A,alloc) \ PASS_MEM_STAT); \ } \ \ +static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \ +{ \ + size_t len_ = vec_ ? vec_->num : 0; \ + VEC (T,A) *new_vec_ = NULL; \ + \ + if (len_) \ + { \ + /* We must request exact size allocation, hence the negation. */ \ + new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve \ + (NULL, -len_, \ + offsetof (VEC(T,A),base.vec), sizeof (T) \ + PASS_MEM_STAT)); \ + \ + new_vec_->base.num = len_; \ + memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \ + } \ + return new_vec_; \ +} \ + \ static inline void VEC_OP (T,A,free) \ (VEC(T,A) **vec_) \ { \ |