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