Make CONSTRUCTOR use VEC to store initializers.
authorGiovanni Bajo <giovannibajo@libero.it>
Wed, 20 Jul 2005 01:19:59 +0000 (03:19 +0200)
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>
Wed, 20 Jul 2005 01:19:59 +0000 (01:19 +0000)
* c-common.c (complete_array_type): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* c-pretty-print.c (pp_c_initializer_list): Use pp_c_constructor_elts.
(pp_c_constructor_elts): New function.
* c-pretty-print.h (pp_c_constructor_elts): Declare.
* c-typeck.c (build_function_call, build_c_cast, digest_init,
struct constructor_stack, struct initializer_stack,
constructor_elements, push_init_level, pop_init_level,
add_pending_init, find_init_member, output_init_element): Update to
cope with VEC in CONSTRUCTOR_ELTS.
* coverage.c (build_fn_info_value, build_ctr_info_value,
build_gcov_info): Likewise.
* expr.c (categorize_ctor_elements_1, store_constructor,
expand_expr_real_1): Likewise.
* fold-const.c (fold_ternary): Likewise.
* gimplify.c (gimplify_init_ctor_preeval, zero_sized_field_decl,
gimplify_init_constructor, gimplify_expr): Likewise.
* tree-dump.c (dequeue_and_dump): Likewise.
* tree-inline.c (copy_tree_r): Add code to duplicate a CONSTRUCTOR
node.
* tree-pretty-print.c (dump_generic_node): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* tree-sra.c (generate_element_init_1): Likewise.
* tree-ssa-ccp.c (fold_const_aggregate_ref): Likewise.
* tree-ssa-operands.c (get_expr_operands): Likewise.
* tree-vect-generic.c (expand_vector_piecewise): Likewise.
* tree-vect-transform.c (vect_get_vec_def_for_operand):
(get_initial_def_for_reduction): Likewise.
* tree-vn.c (set_value_handle, get_value_handle): CONSTURCTOR uses
value handle in annotations.
* tree.c (tree_node_kind, tree_code_size, make_node_stat,
tree_node_structure): Add support for constr_kind.
(build_vector_from_ctor, build_constructor_single,
build_constructor_from_list): New functions.
(build_constructor): Update to take a VEC instead of a TREE_LIST.
(simple_cst_equal, iterative_hash_expr, initializer_zerop, walk_tree):
Update to cope with VEC in CONSTRUCTOR_ELTS.
* tree.def (CONSTRUCTOR): Make it a tcc_exceptional node.
* tree.h (FOR_EACH_CONSTRUCTOR_VALUE, FOR_EACH_CONSTRUCTOR_ELT,
CONSTRUCTOR_APPEND_ELT): New macros.
(struct constructor_elt, struct tree_constructor): New data types.
(union tree_node): Add tree_constructor field.
* treestruct.def: Define TS_CONSTRUCTOR.
* varasm.c (const_hash_1, compare_constant, copy_constant,
compute_reloc_for_constant, output_addressed_constants,
initializer_constant_valid_p, output_constant,
array_size_for_constructor, output_constructor): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* vec.h (VEC_empty, VEC_copy): New macros.

ada/
Make CONSTRUCTOR use VEC to store initializers.
* decl.c (gnat_to_gnu_entity): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* trans.c (extract_values): Likewise.
* utils.c (convert, remove_conversions): Likewise.
* utils2.c (contains_save_expr_p, build_binary_op, build_unary_op,
gnat_build_constructor): Likewise.

cp/
Make CONSTRUCTOR use VEC to store initializers.
* call.c (convert_default_arg): Update call to digest_init.
* class.c (dump_class_hierarchy, dump_array): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* cp-tree.h (EMPTY_CONSTRUCTOR_P): Likewise.
(finish_compound_literal, digest_init): Update declaration.
* decl.c (struct reshape_iter): New data type.
(reshape_init_array): Rename to...
(reshape_init_array_1): Update to cope with VEC in CONSTRUCTOR_ELTS.
(reshape_init): Rewrite from scratch. Split parts into...
(reshape_init_array, reshape_init_vector, reshape_init_class,
reshape_init_r): New functions.
(check_initializer): Update call to reshape_init. Remove obsolete
code.
(initialize_artificial_var, cp_complete_array_type): Update to cope
with VEC in CONSTRUCTOR_ELTS.
* decl2.c (grokfield): Update calls to digest_init.
(mark_vtable_entries): Update to cope with VEC in CONSTRUCTOR_ELTS.
* error.c (dump_expr_init_vec): New function.
(dump_expr): Use dump_expr_init_vec.
* init.c (build_zero_init, build_vec_init): Update to cope with VEC
in CONSTRUCTOR_ELTS.
(expand_default_init): Update call to digest_init.
* parser.c  (cp_parser_postfix_expression): Use a VEC for the
initializers.
(cp_parser_initializer_list): Build a VEC of initializers.
* pt.c (tsubst_copy, tsubst_copy_and_build): Update to cope with VEC
in CONSTRUCTOR_ELTS.
* rtti.c (tinfo_base_init, generic_initializer, ptr_initializer,
ptm_initializer, class_initializer, get_pseudo_ti_init): Use
build_constructor_from_list instead of build_constructor.
* semantics.c (finish_compound_literal): Update call to digest_init.
* tree.c (stabilize_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* typeck.c (build_ptrmemfunc1): Likewise.
* typeck2.c: (cxx_incomplete_type_error, split_nonconstant_init_1):
Likewise.
(store_init_value): Use build_constructor_from_list and update call
to digest_init.
(digest_init): Rewrite.
(process_init_constructor): Rewrite from scratch. Split into...
(process_init_constructor_array, picflag_from_initializer,
process_init_constructor_record, process_init_constructor_union):
New functions.
(PICFLAG_ERRONEOUS, PICFLAG_NOT_ALL_CONSTANT, PICFLAG_NOT_ALL_SIMPLE):
New macros.
(build_functional_cast): Use build_constructor_from_list instead of
build_constructor.

fortran/
Make CONSTRUCTOR use VEC to store initializers.
* trans-array.c (gfc_build_null_descriptor,
gfc_trans_array_constructor_value, gfc_conv_array_initializer):
Update to cope with VEC in CONSTRUCTOR_ELTS.
* trans-common.c (create_common): Likewise.
* trans-expr.c (gfc_conv_structure): Likewise.
* trans-stmt.c (gfc_trans_character_select): Use
build_constructor_from_list instead of build_constructor.

java/
Make CONSTRUCTOR use VEC to store initializers.
* check-init.c (check_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* class.c (make_field_value, make_method_value, get_dispatch_table,
make_class_data, emit_symbol_table, emit_catch_table,
emit_assertion_table): Use build_constructor_from_list instead of
build_constructor.
* constants.c (build_constants_constructor): Likewise.
* java-gimplify.c (java_gimplify_new_array_init): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* java-tree.h (START_RECORD_CONSTRUCTOR, PUSH_SUPER_VALUE,
PUSH_FIELD_VALUE, FINISH_RECORD_CONSTRUCTOR): Create a VEC instead
of a TREE_LIST.
* jcf-write.c (generate_bytecode_insns): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* parse.y (build_new_array_init): Use build_constructor_from_list
instead of build_constructor.
(patch_new_array_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
(array_constructor_check_entry): Likewise.

objc/
Make CONSTRUCTOR use VEC to store initializers.
* objc-act.c (objc_build_constructor): Use build_constructor_from_list
instead of build_constructor.

testsuite/
Make CONSTRUCTOR use VEC to store initializers.
* g++.dg/ext/complit3.C: Check for specific error messages.
* g++.dg/init/brace2.C: Update error message.
* g++.dg/warn/Wbraces2.C: Likewise.

From-SVN: r102182

63 files changed:
gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/decl.c
gcc/ada/trans.c
gcc/ada/utils.c
gcc/ada/utils2.c
gcc/c-common.c
gcc/c-pretty-print.c
gcc/c-pretty-print.h
gcc/c-typeck.c
gcc/coverage.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/expr.c
gcc/fold-const.c
gcc/fortran/ChangeLog
gcc/fortran/trans-array.c
gcc/fortran/trans-common.c
gcc/fortran/trans-expr.c
gcc/fortran/trans-stmt.c
gcc/gimplify.c
gcc/java/ChangeLog
gcc/java/check-init.c
gcc/java/class.c
gcc/java/constants.c
gcc/java/java-gimplify.c
gcc/java/java-tree.h
gcc/java/jcf-write.c
gcc/java/parse.y
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/complit3.C
gcc/testsuite/g++.dg/init/brace2.C
gcc/testsuite/g++.dg/warn/Wbraces2.C
gcc/tree-dump.c
gcc/tree-inline.c
gcc/tree-pretty-print.c
gcc/tree-sra.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-operands.c
gcc/tree-vect-generic.c
gcc/tree-vect-transform.c
gcc/tree-vn.c
gcc/tree.c
gcc/tree.def
gcc/tree.h
gcc/treestruct.def
gcc/varasm.c
gcc/vec.h

index 45251cb..88073eb 100644 (file)
@@ -1,3 +1,56 @@
+2005-07-20  Giovanni Bajo  <giovannibajo@libero.it>
+
+       Make CONSTRUCTOR use VEC to store initializers.
+       * c-common.c (complete_array_type): Update to cope with VEC in
+       CONSTRUCTOR_ELTS.
+       * c-pretty-print.c (pp_c_initializer_list): Use pp_c_constructor_elts.
+       (pp_c_constructor_elts): New function.
+       * c-pretty-print.h (pp_c_constructor_elts): Declare.
+       * c-typeck.c (build_function_call, build_c_cast, digest_init,
+       struct constructor_stack, struct initializer_stack,
+       constructor_elements, push_init_level, pop_init_level,
+       add_pending_init, find_init_member, output_init_element): Update to
+       cope with VEC in CONSTRUCTOR_ELTS.
+       * coverage.c (build_fn_info_value, build_ctr_info_value,
+       build_gcov_info): Likewise.
+       * expr.c (categorize_ctor_elements_1, store_constructor,
+       expand_expr_real_1): Likewise.
+       * fold-const.c (fold_ternary): Likewise.
+       * gimplify.c (gimplify_init_ctor_preeval, zero_sized_field_decl,
+       gimplify_init_constructor, gimplify_expr): Likewise.
+       * tree-dump.c (dequeue_and_dump): Likewise.
+       * tree-inline.c (copy_tree_r): Add code to duplicate a CONSTRUCTOR
+       node.
+       * tree-pretty-print.c (dump_generic_node): Update to cope with VEC in
+       CONSTRUCTOR_ELTS.
+       * tree-sra.c (generate_element_init_1): Likewise.
+       * tree-ssa-ccp.c (fold_const_aggregate_ref): Likewise.
+       * tree-ssa-operands.c (get_expr_operands): Likewise.
+       * tree-vect-generic.c (expand_vector_piecewise): Likewise.
+       * tree-vect-transform.c (vect_get_vec_def_for_operand):
+       (get_initial_def_for_reduction): Likewise.
+       * tree-vn.c (set_value_handle, get_value_handle): CONSTURCTOR uses
+       value handle in annotations.
+       * tree.c (tree_node_kind, tree_code_size, make_node_stat,
+       tree_node_structure): Add support for constr_kind.
+       (build_vector_from_ctor, build_constructor_single,
+       build_constructor_from_list): New functions.
+       (build_constructor): Update to take a VEC instead of a TREE_LIST.
+       (simple_cst_equal, iterative_hash_expr, initializer_zerop, walk_tree):
+       Update to cope with VEC in CONSTRUCTOR_ELTS.
+       * tree.def (CONSTRUCTOR): Make it a tcc_exceptional node.
+       * tree.h (FOR_EACH_CONSTRUCTOR_VALUE, FOR_EACH_CONSTRUCTOR_ELT,
+       CONSTRUCTOR_APPEND_ELT): New macros.
+       (struct constructor_elt, struct tree_constructor): New data types.
+       (union tree_node): Add tree_constructor field.
+       * treestruct.def: Define TS_CONSTRUCTOR.
+       * varasm.c (const_hash_1, compare_constant, copy_constant,
+       compute_reloc_for_constant, output_addressed_constants,
+       initializer_constant_valid_p, output_constant,
+       array_size_for_constructor, output_constructor): Update to cope with
+       VEC in CONSTRUCTOR_ELTS.
+       * vec.h (VEC_empty, VEC_copy): New macros.
+
 2005-07-19  Devang Patel  <dpatel@apple.com>
 
        * dbxout.c (dbxout_type): Check Objective-C++ lang.
index 48c6007..47e24b1 100644 (file)
@@ -1,3 +1,13 @@
+2005-07-20  Giovanni Bajo  <giovannibajo@libero.it>
+
+       Make CONSTRUCTOR use VEC to store initializers.
+       * decl.c (gnat_to_gnu_entity): Update to cope with VEC in
+       CONSTRUCTOR_ELTS.
+       * trans.c (extract_values): Likewise.
+       * utils.c (convert, remove_conversions): Likewise.
+       * utils2.c (contains_save_expr_p, build_binary_op, build_unary_op,
+       gnat_build_constructor): Likewise.
+
 2005-07-09  Andrew Pinski  <pinskia@physics.uc.edu>
 
        * decl.c (components_to_record): Use DECL_FCONTEXT instead of
index f21a699..145ece8 100644 (file)
@@ -940,16 +940,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
                    gnu_alloc_type
                      = TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_alloc_type)));
 
-                   if (TREE_CODE (gnu_expr) == CONSTRUCTOR
-                       &&
-                       TREE_CHAIN (CONSTRUCTOR_ELTS (gnu_expr)) == NULL_TREE)
-                     gnu_expr = 0;
-                   else
-                     gnu_expr
-                       = build_component_ref
-                         (gnu_expr, NULL_TREE,
-                          TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr))),
-                         false);
+                   if (TREE_CODE (gnu_expr) == CONSTRUCTOR
+                       && VEC_length (constructor_elt,
+                                      CONSTRUCTOR_ELTS (gnu_expr)) == 1)
+                     gnu_expr = 0;
+                   else
+                     gnu_expr
+                       = build_component_ref
+                         (gnu_expr, NULL_TREE,
+                         TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr))),
+                             false);
                  }
 
                if (TREE_CODE (TYPE_SIZE_UNIT (gnu_alloc_type)) == INTEGER_CST
index 3a3327a..9614252 100644 (file)
@@ -5625,7 +5625,8 @@ extract_values (tree values, tree record_type)
       else if (DECL_INTERNAL_P (field))
        {
          value = extract_values (values, TREE_TYPE (field));
-         if (TREE_CODE (value) == CONSTRUCTOR && !CONSTRUCTOR_ELTS (value))
+         if (TREE_CODE (value) == CONSTRUCTOR
+             && VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (value)))
            value = 0;
        }
       else
index edd1706..baec9ff 100644 (file)
@@ -2703,9 +2703,10 @@ convert (tree type, tree expr)
       /* If we have just converted to this padded type, just get
         the inner expression.  */
       if (TREE_CODE (expr) == CONSTRUCTOR
-         && CONSTRUCTOR_ELTS (expr)
-         && TREE_PURPOSE (CONSTRUCTOR_ELTS (expr)) == TYPE_FIELDS (etype))
-       return TREE_VALUE (CONSTRUCTOR_ELTS (expr));
+         && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (expr))
+         && VEC_index (constructor_elt, CONSTRUCTOR_ELTS (expr), 0)->index
+            == TYPE_FIELDS (etype))
+       return VEC_index (constructor_elt, CONSTRUCTOR_ELTS (expr), 0)->value;
       else
        return convert (type,
                        build_component_ref (expr, NULL_TREE,
@@ -3025,7 +3026,9 @@ remove_conversions (tree exp, bool true_address)
       if (true_address
          && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
          && TYPE_JUSTIFIED_MODULAR_P (TREE_TYPE (exp)))
-       return remove_conversions (TREE_VALUE (CONSTRUCTOR_ELTS (exp)), true);
+       return remove_conversions (VEC_index (constructor_elt,
+                                             CONSTRUCTOR_ELTS (exp), 0)->value,
+                                  true);
       break;
 
     case COMPONENT_REF:
index 4b0369b..5847910 100644 (file)
@@ -263,13 +263,15 @@ contains_save_expr_p (tree exp)
       return contains_save_expr_p (TREE_OPERAND (exp, 0));
 
     case CONSTRUCTOR:
-      return (CONSTRUCTOR_ELTS (exp)
-             && contains_save_expr_p (CONSTRUCTOR_ELTS (exp)));
+      {
+       tree value;
+       unsigned HOST_WIDE_INT ix;
 
-    case TREE_LIST:
-      return (contains_save_expr_p (TREE_VALUE (exp))
-             || (TREE_CHAIN (exp)
-                 && contains_save_expr_p (TREE_CHAIN (exp))));
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), ix, value)
+         if (contains_save_expr_p (value))
+           return true;
+       return false;
+      }
 
     default:
       return false;
