mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-23 01:50:33 +08:00
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. From-SVN: r102182
This commit is contained in:
parent
f37d7c6065
commit
4038c495fc
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
511
gcc/cp/decl.c
511
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.
|
||||
|
||||
*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:
|
||||
|
||||
struct S { int a; int b; };
|
||||
struct S a[] = { 1, 2, 3, 4 };
|
||||
|
||||
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. */
|
||||
/* Subroutine of reshape_init_r, processes the initializers for arrays.
|
||||
Parameters are the same of reshape_init_r. */
|
||||
|
||||
static tree
|
||||
reshape_init (tree type, tree *initp)
|
||||
reshape_init_array (tree type, reshape_iter *d)
|
||||
{
|
||||
tree inits;
|
||||
tree old_init;
|
||||
tree old_init_value;
|
||||
tree max_index = NULL_TREE;
|
||||
|
||||
gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
|
||||
|
||||
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_class (tree type, reshape_iter *d, bool first_initializer_p)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Build a CONSTRUCTOR to hold the contents of the aggregate. */
|
||||
new_init = build_constructor (NULL_TREE, NULL_TREE);
|
||||
|
||||
if (CLASS_TYPE_P (type))
|
||||
/* 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)
|
||||
{
|
||||
tree field;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
field = next_initializable_field (TYPE_FIELDS (type));
|
||||
|
||||
if (!field)
|
||||
/* 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)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
|
||||
}
|
||||
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)));
|
||||
}
|
||||
|
||||
if (!reshape_init_array (TREE_TYPE (type), max_index,
|
||||
initp, new_init))
|
||||
return error_mark_node;
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
/* The initializers were placed in reverse order in the
|
||||
CONSTRUCTOR. */
|
||||
CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
|
||||
|
||||
if (TREE_CODE (old_init) == TREE_LIST)
|
||||
new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
|
||||
warning (OPT_Wmissing_braces, "missing braces around initializer for %qT",
|
||||
type);
|
||||
}
|
||||
|
||||
/* 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");
|
||||
}
|
||||
/* 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();
|
||||
}
|
||||
|
||||
/* Undo the brace-elision allowed by [dcl.init.aggr] in a
|
||||
brace-enclosed aggregate initializer.
|
||||
|
||||
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:
|
||||
|
||||
struct S { int a; int b; };
|
||||
struct S a[] = { 1, 2, 3, 4 };
|
||||
|
||||
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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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] */
|
||||
|
40
gcc/cp/pt.c
40
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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
789
gcc/cp/typeck2.c
789
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 (SCALAR_TYPE_P (type)
|
||||
|| code == REFERENCE_TYPE)
|
||||
return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
|
||||
"initialization", NULL_TREE, 0);
|
||||
|
||||
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))
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Come here only for records and arrays (and unions with constructors). */
|
||||
|
||||
if (COMPLETE_TYPE_P (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
|
||||
{
|
||||
error ("variable-sized object of type %qT may not be initialized",
|
||||
type);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (code == ARRAY_TYPE || code == VECTOR_TYPE || IS_AGGR_TYPE_CODE (code))
|
||||
{
|
||||
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)
|
||||
{
|
||||
*tail = old_tail_contents;
|
||||
return process_init_constructor (type, 0, tail);
|
||||
}
|
||||
|
||||
if (code != ARRAY_TYPE)
|
||||
{
|
||||
int flags = LOOKUP_NORMAL;
|
||||
/* Initialization from { } is copy-initialization. */
|
||||
if (tail)
|
||||
flags |= LOOKUP_ONLYCONVERTING;
|
||||
|
||||
return convert_for_initialization (NULL_TREE, type, init, flags,
|
||||
"initialization", NULL_TREE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
/* 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
|
||||
|
||||
If INIT is specified, it is a CONSTRUCTOR node which is specifically
|
||||
and solely for initializing this datum.
|
||||
/* Given an initializer INIT, return the flag (PICFLAG_*) which better
|
||||
describe it. */
|
||||
|
||||
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.
|
||||
|
||||
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. */
|
||||
|
||||
static tree
|
||||
process_init_constructor (tree type, tree init, tree* elts)
|
||||
static int
|
||||
picflag_from_initializer (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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Make TAIL be the list of elements to use for the initialization,
|
||||
no matter how the data was given to us. */
|
||||
/* 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 (elts)
|
||||
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)
|
||||
{
|
||||
if (warn_missing_braces)
|
||||
warning (0, "aggregate has a partly bracketed initializer");
|
||||
tail = *elts;
|
||||
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
|
||||
tail = CONSTRUCTOR_ELTS (init);
|
||||
/* Vectors are like simple fixed-size arrays. */
|
||||
len = TYPE_VECTOR_SUBPARTS (type);
|
||||
|
||||
/* 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. */
|
||||
/* 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);
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
|
||||
for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
|
||||
{
|
||||
long len;
|
||||
int i;
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
if (ce->index)
|
||||
{
|
||||
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);
|
||||
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 (ce->value != error_mark_node)
|
||||
gcc_assert (same_type_ignoring_top_level_qualifiers_p
|
||||
(TREE_TYPE (type), TREE_TYPE (ce->value)));
|
||||
|
||||
flags |= picflag_from_initializer (ce->value);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
flags |= picflag_from_initializer (next);
|
||||
CONSTRUCTOR_APPEND_ELT (v, size_int (i), next);
|
||||
}
|
||||
|
||||
CONSTRUCTOR_ELTS (init) = v;
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* 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 int
|
||||
process_init_constructor_record (tree type, tree init)
|
||||
{
|
||||
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))
|
||||
{
|
||||
tree next;
|
||||
|
||||
if (!DECL_NAME (field) && DECL_C_BIT_FIELD (field))
|
||||
{
|
||||
flags |= picflag_from_initializer (integer_zero_node);
|
||||
CONSTRUCTOR_APPEND_ELT (v, field, integer_zero_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
|
||||
continue;
|
||||
|
||||
if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)))
|
||||
{
|
||||
constructor_elt *ce = VEC_index (constructor_elt,
|
||||
CONSTRUCTOR_ELTS (init), idx);
|
||||
if (ce->index)
|
||||
{
|
||||
/* 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");
|
||||
}
|
||||
|
||||
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
|
||||
len = -1; /* Take as many as there are. */
|
||||
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
|
||||
{
|
||||
/* Vectors are like simple fixed-size arrays. */
|
||||
len = TYPE_VECTOR_SUBPARTS (type);
|
||||
}
|
||||
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);
|
||||
|
||||
for (i = 0; len < 0 || i < len; i++)
|
||||
{
|
||||
if (tail)
|
||||
{
|
||||
if (TREE_PURPOSE (tail)
|
||||
&& (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
|
||||
|| compare_tree_int (TREE_PURPOSE (tail), i) != 0))
|
||||
sorry ("non-trivial labeled initializers");
|
||||
/* Warn when some struct elements are implicitly initialized
|
||||
to zero. */
|
||||
warning (OPT_Wmissing_field_initializers,
|
||||
"missing initializer for member %qD", field);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
|
||||
add anything to the CONSTRUCTOR. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tail)
|
||||
flags |= picflag_from_initializer (next);
|
||||
CONSTRUCTOR_APPEND_ELT (v, field, next);
|
||||
}
|
||||
|
||||
CONSTRUCTOR_ELTS (init) = v;
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
static int
|
||||
process_init_constructor_union (tree type, tree init)
|
||||
{
|
||||
constructor_elt *ce;
|
||||
|
||||
/* 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_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);
|
||||
}
|
||||
error ("no field %qD found in union being initialized", field);
|
||||
ce->value = error_mark_node;
|
||||
}
|
||||
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 (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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
ce->index = field;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
if (ce->value && ce->value != error_mark_node)
|
||||
ce->value = digest_init (TREE_TYPE (ce->index), ce->value);
|
||||
|
||||
if (erroneous)
|
||||
return picflag_from_initializer (ce->value);
|
||||
}
|
||||
|
||||
/* 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.).
|
||||
|
||||
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 (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);
|
||||
}
|
||||
|
||||
|
156
gcc/expr.c
156
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;
|
||||
unsigned HOST_WIDE_INT ix;
|
||||
tree field, value;
|
||||
|
||||
for (elem = CONSTRUCTOR_ELTS (array);
|
||||
(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);
|
||||
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;
|
||||
unsigned HOST_WIDE_INT ix;
|
||||
tree field, value;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
123
gcc/gimplify.c
123
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;
|
||||
|
||||
if (! tem)
|
||||
{
|
||||
TREE_OPERAND (*expr_p, 1) = build_vector (type, elt_list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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 (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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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" }
|
||||
|
||||
|
@ -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" }
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
133
gcc/tree.c
133
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 CONSTRUCTOR node whose type is TYPE and whose values
|
||||
are in a list pointed to by VALS. */
|
||||
/* Return a new VECTOR_CST node whose type is TYPE and whose values
|
||||
are extracted from V, a vector of CONSTRUCTOR_ELT. */
|
||||
|
||||
tree
|
||||
build_constructor (tree type, tree vals)
|
||||
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 the VEC pointed by VALS. */
|
||||
tree
|
||||
build_constructor (tree type, VEC(constructor_elt,gc) *vals)
|
||||
{
|
||||
tree c = make_node (CONSTRUCTOR);
|
||||
TREE_TYPE (c) = type;
|
||||
CONSTRUCTOR_ELTS (c) = vals;
|
||||
|
||||
/* ??? 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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (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 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));
|
||||
|
14
gcc/tree.def
14
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.
|
||||
|
63
gcc/tree.h
63
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,
|
||||
|
@ -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")
|
||||
|
112
gcc/varasm.c
112
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;
|
||||
}
|
||||
|
53
gcc/vec.h
53
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_) \
|
||||
{ \
|
||||
|
Loading…
x
Reference in New Issue
Block a user