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:
Giovanni Bajo 2005-07-20 03:19:59 +02:00 committed by Giovanni Bajo
parent f37d7c6065
commit 4038c495fc
63 changed files with 1685 additions and 1219 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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++;

View File

@ -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] */

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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) \

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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];
}

View File

@ -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" }

View File

@ -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" }

View File

@ -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:

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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;
}

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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));

View File

@ -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.

View File

@ -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,

View File

@ -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")

View File

@ -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;
}

View File

@ -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_) \
{ \