@@ -884,8 +886,9 @@ build_binary_op (enum tree_code op_code, tree result_type,
         just compare the data pointer.  */
       else if (TYPE_FAT_POINTER_P (left_base_type)
               && TREE_CODE (right_operand) == CONSTRUCTOR
-              && integer_zerop (TREE_VALUE
-                                (CONSTRUCTOR_ELTS (right_operand))))
+              && integer_zerop (VEC_index (constructor_elt,
+                                           CONSTRUCTOR_ELTS (right_operand),
+                                           0)->value))
        {
          right_operand = build_component_ref (left_operand, NULL_TREE,
                                               TYPE_FIELDS (left_base_type),
@@ -1138,9 +1141,11 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
             a pointer to our type.  */
          if (TREE_CODE (type) == RECORD_TYPE && TYPE_IS_PADDING_P (type))
            {
+             result = VEC_index (constructor_elt,
+                                 CONSTRUCTOR_ELTS (operand),
+                                 0)->value;
              result
-               = build_unary_op (ADDR_EXPR, NULL_TREE,
-                                 TREE_VALUE (CONSTRUCTOR_ELTS (operand)));
+               = build_unary_op (ADDR_EXPR, NULL_TREE, result);
              result = convert (build_pointer_type (TREE_TYPE (operand)),
                                result);
              break;
@@ -1501,7 +1506,7 @@ gnat_build_constructor (tree type, tree list)
        }
     }
 
-  result = build_constructor (type, list);
+  result = build_constructor_from_list (type, list);
   TREE_CONSTANT (result) = TREE_INVARIANT (result)
     = TREE_STATIC (result) = allconstant;
   TREE_SIDE_EFFECTS (result) = side_effects;
index 90a373c..3c341d8 100644 (file)
@@ -5938,9 +5938,9 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
        }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
-         tree elts = CONSTRUCTOR_ELTS (initial_value);
+         VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
 
-         if (elts == NULL)
+         if (VEC_empty (constructor_elt, v))
            {
              if (pedantic)
                failure = 3;
@@ -5949,15 +5949,21 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
          else
            {
              tree curindex;
+             unsigned HOST_WIDE_INT cnt;
+             constructor_elt *ce;
 
-             if (TREE_PURPOSE (elts))
-               maxindex = fold_convert (sizetype, TREE_PURPOSE (elts));
+             if (VEC_index (constructor_elt, v, 0)->index)
+               maxindex = fold_convert (sizetype,
+                                        VEC_index (constructor_elt,
+                                                   v, 0)->index);
              curindex = maxindex;
 
-             for (elts = TREE_CHAIN (elts); elts; elts = TREE_CHAIN (elts))
+             for (cnt = 1;
+                  VEC_iterate (constructor_elt, v, cnt, ce);
+                  cnt++)
                {
-                 if (TREE_PURPOSE (elts))
-                   curindex = fold_convert (sizetype, TREE_PURPOSE (elts));
+                 if (ce->index)
+                   curindex = fold_convert (sizetype, ce->index);
                  else
                    curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
 
index 6276923..bbc19be 100644 (file)
@@ -1137,14 +1137,14 @@ pp_c_initializer_list (c_pretty_printer *pp, tree e)
       if (TREE_CODE (e) == VECTOR_CST)
         pp_c_expression_list (pp, TREE_VECTOR_CST_ELTS (e));
       else if (TREE_CODE (e) == CONSTRUCTOR)
-        pp_c_expression_list (pp, CONSTRUCTOR_ELTS (e));
+        pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e));
       else
         break;
       return;
 
     case COMPLEX_TYPE:
       if (TREE_CODE (e) == CONSTRUCTOR)
-       pp_c_expression_list (pp, CONSTRUCTOR_ELTS (e));
+       pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e));
       else if (TREE_CODE (e) == COMPLEX_CST || TREE_CODE (e) == COMPLEX_EXPR)
        {
          const bool cst = TREE_CODE (e) == COMPLEX_CST;
@@ -1369,6 +1369,22 @@ pp_c_expression_list (c_pretty_printer *pp, tree e)
     }
 }
 
+/* Print out V, which contains the elements of a constructor.  */
+
+void
+pp_c_constructor_elts (c_pretty_printer *pp, VEC(constructor_elt,gc) *v)
+{
+  unsigned HOST_WIDE_INT ix;
+  tree value;
+
+  FOR_EACH_CONSTRUCTOR_VALUE (v, ix, value)
+    {
+      pp_expression (pp, value);
+      if (ix != VEC_length (constructor_elt, v) - 1)
+       pp_separate_with (pp, ',');
+    }
+}
+
 /* Print out an expression-list in parens, as in a function call.  */
 
 void
index 1291203..0f9d46a 100644 (file)
@@ -192,6 +192,7 @@ void pp_c_statement (c_pretty_printer *, tree);
 void pp_c_expression (c_pretty_printer *, tree);
 void pp_c_logical_or_expression (c_pretty_printer *, tree);
 void pp_c_expression_list (c_pretty_printer *, tree);
+void pp_c_constructor_elts (c_pretty_printer *, VEC(constructor_elt,gc) *);
 void pp_c_call_argument_list (c_pretty_printer *, tree);
 void pp_c_unary_expression (c_pretty_printer *, tree);
 void pp_c_cast_expression (c_pretty_printer *, tree);
index 928084f..d9c9949 100644 (file)
@@ -2061,8 +2061,7 @@ build_function_call (tree function, tree params)
 
          if (AGGREGATE_TYPE_P (return_type))
            rhs = build_compound_literal (return_type,
-                                         build_constructor (return_type,
-                                                            NULL_TREE));
+                                         build_constructor (return_type, 0));
          else
            rhs = fold_build1 (NOP_EXPR, return_type, integer_zero_node);
 
@@ -3210,8 +3209,7 @@ build_c_cast (tree type, tree expr)
          if (pedantic)
            pedwarn ("ISO C forbids casts to union type");
          t = digest_init (type,
-                          build_constructor (type,
-                                             build_tree_list (field, value)),
+                          build_constructor_single (type, field, value),
                           true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
          TREE_INVARIANT (t) = TREE_INVARIANT (value);
@@ -4397,18 +4395,22 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
 
       if (TREE_CODE (inside_init) == CONSTRUCTOR)
        {
-         tree link;
+         unsigned HOST_WIDE_INT ix;
+         tree value;
+         bool constant_p = true;
 
          /* Iterate through elements and check if all constructor
             elements are *_CSTs.  */
-         for (link = CONSTRUCTOR_ELTS (inside_init);
-              link;
-              link = TREE_CHAIN (link))
-           if (! CONSTANT_CLASS_P (TREE_VALUE (link)))
-             break;
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value)
+           if (!CONSTANT_CLASS_P (value))
+             {
+               constant_p = false;
+               break;
+             }
 
-         if (link == NULL)
-           return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
+         if (constant_p)
+           return build_vector_from_ctor (type,
+                                          CONSTRUCTOR_ELTS (inside_init));
        }
     }
 
@@ -4574,7 +4576,7 @@ static tree constructor_bit_index;
 /* If we are saving up the elements rather than allocating them,
    this is the list of elements so far (in reverse order,
    most recent first).  */
-static tree constructor_elements;
+static VEC(constructor_elt,gc) *constructor_elements;
 
 /* 1 if constructor should be incrementally stored into a constructor chain,
    0 if all the elements should be kept in AVL tree.  */
@@ -4645,7 +4647,7 @@ struct constructor_stack
   tree unfilled_index;
   tree unfilled_fields;
   tree bit_index;
-  tree elements;
+  VEC(constructor_elt,gc) *elements;
   struct init_node *pending_elts;
   int offset;
   int depth;
@@ -4689,7 +4691,7 @@ struct initializer_stack
   tree decl;
   struct constructor_stack *constructor_stack;
   struct constructor_range_stack *constructor_range_stack;
-  tree elements;
+  VEC(constructor_elt,gc) *elements;
   struct spelling *spelling;
   struct spelling *spelling_base;
   int spelling_size;
@@ -5024,7 +5026,7 @@ push_init_level (int implicit)
       constructor_constant = TREE_CONSTANT (value);
       constructor_simple = TREE_STATIC (value);
       constructor_elements = CONSTRUCTOR_ELTS (value);
-      if (constructor_elements
+      if (!VEC_empty (constructor_elt, constructor_elements)
          && (TREE_CODE (constructor_type) == RECORD_TYPE
              || TREE_CODE (constructor_type) == ARRAY_TYPE))
        set_nonincremental_init ();
@@ -5199,19 +5201,19 @@ pop_init_level (int implicit)
     {
       /* A nonincremental scalar initializer--just return
         the element, after verifying there is just one.  */
-      if (constructor_elements == 0)
+      if (VEC_empty (constructor_elt,constructor_elements))
        {
          if (!constructor_erroneous)
            error_init ("empty scalar initializer");
          ret.value = error_mark_node;
        }
-      else if (TREE_CHAIN (constructor_elements) != 0)
+      else if (VEC_length (constructor_elt,constructor_elements) != 1)
        {
          error_init ("extra elements in scalar initializer");
-         ret.value = TREE_VALUE (constructor_elements);
+         ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
        }
       else
-       ret.value = TREE_VALUE (constructor_elements);
+       ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
     }
   else
     {
@@ -5220,7 +5222,7 @@ pop_init_level (int implicit)
       else
        {
          ret.value = build_constructor (constructor_type,
-                                        nreverse (constructor_elements));
+                                        constructor_elements);
          if (constructor_constant)
            TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
          if (constructor_constant && constructor_simple)
@@ -5669,14 +5671,15 @@ add_pending_init (tree purpose, tree value)
 static void
 set_nonincremental_init (void)
 {
-  tree chain;
+  unsigned HOST_WIDE_INT ix;
+  tree index, value;
 
   if (TREE_CODE (constructor_type) != RECORD_TYPE
       && TREE_CODE (constructor_type) != ARRAY_TYPE)
     return;
 
-  for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain))
-    add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain));
+  FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
+    add_pending_init (index, value);
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -5828,9 +5831,10 @@ find_init_member (tree field)
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE)
     {
-      if (constructor_elements
-         && TREE_PURPOSE (constructor_elements) == field)
-       return TREE_VALUE (constructor_elements);
+      if (!VEC_empty (constructor_elt, constructor_elements)
+         && (VEC_last (constructor_elt, constructor_elements)->index
+             == field))
+       return VEC_last (constructor_elt, constructor_elements)->value;
     }
   return 0;
 }
@@ -5852,6 +5856,8 @@ static void
 output_init_element (tree value, bool strict_string, tree type, tree field,
                     int pending)
 {
+  constructor_elt *celt;
+
   if (type == error_mark_node || value == error_mark_node)
     {
       constructor_erroneous = 1;
@@ -5956,9 +5962,10 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
-          && constructor_elements)
+          && !VEC_empty (constructor_elt, constructor_elements))
     {
-      if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements)))
+      if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
+                                      constructor_elements)->value))
        warning_init ("initialized field with side-effects overwritten");
 
       /* We can have just one union field set.  */
@@ -5970,8 +5977,9 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
 
   if (field && TREE_CODE (field) == INTEGER_CST)
     field = copy_node (field);
-  constructor_elements
-    = tree_cons (field, value, constructor_elements);
+  celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL);
+  celt->index = field;
+  celt->value = value;
 
   /* Advance the variable that indicates sequential elements output.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE)
index b1e2e51..5c1d092 100644 (file)
@@ -672,10 +672,13 @@ build_fn_info_value (const struct function_list *function, tree type)
        array_value = tree_cons (NULL_TREE, counters, array_value);
       }
 
-  array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
+  /* FIXME: use build_constructor directly.  */
+  array_value = build_constructor_from_list (TREE_TYPE (fields),
+                                            nreverse (array_value));
   value = tree_cons (fields, array_value, value);
 
-  value = build_constructor (type, nreverse (value));
+  /* FIXME: use build_constructor directly.  */
+  value = build_constructor_from_list (type, nreverse (value));
 
   return value;
 }
@@ -768,7 +771,8 @@ build_ctr_info_value (unsigned int counter, tree type)
                     build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
                     value);
 
-  value = build_constructor (type, nreverse (value));
+  /* FIXME: use build_constructor directly.  */
+  value = build_constructor_from_list (type, nreverse (value));
 
   return value;
 }
@@ -856,7 +860,9 @@ build_gcov_info (void)
       array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
       array_type = build_array_type (fn_info_type, array_type);
 
-      fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
+      /* FIXME: use build_constructor directly.  */
+      fn_info_value = build_constructor_from_list (array_type,
+                                                  nreverse (fn_info_value));
       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
     }
   else
@@ -894,8 +900,9 @@ build_gcov_info (void)
       ctr_info_value = tree_cons (NULL_TREE,
                                  build_ctr_info_value (ix, ctr_info_type),
                                  ctr_info_value);
-  ctr_info_value = build_constructor (ctr_info_ary_type,
-                                     nreverse (ctr_info_value));
+  /* FIXME: use build_constructor directly.  */
+  ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
+                                               nreverse (ctr_info_value));
 
   field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
   TREE_CHAIN (field) = fields;
@@ -904,7 +911,8 @@ build_gcov_info (void)
 
   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
 
-  value = build_constructor (type, nreverse (value));
+  /* FIXME: use build_constructor directly.  */
+  value = build_constructor_from_list (type, nreverse (value));
 
   return value;
 }
index b30aabc..0704146 100644 (file)
@@ -1,3 +1,54 @@
+2005-07-20  Giovanni Bajo  <giovannibajo@libero.it>
+
+       Make CONSTRUCTOR use VEC to store initializers.
+       * call.c (convert_default_arg): Update call to digest_init.
+       * class.c (dump_class_hierarchy, dump_array): Update to cope with
+       VEC in CONSTRUCTOR_ELTS.
+       * cp-tree.h (EMPTY_CONSTRUCTOR_P): Likewise.
+       (finish_compound_literal, digest_init): Update declaration.
+       * decl.c (struct reshape_iter): New data type.
+       (reshape_init_array): Rename to...
+       (reshape_init_array_1): Update to cope with VEC in CONSTRUCTOR_ELTS.
+       (reshape_init): Rewrite from scratch. Split parts into...
+       (reshape_init_array, reshape_init_vector, reshape_init_class,
+       reshape_init_r): New functions.
+       (check_initializer): Update call to reshape_init. Remove obsolete
+       code.
+       (initialize_artificial_var, cp_complete_array_type): Update to cope
+       with VEC in CONSTRUCTOR_ELTS.
+       * decl2.c (grokfield): Update calls to digest_init.
+       (mark_vtable_entries): Update to cope with VEC in CONSTRUCTOR_ELTS.
+       * error.c (dump_expr_init_vec): New function.
+       (dump_expr): Use dump_expr_init_vec.
+       * init.c (build_zero_init, build_vec_init): Update to cope with VEC
+       in CONSTRUCTOR_ELTS.
+       (expand_default_init): Update call to digest_init.
+       * parser.c  (cp_parser_postfix_expression): Use a VEC for the
+       initializers.
+       (cp_parser_initializer_list): Build a VEC of initializers.
+       * pt.c (tsubst_copy, tsubst_copy_and_build): Update to cope with VEC
+       in CONSTRUCTOR_ELTS.
+       * rtti.c (tinfo_base_init, generic_initializer, ptr_initializer,
+       ptm_initializer, class_initializer, get_pseudo_ti_init): Use
+       build_constructor_from_list instead of build_constructor.
+       * semantics.c (finish_compound_literal): Update call to digest_init.
+       * tree.c (stabilize_init): Update to cope with VEC in
+       CONSTRUCTOR_ELTS.
+       * typeck.c (build_ptrmemfunc1): Likewise.
+       * typeck2.c: (cxx_incomplete_type_error, split_nonconstant_init_1):
+       Likewise.
+       (store_init_value): Use build_constructor_from_list and update call
+       to digest_init.
+       (digest_init): Rewrite.
+       (process_init_constructor): Rewrite from scratch. Split into...
+       (process_init_constructor_array, picflag_from_initializer,
+       process_init_constructor_record, process_init_constructor_union):
+       New functions.
+       (PICFLAG_ERRONEOUS, PICFLAG_NOT_ALL_CONSTANT, PICFLAG_NOT_ALL_SIMPLE):
+       New macros.
+       (build_functional_cast): Use build_constructor_from_list instead of
+       build_constructor.
+
 2005-07-18  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/22263
index 21201cf..6e88708 100644 (file)
@@ -4544,7 +4544,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum)
 
   if (TREE_CODE (arg) == CONSTRUCTOR)
     {
-      arg = digest_init (type, arg, 0);
+      arg = digest_init (type, arg);
       arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
                                        "default argument", fn, parmnum);
     }
index 5dbec46..9b85a4d 100644 (file)
@@ -6437,8 +6437,8 @@ dump_class_hierarchy (tree t)
 static void
 dump_array (FILE * stream, tree decl)
 {
-  tree inits;
-  int ix;
+  tree value;
+  unsigned HOST_WIDE_INT ix;
   HOST_WIDE_INT elt;
   tree size = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (decl)));
 
@@ -6450,10 +6450,10 @@ dump_array (FILE * stream, tree decl)
                           TFF_PLAIN_IDENTIFIER));
   fprintf (stream, "\n");
 
-  for (ix = 0, inits = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
-       inits; ix++, inits = TREE_CHAIN (inits))
+  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)),
+                             ix, value)
     fprintf (stream, "%-4ld  %s\n", (long)(ix * elt),
-            expr_as_string (TREE_VALUE (inits), TFF_PLAIN_IDENTIFIER));
+            expr_as_string (value, TFF_PLAIN_IDENTIFIER));
 }
 
 static void
index d9d053d..0ac7bba 100644 (file)
@@ -2417,9 +2417,10 @@ extern void decl_shadowed_for_var_insert (tree, tree);
 #define BRACE_ENCLOSED_INITIALIZER_P(NODE) \
   (TREE_CODE (NODE) == CONSTRUCTOR && !TREE_TYPE (NODE))
 
-#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR        \
-                                  && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \
-                                  && ! TREE_HAS_CONSTRUCTOR (NODE))
+#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
+                                  && VEC_empty (constructor_elt, \
+                                                CONSTRUCTOR_ELTS (NODE)) \
+                                  && !TREE_HAS_CONSTRUCTOR (NODE))
 
 /* Nonzero means that an object of this type can not be initialized using
    an initializer list.  */
@@ -4168,7 +4169,7 @@ extern tree finish_increment_expr         (tree, enum tree_code);
 extern tree finish_this_expr                   (void);
 extern tree finish_pseudo_destructor_expr       (tree, tree, tree);
 extern tree finish_unary_op_expr               (enum tree_code, tree);
-extern tree finish_compound_literal            (tree, tree);
+extern tree finish_compound_literal            (tree, VEC(constructor_elt,gc) *);
 extern tree finish_fname                       (tree);
 extern void finish_translation_unit            (void);
 extern tree finish_template_type_parm          (tree, tree);
@@ -4348,7 +4349,7 @@ extern void complete_type_check_abstract  (tree);
 extern int abstract_virtuals_error             (tree, tree);
 
 extern tree store_init_value                   (tree, tree);
-extern tree digest_init                                (tree, tree, tree *);
+extern tree digest_init                                (tree, tree);
 extern tree build_scoped_ref                   (tree, tree, tree *);
 extern tree build_x_arrow                      (tree);
 extern tree build_m_component_ref              (tree, tree);
index 855906a..ddcab2e 100644 (file)
@@ -114,7 +114,7 @@ static void store_parm_decls (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
 static tree next_initializable_field (tree);
-static tree reshape_init (tree, tree *);
+static tree reshape_init (tree, tree);
 
 /* Erroneous argument lists can use this *IFF* they do not modify it.  */
 tree error_mark_list;
@@ -4103,6 +4103,18 @@ check_for_uninitialized_const_var (tree decl)
     error ("uninitialized const %qD", decl);
 }
 
+\f
+/* 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);
index 5afcd89..e7db552 100644 (file)
@@ -903,37 +903,24 @@ grokfield (const cp_declarator *declarator,
       else if (pedantic && TREE_CODE (value) != VAR_DECL)
        /* Already complained in grokdeclarator.  */
        init = NULL_TREE;
-      else
+      else if (!processing_template_decl)
        {
-         /* We allow initializers to become parameters to base
-            initializers.  */
-         if (TREE_CODE (init) == TREE_LIST)
-           {
-             if (TREE_CHAIN (init) == NULL_TREE)
-               init = TREE_VALUE (init);
-             else
-               init = digest_init (TREE_TYPE (value), init, (tree *)0);
-           }
+         if (TREE_CODE (init) == CONSTRUCTOR)
+           init = digest_init (TREE_TYPE (value), init);
+         else
+           init = integral_constant_value (init);
 
-         if (!processing_template_decl)
+         if (init != error_mark_node && !TREE_CONSTANT (init))
            {
-             if (TREE_CODE (init) == CONSTRUCTOR)
-               init = digest_init (TREE_TYPE (value), init, (tree *)0);
-             else
-               init = integral_constant_value (init);
-
-             if (init != error_mark_node && ! TREE_CONSTANT (init))
+             /* We can allow references to things that are effectively
+                static, since references are initialized with the
+                address.  */
+             if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
+                 || (TREE_STATIC (init) == 0
+                     && (!DECL_P (init) || DECL_EXTERNAL (init) == 0)))
                {
-                 /* We can allow references to things that are effectively
-                    static, since references are initialized with the
-                    address.  */
-                 if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
-                     || (TREE_STATIC (init) == 0
-                         && (!DECL_P (init) || DECL_EXTERNAL (init) == 0)))
-                   {
-                     error ("field initializer is not constant");
-                     init = error_mark_node;
-                   }
+                 error ("field initializer is not constant");
+                 init = error_mark_node;
                }
            }
        }
@@ -1262,11 +1249,12 @@ coerce_delete_type (tree type)
 static void
 mark_vtable_entries (tree decl)
 {
-  tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
+  tree fnaddr;
+  unsigned HOST_WIDE_INT idx;
 
-  for (; entries; entries = TREE_CHAIN (entries))
+  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)),
+                             idx, fnaddr)
     {
-      tree fnaddr = TREE_VALUE (entries);
       tree fn;
 
       STRIP_NOPS (fnaddr);
index 6d80fc6..9905e25 100644 (file)
@@ -1266,6 +1266,23 @@ dump_expr_list (tree l, int flags)
     }
 }
 
+/* Print out a vector of initializers (subr of dump_expr).  */
+
+static void
+dump_expr_init_vec (VEC(constructor_elt,gc) *v, int flags)
+{
+  unsigned HOST_WIDE_INT idx;
+  tree value;
+
+  FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
+    {
+      dump_expr (value, flags | TFF_EXPR_IN_PARENS);
+      if (idx != VEC_length (constructor_elt, v) - 1)
+       pp_separate_with_comma (cxx_pp);
+    }
+}
+
+
 /* Print out an expression E under control of FLAGS.  */
 
 static void
@@ -1659,7 +1676,7 @@ dump_expr (tree t, int flags)
                }
            }
        }
-      if (TREE_TYPE (t) && !CONSTRUCTOR_ELTS (t))
+      if (TREE_TYPE (t) && EMPTY_CONSTRUCTOR_P (t))
        {
          dump_type (TREE_TYPE (t), 0);
          pp_cxx_left_paren (cxx_pp);
@@ -1668,7 +1685,7 @@ dump_expr (tree t, int flags)
       else
        {
          pp_cxx_left_brace (cxx_pp);
-         dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
+         dump_expr_init_vec (CONSTRUCTOR_ELTS (t), flags);
          pp_cxx_right_brace (cxx_pp);
        }
 
index 05491c4..9383e92 100644 (file)
@@ -184,12 +184,9 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
   else if (CLASS_TYPE_P (type))
     {
       tree field;
-      tree inits;
+      VEC(constructor_elt,gc) *v = NULL;
 
-      /* Build a constructor to contain the initializations.  */
-      init = build_constructor (type, NULL_TREE);
       /* Iterate over the fields, building initializations.  */
-      inits = NULL_TREE;
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        {
          if (TREE_CODE (field) != FIELD_DECL)
@@ -200,27 +197,27 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
             over TYPE_FIELDs will result in correct initialization of
             all of the subobjects.  */
          if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
-           inits = tree_cons (field,
-                              build_zero_init (TREE_TYPE (field),
-                                               /*nelts=*/NULL_TREE,
-                                               static_storage_p),
-                              inits);
+           {
+             tree value = build_zero_init (TREE_TYPE (field),
+                                           /*nelts=*/NULL_TREE,
+                                           static_storage_p);
+             CONSTRUCTOR_APPEND_ELT(v, field, value);
+           }
 
          /* For unions, only the first field is initialized.  */
          if (TREE_CODE (type) == UNION_TYPE)
            break;
        }
-      CONSTRUCTOR_ELTS (init) = nreverse (inits);
+
+       /* Build a constructor to contain the initializations.  */
+       init = build_constructor (type, v);
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
     {
       tree max_index;
-      tree inits;
+      VEC(constructor_elt,gc) *v = NULL;
 
-      /* Build a constructor to contain the initializations.  */
-      init = build_constructor (type, NULL_TREE);
       /* Iterate over the array elements, building initializations.  */
-      inits = NULL_TREE;
       if (nelts)
        max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts),
                                 nelts, integer_one_node);
@@ -232,21 +229,25 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
         have an upper bound of -1.  */
       if (!tree_int_cst_equal (max_index, integer_minus_one_node))
        {
-         tree elt_init = build_zero_init (TREE_TYPE (type),
-                                          /*nelts=*/NULL_TREE,
-                                          static_storage_p);
-         tree range;
+         constructor_elt *ce;
+
+         v = VEC_alloc (constructor_elt, gc, 1);
+         ce = VEC_quick_push (constructor_elt, v, NULL);
 
          /* If this is a one element array, we just use a regular init.  */
          if (tree_int_cst_equal (size_zero_node, max_index))
-           range = size_zero_node;
+           ce->index = size_zero_node;
          else
-          range = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index);
+           ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
+                               max_index);
 
-         inits = tree_cons (range, elt_init, inits);
+         ce->value = build_zero_init (TREE_TYPE (type),
+                                      /*nelts=*/NULL_TREE,
+                                      static_storage_p);
        }
 
-      CONSTRUCTOR_ELTS (init) = nreverse (inits);
+      /* Build a constructor to contain the initializations.  */
+      init = build_constructor (type, v);
     }
   else
     gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
@@ -1191,7 +1192,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
        {
          /* A brace-enclosed initializer for an aggregate.  */
          gcc_assert (CP_AGGREGATE_TYPE_P (type));
-         init = digest_init (type, init, (tree *)NULL);
+         init = digest_init (type, init);
        }
       else
        init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
@@ -2417,7 +2418,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
       && ((TREE_CODE (init) == CONSTRUCTOR
           /* Don't do this if the CONSTRUCTOR might contain something
              that might throw and require us to clean up.  */
-          && (CONSTRUCTOR_ELTS (init) == NULL_TREE
+          && (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init))
               || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
          || from_array))
     {
@@ -2485,13 +2486,12 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
     {
       /* Do non-default initialization of non-POD arrays resulting from
         brace-enclosed initializers.  */
-
-      tree elts;
+      unsigned HOST_WIDE_INT idx;
+      tree elt;
       from_array = 0;
 
-      for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts))
+      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt)
        {
-         tree elt = TREE_VALUE (elts);
          tree baseref = build1 (INDIRECT_REF, type, base);
 
          num_initialized_elts++;
index bd39a67..082727e 100644 (file)
@@ -1546,7 +1546,7 @@ static tree cp_parser_initializer
   (cp_parser *, bool *, bool *);
 static tree cp_parser_initializer_clause
   (cp_parser *, bool *);
-static tree cp_parser_initializer_list
+static VEC(constructor_elt,gc) *cp_parser_initializer_list
   (cp_parser *, bool *);
 
 static bool cp_parser_ctor_initializer_opt_and_function_body
@@ -4027,7 +4027,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
        if (cp_parser_allow_gnu_extensions_p (parser)
            && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
          {
-           tree initializer_list = NULL_TREE;
+           VEC(constructor_elt,gc) *initializer_list = NULL;
            bool saved_in_type_id_in_expr_p;
 
            cp_parser_parse_tentatively (parser);
@@ -12298,7 +12298,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
    returned is simply a representation for the expression.
 
    Otherwise, a CONSTRUCTOR is returned.  The CONSTRUCTOR_ELTS will be
-   the elements of the initializer-list (or NULL_TREE, if the last
+   the elements of the initializer-list (or NULL, if the last
    production is used).  The TREE_TYPE for the CONSTRUCTOR will be
    NULL_TREE.  There is no way to detect whether or not the optional
    trailing `,' was provided.  NON_CONSTANT_P is as for
@@ -12358,15 +12358,15 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
      identifier : initializer-clause
      initializer-list, identifier : initializer-clause
 
-   Returns a TREE_LIST.  The TREE_VALUE of each node is an expression
-   for the initializer.  If the TREE_PURPOSE is non-NULL, it is the
+   Returns a VEC of constructor_elt.  The VALUE of each elt is an expression
+   for the initializer.  If the INDEX of the elt is non-NULL, it is the
    IDENTIFIER_NODE naming the field to initialize.  NON_CONSTANT_P is
    as for cp_parser_initializer.  */
 
-static tree
+static VEC(constructor_elt,gc) *
 cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
 {
-  tree initializers = NULL_TREE;
+  VEC(constructor_elt,gc) *v = NULL;
 
   /* Assume all of the expressions are constant.  */
   *non_constant_p = false;
@@ -12400,8 +12400,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
       /* If any clause is non-constant, so is the entire initializer.  */
       if (clause_non_constant_p)
        *non_constant_p = true;
-      /* Add it to the list.  */
-      initializers = tree_cons (identifier, initializer, initializers);
+
+      /* Add it to the vector.  */
+      CONSTRUCTOR_APPEND_ELT(v, identifier, initializer);
 
       /* If the next token is not a comma, we have reached the end of
         the list.  */
@@ -12420,9 +12421,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
       cp_lexer_consume_token (parser->lexer);
     }
 
-  /* The initializers were built up in reverse order, so we need to
-     reverse them now.  */
-  return nreverse (initializers);
+  return v;
 }
 
 /* Classes [gram.class] */
index 619cdc1..2ab89b2 100644 (file)
@@ -8006,13 +8006,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        return t;
 
     case CONSTRUCTOR:
-      {
-       r = build_constructor
-         (tsubst (TREE_TYPE (t), args, complain, in_decl),
-          tsubst_copy (CONSTRUCTOR_ELTS (t), args, complain, in_decl));
-       TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
-       return r;
-      }
+      /* This is handled by tsubst_copy_and_build.  */
+      gcc_unreachable ();
 
     case VA_ARG_EXPR:
       return build_x_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
@@ -8814,38 +8809,35 @@ tsubst_copy_and_build (tree t,
 
     case CONSTRUCTOR:
       {
+       VEC(constructor_elt,gc) *n;
+       constructor_elt *ce;
+       unsigned HOST_WIDE_INT idx;
        tree r;
-       tree elts;
        tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
-       bool purpose_p;
+       bool process_index_p;
 
        /* digest_init will do the wrong thing if we let it.  */
        if (type && TYPE_PTRMEMFUNC_P (type))
          return t;
 
-       r = NULL_TREE;
-       /* We do not want to process the purpose of aggregate
+       /* We do not want to process the index of aggregate
           initializers as they are identifier nodes which will be
           looked up by digest_init.  */
-       purpose_p = !(type && IS_AGGR_TYPE (type));
-       for (elts = CONSTRUCTOR_ELTS (t);
-            elts;
-            elts = TREE_CHAIN (elts))
-         {
-           tree purpose = TREE_PURPOSE (elts);
-           tree value = TREE_VALUE (elts);
+       process_index_p = !(type && IS_AGGR_TYPE (type));
 
-           if (purpose && purpose_p)
-             purpose = RECUR (purpose);
-           value = RECUR (value);
-           r = tree_cons (purpose, value, r);
+       n = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
+       for (idx = 0; VEC_iterate (constructor_elt, n, idx, ce); idx++)
+         {
+           if (ce->index && process_index_p)
+             ce->index = RECUR (ce->index);
+           ce->value = RECUR (ce->value);
          }
 
-       r = build_constructor (NULL_TREE, nreverse (r));
+       r = build_constructor (NULL_TREE, n);
        TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
 
        if (type)
-         return digest_init (type, r, 0);
+         return digest_init (type, r);
        return r;
       }
 
index dd59f69..e006938 100644 (file)
@@ -861,7 +861,7 @@ tinfo_base_init (tinfo_s *ti, tree target)
 
   init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
 
-  init = build_constructor (NULL_TREE, nreverse (init));
+  init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
   TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
@@ -879,7 +879,7 @@ generic_initializer (tinfo_s *ti, tree target)
 {
   tree init = tinfo_base_init (ti, target);
   
-  init = build_constructor (NULL_TREE, init);
+  init = build_constructor_from_list (NULL_TREE, init);
   TREE_CONSTANT (init) = 1;
   TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
@@ -905,7 +905,7 @@ ptr_initializer (tinfo_s *ti, tree target)
                    get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
                    init);
 
-  init = build_constructor (NULL_TREE, nreverse (init));
+  init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
   TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
@@ -937,8 +937,8 @@ ptm_initializer (tinfo_s *ti, tree target)
   init = tree_cons (NULL_TREE,
                    get_tinfo_ptr (klass),
                    init);
-
-  init = build_constructor (NULL_TREE, nreverse (init));
+  
+  init = build_constructor_from_list (NULL_TREE, nreverse (init));
   TREE_CONSTANT (init) = 1;
   TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
@@ -955,7 +955,7 @@ class_initializer (tinfo_s *ti, tree target, tree trail)
   tree init = tinfo_base_init (ti, target);
 
   TREE_CHAIN (init) = trail;
-  init = build_constructor (NULL_TREE, init);
+  init = build_constructor_from_list (NULL_TREE, init);
   TREE_CONSTANT (init) = 1;
   TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
@@ -1066,10 +1066,10 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
                                         build_int_cst (NULL_TREE, flags));
            base_init = tree_cons (NULL_TREE, offset, base_init);
            base_init = tree_cons (NULL_TREE, tinfo, base_init);
-           base_init = build_constructor (NULL_TREE, base_init);
+           base_init = build_constructor_from_list (NULL_TREE, base_init);
            base_inits = tree_cons (NULL_TREE, base_init, base_inits);
          }
-       base_inits = build_constructor (NULL_TREE, base_inits);
+       base_inits = build_constructor_from_list (NULL_TREE, base_inits);
        base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
        /* Prepend the number of bases.  */
        base_inits = tree_cons (NULL_TREE,
index 3d99c5d..e935bb9 100644 (file)
@@ -2011,20 +2011,19 @@ finish_unary_op_expr (enum tree_code code, tree expr)
    the INITIALIZER_LIST is being cast.  */
 
 tree
-finish_compound_literal (tree type, tree initializer_list)
+finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list)
 {
   tree compound_literal;
 
   /* Build a CONSTRUCTOR for the INITIALIZER_LIST.  */
   compound_literal = build_constructor (NULL_TREE, initializer_list);
   /* Mark it as a compound-literal.  */
-  TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
   if (processing_template_decl)
     TREE_TYPE (compound_literal) = type;
   else
     {
       /* Check the initialization.  */
-      compound_literal = digest_init (type, compound_literal, NULL);
+      compound_literal = digest_init (type, compound_literal);
       /* If the TYPE was an array type with an unknown bound, then we can
         figure out the dimension now.  For example, something like:
 
@@ -2036,6 +2035,7 @@ finish_compound_literal (tree type, tree initializer_list)
                                compound_literal, 1);
     }
 
+  TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
   return compound_literal;
 }
 
index 0cf6b4e..ddc0b51 100644 (file)
@@ -2241,7 +2241,7 @@ stabilize_init (tree init, tree *initp)
       if (TREE_CODE (t) == COMPOUND_EXPR)
        t = expr_last (t);
       if (TREE_CODE (t) == CONSTRUCTOR
-         && CONSTRUCTOR_ELTS (t) == NULL_TREE)
+         && EMPTY_CONSTRUCTOR_P (t))
        {
          /* Default-initialization.  */
          *initp = NULL_TREE;
index b13c8cf..9a14f48 100644 (file)
@@ -5640,6 +5640,7 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
   tree u = NULL_TREE;
   tree delta_field;
   tree pfn_field;
+  VEC(constructor_elt, gc) *v;
 
   /* Pull the FIELD_DECLs out of the type.  */
   pfn_field = TYPE_FIELDS (type);
@@ -5649,9 +5650,10 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
   delta = convert_and_check (delta_type_node, delta);
 
   /* Finish creating the initializer.  */
-  u = tree_cons (pfn_field, pfn,
-                build_tree_list (delta_field, delta));
-  u = build_constructor (type, u);
+  v = VEC_alloc(constructor_elt, gc, 2);
+  CONSTRUCTOR_APPEND_ELT(v, pfn_field, pfn);
+  CONSTRUCTOR_APPEND_ELT(v, delta_field, delta);
+  u = build_constructor (type, v);
   TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta);
   TREE_INVARIANT (u) = TREE_INVARIANT (pfn) & TREE_INVARIANT (delta);
   TREE_STATIC (u) = (TREE_CONSTANT (u)
index 4244088..2564a05 100644 (file)
@@ -39,7 +39,9 @@ Boston, MA 02110-1301, USA.  */
 #include "output.h"
 #include "diagnostic.h"
 
-static tree process_init_constructor (tree, tree, tree *);
+static tree
+process_init_constructor (tree type, tree init);
+
 
 /* Print an error message stemming from an attempt to use
    BASETYPE as a base class for TYPE.  */
@@ -435,11 +437,12 @@ cxx_incomplete_type_error (tree value, tree type)
 static void
 split_nonconstant_init_1 (tree dest, tree init)
 {
-  tree *pelt, elt, type = TREE_TYPE (dest);
-  tree sub, code, inner_type = NULL;
+  unsigned HOST_WIDE_INT idx;
+  tree field_index, value;
+  tree type = TREE_TYPE (dest);
+  tree inner_type = NULL;
   bool array_type_p = false;
 
-  pelt = &CONSTRUCTOR_ELTS (init);
   switch (TREE_CODE (type))
     {
     case ARRAY_TYPE:
@@ -450,16 +453,21 @@ split_nonconstant_init_1 (tree dest, tree init)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      while ((elt = *pelt))
+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx,
+                               field_index, value)
        {
-         tree field_index = TREE_PURPOSE (elt);
-         tree value = TREE_VALUE (elt);
+         /* The current implementation of this algorithm assumes that
+            the field was set for all the elements. This is usually done
+            by process_init_constructor.  */
+         gcc_assert (field_index);
 
          if (!array_type_p)
            inner_type = TREE_TYPE (field_index);
 
          if (TREE_CODE (value) == CONSTRUCTOR)
            {
+             tree sub;
+
              if (array_type_p)
                sub = build4 (ARRAY_REF, inner_type, dest, field_index,
                              NULL_TREE, NULL_TREE);
@@ -471,7 +479,19 @@ split_nonconstant_init_1 (tree dest, tree init)
            }
          else if (!initializer_constant_valid_p (value, inner_type))
            {
-             *pelt = TREE_CHAIN (elt);
+             tree code;
+             tree sub;
+
+             /* FIXME: Ordered removal is O(1) so the whole function is
+                worst-case quadratic. This could be fixed using an aside
+                bitmap to record which elements must be removed and remove
+                them all at the same time. Or by merging
+                split_non_constant_init into process_init_constructor_array,
+                that is separating constants from non-constants while building
+                the vector.  */
+             VEC_ordered_remove (constructor_elt, CONSTRUCTOR_ELTS (init),
+                                 idx);
+             --idx;
 
              if (array_type_p)
                sub = build4 (ARRAY_REF, inner_type, dest, field_index,
@@ -485,14 +505,13 @@ split_nonconstant_init_1 (tree dest, tree init)
              add_stmt (code);
              continue;
            }
-
-         pelt = &TREE_CHAIN (elt);
        }
       break;
 
     case VECTOR_TYPE:
       if (!initializer_constant_valid_p (init, type))
        {
+         tree code;
          tree cons = copy_node (init);
          CONSTRUCTOR_ELTS (init) = NULL;
          code = build2 (MODIFY_EXPR, type, dest, cons);
@@ -568,7 +587,7 @@ store_init_value (tree decl, tree init)
        {
          error ("constructor syntax used, but no constructor declared "
                 "for type %qT", type);
-         init = build_constructor (NULL_TREE, nreverse (init));
+         init = build_constructor_from_list (NULL_TREE, nreverse (init));
        }
     }
   else if (TREE_CODE (init) == TREE_LIST
@@ -591,7 +610,7 @@ store_init_value (tree decl, tree init)
   /* End of special C++ code.  */
 
   /* Digest the specified initializer into an expression.  */
-  value = digest_init (type, init, (tree *) 0);
+  value = digest_init (type, init);
   /* If the initializer is not a constant, fill in DECL_INITIAL with
      the bits that are constant, and then return an expression that
      will perform the dynamic initialization.  */
@@ -607,39 +626,22 @@ store_init_value (tree decl, tree init)
 }
 
 \f
-/* 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);
     }
+}
+
+\f
+/* 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;
-}
-\f
-/* 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;
 }
 \f
 /* 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);
     }
 
index 182ab23..60d45f3 100644 (file)
@@ -4398,17 +4398,16 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
                            HOST_WIDE_INT *p_elt_count,
                            bool *p_must_clear)
 {
+  unsigned HOST_WIDE_INT idx;
   HOST_WIDE_INT nz_elts, nc_elts, elt_count;
-  tree list;
+  tree value, purpose;
 
   nz_elts = 0;
   nc_elts = 0;
   elt_count = 0;
 
-  for (list = CONSTRUCTOR_ELTS (ctor); list; list = TREE_CHAIN (list))
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, purpose, value)
     {
-      tree value = TREE_VALUE (list);
-      tree purpose = TREE_PURPOSE (list);
       HOST_WIDE_INT mult;
 
       mult = 1;
@@ -4482,14 +4481,16 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
       tree init_sub_type;
       bool clear_this = true;
 
-      list = CONSTRUCTOR_ELTS (ctor);
-      if (list)
+      if (!VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)))
        {
          /* We don't expect more than one element of the union to be
             initialized.  Not sure what we should do otherwise... */
-          gcc_assert (TREE_CHAIN (list) == NULL);
+          gcc_assert (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (ctor))
+                     == 1);
 
-          init_sub_type = TREE_TYPE (TREE_VALUE (list));
+          init_sub_type = TREE_TYPE (VEC_index (constructor_elt,
+                                               CONSTRUCTOR_ELTS (ctor),
+                                               0)->value);
 
          /* ??? We could look at each element of the union, and find the
             largest element.  Which would avoid comparing the size of the
@@ -4699,7 +4700,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
       {
-       tree elt;
+       unsigned HOST_WIDE_INT idx;
+       tree field, value;
 
        /* If size is zero or the target is already cleared, do nothing.  */
        if (size == 0 || cleared)
@@ -4731,7 +4733,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
           register whose mode size isn't equal to SIZE since
           clear_storage can't handle this case.  */
        else if (size > 0
-                && ((list_length (CONSTRUCTOR_ELTS (exp))
+                && (((int)VEC_length (constructor_elt, CONSTRUCTOR_ELTS (exp))
                      != fields_length (type))
                     || mostly_zeros_p (exp))
                 && (!REG_P (target)
@@ -4747,11 +4749,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
 
        /* Store each element of the constructor into the
           corresponding field of TARGET.  */
-
-       for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, field, value)
          {
-           tree field = TREE_PURPOSE (elt);
-           tree value = TREE_VALUE (elt);
            enum machine_mode mode;
            HOST_WIDE_INT bitsize;
            HOST_WIDE_INT bitpos = 0;
@@ -4857,8 +4856,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
       }
     case ARRAY_TYPE:
       {
-       tree elt;
-       int i;
+       tree value, index;
+       unsigned HOST_WIDE_INT i;
        int need_to_clear;
        tree domain;
        tree elttype = TREE_TYPE (type);
@@ -4888,18 +4887,20 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
          need_to_clear = 1;
        else
          {
+           unsigned HOST_WIDE_INT idx;
+           tree index, value;
            HOST_WIDE_INT count = 0, zero_count = 0;
            need_to_clear = ! const_bounds_p;
            
            /* This loop is a more accurate version of the loop in
               mostly_zeros_p (it handles RANGE_EXPR in an index).  It
               is also needed to check for missing elements.  */
-           for (elt = CONSTRUCTOR_ELTS (exp);
-                elt != NULL_TREE && ! need_to_clear;
-                elt = TREE_CHAIN (elt))
+           FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, index, value)
              {
-               tree index = TREE_PURPOSE (elt);
                HOST_WIDE_INT this_node_count;
+
+               if (need_to_clear)
+                 break;
                
                if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
                  {
@@ -4920,7 +4921,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                  this_node_count = 1;
                
                count += this_node_count;
-               if (mostly_zeros_p (TREE_VALUE (elt)))
+               if (mostly_zeros_p (value))
                  zero_count += this_node_count;
              }
            
@@ -4949,16 +4950,12 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
        /* Store each element of the constructor into the
           corresponding element of TARGET, determined by counting the
           elements.  */
-       for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
-            elt;
-            elt = TREE_CHAIN (elt), i++)
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), i, index, value)
          {
            enum machine_mode mode;
            HOST_WIDE_INT bitsize;
            HOST_WIDE_INT bitpos;
            int unsignedp;
-           tree value = TREE_VALUE (elt);
-           tree index = TREE_PURPOSE (elt);
            rtx xtarget = target;
            
            if (cleared && initializer_zerop (value))
@@ -5118,7 +5115,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
 
     case VECTOR_TYPE:
       {
-       tree elt;
+       unsigned HOST_WIDE_INT idx;
+       constructor_elt *ce;
        int i;
        int need_to_clear;
        int icode = 0;
@@ -5158,18 +5156,17 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
        else
          {
            unsigned HOST_WIDE_INT count = 0, zero_count = 0;
+           tree value;
            
-           for (elt = CONSTRUCTOR_ELTS (exp);
-                elt != NULL_TREE;
-                elt = TREE_CHAIN (elt))
+           FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
              {
                int n_elts_here = tree_low_cst
                  (int_const_binop (TRUNC_DIV_EXPR,
-                                   TYPE_SIZE (TREE_TYPE (TREE_VALUE (elt))),
+                                   TYPE_SIZE (TREE_TYPE (value)),
                                    TYPE_SIZE (elttype), 0), 1);
                
                count += n_elts_here;
-               if (mostly_zeros_p (TREE_VALUE (elt)))
+               if (mostly_zeros_p (value))
                  zero_count += n_elts_here;
              }
 
@@ -5193,20 +5190,19 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
 
         /* Store each element of the constructor into the corresponding
           element of TARGET, determined by counting the elements.  */
-       for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
-            elt;
-            elt = TREE_CHAIN (elt), i += bitsize / elt_size)
+       for (idx = 0, i = 0;
+            VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), idx, ce);
+            idx++, i += bitsize / elt_size)
          {
-           tree value = TREE_VALUE (elt);
-           tree index = TREE_PURPOSE (elt);
            HOST_WIDE_INT eltpos;
+           tree value = ce->value;
            
            bitsize = tree_low_cst (TYPE_SIZE (TREE_TYPE (value)), 1);
            if (cleared && initializer_zerop (value))
              continue;
            
-           if (index != 0)
-             eltpos = tree_low_cst (index, 1);
+           if (ce->index)
+             eltpos = tree_low_cst (ce->index, 1);
            else
              eltpos = i;
            
@@ -6733,8 +6729,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_FLOAT)
        return const_vector_from_tree (exp);
       else
-       return expand_expr (build1 (CONSTRUCTOR, TREE_TYPE (exp),
-                                   TREE_VECTOR_CST_ELTS (exp)),
+       return expand_expr (build_constructor_from_list
+                           (TREE_TYPE (exp),
+                            TREE_VECTOR_CST_ELTS (exp)),
                            ignore ? const0_rtx : target, tmode, modifier);
 
     case CONST_DECL:
@@ -6832,10 +6829,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         subexpressions.  */
       if (ignore)
        {
-         tree elt;
+         unsigned HOST_WIDE_INT idx;
+         tree value;
 
-         for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
-           expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
+           expand_expr (value, const0_rtx, VOIDmode, 0);
 
          return const0_rtx;
        }
@@ -6997,16 +6995,17 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            && ! TREE_SIDE_EFFECTS (array)
            && TREE_CODE (index) == INTEGER_CST)
          {
-           tree elem;
-
-           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);
index 0e414bc..273a912 100644 (file)
@@ -9861,9 +9861,11 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
       if (TREE_CODE (arg0) == CONSTRUCTOR
          && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
        {
-         tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
-         if (m)
-           return TREE_VALUE (m);
+         unsigned HOST_WIDE_INT idx;
+         tree field, value;
+         FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg0), idx, field, value)
+           if (field == arg1)
+             return value;
        }
       return NULL_TREE;
 
index 12c6b2e..80a1538 100644 (file)
@@ -1,3 +1,14 @@
+2005-07-20  Giovanni Bajo  <giovannibajo@libero.it>
+
+       Make CONSTRUCTOR use VEC to store initializers.
+       * trans-array.c (gfc_build_null_descriptor,
+       gfc_trans_array_constructor_value, gfc_conv_array_initializer):
+       Update to cope with VEC in CONSTRUCTOR_ELTS.
+       * trans-common.c (create_common): Likewise.
+       * trans-expr.c (gfc_conv_structure): Likewise.
+       * trans-stmt.c (gfc_trans_character_select): Use
+       build_constructor_from_list instead of build_constructor.
+
 2005-07-19 Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/16940
index d54dff3..e634154 100644 (file)
@@ -299,8 +299,7 @@ gfc_build_null_descriptor (tree type)
   field = TYPE_FIELDS (type);
 
   /* Set a NULL data pointer.  */
-  tmp = tree_cons (field, null_pointer_node, NULL_TREE);
-  tmp = build1 (CONSTRUCTOR, type, tmp);
+  tmp = build_constructor_single (type, field, null_pointer_node);
   TREE_CONSTANT (tmp) = 1;
   TREE_INVARIANT (tmp) = 1;
   /* All other fields are ignored.  */
@@ -834,7 +833,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
                                          gfc_index_zero_node, bound);
              tmptype = build_array_type (type, tmptype);
 
-             init = build1 (CONSTRUCTOR, tmptype, nreverse (list));
+             init = build_constructor_from_list (tmptype, nreverse (list));
              TREE_CONSTANT (init) = 1;
              TREE_INVARIANT (init) = 1;
              TREE_STATIC (init) = 1;
@@ -2833,15 +2832,14 @@ tree
 gfc_conv_array_initializer (tree type, gfc_expr * expr)
 {
   gfc_constructor *c;
-  tree list;
   tree tmp;
   mpz_t maxval;
   gfc_se se;
   HOST_WIDE_INT hi;
   unsigned HOST_WIDE_INT lo;
   tree index, range;
+  VEC(constructor_elt,gc) *v = NULL;
 
-  list = NULL_TREE;
   switch (expr->expr_type)
     {
     case EXPR_CONSTANT:
@@ -2865,7 +2863,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
       /* This will probably eat buckets of memory for large arrays.  */
       while (hi != 0 || lo != 0)
         {
-          list = tree_cons (NULL_TREE, se.expr, list);
+         CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
           if (lo == 0)
             hi--;
           lo--;
@@ -2873,7 +2871,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
       break;
 
     case EXPR_ARRAY:
-      /* Create a list of all the elements.  */
+      /* Create a vector of all the elements.  */
       for (c = expr->value.constructor; c; c = c->next)
         {
           if (c->iterator)
@@ -2917,26 +2915,24 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
            case EXPR_CONSTANT:
              gfc_conv_constant (&se, c->expr);
               if (range == NULL_TREE)
-                list = tree_cons (index, se.expr, list);
+               CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
               else
                 {
                   if (index != NULL_TREE)
-                    list = tree_cons (index, se.expr, list);
-                  list = tree_cons (range, se.expr, list);
+                   CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
+                 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
                 }
              break;
 
            case EXPR_STRUCTURE:
               gfc_conv_structure (&se, c->expr, 1);
-              list = tree_cons (index, se.expr, list);
+             CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
              break;
 
            default:
              gcc_unreachable ();
            }
         }
-      /* We created the list in reverse order.  */
-      list = nreverse (list);
       break;
 
     default:
@@ -2944,7 +2940,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
     }
 
   /* Create a constructor from the list of elements.  */
-  tmp = build1 (CONSTRUCTOR, type, list);
+  tmp = build_constructor (type, v);
   TREE_CONSTANT (tmp) = 1;
   TREE_INVARIANT (tmp) = 1;
   return tmp;
index 39b49e2..4defe0f 100644 (file)
@@ -422,10 +422,10 @@ create_common (gfc_common_head *com, segment_info * head, bool saw_equiv)
 
   if (is_init)
     {
-      tree list, ctor, tmp;
+      tree ctor, tmp;
       HOST_WIDE_INT offset = 0;
+      VEC(constructor_elt,gc) *v = NULL;
 
-      list = NULL_TREE;
       for (s = head; s; s = s->next)
         {
           if (s->sym->value)
@@ -442,20 +442,25 @@ create_common (gfc_common_head *com, segment_info * head, bool saw_equiv)
              tmp = gfc_conv_initializer (s->sym->value, &s->sym->ts,
                  TREE_TYPE (s->field), s->sym->attr.dimension,
                  s->sym->attr.pointer || s->sym->attr.allocatable);
-             list = tree_cons (s->field, tmp, list);
+
+             CONSTRUCTOR_APPEND_ELT (v, s->field, tmp);
               offset = s->offset + s->length;
             }
         }
-      gcc_assert (list);
-      ctor = build1 (CONSTRUCTOR, union_type, nreverse(list));
+      gcc_assert (!VEC_empty (constructor_elt, v));
+      ctor = build_constructor (union_type, v);
       TREE_CONSTANT (ctor) = 1;
       TREE_INVARIANT (ctor) = 1;
       TREE_STATIC (ctor) = 1;
       DECL_INITIAL (decl) = ctor;
 
 #ifdef ENABLE_CHECKING
-      for (tmp = CONSTRUCTOR_ELTS (ctor); tmp; tmp = TREE_CHAIN (tmp))
-       gcc_assert (TREE_CODE (TREE_PURPOSE (tmp)) == FIELD_DECL);
+      {
+       tree field, value;
+       unsigned HOST_WIDE_INT idx;
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, field, value)
+         gcc_assert (TREE_CODE (field) == FIELD_DECL);
+      }
 #endif
     }
 
index c1863fc..0cd8741 100644 (file)
@@ -1812,11 +1812,10 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
 {
   gfc_constructor *c;
   gfc_component *cm;
-  tree head;
-  tree tail;
   tree val;
   tree type;
   tree tmp;
+  VEC(constructor_elt,gc) *v = NULL;
 
   gcc_assert (se->ss == NULL);
   gcc_assert (expr->expr_type == EXPR_STRUCTURE);
@@ -1831,9 +1830,6 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
       return;
     }
 
-  head = build1 (CONSTRUCTOR, type, NULL_TREE);
-  tail = NULL_TREE;
-
   cm = expr->ts.derived->components;
   for (c = expr->value.constructor; c; c = c->next, cm = cm->next)
     {
@@ -1844,19 +1840,10 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
       val = gfc_conv_initializer (c->expr, &cm->ts,
          TREE_TYPE (cm->backend_decl), cm->dimension, cm->pointer);
 
-      /* Build a TREE_CHAIN to hold it.  */
-      val = tree_cons (cm->backend_decl, val, NULL_TREE);
-
-      /* Add it to the list.  */
-      if (tail == NULL_TREE)
-        TREE_OPERAND(head, 0) = tail = val;
-      else
-        {
-          TREE_CHAIN (tail) = val;
-          tail = val;
-        }
+      /* Append it to the constructor list.  */
+      CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, val);
     }
-  se->expr = head;
+  se->expr = build_constructor (type, v);
 }
 
 
index 0ec029f..99467b4 100644 (file)
@@ -1220,14 +1220,14 @@ gfc_trans_character_select (gfc_code *code)
       tmp = gfc_build_addr_expr (pvoid_type_node, labels[i]);
       node = tree_cons (ss_target, tmp, node);
 
-      tmp = build1 (CONSTRUCTOR, select_struct, nreverse (node));
+      tmp = build_constructor_from_list (select_struct, nreverse (node));
       init = tree_cons (NULL_TREE, tmp, init);
     }
 
   type = build_array_type (select_struct, build_index_type
                           (build_int_cst (NULL_TREE, n - 1)));
 
-  init = build1 (CONSTRUCTOR, type, nreverse(init));
+  init = build_constructor_from_list (type, nreverse(init));
   TREE_CONSTANT (init) = 1;
   TREE_INVARIANT (init) = 1;
   TREE_STATIC (init) = 1;
index 3f06d7a..bb08c2b 100644 (file)
@@ -2385,9 +2385,12 @@ gimplify_init_ctor_preeval (tree *expr_p, tree *pre_p, tree *post_p,
   /* Recurse for nested constructors.  */
   if (TREE_CODE (*expr_p) == CONSTRUCTOR)
     {
-      tree list;
-      for (list = CONSTRUCTOR_ELTS (*expr_p); list ; list = TREE_CHAIN (list))
-       gimplify_init_ctor_preeval (&TREE_VALUE (list), pre_p, post_p, data);
+      unsigned HOST_WIDE_INT ix;
+      constructor_elt *ce;
+      VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (*expr_p);
+
+      for (ix = 0; VEC_iterate (constructor_elt, v, ix, ce); ix++)
+       gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
       return;
     }
 
@@ -2446,7 +2449,8 @@ gimplify_init_ctor_preeval (tree *expr_p, tree *pre_p, tree *post_p,
    Note that we never have to deal with SAVE_EXPRs here, because this has
    already been taken care of for us, in gimplify_init_ctor_preeval().  */
 
-static void gimplify_init_ctor_eval (tree, tree, tree *, bool);
+static void gimplify_init_ctor_eval (tree, VEC(constructor_elt,gc) *,
+                                    tree *, bool);
 
 static void
 gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
@@ -2530,24 +2534,24 @@ zero_sized_field_decl (tree fdecl)
 
 /* A subroutine of gimplify_init_constructor.  Generate individual
    MODIFY_EXPRs for a CONSTRUCTOR.  OBJECT is the LHS against which the
-   assignments should happen.  LIST is the CONSTRUCTOR_ELTS of the
+   assignments should happen.  ELTS is the CONSTRUCTOR_ELTS of the
    CONSTRUCTOR.  CLEARED is true if the entire LHS object has been
    zeroed first.  */
 
 static void
-gimplify_init_ctor_eval (tree object, tree list, tree *pre_p, bool cleared)
+gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
+                        tree *pre_p, bool cleared)
 {
   tree array_elt_type = NULL;
+  unsigned HOST_WIDE_INT ix;
+  tree purpose, value;
 
   if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE)
     array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
 
-  for (; list; list = TREE_CHAIN (list))
+  FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value)
     {
-      tree purpose, value, cref, init;
-
-      purpose = TREE_PURPOSE (list);
-      value = TREE_VALUE (list);
+      tree cref, init;
 
       /* NULL values are created above for gimplification errors.  */
       if (value == NULL)
@@ -2617,7 +2621,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
   tree ctor = TREE_OPERAND (*expr_p, 1);
   tree type = TREE_TYPE (ctor);
   enum gimplify_status ret;
-  tree elt_list;
+  VEC(constructor_elt,gc) *elts;
 
   if (TREE_CODE (ctor) != CONSTRUCTOR)
     return GS_UNHANDLED;
@@ -2628,7 +2632,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
     return ret;
   object = TREE_OPERAND (*expr_p, 0);
 
-  elt_list = CONSTRUCTOR_ELTS (ctor);
+  elts = CONSTRUCTOR_ELTS (ctor);
 
   ret = GS_ALL_DONE;
   switch (TREE_CODE (type))
@@ -2646,7 +2650,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
        /* Aggregate types must lower constructors to initialization of
           individual elements.  The exception is that a CONSTRUCTOR node
           with no elements indicates zero-initialization of the whole.  */
-       if (elt_list == NULL)
+       if (VEC_empty (constructor_elt, elts))
          break;
 
        categorize_ctor_elements (ctor, &num_nonzero_elements,
@@ -2758,7 +2762,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
            /* Zap the CONSTRUCTOR element list, which simplifies this case.
               Note that we still have to gimplify, in order to handle the
               case of variable sized types.  Avoid shared tree structures.  */
-           CONSTRUCTOR_ELTS (ctor) = NULL_TREE;
+           CONSTRUCTOR_ELTS (ctor) = NULL;
            object = unshare_expr (object);
            gimplify_stmt (expr_p);
            append_to_statement_list (*expr_p, pre_p);
@@ -2776,7 +2780,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
 
            gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
                                        pre_p, post_p, &preeval_data);
-           gimplify_init_ctor_eval (object, elt_list, pre_p, cleared);
+           gimplify_init_ctor_eval (object, elts, pre_p, cleared);
          }
 
        *expr_p = NULL_TREE;
@@ -2788,17 +2792,9 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
        tree r, i;
 
        /* Extract the real and imaginary parts out of the ctor.  */
-       r = i = NULL_TREE;
-       if (elt_list)
-         {
-           r = TREE_VALUE (elt_list);
-           elt_list = TREE_CHAIN (elt_list);
-           if (elt_list)
-             {
-               i = TREE_VALUE (elt_list);
-               gcc_assert (!TREE_CHAIN (elt_list));
-             }
-         }
+       gcc_assert (VEC_length (constructor_elt, elts) == 2);
+       r = VEC_index (constructor_elt, elts, 0)->value;
+       i = VEC_index (constructor_elt, elts, 1)->value;
        if (r == NULL || i == NULL)
          {
            tree zero = convert (TREE_TYPE (type), integer_zero_node);
@@ -2827,35 +2823,44 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
       break;
 
     case VECTOR_TYPE:
-      /* Go ahead and simplify constant constructors to VECTOR_CST.  */
-      if (TREE_CONSTANT (ctor))
-       {
-         tree tem;
+      {
+       unsigned HOST_WIDE_INT ix;
+       constructor_elt *ce;
 
-         /* Even when ctor is constant, it might contain non-*_CST
-            elements (e.g. { 1.0/0.0 - 1.0/0.0, 0.0 }) and those don't
-            belong into VECTOR_CST nodes.  */
-         for (tem = elt_list; tem; tem = TREE_CHAIN (tem))
-           if (! CONSTANT_CLASS_P (TREE_VALUE (tem)))
-             break;
+       /* Go ahead and simplify constant constructors to VECTOR_CST.  */
+       if (TREE_CONSTANT (ctor))
+         {
+           bool constant_p = true;
+           tree value;
+
+           /* 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;
index 26459df..1b6eccf 100644 (file)
@@ -1,3 +1,26 @@
+2005-07-20  Giovanni Bajo  <giovannibajo@libero.it>
+
+       Make CONSTRUCTOR use VEC to store initializers.
+       * check-init.c (check_init): Update to cope with VEC in
+       CONSTRUCTOR_ELTS.
+       * class.c (make_field_value, make_method_value, get_dispatch_table,
+       make_class_data, emit_symbol_table, emit_catch_table,
+       emit_assertion_table): Use build_constructor_from_list instead of
+       build_constructor.
+       * constants.c (build_constants_constructor): Likewise.
+       * java-gimplify.c (java_gimplify_new_array_init): Update to cope with
+       VEC in CONSTRUCTOR_ELTS.
+       * java-tree.h (START_RECORD_CONSTRUCTOR, PUSH_SUPER_VALUE,
+       PUSH_FIELD_VALUE, FINISH_RECORD_CONSTRUCTOR): Create a VEC instead
+       of a TREE_LIST.
+       * jcf-write.c (generate_bytecode_insns): Update to cope with VEC in
+       CONSTRUCTOR_ELTS.
+       * parse.y (build_new_array_init): Use build_constructor_from_list
+       instead of build_constructor.
+       (patch_new_array_init): Update to cope with VEC in
+       CONSTRUCTOR_ELTS.
+       (array_constructor_check_entry): Likewise.
+
 2005-07-12  Tom Tromey  <tromey@redhat.com>
 
        * jvspec.c (lang_specific_driver): Put filelist_filename first on
index f8b1736..377ac78 100644 (file)
@@ -918,9 +918,11 @@ check_init (tree exp, words before)
 
     case NEW_ARRAY_INIT:
       {
-       tree x = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
-       for ( ;  x != NULL_TREE;  x = TREE_CHAIN (x))
-         check_init (TREE_VALUE (x), before);
+       tree value;
+       unsigned HOST_WIDE_INT idx;
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
+                                   idx, value)
+         check_init (value, before);
       }
       break;
 
index eca8017..c2bd62f 100644 (file)
@@ -1278,7 +1278,7 @@ make_field_value (tree fdecl)
 
   PUSH_FIELD_VALUE
     (finit, "info",
-     build_constructor (field_info_union_node,
+     build_constructor_from_list (field_info_union_node,
            build_tree_list
            ((FIELD_STATIC (fdecl)
              ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node))
@@ -1359,7 +1359,7 @@ make_method_value (tree mdecl)
            table = tree_cons (NULL_TREE, utf8, table);
          }
        type = build_prim_array_type (ptr_type_node, length);
-       table = build_constructor (type, table);
+       table = build_constructor_from_list (type, table);
        /* Compute something unique enough.  */
        sprintf (buf, "_methods%d", method_name_count++);
        array = build_decl (VAR_DECL, get_identifier (buf), type);
@@ -1480,8 +1480,9 @@ get_dispatch_table (tree type, tree this_class_addr)
   if (TARGET_VTABLE_USES_DESCRIPTORS)
     arraysize *= TARGET_VTABLE_USES_DESCRIPTORS;
   arraysize += 2;
-  return build_constructor (build_prim_array_type (nativecode_ptr_type_node,
-                                                  arraysize), list);
+  return build_constructor_from_list
+         (build_prim_array_type (nativecode_ptr_type_node,
+                                 arraysize), list);
 }
 
 
@@ -1608,8 +1609,8 @@ make_class_data (tree type)
       field_array_type = build_prim_array_type (field_type_node, field_count);
       fields_decl = build_decl (VAR_DECL, mangled_classname ("_FL_", type),
                                field_array_type);
-      DECL_INITIAL (fields_decl) = build_constructor (field_array_type,
-                                                     static_fields);
+      DECL_INITIAL (fields_decl) = build_constructor_from_list
+                                   (field_array_type, static_fields);
       TREE_STATIC (fields_decl) = 1;
       DECL_ARTIFICIAL (fields_decl) = 1;
       DECL_IGNORED_P (fields_decl) = 1;
@@ -1639,8 +1640,8 @@ make_class_data (tree type)
   method_array_type = build_prim_array_type (method_type_node, method_count);
   methods_decl = build_decl (VAR_DECL, mangled_classname ("_MT_", type),
                             method_array_type);
-  DECL_INITIAL (methods_decl) = build_constructor (method_array_type,
-                                                  nreverse (methods));
+  DECL_INITIAL (methods_decl) = build_constructor_from_list
+                                (method_array_type, nreverse (methods));
   TREE_STATIC (methods_decl) = 1;
   DECL_ARTIFICIAL (methods_decl) = 1;
   DECL_IGNORED_P (methods_decl) = 1;
@@ -1715,7 +1716,8 @@ make_class_data (tree type)
            }
          init = tree_cons (NULL_TREE, index, init); 
        }
-      DECL_INITIAL (idecl) = build_constructor (interface_array_type, init);
+      DECL_INITIAL (idecl) = build_constructor_from_list (interface_array_type,
+                                                         init);
       TREE_STATIC (idecl) = 1;
       DECL_ARTIFICIAL (idecl) = 1;
       DECL_IGNORED_P (idecl) = 1;
@@ -2528,7 +2530,7 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
 
   /* Put the list in the right order and make it a constructor. */
   list = nreverse (list);
-  table = build_constructor (symbols_array_type, list);  
+  table = build_constructor_from_list (symbols_array_type, list);  
 
   /* Make it the initial value for otable_syms and emit the decl. */
   DECL_INITIAL (the_syms_decl) = table;
@@ -2589,7 +2591,7 @@ emit_catch_table (tree this_class)
   table = 
     build_decl (VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type);
   DECL_INITIAL (table) = 
-    build_constructor (array_type, TYPE_CATCH_CLASSES (this_class));
+    build_constructor_from_list (array_type, TYPE_CATCH_CLASSES (this_class));
   TREE_STATIC (table) = 1;
   TREE_READONLY (table) = 1;  
   DECL_IGNORED_P (table) = 1;
@@ -2669,7 +2671,7 @@ emit_assertion_table (tree class)
   
   /* Put the list in the right order and make it a constructor. */
   list = nreverse (list);
-  ctor = build_constructor (assertion_table_type, list);
+  ctor = build_constructor_from_list (assertion_table_type, list);
 
   table_decl = build_decl (VAR_DECL, mangled_classname ("_type_assert_", class),
                           assertion_table_type);
index 335f20c..bba67a7 100644 (file)
@@ -515,8 +515,8 @@ build_constants_constructor (void)
   
       data_decl = build_constant_data_ref ();
       TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type);
-      DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl),
-                                                   data_list);
+      DECL_INITIAL (data_decl) = build_constructor_from_list
+                                 (TREE_TYPE (data_decl), data_list);
       DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
       DECL_SIZE_UNIT (data_decl) = TYPE_SIZE_UNIT (TREE_TYPE (data_decl));
       rest_of_decl_compilation (data_decl, 1, 0);
@@ -527,7 +527,8 @@ build_constants_constructor (void)
                                                           current_class),
                              tags_type);
       TREE_STATIC (tags_decl) = 1;
-      DECL_INITIAL (tags_decl) = build_constructor (tags_type, tags_list);
+      DECL_INITIAL (tags_decl) = build_constructor_from_list
+                                (tags_type, tags_list);
       rest_of_decl_compilation (tags_decl, 1, 0);
       tags_value = build_address_of (tags_decl);
     }
index 60713a4..cbc174d 100644 (file)
@@ -296,7 +296,8 @@ java_gimplify_new_array_init (tree exp)
   HOST_WIDE_INT ilength = java_array_type_length (array_type);
   tree length = build_int_cst (NULL_TREE, ilength);
   tree init = TREE_OPERAND (exp, 0);
-  tree values = CONSTRUCTOR_ELTS (init);
+  tree value;
+  unsigned HOST_WIDE_INT cnt;
 
   tree array_ptr_type = build_pointer_type (array_type);
   tree tmp = create_tmp_var (array_ptr_type, "array");
@@ -306,7 +307,7 @@ java_gimplify_new_array_init (tree exp)
   int index = 0;
 
   /* FIXME: try to allocate array statically?  */
-  while (values != NULL_TREE)
+  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), cnt, value)
     {
       /* FIXME: Should use build_java_arrayaccess here, but avoid
         bounds checking.  */
@@ -317,9 +318,8 @@ java_gimplify_new_array_init (tree exp)
                                build4 (ARRAY_REF, element_type, lhs,
                                        build_int_cst (NULL_TREE, index++),
                                        NULL_TREE, NULL_TREE),
-                               TREE_VALUE (values));
+                               value);
       body = build2 (COMPOUND_EXPR, element_type, body, assignment);
-      values = TREE_CHAIN (values);
     }
 
   return build2 (COMPOUND_EXPR, array_ptr_type, body, tmp);
index 5b63435..ab6157b 100644 (file)
@@ -1762,41 +1762,49 @@ extern tree *type_map;
 #define FINISH_RECORD(RTYPE) layout_type (RTYPE)
 
 /* Start building a RECORD_TYPE constructor with a given TYPE in CONS. */
-#define START_RECORD_CONSTRUCTOR(CONS, CTYPE)  \
-{ CONS = build_constructor ((CTYPE), NULL_TREE);       \
-  TREE_CHAIN (CONS) = TYPE_FIELDS (CTYPE); }
+#define START_RECORD_CONSTRUCTOR(CONS, CTYPE) \
+  do \
+    { \
+      CONS = build_constructor ((CTYPE), VEC_alloc (constructor_elt, gc, 0)); \
+      CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (CONS), TYPE_FIELDS (CTYPE), \
+                             NULL); \
+    } \
+  while (0)
 
 /* Append a field initializer to CONS for the dummy field for the inherited
    fields.  The dummy field has the given VALUE, and the same type as the
    super-class.   Must be specified before calls to PUSH_FIELD_VALUE. */
-#define PUSH_SUPER_VALUE(CONS, VALUE)                  \
-{                                                      \
-  tree _field = TREE_CHAIN (CONS);                     \
-  if (DECL_NAME (_field) != NULL_TREE)                 \
-    abort ();                                          \
-  CONSTRUCTOR_ELTS (CONS)                              \
-    = tree_cons (_field, (VALUE), CONSTRUCTOR_ELTS (CONS)); \
-  TREE_CHAIN (CONS) = TREE_CHAIN (_field);             \
-}
+#define PUSH_SUPER_VALUE(CONS, VALUE) \
+  do \
+    { \
+      constructor_elt *_elt___ = VEC_last (constructor_elt, \
+                                          CONSTRUCTOR_ELTS (CONS)); \
+      tree _next___ = TREE_CHAIN (_elt___->index); \
+      gcc_assert (!DECL_NAME (_elt___->index)); \
+      _elt___->value = VALUE; \
+      CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (CONS), _next___, NULL); \
+    } \
+  while (0)
 
 /* Append a field initializer to CONS for a field with the given VALUE.
    NAME is a char* string used for error checking;
    the initializer must be specified in order. */
 #define PUSH_FIELD_VALUE(CONS, NAME, VALUE)                            \
-do                                                                     \
-{                                                                      \
-  tree _field = TREE_CHAIN (CONS);                                     \
-  if (strcmp (IDENTIFIER_POINTER (DECL_NAME (_field)), NAME) != 0)     \
-    abort ();                                                          \
-  CONSTRUCTOR_ELTS (CONS)                                              \
-    = tree_cons (_field, (VALUE), CONSTRUCTOR_ELTS (CONS));            \
-  TREE_CHAIN (CONS) = TREE_CHAIN (_field);                             \
-}                                                                      \
-while (0)
+  do \
+    { \
+      constructor_elt *_elt___ = VEC_last (constructor_elt, \
+                                          CONSTRUCTOR_ELTS (CONS)); \
+      tree _next___ = TREE_CHAIN (_elt___->index); \
+      gcc_assert (strcmp (IDENTIFIER_POINTER (DECL_NAME (_elt___->index)), \
+                         NAME) == 0); \
+      _elt___->value = VALUE; \
+      CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (CONS), _next___, NULL); \
+    } \
+  while (0)
 
 /* Finish creating a record CONSTRUCTOR CONS. */
 #define FINISH_RECORD_CONSTRUCTOR(CONS) \
-  CONSTRUCTOR_ELTS(CONS) = nreverse (CONSTRUCTOR_ELTS (CONS))
+  VEC_pop (constructor_elt, CONSTRUCTOR_ELTS (CONS))
 
 /* Macros on constructors invocations.  */
 #define CALL_CONSTRUCTOR_P(NODE)               \
index c27b732..4576499 100644 (file)
@@ -2461,14 +2461,16 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state)
       break;
     case NEW_ARRAY_INIT:
       {
-       tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
+       VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
        tree array_type = TREE_TYPE (TREE_TYPE (exp));
        tree element_type = TYPE_ARRAY_ELEMENT (array_type);
+       unsigned HOST_WIDE_INT idx;
+       tree value;
        HOST_WIDE_INT length = java_array_type_length (array_type);
        if (target == IGNORE_TARGET)
          {
-           for ( ;  values != NULL_TREE;  values = TREE_CHAIN (values))
-             generate_bytecode_insns (TREE_VALUE (values), target, state);
+           FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
+             generate_bytecode_insns (value, target, state);
            break;
          }
        push_int_const (length, state);
@@ -2489,16 +2491,17 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state)
          }
        offset = 0;
        jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
-       for ( ;  values != NULL_TREE;  values = TREE_CHAIN (values), offset++)
+       FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
          {
            int save_SP = state->code_SP;
            emit_dup (1, 0, state);
            push_int_const (offset, state);
            NOTE_PUSH (1);
-           generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
+           generate_bytecode_insns (value, STACK_TARGET, state);
            RESERVE (1);
            OP1 (jopcode);
            state->code_SP = save_SP;
+           offset++;
          }
       }
       break;
index 6007b18..10a37e0 100644 (file)
@@ -274,7 +274,7 @@ static void missing_return_error (tree);
 static tree build_new_array_init (int, tree);
 static tree patch_new_array_init (tree, tree);
 static tree maybe_build_array_element_wfl (tree);
-static int array_constructor_check_entry (tree, tree);
+static int array_constructor_check_entry (tree, constructor_elt *);
 static const char *purify_type_name (const char *);
 static tree fold_constant_for_init (tree, tree);
 static jdeplist *reverse_jdep_list (struct parser_ctxt *);
@@ -14793,7 +14793,8 @@ maybe_build_array_element_wfl (tree node)
 static tree
 build_new_array_init (int location, tree values)
 {
-  tree constructor = build_constructor (NULL_TREE, values);
+  tree constructor = build_constructor_from_list (NULL_TREE,
+                                                 nreverse (values));
   tree to_return = build1 (NEW_ARRAY_INIT, NULL_TREE, constructor);
   EXPR_WFL_LINECOL (to_return) = location;
   return to_return;
@@ -14807,8 +14808,9 @@ static tree
 patch_new_array_init (tree type, tree node)
 {
   int error_seen = 0;
-  tree current, element_type;
-  HOST_WIDE_INT length;
+  tree element_type;
+  unsigned HOST_WIDE_INT length;
+  constructor_elt *current;
   int all_constant = 1;
   tree init = TREE_OPERAND (node, 0);
 
@@ -14822,16 +14824,16 @@ patch_new_array_init (tree type, tree node)
   type = TREE_TYPE (type);
   element_type = TYPE_ARRAY_ELEMENT (type);
 
-  CONSTRUCTOR_ELTS (init) = nreverse (CONSTRUCTOR_ELTS (init));
-
-  for (length = 0, current = CONSTRUCTOR_ELTS (init);
-       current;  length++, current = TREE_CHAIN (current))
+  for (length = 0;
+       VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (init),
+                   length, current);
+       length++)
     {
-      tree elt = TREE_VALUE (current);
+      tree elt = current->value;
       if (elt == NULL_TREE || TREE_CODE (elt) != NEW_ARRAY_INIT)
        {
          error_seen |= array_constructor_check_entry (element_type, current);
-         elt = TREE_VALUE (current);
+         elt = current->value;
          /* When compiling to native code, STRING_CST is converted to
             INDIRECT_REF, but still with a TREE_CONSTANT flag. */
          if (! TREE_CONSTANT (elt) || TREE_CODE (elt) == INDIRECT_REF)
@@ -14839,8 +14841,8 @@ patch_new_array_init (tree type, tree node)
        }
       else
        {
-         TREE_VALUE (current) = patch_new_array_init (element_type, elt);
-         TREE_PURPOSE (current) = NULL_TREE;
+         current->value = patch_new_array_init (element_type, elt);
+         current->index = NULL_TREE;
          all_constant = 0;
        }
       if (elt && TREE_CODE (elt) == TREE_LIST
@@ -14869,16 +14871,16 @@ patch_new_array_init (tree type, tree node)
    otherwise.  */
 
 static int
-array_constructor_check_entry (tree type, tree entry)
+array_constructor_check_entry (tree type, constructor_elt *entry)
 {
   char *array_type_string = NULL;      /* For error reports */
   tree value, type_value, new_value, wfl_value, patched;
   int error_seen = 0;
 
   new_value = NULL_TREE;
-  wfl_value = TREE_VALUE (entry);
+  wfl_value = entry->value;
 
-  value = java_complete_tree (TREE_VALUE (entry));
+  value = java_complete_tree (entry->value);
   /* patch_string return error_mark_node if arg is error_mark_node */
   if ((patched = patch_string (value)))
     value = patched;
@@ -14889,7 +14891,7 @@ array_constructor_check_entry (tree type, tree entry)
 
   /* At anytime, try_builtin_assignconv can report a warning on
      constant overflow during narrowing. */
-  SET_WFL_OPERATOR (wfl_operator, TREE_PURPOSE (entry), wfl_value);
+  SET_WFL_OPERATOR (wfl_operator, entry->index, wfl_value);
   new_value = try_builtin_assignconv (wfl_operator, type, value);
   if (!new_value && (new_value = try_reference_assignconv (type, value)))
     type_value = promote_type (type);
@@ -14908,12 +14910,12 @@ array_constructor_check_entry (tree type, tree entry)
     }
 
   if (new_value)
-    TREE_VALUE (entry) = new_value;
+    entry->value = new_value;
 
   if (array_type_string)
     free (array_type_string);
 
-  TREE_PURPOSE (entry) = NULL_TREE;
+  entry->index = NULL_TREE;
   return error_seen;
 }
 
index 9bd62da..31a1e8f 100644 (file)
@@ -1,3 +1,9 @@
+2005-07-20  Giovanni Bajo  <giovannibajo@libero.it>
+
+       Make CONSTRUCTOR use VEC to store initializers.
+       * objc-act.c (objc_build_constructor): Use build_constructor_from_list
+       instead of build_constructor.
+
 2005-07-08  Daniel Berlin  <dberlin@dberlin.org>
        
        * objc-act.c (objc_push_parm): DECL_ARG_TYPE_AS_WRITTEN is
index ee7b028..d004fb5 100644 (file)
@@ -2001,7 +2001,7 @@ objc_add_static_instance (tree constructor, tree class_decl)
 static tree
 objc_build_constructor (tree type, tree elts)
 {
-  tree constructor = build_constructor (type, elts);
+  tree constructor = build_constructor_from_list (type, elts);
 
   TREE_CONSTANT (constructor) = 1;
   TREE_STATIC (constructor) = 1;
index 4ffcf4c..5d69c6f 100644 (file)
@@ -1,3 +1,10 @@
+2005-07-20  Giovanni Bajo  <giovannibajo@libero.it>
+
+       Make CONSTRUCTOR use VEC to store initializers.
+       * g++.dg/ext/complit3.C: Check for specific error messages.
+       * g++.dg/init/brace2.C: Update error message.
+       * g++.dg/warn/Wbraces2.C: Likewise.
+
 2005-07-19 Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/16940
index 92e2033..1783a08 100644 (file)
@@ -2,7 +2,7 @@
 
 int Compound_Literals_0()
 {
-  static int y[] = (int []) {1, 2, 3}; // { dg-error "" }
-  static int z[] = (int [3]) {1}; // { dg-error "" }
+  static int y[] = (int []) {1, 2, 3}; // { dg-error "compound literal" }
+  static int z[] = (int [3]) {1}; // { dg-error "compound literal" }
   return y[0]+z[0]; 
 }
index 488d916..5138430 100644 (file)
@@ -3,6 +3,6 @@
 int x = { 2 };
 const char * y = { "hello" };
 int a = 2;
-int b = { 2,3 }; // { dg-error "requires one element" }
+int b = { 2,3 }; // { dg-error "too many initializers" }
 int c = { { 2 } } ; // { dg-error "braces around scalar initializer" }
 
index b51d5ca..6d54ede 100644 (file)
@@ -2,14 +2,14 @@
 // { dg-options "-Wmissing-braces" }
 int a[2][2] = { 0, 1, 2, 3 };                   // { dg-warning "missing braces" }
 int b[2][2] = { { 0, 1 }, { 2, 3 } };
-int c[2][2] = { { { 0 }, 1 }, { 2, 3 } };       // { dg-error "brace-enclosed" }
+int c[2][2] = { { { 0 }, 1 }, { 2, 3 } };       // { dg-error "braces around scalar" }
 struct S { char s[6]; int i; };
 S d = { "hello", 1 };
 S e = { { "hello" }, 1 };
-S f = { { { "hello" } }, 1 };                   // { dg-error "brace-enclosed" }
+S f = { { { "hello" } }, 1 };                   // { dg-error "braces around scalar" }
 S g = { 'h', 'e', 'l', 'l', 'o', '\0', 1 };     // { dg-warning "missing braces" }
 struct T { wchar_t s[6]; int i; };
 T i = { L"hello", 1 };
 T j = { { L"hello" }, 1 };
-T k = { { { L"hello" } }, 1 };                  // { dg-error "brace-enclosed" }
+T k = { { { L"hello" } }, 1 };                  // { dg-error "braces around scalar" }
 T l = { L'h', L'e', L'l', L'l', L'o', L'\0', 1 };// { dg-warning "missing braces" }
index 3f6592b..2beecc7 100644 (file)
@@ -583,7 +583,17 @@ dequeue_and_dump (dump_info_p di)
       break;
 
     case CONSTRUCTOR:
-      dump_child ("elts", CONSTRUCTOR_ELTS (t));
+      {
+       unsigned HOST_WIDE_INT cnt;
+       tree index, value;
+       dump_int (di, "lngt", VEC_length (constructor_elt,
+                                         CONSTRUCTOR_ELTS (t)));
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
+         {
+           dump_child ("idx", index);
+           dump_child ("val", value);
+         }
+      }
       break;
 
     case BIND_EXPR:
index fe70751..ff7ea43 100644 (file)
@@ -2395,7 +2395,22 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       if (TREE_CODE (*tp) == BIND_EXPR)
        BIND_EXPR_BLOCK (*tp) = NULL_TREE;
     }
+  else if (code == CONSTRUCTOR)
+    {
+      /* CONSTRUCTOR nodes need special handling because
+         we need to duplicate the vector of elements.  */
+      tree new;
+
+      new = copy_node (*tp);
+
+      /* Propagate mudflap marked-ness.  */
+      if (flag_mudflap && mf_marked_p (*tp))
+        mf_mark (new);
 
+      CONSTRUCTOR_ELTS (new) = VEC_copy (constructor_elt, gc,
+                                        CONSTRUCTOR_ELTS (*tp));
+      *tp = new;
+    }
   else if (TREE_CODE_CLASS (code) == tcc_type)
     *walk_subtrees = 0;
   else if (TREE_CODE_CLASS (code) == tcc_declaration)
index 1d61de2..d7bfe8c 100644 (file)
@@ -778,36 +778,29 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
 
     case CONSTRUCTOR:
       {
-       tree lnode;
+       unsigned HOST_WIDE_INT ix;
+       tree field, val;
        bool is_struct_init = FALSE;
        pp_character (buffer, '{');
-       lnode = CONSTRUCTOR_ELTS (node);
        if (TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE
            || TREE_CODE (TREE_TYPE (node)) == UNION_TYPE)
          is_struct_init = TRUE;
-       while (lnode && lnode != error_mark_node)
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (node), ix, field, val)
          {
-           tree val;
-           if (TREE_PURPOSE (lnode) && is_struct_init)
+           if (field && is_struct_init)
              {
                pp_character (buffer, '.');
-               dump_generic_node (buffer, TREE_PURPOSE (lnode), spc, flags, false);
+               dump_generic_node (buffer, field, spc, flags, false);
                pp_string (buffer, "=");
              }
-           val = TREE_VALUE (lnode);
            if (val && TREE_CODE (val) == ADDR_EXPR)
              if (TREE_CODE (TREE_OPERAND (val, 0)) == FUNCTION_DECL)
                val = TREE_OPERAND (val, 0);
            if (val && TREE_CODE (val) == FUNCTION_DECL)
-             {
                dump_decl_name (buffer, val, flags);
-             }
            else
-             {
-               dump_generic_node (buffer, TREE_VALUE (lnode), spc, flags, false);
-             }
-           lnode = TREE_CHAIN (lnode);
-           if (lnode && TREE_CODE (lnode) == TREE_LIST)
+               dump_generic_node (buffer, val, spc, flags, false);
+           if (ix != VEC_length (constructor_elt, CONSTRUCTOR_ELTS (node)) - 1)
              {
                pp_character (buffer, ',');
                pp_space (buffer);
index b3494af..0d839d8 100644 (file)
@@ -1642,6 +1642,8 @@ generate_element_init_1 (struct sra_elt *elt, tree init, tree *list_p)
   enum tree_code init_code;
   struct sra_elt *sub;
   tree t;
+  unsigned HOST_WIDE_INT idx;
+  tree value, purpose;
 
   /* We can be passed DECL_INITIAL of a static variable.  It might have a
      conversion, which we strip off here.  */
@@ -1675,11 +1677,8 @@ generate_element_init_1 (struct sra_elt *elt, tree init, tree *list_p)
       break;
 
     case CONSTRUCTOR:
-      for (t = CONSTRUCTOR_ELTS (init); t ; t = TREE_CHAIN (t))
+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, purpose, value)
        {
-         tree purpose = TREE_PURPOSE (t);
-         tree value = TREE_VALUE (t);
-
          if (TREE_CODE (purpose) == RANGE_EXPR)
            {
              tree lower = TREE_OPERAND (purpose, 0);
index 8bf8242..95a2fa1 100644 (file)
@@ -936,7 +936,9 @@ static tree
 fold_const_aggregate_ref (tree t)
 {
   prop_value_t *value;
-  tree base, ctor, idx, field, elt;
+  tree base, ctor, idx, field;
+  unsigned HOST_WIDE_INT cnt;
+  tree cfield, cval;
 
   switch (TREE_CODE (t))
     {
@@ -993,13 +995,9 @@ fold_const_aggregate_ref (tree t)
        }
 
       /* Whoo-hoo!  I'll fold ya baby.  Yeah!  */
-      for (elt = CONSTRUCTOR_ELTS (ctor);
-          (elt && !tree_int_cst_equal (TREE_PURPOSE (elt), idx));
-          elt = TREE_CHAIN (elt))
-       ;
-
-      if (elt)
-       return TREE_VALUE (elt);
+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+       if (tree_int_cst_equal (cfield, idx))
+         return cval;
       break;
 
     case COMPONENT_REF:
@@ -1035,11 +1033,11 @@ fold_const_aggregate_ref (tree t)
 
       field = TREE_OPERAND (t, 1);
 
-      for (elt = CONSTRUCTOR_ELTS (ctor); elt; elt = TREE_CHAIN (elt))
-       if (TREE_PURPOSE (elt) == field
+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+       if (cfield == field
            /* FIXME: Handle bit-fields.  */
-           && ! DECL_BIT_FIELD (TREE_PURPOSE (elt)))
-         return TREE_VALUE (elt);
+           && ! DECL_BIT_FIELD (cfield))
+         return cval;
       break;
 
     default:
index 609fa0f..2044394 100644 (file)
@@ -1390,10 +1390,13 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
       {
        /* General aggregate CONSTRUCTORs have been decomposed, but they
           are still in use as the COMPLEX_EXPR equivalent for vectors.  */
+       constructor_elt *ce;
+       unsigned HOST_WIDE_INT idx;
 
-       tree t;
-       for (t = TREE_OPERAND (expr, 0); t ; t = TREE_CHAIN (t))
-         get_expr_operands (stmt, &TREE_VALUE (t), opf_none);
+       for (idx = 0;
+            VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (expr), idx, ce);
+            idx++)
+         get_expr_operands (stmt, &ce->value, opf_none);
 
        return;
       }
index 015a727..f9c9fda 100644 (file)
@@ -207,7 +207,7 @@ expand_vector_piecewise (block_stmt_iterator *bsi, elem_op_func f,
                         tree type, tree inner_type,
                         tree a, tree b, enum tree_code code)
 {
-  tree head, *chain = &head;
+  VEC(constructor_elt,gc) *v;
   tree part_width = TYPE_SIZE (inner_type);
   tree index = bitsize_int (0);
   int nunits = TYPE_VECTOR_SUBPARTS (type);
@@ -215,15 +215,17 @@ expand_vector_piecewise (block_stmt_iterator *bsi, elem_op_func f,
              / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
   int i;
 
+  v = VEC_alloc(constructor_elt, gc, (nunits + delta - 1) / delta);
   for (i = 0; i < nunits;
        i += delta, index = int_const_binop (PLUS_EXPR, index, part_width, 0))
     {
       tree result = f (bsi, inner_type, a, b, index, part_width, code);
-      *chain = tree_cons (NULL_TREE, result, NULL_TREE);
-      chain = &TREE_CHAIN (*chain);
+      constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL);
+      ce->index = NULL_TREE;
+      ce->value = result;
     }
 
-  return build1 (CONSTRUCTOR, type, head);
+  return build_constructor (type, v);
 }
 
 /* Expand a vector operation to scalars with the freedom to use
index 525eef4..c2a8f0d 100644 (file)
@@ -596,7 +596,8 @@ vect_get_vec_def_for_operand (tree op, tree stmt, tree *scalar_def)
             t = tree_cons (NULL_TREE, def, t);
           }
 
-        vec_inv = build_constructor (vectype, t);
+       /* FIXME: use build_constructor directly.  */
+        vec_inv = build_constructor_from_list (vectype, t);
         return vect_init_vector (stmt, vec_inv);
       }
 
@@ -771,7 +772,7 @@ get_initial_def_for_reduction (tree stmt, tree init_val, tree *scalar_def)
   if (TREE_CODE (init_val) == INTEGER_CST || TREE_CODE (init_val) == REAL_CST)
     vec = build_vector (vectype, t);
   else
-    vec = build_constructor (vectype, t);
+    vec = build_constructor_from_list (vectype, t);
     
   if (!need_epilog_adjust)
     {
index 38ba39b..4863cb7 100644 (file)
@@ -182,7 +182,8 @@ set_value_handle (tree e, tree v)
 {
   if (TREE_CODE (e) == SSA_NAME)
     SSA_NAME_VALUE (e) = v;
-  else if (EXPR_P (e) || DECL_P (e) || TREE_CODE (e) == TREE_LIST)
+  else if (EXPR_P (e) || DECL_P (e) || TREE_CODE (e) == TREE_LIST
+          || TREE_CODE (e) == CONSTRUCTOR)
     get_tree_ann (e)->common.value_handle = v;
   else
     /* Do nothing.  Constants are their own value handles.  */
@@ -287,7 +288,8 @@ get_value_handle (tree expr)
 
   if (TREE_CODE (expr) == SSA_NAME)
     return SSA_NAME_VALUE (expr);
-  else if (EXPR_P (expr) || DECL_P (expr) || TREE_CODE (expr) == TREE_LIST)
+  else if (EXPR_P (expr) || DECL_P (expr) || TREE_CODE (expr) == TREE_LIST
+          || TREE_CODE (expr) == CONSTRUCTOR)
     {
       tree_ann_t ann = tree_ann (expr);
       return ((ann) ? ann->common.value_handle : NULL_TREE);
index 20cd722..770ed31 100644 (file)
@@ -93,6 +93,7 @@ static const char * const tree_node_kind_names[] = {
   "binfos",
   "phi_nodes",
   "ssa names",
+  "constructors",
   "random kinds",
   "lang_decl kinds",
   "lang_type kinds"
@@ -328,6 +329,7 @@ tree_code_size (enum tree_code code)
        case STATEMENT_LIST:    return sizeof (struct tree_statement_list);
        case BLOCK:             return sizeof (struct tree_block);
        case VALUE_HANDLE:      return sizeof (struct tree_value_handle);
+       case CONSTRUCTOR:       return sizeof (struct tree_constructor);
 
        default:
          return lang_hooks.tree_size (code);
@@ -418,7 +420,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
          kind = id_kind;
          break;
 
-       case TREE_VEC:;
+       case TREE_VEC:
          kind = vec_kind;
          break;
 
@@ -438,6 +440,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
          kind = b_kind;
          break;
 
+       case CONSTRUCTOR:
+         kind = constr_kind;
+         break;
+
        default:
          kind = x_kind;
          break;
@@ -904,27 +910,72 @@ build_vector (tree type, tree vals)
   return v;
 }
 
+/* Return a new 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));
index 43fa835..00b130f 100644 (file)
@@ -435,19 +435,19 @@ DEFTREECODE (FILTER_EXPR, "filter_expr", tcc_expression, 0)
 
 /* Constructor: return an aggregate value made from specified components.
    In C, this is used only for structure and array initializers.
-   The operand is a list of component values made out of a chain of
-   TREE_LIST nodes.
+   The operand is a sequence of component values made out of a VEC of
+   struct constructor_elt.
 
    For ARRAY_TYPE:
-   The TREE_PURPOSE of each node is the corresponding index.
-   If the TREE_PURPOSE is a RANGE_EXPR, it is a short-hand for many nodes,
-   one for each index in the range.  (If the corresponding TREE_VALUE
+   The field INDEX of each constructor_elt is the corresponding index.
+   If the index is a RANGE_EXPR, it is a short-hand for many nodes,
+   one for each index in the range.  (If the corresponding field VALUE
    has side-effects, they are evaluated once for each element.  Wrap the
    value in a SAVE_EXPR if you want to evaluate side effects only once.)
 
    For RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE:
-   The TREE_PURPOSE of each node is a FIELD_DECL.  */
-DEFTREECODE (CONSTRUCTOR, "constructor", tcc_expression, 1)
+   The field INDEX of each node is a FIELD_DECL.  */
+DEFTREECODE (CONSTRUCTOR, "constructor", tcc_exceptional, 0)
 
 /* The expression types are mostly straightforward, with the fourth argument
    of DEFTREECODE saying how many operands there are.
index e1007a3..b9cd508 100644 (file)
@@ -1190,6 +1190,57 @@ struct tree_vec GTY(())
   tree GTY ((length ("TREE_VEC_LENGTH ((tree)&%h)"))) a[1];
 };
 
+/* In a CONSTRUCTOR node.  */
+#define CONSTRUCTOR_ELTS(NODE) (CONSTRUCTOR_CHECK (NODE)->constructor.elts)
+
+/* Iterate through the vector V of CONSTRUCTOR_ELT elements, yielding the
+   value of each element (stored within VAL). IX must be a scratch variable
+   of unsigned integer type.  */
+#define FOR_EACH_CONSTRUCTOR_VALUE(V, IX, VAL) \
+  for (IX = 0; (IX >= VEC_length (constructor_elt, V)) \
+              ? false \
+              : ((VAL = VEC_index (constructor_elt, V, IX)->value), \
+              true); \
+       (IX)++)
+
+/* Iterate through the vector V of CONSTRUCTOR_ELT elements, yielding both
+   the value of each element (stored within VAL) and its index (stored
+   within INDEX). IX must be a scratch variable of unsigned integer type.  */
+#define FOR_EACH_CONSTRUCTOR_ELT(V, IX, INDEX, VAL) \
+  for (IX = 0; (IX >= VEC_length (constructor_elt, V)) \
+              ? false \
+              : ((VAL = VEC_index (constructor_elt, V, IX)->value), \
+                 (INDEX = VEC_index (constructor_elt, V, IX)->index), \
+              true); \
+       (IX)++)
+
+/* Append a new constructor element to V, with the specified INDEX and VAL.  */
+#define CONSTRUCTOR_APPEND_ELT(V, INDEX, VALUE) \
+  do { \
+    constructor_elt *_ce___ = VEC_safe_push (constructor_elt, gc, V, NULL); \
+    _ce___->index = INDEX; \
+    _ce___->value = VALUE; \
+  } while (0)
+
+/* A single element of a CONSTRUCTOR. VALUE holds the actual value of the
+   element. INDEX can optionally design the position of VALUE: in arrays,
+   it is the index where VALUE has to be placed; in structures, it is the
+   FIELD_DECL of the member.  */
+typedef struct constructor_elt_d GTY(())
+{
+  tree index;
+  tree value;
+} constructor_elt;
+
+DEF_VEC_O(constructor_elt);
+DEF_VEC_ALLOC_O(constructor_elt,gc);
+
+struct tree_constructor GTY(())
+{
+  struct tree_common common;
+  VEC(constructor_elt,gc) *elts;
+};
+
 /* Define fields and accessors for some nodes that represent expressions.  */
 
 /* Nonzero if NODE is an empty statement (NOP_EXPR <0>).  */
@@ -1197,9 +1248,6 @@ struct tree_vec GTY(())
                                 && VOID_TYPE_P (TREE_TYPE (NODE)) \
                                 && integer_zerop (TREE_OPERAND (NODE, 0)))
 
-/* In a CONSTRUCTOR node.  */
-#define CONSTRUCTOR_ELTS(NODE) TREE_OPERAND_CHECK_CODE (NODE, CONSTRUCTOR, 0)
-
 /* In ordinary expression nodes.  */
 #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
 #define TREE_COMPLEXITY(NODE) (EXPR_CHECK (NODE)->exp.complexity)
@@ -2725,8 +2773,6 @@ struct tree_value_handle GTY(())
   unsigned int id;
 };
 \f
-
-
 /* 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;
 };
 \f
 /* 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,
index 43a465d..bdcc446 100644 (file)
@@ -58,3 +58,4 @@ DEFTREESTRUCT(TS_BLOCK, "block")
 DEFTREESTRUCT(TS_BINFO, "binfo")
 DEFTREESTRUCT(TS_STATEMENT_LIST, "statement list")
 DEFTREESTRUCT(TS_VALUE_HANDLE, "value handle")
+DEFTREESTRUCT(TS_CONSTRUCTOR, "constructor")
index db54f98..e4d3097 100644 (file)
@@ -2400,13 +2400,14 @@ const_hash_1 (const tree exp)
 
     case CONSTRUCTOR:
       {
-       tree link;
+       unsigned HOST_WIDE_INT idx;
+       tree value;
        
        hi = 5 + int_size_in_bytes (TREE_TYPE (exp));
        
-       for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
-         if (TREE_VALUE (link))
-           hi = hi * 603 + const_hash_1 (TREE_VALUE (link));
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
+         if (value)
+           hi = hi * 603 + const_hash_1 (value);
        
        return hi;
       }
@@ -2517,7 +2518,8 @@ compare_constant (const tree t1, const tree t2)
 
     case CONSTRUCTOR:
       {
-       tree l1, l2;
+       VEC(constructor_elt, gc) *v1, *v2;
+       unsigned HOST_WIDE_INT idx;
        
        typecode = TREE_CODE (TREE_TYPE (t1));
        if (typecode != TREE_CODE (TREE_TYPE (t2)))
@@ -2540,28 +2542,34 @@ compare_constant (const tree t1, const tree t2)
              return 0;
          }
 
-       for (l1 = CONSTRUCTOR_ELTS (t1), l2 = CONSTRUCTOR_ELTS (t2);
-            l1 && l2;
-            l1 = TREE_CHAIN (l1), l2 = TREE_CHAIN (l2))
+       v1 = CONSTRUCTOR_ELTS (t1);
+       v2 = CONSTRUCTOR_ELTS (t2);
+       if (VEC_length (constructor_elt, v1)
+           != VEC_length (constructor_elt, v2))
+           return 0;
+
+       for (idx = 0; idx < VEC_length (constructor_elt, v1); ++idx)
          {
+           constructor_elt *c1 = VEC_index (constructor_elt, v1, idx);
+           constructor_elt *c2 = VEC_index (constructor_elt, v2, idx);
+
            /* Check that each value is the same...  */
-           if (! compare_constant (TREE_VALUE (l1), TREE_VALUE (l2)))
+           if (!compare_constant (c1->value, c2->value))
              return 0;
            /* ... and that they apply to the same fields!  */
            if (typecode == ARRAY_TYPE)
              {
-               if (! compare_constant (TREE_PURPOSE (l1),
-                                       TREE_PURPOSE (l2)))
+               if (!compare_constant (c1->index, c2->index))
                  return 0;
              }
            else
              {
-               if (TREE_PURPOSE (l1) != TREE_PURPOSE (l2))
+               if (c1->index != c2->index)
                  return 0;
              }
          }
        
-       return l1 == NULL_TREE && l2 == NULL_TREE;
+       return 1;
       }
 
     case ADDR_EXPR:
@@ -2645,13 +2653,19 @@ copy_constant (tree exp)
     case CONSTRUCTOR:
       {
        tree copy = copy_node (exp);
-       tree list = copy_list (CONSTRUCTOR_ELTS (exp));
-       tree tail;
-
-       CONSTRUCTOR_ELTS (copy) = list;
-       for (tail = list; tail; tail = TREE_CHAIN (tail))
-         TREE_VALUE (tail) = copy_constant (TREE_VALUE (tail));
-
+       VEC(constructor_elt, gc) *v;
+       unsigned HOST_WIDE_INT idx;
+       tree purpose, value;
+       
+       v = VEC_alloc(constructor_elt, gc, VEC_length(constructor_elt,
+                                                     CONSTRUCTOR_ELTS (exp)));
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, purpose, value)
+         {
+           constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL);
+           ce->index = purpose;
+           ce->value = copy_constant (value);
+         }
+       CONSTRUCTOR_ELTS (copy) = v;
        return copy;
       }
 
@@ -3476,10 +3490,12 @@ compute_reloc_for_constant (tree exp)
       break;
 
     case CONSTRUCTOR:
-      for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
-       if (TREE_VALUE (tem) != 0)
-         reloc |= compute_reloc_for_constant (TREE_VALUE (tem));
-
+      {
+       unsigned HOST_WIDE_INT idx;
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, tem)
+         if (tem != 0)
+           reloc |= compute_reloc_for_constant (tem);
+      }
       break;
 
     default:
@@ -3533,10 +3549,12 @@ output_addressed_constants (tree exp)
       break;
 
     case CONSTRUCTOR:
-      for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
-       if (TREE_VALUE (tem) != 0)
-         output_addressed_constants (TREE_VALUE (tem));
-
+      {
+       unsigned HOST_WIDE_INT idx;
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, tem)
+         if (tem != 0)
+           output_addressed_constants (tem);
+      }
       break;
 
     default:
@@ -3567,16 +3585,16 @@ initializer_constant_valid_p (tree value, tree endtype)
       if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
           || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
          && TREE_CONSTANT (value)
-         && CONSTRUCTOR_ELTS (value))
+         && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (value)))
        {
+         unsigned HOST_WIDE_INT idx;
          tree elt;
          bool absolute = true;
 
-         for (elt = CONSTRUCTOR_ELTS (value); elt; elt = TREE_CHAIN (elt))
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
            {
              tree reloc;
-             value = TREE_VALUE (elt);
-             reloc = initializer_constant_valid_p (value, TREE_TYPE (value));
+             reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt));
              if (!reloc)
                return NULL_TREE;
              if (reloc != null_pointer_node)
@@ -3832,7 +3850,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
 
   /* Allow a constructor with no elements for any data type.
      This means to fill the space with zeros.  */
-  if (TREE_CODE (exp) == CONSTRUCTOR && CONSTRUCTOR_ELTS (exp) == 0)
+  if (TREE_CODE (exp) == CONSTRUCTOR
+      && VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (exp)))
     {
       assemble_zeros (size);
       return;
@@ -3942,6 +3961,8 @@ static unsigned HOST_WIDE_INT
 array_size_for_constructor (tree val)
 {
   tree max_index, i;
+  unsigned HOST_WIDE_INT cnt;
+  tree index, value;
 
   /* This code used to attempt to handle string constants that are not
      arrays of single-bytes, but nothing else does, so there's no point in
@@ -3950,10 +3971,8 @@ array_size_for_constructor (tree val)
     return TREE_STRING_LENGTH (val);
 
   max_index = NULL_TREE;
-  for (i = CONSTRUCTOR_ELTS (val); i; i = TREE_CHAIN (i))
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (val), cnt, index, value)
     {
-      tree index = TREE_PURPOSE (i);
-
       if (TREE_CODE (index) == RANGE_EXPR)
        index = TREE_OPERAND (index, 1);
       if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index))
@@ -3983,7 +4002,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
                    unsigned int align)
 {
   tree type = TREE_TYPE (exp);
-  tree link, field = 0;
+  tree field = 0;
   tree min_index = 0;
   /* Number of bytes output or skipped so far.
      In other words, current position within the constructor.  */
@@ -3991,6 +4010,8 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
   /* Nonzero means BYTE contains part of a byte, to be output.  */
   int byte_buffer_in_use = 0;
   int byte = 0;
+  unsigned HOST_WIDE_INT cnt;
+  constructor_elt *ce;
 
   gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
 
@@ -4010,23 +4031,22 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
      There is always a maximum of one element in the chain LINK for unions
      (even if the initializer in a source program incorrectly contains
      more one).  */
-  for (link = CONSTRUCTOR_ELTS (exp);
-       link;
-       link = TREE_CHAIN (link),
-       field = field ? TREE_CHAIN (field) : 0)
+  for (cnt = 0;
+       VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
+       cnt++, field = field ? TREE_CHAIN (field) : 0)
     {
-      tree val = TREE_VALUE (link);
+      tree val = ce->value;
       tree index = 0;
 
       /* The element in a union constructor specifies the proper field
         or index.  */
       if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
           || TREE_CODE (type) == QUAL_UNION_TYPE)
-         && TREE_PURPOSE (link) != 0)
-       field = TREE_PURPOSE (link);
+         && ce->index != 0)
+       field = ce->index;
 
       else if (TREE_CODE (type) == ARRAY_TYPE)
-       index = TREE_PURPOSE (link);
+       index = ce->index;
 
 #ifdef ASM_COMMENT_START
       if (field && flag_verbose_asm)
@@ -4089,6 +4109,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
             if each element has the proper size.  */
          if ((field != 0 || index != 0) && pos != total_bytes)
            {
+             gcc_assert (pos >= total_bytes);
              assemble_zeros (pos - total_bytes);
              total_bytes = pos;
            }
@@ -4164,6 +4185,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
              /* If still not at proper byte, advance to there.  */
              if (next_offset / BITS_PER_UNIT != total_bytes)
                {
+                 gcc_assert (next_offset / BITS_PER_UNIT >= total_bytes);
                  assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
                  total_bytes = next_offset / BITS_PER_UNIT;
                }
index 63840a1..842ac7b 100644 (file)
--- 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_)                                                   \
 {                                                                        \