diff options
author | Giovanni Bajo <giovannibajo@libero.it> | 2005-07-20 03:19:59 +0200 |
---|---|---|
committer | Giovanni Bajo <giovannibajo@gcc.gnu.org> | 2005-07-20 01:19:59 +0000 |
commit | 4038c495fc9685efdb400b36848627daab979e78 (patch) | |
tree | cee4baf52782472c6ce30e28249d2a5df154551f /gcc/cp | |
parent | f37d7c6065a4f64b7af059bc8cbd05c3e7f2e9cf (diff) | |
download | gcc-4038c495fc9685efdb400b36848627daab979e78.zip gcc-4038c495fc9685efdb400b36848627daab979e78.tar.gz gcc-4038c495fc9685efdb400b36848627daab979e78.tar.bz2 |
Make CONSTRUCTOR use VEC to store initializers.
* c-common.c (complete_array_type): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* c-pretty-print.c (pp_c_initializer_list): Use pp_c_constructor_elts.
(pp_c_constructor_elts): New function.
* c-pretty-print.h (pp_c_constructor_elts): Declare.
* c-typeck.c (build_function_call, build_c_cast, digest_init,
struct constructor_stack, struct initializer_stack,
constructor_elements, push_init_level, pop_init_level,
add_pending_init, find_init_member, output_init_element): Update to
cope with VEC in CONSTRUCTOR_ELTS.
* coverage.c (build_fn_info_value, build_ctr_info_value,
build_gcov_info): Likewise.
* expr.c (categorize_ctor_elements_1, store_constructor,
expand_expr_real_1): Likewise.
* fold-const.c (fold_ternary): Likewise.
* gimplify.c (gimplify_init_ctor_preeval, zero_sized_field_decl,
gimplify_init_constructor, gimplify_expr): Likewise.
* tree-dump.c (dequeue_and_dump): Likewise.
* tree-inline.c (copy_tree_r): Add code to duplicate a CONSTRUCTOR
node.
* tree-pretty-print.c (dump_generic_node): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* tree-sra.c (generate_element_init_1): Likewise.
* tree-ssa-ccp.c (fold_const_aggregate_ref): Likewise.
* tree-ssa-operands.c (get_expr_operands): Likewise.
* tree-vect-generic.c (expand_vector_piecewise): Likewise.
* tree-vect-transform.c (vect_get_vec_def_for_operand):
(get_initial_def_for_reduction): Likewise.
* tree-vn.c (set_value_handle, get_value_handle): CONSTURCTOR uses
value handle in annotations.
* tree.c (tree_node_kind, tree_code_size, make_node_stat,
tree_node_structure): Add support for constr_kind.
(build_vector_from_ctor, build_constructor_single,
build_constructor_from_list): New functions.
(build_constructor): Update to take a VEC instead of a TREE_LIST.
(simple_cst_equal, iterative_hash_expr, initializer_zerop, walk_tree):
Update to cope with VEC in CONSTRUCTOR_ELTS.
* tree.def (CONSTRUCTOR): Make it a tcc_exceptional node.
* tree.h (FOR_EACH_CONSTRUCTOR_VALUE, FOR_EACH_CONSTRUCTOR_ELT,
CONSTRUCTOR_APPEND_ELT): New macros.
(struct constructor_elt, struct tree_constructor): New data types.
(union tree_node): Add tree_constructor field.
* treestruct.def: Define TS_CONSTRUCTOR.
* varasm.c (const_hash_1, compare_constant, copy_constant,
compute_reloc_for_constant, output_addressed_constants,
initializer_constant_valid_p, output_constant,
array_size_for_constructor, output_constructor): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* vec.h (VEC_empty, VEC_copy): New macros.
ada/
Make CONSTRUCTOR use VEC to store initializers.
* decl.c (gnat_to_gnu_entity): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* trans.c (extract_values): Likewise.
* utils.c (convert, remove_conversions): Likewise.
* utils2.c (contains_save_expr_p, build_binary_op, build_unary_op,
gnat_build_constructor): Likewise.
cp/
Make CONSTRUCTOR use VEC to store initializers.
* call.c (convert_default_arg): Update call to digest_init.
* class.c (dump_class_hierarchy, dump_array): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* cp-tree.h (EMPTY_CONSTRUCTOR_P): Likewise.
(finish_compound_literal, digest_init): Update declaration.
* decl.c (struct reshape_iter): New data type.
(reshape_init_array): Rename to...
(reshape_init_array_1): Update to cope with VEC in CONSTRUCTOR_ELTS.
(reshape_init): Rewrite from scratch. Split parts into...
(reshape_init_array, reshape_init_vector, reshape_init_class,
reshape_init_r): New functions.
(check_initializer): Update call to reshape_init. Remove obsolete
code.
(initialize_artificial_var, cp_complete_array_type): Update to cope
with VEC in CONSTRUCTOR_ELTS.
* decl2.c (grokfield): Update calls to digest_init.
(mark_vtable_entries): Update to cope with VEC in CONSTRUCTOR_ELTS.
* error.c (dump_expr_init_vec): New function.
(dump_expr): Use dump_expr_init_vec.
* init.c (build_zero_init, build_vec_init): Update to cope with VEC
in CONSTRUCTOR_ELTS.
(expand_default_init): Update call to digest_init.
* parser.c (cp_parser_postfix_expression): Use a VEC for the
initializers.
(cp_parser_initializer_list): Build a VEC of initializers.
* pt.c (tsubst_copy, tsubst_copy_and_build): Update to cope with VEC
in CONSTRUCTOR_ELTS.
* rtti.c (tinfo_base_init, generic_initializer, ptr_initializer,
ptm_initializer, class_initializer, get_pseudo_ti_init): Use
build_constructor_from_list instead of build_constructor.
* semantics.c (finish_compound_literal): Update call to digest_init.
* tree.c (stabilize_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* typeck.c (build_ptrmemfunc1): Likewise.
* typeck2.c: (cxx_incomplete_type_error, split_nonconstant_init_1):
Likewise.
(store_init_value): Use build_constructor_from_list and update call
to digest_init.
(digest_init): Rewrite.
(process_init_constructor): Rewrite from scratch. Split into...
(process_init_constructor_array, picflag_from_initializer,
process_init_constructor_record, process_init_constructor_union):
New functions.
(PICFLAG_ERRONEOUS, PICFLAG_NOT_ALL_CONSTANT, PICFLAG_NOT_ALL_SIMPLE):
New macros.
(build_functional_cast): Use build_constructor_from_list instead of
build_constructor.
fortran/
Make CONSTRUCTOR use VEC to store initializers.
* trans-array.c (gfc_build_null_descriptor,
gfc_trans_array_constructor_value, gfc_conv_array_initializer):
Update to cope with VEC in CONSTRUCTOR_ELTS.
* trans-common.c (create_common): Likewise.
* trans-expr.c (gfc_conv_structure): Likewise.
* trans-stmt.c (gfc_trans_character_select): Use
build_constructor_from_list instead of build_constructor.
java/
Make CONSTRUCTOR use VEC to store initializers.
* check-init.c (check_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* class.c (make_field_value, make_method_value, get_dispatch_table,
make_class_data, emit_symbol_table, emit_catch_table,
emit_assertion_table): Use build_constructor_from_list instead of
build_constructor.
* constants.c (build_constants_constructor): Likewise.
* java-gimplify.c (java_gimplify_new_array_init): Update to cope with
VEC in CONSTRUCTOR_ELTS.
* java-tree.h (START_RECORD_CONSTRUCTOR, PUSH_SUPER_VALUE,
PUSH_FIELD_VALUE, FINISH_RECORD_CONSTRUCTOR): Create a VEC instead
of a TREE_LIST.
* jcf-write.c (generate_bytecode_insns): Update to cope with VEC in
CONSTRUCTOR_ELTS.
* parse.y (build_new_array_init): Use build_constructor_from_list
instead of build_constructor.
(patch_new_array_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
(array_constructor_check_entry): Likewise.
objc/
Make CONSTRUCTOR use VEC to store initializers.
* objc-act.c (objc_build_constructor): Use build_constructor_from_list
instead of build_constructor.
testsuite/
Make CONSTRUCTOR use VEC to store initializers.
* g++.dg/ext/complit3.C: Check for specific error messages.
* g++.dg/init/brace2.C: Update error message.
* g++.dg/warn/Wbraces2.C: Likewise.
From-SVN: r102182
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 51 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/class.c | 10 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 11 | ||||
-rw-r--r-- | gcc/cp/decl.c | 499 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 48 | ||||
-rw-r--r-- | gcc/cp/error.c | 21 | ||||
-rw-r--r-- | gcc/cp/init.c | 56 | ||||
-rw-r--r-- | gcc/cp/parser.c | 23 | ||||
-rw-r--r-- | gcc/cp/pt.c | 40 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 16 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 6 | ||||
-rw-r--r-- | gcc/cp/tree.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 8 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 767 |
15 files changed, 809 insertions, 751 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b30aabc..0704146 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,54 @@ +2005-07-20 Giovanni Bajo <giovannibajo@libero.it> + + Make CONSTRUCTOR use VEC to store initializers. + * call.c (convert_default_arg): Update call to digest_init. + * class.c (dump_class_hierarchy, dump_array): Update to cope with + VEC in CONSTRUCTOR_ELTS. + * cp-tree.h (EMPTY_CONSTRUCTOR_P): Likewise. + (finish_compound_literal, digest_init): Update declaration. + * decl.c (struct reshape_iter): New data type. + (reshape_init_array): Rename to... + (reshape_init_array_1): Update to cope with VEC in CONSTRUCTOR_ELTS. + (reshape_init): Rewrite from scratch. Split parts into... + (reshape_init_array, reshape_init_vector, reshape_init_class, + reshape_init_r): New functions. + (check_initializer): Update call to reshape_init. Remove obsolete + code. + (initialize_artificial_var, cp_complete_array_type): Update to cope + with VEC in CONSTRUCTOR_ELTS. + * decl2.c (grokfield): Update calls to digest_init. + (mark_vtable_entries): Update to cope with VEC in CONSTRUCTOR_ELTS. + * error.c (dump_expr_init_vec): New function. + (dump_expr): Use dump_expr_init_vec. + * init.c (build_zero_init, build_vec_init): Update to cope with VEC + in CONSTRUCTOR_ELTS. + (expand_default_init): Update call to digest_init. + * parser.c (cp_parser_postfix_expression): Use a VEC for the + initializers. + (cp_parser_initializer_list): Build a VEC of initializers. + * pt.c (tsubst_copy, tsubst_copy_and_build): Update to cope with VEC + in CONSTRUCTOR_ELTS. + * rtti.c (tinfo_base_init, generic_initializer, ptr_initializer, + ptm_initializer, class_initializer, get_pseudo_ti_init): Use + build_constructor_from_list instead of build_constructor. + * semantics.c (finish_compound_literal): Update call to digest_init. + * tree.c (stabilize_init): Update to cope with VEC in + CONSTRUCTOR_ELTS. + * typeck.c (build_ptrmemfunc1): Likewise. + * typeck2.c: (cxx_incomplete_type_error, split_nonconstant_init_1): + Likewise. + (store_init_value): Use build_constructor_from_list and update call + to digest_init. + (digest_init): Rewrite. + (process_init_constructor): Rewrite from scratch. Split into... + (process_init_constructor_array, picflag_from_initializer, + process_init_constructor_record, process_init_constructor_union): + New functions. + (PICFLAG_ERRONEOUS, PICFLAG_NOT_ALL_CONSTANT, PICFLAG_NOT_ALL_SIMPLE): + New macros. + (build_functional_cast): Use build_constructor_from_list instead of + build_constructor. + 2005-07-18 Mark Mitchell <mark@codesourcery.com> PR c++/22263 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 21201cf..6e88708 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4544,7 +4544,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum) if (TREE_CODE (arg) == CONSTRUCTOR) { - arg = digest_init (type, arg, 0); + arg = digest_init (type, arg); arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, "default argument", fn, parmnum); } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 5dbec46..9b85a4d 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6437,8 +6437,8 @@ dump_class_hierarchy (tree t) static void dump_array (FILE * stream, tree decl) { - tree inits; - int ix; + tree value; + unsigned HOST_WIDE_INT ix; HOST_WIDE_INT elt; tree size = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (decl))); @@ -6450,10 +6450,10 @@ dump_array (FILE * stream, tree decl) TFF_PLAIN_IDENTIFIER)); fprintf (stream, "\n"); - for (ix = 0, inits = CONSTRUCTOR_ELTS (DECL_INITIAL (decl)); - inits; ix++, inits = TREE_CHAIN (inits)) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)), + ix, value) fprintf (stream, "%-4ld %s\n", (long)(ix * elt), - expr_as_string (TREE_VALUE (inits), TFF_PLAIN_IDENTIFIER)); + expr_as_string (value, TFF_PLAIN_IDENTIFIER)); } static void diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d9d053d..0ac7bba 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2417,9 +2417,10 @@ extern void decl_shadowed_for_var_insert (tree, tree); #define BRACE_ENCLOSED_INITIALIZER_P(NODE) \ (TREE_CODE (NODE) == CONSTRUCTOR && !TREE_TYPE (NODE)) -#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ - && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \ - && ! TREE_HAS_CONSTRUCTOR (NODE)) +#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ + && VEC_empty (constructor_elt, \ + CONSTRUCTOR_ELTS (NODE)) \ + && !TREE_HAS_CONSTRUCTOR (NODE)) /* Nonzero means that an object of this type can not be initialized using an initializer list. */ @@ -4168,7 +4169,7 @@ extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree); extern tree finish_unary_op_expr (enum tree_code, tree); -extern tree finish_compound_literal (tree, tree); +extern tree finish_compound_literal (tree, VEC(constructor_elt,gc) *); extern tree finish_fname (tree); extern void finish_translation_unit (void); extern tree finish_template_type_parm (tree, tree); @@ -4348,7 +4349,7 @@ extern void complete_type_check_abstract (tree); extern int abstract_virtuals_error (tree, tree); extern tree store_init_value (tree, tree); -extern tree digest_init (tree, tree, tree *); +extern tree digest_init (tree, tree); extern tree build_scoped_ref (tree, tree, tree *); extern tree build_x_arrow (tree); extern tree build_m_component_ref (tree, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 855906a..ddcab2e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -114,7 +114,7 @@ static void store_parm_decls (tree); static void initialize_local_var (tree, tree); static void expand_static_init (tree, tree); static tree next_initializable_field (tree); -static tree reshape_init (tree, tree *); +static tree reshape_init (tree, tree); /* Erroneous argument lists can use this *IFF* they do not modify it. */ tree error_mark_list; @@ -4103,6 +4103,18 @@ check_for_uninitialized_const_var (tree decl) error ("uninitialized const %qD", decl); } + +/* Structure holding the current initializer being processed by reshape_init. + CUR is a pointer to the current element being processed, END is a pointer + after the last element present in the initializer. */ +typedef struct reshape_iterator_t +{ + constructor_elt *cur; + constructor_elt *end; +} reshape_iter; + +static tree reshape_init_r (tree, reshape_iter *, bool); + /* FIELD is a FIELD_DECL or NULL. In the former case, the value returned is the next FIELD_DECL (possibly FIELD itself) that can be initialized. If there are no more such fields, the return value @@ -4120,22 +4132,23 @@ next_initializable_field (tree field) return field; } -/* Subroutine of reshape_init. Reshape the constructor for an array. INITP - is the pointer to the old constructor list (to the CONSTRUCTOR_ELTS of - the CONSTRUCTOR we are processing), while NEW_INIT is the CONSTRUCTOR we - are building. - ELT_TYPE is the element type of the array. MAX_INDEX is an INTEGER_CST - representing the size of the array minus one (the maximum index), or - NULL_TREE if the array was declared without specifying the size. */ +/* Subroutine of reshape_init_array and reshape_init_vector, which does + the actual work. ELT_TYPE is the element type of the array. MAX_INDEX is an + INTEGER_CST representing the size of the array minus one (the maximum index), + or NULL_TREE if the array was declared without specifying the size. D is + the iterator within the constructor. */ -static bool -reshape_init_array (tree elt_type, tree max_index, - tree *initp, tree new_init) +static tree +reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d) { + tree new_init; bool sized_array_p = (max_index != NULL_TREE); unsigned HOST_WIDE_INT max_index_cst = 0; unsigned HOST_WIDE_INT index; + /* The initializer for an array is always a CONSTRUCTOR. */ + new_init = build_constructor (NULL_TREE, NULL); + if (sized_array_p) { if (host_integerp (max_index, 1)) @@ -4148,104 +4161,181 @@ reshape_init_array (tree elt_type, tree max_index, /* Loop until there are no more initializers. */ for (index = 0; - *initp && (!sized_array_p || index <= max_index_cst); + d->cur != d->end && (!sized_array_p || index <= max_index_cst); ++index) { - tree element_init; - tree designated_index; + tree elt_init; - element_init = reshape_init (elt_type, initp); - if (element_init == error_mark_node) - return false; - TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init); - CONSTRUCTOR_ELTS (new_init) = element_init; - designated_index = TREE_PURPOSE (element_init); - if (designated_index) + if (d->cur->index) { /* Handle array designated initializers (GNU extension). */ - if (TREE_CODE (designated_index) == IDENTIFIER_NODE) + if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE) { error ("name %qD used in a GNU-style designated " - "initializer for an array", designated_index); - TREE_PURPOSE (element_init) = NULL_TREE; + "initializer for an array", d->cur->index); } else gcc_unreachable (); } + + elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false); + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), NULL_TREE, elt_init); } - return true; + return new_init; } -/* Undo the brace-elision allowed by [dcl.init.aggr] in a - brace-enclosed aggregate initializer. +/* Subroutine of reshape_init_r, processes the initializers for arrays. + Parameters are the same of reshape_init_r. */ - *INITP is one of a list of initializers describing a brace-enclosed - initializer for an entity of the indicated aggregate TYPE. It may - not presently match the shape of the TYPE; for example: +static tree +reshape_init_array (tree type, reshape_iter *d) +{ + tree max_index = NULL_TREE; - struct S { int a; int b; }; - struct S a[] = { 1, 2, 3, 4 }; + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); - Here *INITP will point to TREE_LIST of four elements, rather than a - list of two elements, each itself a list of two elements. This - routine transforms INIT from the former form into the latter. The - revised initializer is returned. */ + if (TYPE_DOMAIN (type)) + max_index = array_type_nelts (type); + + return reshape_init_array_1 (TREE_TYPE (type), max_index, d); +} + +/* Subroutine of reshape_init_r, processes the initializers for vectors. + Parameters are the same of reshape_init_r. */ + +static tree +reshape_init_vector (tree type, reshape_iter *d) +{ + tree max_index = NULL_TREE; + tree rtype; + + gcc_assert (TREE_CODE (type) == VECTOR_TYPE); + + if (TREE_CODE (d->cur->value) == CONSTRUCTOR + && TREE_HAS_CONSTRUCTOR (d->cur->value)) + { + tree value = d->cur->value; + if (!same_type_p (TREE_TYPE (value), type)) + { + error ("invalid type %qT as initializer for a vector of type %qT", + TREE_TYPE (d->cur->value), type); + value = error_mark_node; + } + ++d->cur; + return value; + } + + /* For a vector, the representation type is a struct + containing a single member which is an array of the + appropriate size. */ + rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type); + if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype)))) + max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS (rtype))); + + return reshape_init_array_1 (TREE_TYPE (type), max_index, d); +} + +/* Subroutine of reshape_init_r, processes the initializers for classes + or union. Parameters are the same of reshape_init_r. */ static tree -reshape_init (tree type, tree *initp) +reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p) { - tree inits; - tree old_init; - tree old_init_value; + tree field; tree new_init; - bool brace_enclosed_p; - bool string_init_p; - old_init = *initp; - old_init_value = (TREE_CODE (*initp) == TREE_LIST - ? TREE_VALUE (*initp) : old_init); + gcc_assert (CLASS_TYPE_P (type)); - gcc_assert (old_init_value); + /* The initializer for a class is always a CONSTRUCTOR. */ + new_init = build_constructor (NULL_TREE, NULL); + field = next_initializable_field (TYPE_FIELDS (type)); - /* If the initializer is brace-enclosed, pull initializers from the - enclosed elements. Advance past the brace-enclosed initializer - now. */ - if (TREE_CODE (old_init_value) == CONSTRUCTOR - && BRACE_ENCLOSED_INITIALIZER_P (old_init_value)) + if (!field) { - *initp = TREE_CHAIN (old_init); - TREE_CHAIN (old_init) = NULL_TREE; - inits = CONSTRUCTOR_ELTS (old_init_value); - initp = &inits; - brace_enclosed_p = true; + /* [dcl.init.aggr] + + An initializer for an aggregate member that is an + empty class shall have the form of an empty + initializer-list {}. */ + if (!first_initializer_p) + { + error ("initializer for %qT must be brace-enclosed", type); + return error_mark_node; + } + return new_init; } - else + + /* Loop through the initializable fields, gathering initializers. */ + while (d->cur != d->end) { - inits = NULL_TREE; - brace_enclosed_p = false; + tree field_init; + + /* Handle designated initializers, as an extension. */ + if (d->cur->index) + { + if (pedantic) + pedwarn ("ISO C++ does not allow designated initializers"); + + field = lookup_field_1 (type, d->cur->index, /*want_type=*/false); + + if (!field || TREE_CODE (field) != FIELD_DECL) + error ("%qT has no non-static data member named %qD", type, + d->cur->index); + } + + /* If we processed all the member of the class, we are done. */ + if (!field) + break; + + field_init = reshape_init_r (TREE_TYPE (field), d, + /*first_initializer_p=*/false); + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), field, field_init); + + /* [dcl.init.aggr] + + When a union is initialized with a brace-enclosed + initializer, the braces shall only contain an + initializer for the first member of the union. */ + if (TREE_CODE (type) == UNION_TYPE) + break; + + field = next_initializable_field (TREE_CHAIN (field)); } + return new_init; +} + +/* Subroutine of reshape_init, which processes a single initializer (part of + a CONSTRUCTOR). TYPE is the type of the variable being initialized, D is the + iterator within the CONSTRUCTOR which points to the initializer to process. + FIRST_INITIALIZER_P is true if this is the first initializer of the + CONSTRUCTOR node. */ + +static tree +reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) +{ + tree init = d->cur->value; + /* A non-aggregate type is always initialized with a single initializer. */ if (!CP_AGGREGATE_TYPE_P (type)) - { - *initp = TREE_CHAIN (old_init); - TREE_CHAIN (old_init) = NULL_TREE; - /* It is invalid to initialize a non-aggregate type with a - brace-enclosed initializer. */ - if (brace_enclosed_p) - { - error ("brace-enclosed initializer used to initialize %qT", - type); - if (TREE_CODE (old_init) == TREE_LIST) - TREE_VALUE (old_init) = error_mark_node; - else - old_init = error_mark_node; - } - - return old_init; - } + { + /* It is invalid to initialize a non-aggregate type with a + brace-enclosed initializer. + We need to check for BRACE_ENCLOSED_INITIALIZER_P here because + of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is + a CONSTRUCTOR (with a record type). */ + if (TREE_CODE (init) == CONSTRUCTOR + && BRACE_ENCLOSED_INITIALIZER_P (init)) /* p7626.C */ + { + error ("braces around scalar initializer for type %qT", type); + init = error_mark_node; + } + + d->cur++; + return init; + } /* [dcl.init.aggr] @@ -4256,139 +4346,124 @@ reshape_init (tree type, tree *initp) non-empty subaggregate, brace elision is assumed and the initializer is considered for the initialization of the first member of the subaggregate. */ - if (!brace_enclosed_p - && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value)) + if (TREE_CODE (init) != CONSTRUCTOR + && can_convert_arg (type, TREE_TYPE (init), init)) { - *initp = TREE_CHAIN (old_init); - TREE_CHAIN (old_init) = NULL_TREE; - return old_init; + d->cur++; + return init; } - string_init_p = false; - if (TREE_CODE (old_init_value) == STRING_CST - && TREE_CODE (type) == ARRAY_TYPE + /* [dcl.init.string] + + A char array (whether plain char, signed char, or unsigned char) + can be initialized by a string-literal (optionally enclosed in + braces); a wchar_t array can be initialized by a wide + string-literal (optionally enclosed in braces). */ + if (TREE_CODE (type) == ARRAY_TYPE && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))) { - /* [dcl.init.string] + tree str_init = init; - A char array (whether plain char, signed char, or unsigned char) - can be initialized by a string-literal (optionally enclosed in - braces); a wchar_t array can be initialized by a wide - string-literal (optionally enclosed in braces). */ - new_init = old_init; - /* Move past the initializer. */ - *initp = TREE_CHAIN (old_init); - TREE_CHAIN (old_init) = NULL_TREE; - string_init_p = true; + /* Strip one level of braces if and only if they enclose a single + element (as allowed by [dcl.init.string]). */ + if (!first_initializer_p + && TREE_CODE (str_init) == CONSTRUCTOR + && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (str_init)) == 1) + { + str_init = VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (str_init), 0)->value; + } + + /* If it's a string literal, then it's the initializer for the array + as a whole. Otherwise, continue with normal initialization for + array types (one value per array element). */ + if (TREE_CODE (str_init) == STRING_CST) + { + d->cur++; + return str_init; + } } - else - { - /* Build a CONSTRUCTOR to hold the contents of the aggregate. */ - new_init = build_constructor (NULL_TREE, NULL_TREE); - if (CLASS_TYPE_P (type)) + /* The following cases are about aggregates. If we are not within a full + initializer already, and there is not a CONSTRUCTOR, it means that there + is a missing set of braces (that is, we are processing the case for + which reshape_init exists). */ + if (!first_initializer_p) + { + if (TREE_CODE (init) == CONSTRUCTOR) { - tree field; - - field = next_initializable_field (TYPE_FIELDS (type)); - - if (!field) + /* For a nested compound literal, there is no need to reshape since + brace elision is not allowed. Even if we decided to allow it, + we should add a call to reshape_init in finish_compound_literal, + before calling digest_init, so changing this code would still + not be necessary. */ + if (!TREE_HAS_CONSTRUCTOR (init)) { - /* [dcl.init.aggr] - - An initializer for an aggregate member that is an - empty class shall have the form of an empty - initializer-list {}. */ - if (!brace_enclosed_p) - { - error ("initializer for %qT must be brace-enclosed", type); - return error_mark_node; - } + ++d->cur; + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); + return reshape_init (type, init); } else - { - /* Loop through the initializable fields, gathering - initializers. */ - while (*initp) - { - tree field_init; + gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init)); + } - /* Handle designated initializers, as an extension. */ - if (TREE_PURPOSE (*initp)) - { - if (pedantic) - pedwarn ("ISO C++ does not allow designated initializers"); - field = lookup_field_1 (type, TREE_PURPOSE (*initp), - /*want_type=*/false); - if (!field || TREE_CODE (field) != FIELD_DECL) - error ("%qT has no non-static data member named %qD", - type, TREE_PURPOSE (*initp)); - } - if (!field) - break; + warning (OPT_Wmissing_braces, "missing braces around initializer for %qT", + type); + } - field_init = reshape_init (TREE_TYPE (field), initp); - if (field_init == error_mark_node) - return error_mark_node; - TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init); - CONSTRUCTOR_ELTS (new_init) = field_init; - /* [dcl.init.aggr] - - When a union is initialized with a brace-enclosed - initializer, the braces shall only contain an - initializer for the first member of the union. */ - if (TREE_CODE (type) == UNION_TYPE) - break; - field = next_initializable_field (TREE_CHAIN (field)); - } - } - } - else if (TREE_CODE (type) == ARRAY_TYPE - || TREE_CODE (type) == VECTOR_TYPE) - { - /* If the bound of the array is known, take no more initializers - than are allowed. */ - tree max_index = NULL_TREE; - if (TREE_CODE (type) == ARRAY_TYPE) - { - if (TYPE_DOMAIN (type)) - max_index = array_type_nelts (type); - } - else - { - /* For a vector, the representation type is a struct - containing a single member which is an array of the - appropriate size. */ - tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type); - if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype)))) - max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS - (rtype))); - } + /* Dispatch to specialized routines. */ + if (CLASS_TYPE_P (type)) + return reshape_init_class (type, d, first_initializer_p); + else if (TREE_CODE (type) == ARRAY_TYPE) + return reshape_init_array (type, d); + else if (TREE_CODE (type) == VECTOR_TYPE) + return reshape_init_vector (type, d); + else + gcc_unreachable(); +} - if (!reshape_init_array (TREE_TYPE (type), max_index, - initp, new_init)) - return error_mark_node; - } - else - gcc_unreachable (); +/* Undo the brace-elision allowed by [dcl.init.aggr] in a + brace-enclosed aggregate initializer. - /* The initializers were placed in reverse order in the - CONSTRUCTOR. */ - CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init)); + INIT is the CONSTRUCTOR containing the list of initializers describing + a brace-enclosed initializer for an entity of the indicated aggregate TYPE. + It may not presently match the shape of the TYPE; for example: - if (TREE_CODE (old_init) == TREE_LIST) - new_init = build_tree_list (TREE_PURPOSE (old_init), new_init); - } + struct S { int a; int b; }; + struct S a[] = { 1, 2, 3, 4 }; - /* If there are more initializers than necessary, issue a - diagnostic. */ - if (*initp) - { - if (brace_enclosed_p) - error ("too many initializers for %qT", type); - else if (warn_missing_braces && !string_init_p) - warning (0, "missing braces around initializer"); - } + Here INIT will hold a VEC of four elements, rather than a + VEC of two elements, each itself a VEC of two elements. This + routine transforms INIT from the former form into the latter. The + revised CONSTRUCTOR node is returned. */ + +static tree +reshape_init (tree type, tree init) +{ + VEC(constructor_elt, gc) *v; + reshape_iter d; + tree new_init; + + gcc_assert (TREE_CODE (init) == CONSTRUCTOR); + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); + + v = CONSTRUCTOR_ELTS (init); + + /* An empty constructor does not need reshaping, and it is always a valid + initializer. */ + if (VEC_empty (constructor_elt, v)) + return init; + + /* Recurse on this CONSTRUCTOR. */ + d.cur = VEC_index (constructor_elt, v, 0); + d.end = d.cur + VEC_length (constructor_elt, v); + + new_init = reshape_init_r (type, &d, true); + + /* Make sure all the element of the constructor were used. Otherwise, + issue an error about exceeding initializers. */ + if (d.cur != d.end) + error ("too many initializers for %qT", type); return new_init; } @@ -4455,20 +4530,13 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) init = grok_reference_init (decl, type, init, cleanup); else if (init) { + /* Do not reshape constructors of vectors (they don't need to be + reshaped. */ if (TREE_CODE (init) == CONSTRUCTOR - && BRACE_ENCLOSED_INITIALIZER_P (init)) + && !TREE_HAS_CONSTRUCTOR (init) + && !TREE_TYPE (init)) /* ptrmemfunc */ { - /* [dcl.init] paragraph 13, - If T is a scalar type, then a declaration of the form - T x = { a }; - is equivalent to - T x = a; - - reshape_init will complain about the extra braces, - and doesn't do anything useful in the case where TYPE is - scalar, so just don't call it. */ - if (CP_AGGREGATE_TYPE_P (type)) - init = reshape_init (type, &init); + init = reshape_init (type, init); if ((*targetm.vector_opaque_p) (type)) { @@ -4486,9 +4554,9 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) { if (TREE_CODE (type) == ARRAY_TYPE) goto initialize_aggr; - else if (TREE_CODE (init) == CONSTRUCTOR - && BRACE_ENCLOSED_INITIALIZER_P (init)) + else if (TREE_CODE (init) == CONSTRUCTOR) { + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); if (TYPE_NON_AGGREGATE_CLASS (type)) { error ("%qD must be initialized by constructor, " @@ -4713,7 +4781,7 @@ initialize_local_var (tree decl, tree init) void initialize_artificial_var (tree decl, tree init) { - DECL_INITIAL (decl) = build_constructor (NULL_TREE, init); + DECL_INITIAL (decl) = build_constructor_from_list (NULL_TREE, init); DECL_INITIALIZED_P (decl) = 1; determine_visibility (decl); layout_var_decl (decl); @@ -5401,14 +5469,21 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default) if (initial_value) { /* An array of character type can be initialized from a - brace-enclosed string constant. */ + brace-enclosed string constant. + + FIXME: this code is duplicated from reshape_init. Probably + we should just call reshape_init here? */ if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype))) && TREE_CODE (initial_value) == CONSTRUCTOR - && CONSTRUCTOR_ELTS (initial_value) - && (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value))) - == STRING_CST) - && TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE) - initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)); + && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (initial_value))) + { + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value); + tree value = VEC_index (constructor_elt, v, 0)->value; + + if (TREE_CODE (value) == STRING_CST + && VEC_length (constructor_elt, v) == 1) + initial_value = value; + } } failure = complete_array_type (ptype, initial_value, do_default); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 5afcd89..e7db552 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -903,37 +903,24 @@ grokfield (const cp_declarator *declarator, else if (pedantic && TREE_CODE (value) != VAR_DECL) /* Already complained in grokdeclarator. */ init = NULL_TREE; - else + else if (!processing_template_decl) { - /* We allow initializers to become parameters to base - initializers. */ - if (TREE_CODE (init) == TREE_LIST) - { - if (TREE_CHAIN (init) == NULL_TREE) - init = TREE_VALUE (init); - else - init = digest_init (TREE_TYPE (value), init, (tree *)0); - } + if (TREE_CODE (init) == CONSTRUCTOR) + init = digest_init (TREE_TYPE (value), init); + else + init = integral_constant_value (init); - if (!processing_template_decl) + if (init != error_mark_node && !TREE_CONSTANT (init)) { - if (TREE_CODE (init) == CONSTRUCTOR) - init = digest_init (TREE_TYPE (value), init, (tree *)0); - else - init = integral_constant_value (init); - - if (init != error_mark_node && ! TREE_CONSTANT (init)) + /* We can allow references to things that are effectively + static, since references are initialized with the + address. */ + if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE + || (TREE_STATIC (init) == 0 + && (!DECL_P (init) || DECL_EXTERNAL (init) == 0))) { - /* We can allow references to things that are effectively - static, since references are initialized with the - address. */ - if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE - || (TREE_STATIC (init) == 0 - && (!DECL_P (init) || DECL_EXTERNAL (init) == 0))) - { - error ("field initializer is not constant"); - init = error_mark_node; - } + error ("field initializer is not constant"); + init = error_mark_node; } } } @@ -1262,11 +1249,12 @@ coerce_delete_type (tree type) static void mark_vtable_entries (tree decl) { - tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl)); + tree fnaddr; + unsigned HOST_WIDE_INT idx; - for (; entries; entries = TREE_CHAIN (entries)) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)), + idx, fnaddr) { - tree fnaddr = TREE_VALUE (entries); tree fn; STRIP_NOPS (fnaddr); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 6d80fc6..9905e25 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1266,6 +1266,23 @@ dump_expr_list (tree l, int flags) } } +/* Print out a vector of initializers (subr of dump_expr). */ + +static void +dump_expr_init_vec (VEC(constructor_elt,gc) *v, int flags) +{ + unsigned HOST_WIDE_INT idx; + tree value; + + FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) + { + dump_expr (value, flags | TFF_EXPR_IN_PARENS); + if (idx != VEC_length (constructor_elt, v) - 1) + pp_separate_with_comma (cxx_pp); + } +} + + /* Print out an expression E under control of FLAGS. */ static void @@ -1659,7 +1676,7 @@ dump_expr (tree t, int flags) } } } - if (TREE_TYPE (t) && !CONSTRUCTOR_ELTS (t)) + if (TREE_TYPE (t) && EMPTY_CONSTRUCTOR_P (t)) { dump_type (TREE_TYPE (t), 0); pp_cxx_left_paren (cxx_pp); @@ -1668,7 +1685,7 @@ dump_expr (tree t, int flags) else { pp_cxx_left_brace (cxx_pp); - dump_expr_list (CONSTRUCTOR_ELTS (t), flags); + dump_expr_init_vec (CONSTRUCTOR_ELTS (t), flags); pp_cxx_right_brace (cxx_pp); } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 05491c4..9383e92 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -184,12 +184,9 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) else if (CLASS_TYPE_P (type)) { tree field; - tree inits; + VEC(constructor_elt,gc) *v = NULL; - /* Build a constructor to contain the initializations. */ - init = build_constructor (type, NULL_TREE); /* Iterate over the fields, building initializations. */ - inits = NULL_TREE; for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { if (TREE_CODE (field) != FIELD_DECL) @@ -200,27 +197,27 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) over TYPE_FIELDs will result in correct initialization of all of the subobjects. */ if (static_storage_p && !zero_init_p (TREE_TYPE (field))) - inits = tree_cons (field, - build_zero_init (TREE_TYPE (field), - /*nelts=*/NULL_TREE, - static_storage_p), - inits); + { + tree value = build_zero_init (TREE_TYPE (field), + /*nelts=*/NULL_TREE, + static_storage_p); + CONSTRUCTOR_APPEND_ELT(v, field, value); + } /* For unions, only the first field is initialized. */ if (TREE_CODE (type) == UNION_TYPE) break; } - CONSTRUCTOR_ELTS (init) = nreverse (inits); + + /* Build a constructor to contain the initializations. */ + init = build_constructor (type, v); } else if (TREE_CODE (type) == ARRAY_TYPE) { tree max_index; - tree inits; + VEC(constructor_elt,gc) *v = NULL; - /* Build a constructor to contain the initializations. */ - init = build_constructor (type, NULL_TREE); /* Iterate over the array elements, building initializations. */ - inits = NULL_TREE; if (nelts) max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts), nelts, integer_one_node); @@ -232,21 +229,25 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) have an upper bound of -1. */ if (!tree_int_cst_equal (max_index, integer_minus_one_node)) { - tree elt_init = build_zero_init (TREE_TYPE (type), - /*nelts=*/NULL_TREE, - static_storage_p); - tree range; + constructor_elt *ce; + + v = VEC_alloc (constructor_elt, gc, 1); + ce = VEC_quick_push (constructor_elt, v, NULL); /* If this is a one element array, we just use a regular init. */ if (tree_int_cst_equal (size_zero_node, max_index)) - range = size_zero_node; + ce->index = size_zero_node; else - range = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index); + ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node, + max_index); - inits = tree_cons (range, elt_init, inits); + ce->value = build_zero_init (TREE_TYPE (type), + /*nelts=*/NULL_TREE, + static_storage_p); } - CONSTRUCTOR_ELTS (init) = nreverse (inits); + /* Build a constructor to contain the initializations. */ + init = build_constructor (type, v); } else gcc_assert (TREE_CODE (type) == REFERENCE_TYPE); @@ -1191,7 +1192,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags) { /* A brace-enclosed initializer for an aggregate. */ gcc_assert (CP_AGGREGATE_TYPE_P (type)); - init = digest_init (type, init, (tree *)NULL); + init = digest_init (type, init); } else init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); @@ -2417,7 +2418,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) && ((TREE_CODE (init) == CONSTRUCTOR /* Don't do this if the CONSTRUCTOR might contain something that might throw and require us to clean up. */ - && (CONSTRUCTOR_ELTS (init) == NULL_TREE + && (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init)) || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type))) || from_array)) { @@ -2485,13 +2486,12 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) { /* Do non-default initialization of non-POD arrays resulting from brace-enclosed initializers. */ - - tree elts; + unsigned HOST_WIDE_INT idx; + tree elt; from_array = 0; - for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts)) + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt) { - tree elt = TREE_VALUE (elts); tree baseref = build1 (INDIRECT_REF, type, base); num_initialized_elts++; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bd39a67..082727e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1546,7 +1546,7 @@ static tree cp_parser_initializer (cp_parser *, bool *, bool *); static tree cp_parser_initializer_clause (cp_parser *, bool *); -static tree cp_parser_initializer_list +static VEC(constructor_elt,gc) *cp_parser_initializer_list (cp_parser *, bool *); static bool cp_parser_ctor_initializer_opt_and_function_body @@ -4027,7 +4027,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) if (cp_parser_allow_gnu_extensions_p (parser) && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - tree initializer_list = NULL_TREE; + VEC(constructor_elt,gc) *initializer_list = NULL; bool saved_in_type_id_in_expr_p; cp_parser_parse_tentatively (parser); @@ -12298,7 +12298,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, returned is simply a representation for the expression. Otherwise, a CONSTRUCTOR is returned. The CONSTRUCTOR_ELTS will be - the elements of the initializer-list (or NULL_TREE, if the last + the elements of the initializer-list (or NULL, if the last production is used). The TREE_TYPE for the CONSTRUCTOR will be NULL_TREE. There is no way to detect whether or not the optional trailing `,' was provided. NON_CONSTANT_P is as for @@ -12358,15 +12358,15 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) identifier : initializer-clause initializer-list, identifier : initializer-clause - Returns a TREE_LIST. The TREE_VALUE of each node is an expression - for the initializer. If the TREE_PURPOSE is non-NULL, it is the + Returns a VEC of constructor_elt. The VALUE of each elt is an expression + for the initializer. If the INDEX of the elt is non-NULL, it is the IDENTIFIER_NODE naming the field to initialize. NON_CONSTANT_P is as for cp_parser_initializer. */ -static tree +static VEC(constructor_elt,gc) * cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) { - tree initializers = NULL_TREE; + VEC(constructor_elt,gc) *v = NULL; /* Assume all of the expressions are constant. */ *non_constant_p = false; @@ -12400,8 +12400,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) /* If any clause is non-constant, so is the entire initializer. */ if (clause_non_constant_p) *non_constant_p = true; - /* Add it to the list. */ - initializers = tree_cons (identifier, initializer, initializers); + + /* Add it to the vector. */ + CONSTRUCTOR_APPEND_ELT(v, identifier, initializer); /* If the next token is not a comma, we have reached the end of the list. */ @@ -12420,9 +12421,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) cp_lexer_consume_token (parser->lexer); } - /* The initializers were built up in reverse order, so we need to - reverse them now. */ - return nreverse (initializers); + return v; } /* Classes [gram.class] */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 619cdc1..2ab89b2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8006,13 +8006,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) return t; case CONSTRUCTOR: - { - r = build_constructor - (tsubst (TREE_TYPE (t), args, complain, in_decl), - tsubst_copy (CONSTRUCTOR_ELTS (t), args, complain, in_decl)); - TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t); - return r; - } + /* This is handled by tsubst_copy_and_build. */ + gcc_unreachable (); case VA_ARG_EXPR: return build_x_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain, @@ -8814,38 +8809,35 @@ tsubst_copy_and_build (tree t, case CONSTRUCTOR: { + VEC(constructor_elt,gc) *n; + constructor_elt *ce; + unsigned HOST_WIDE_INT idx; tree r; - tree elts; tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); - bool purpose_p; + bool process_index_p; /* digest_init will do the wrong thing if we let it. */ if (type && TYPE_PTRMEMFUNC_P (type)) return t; - r = NULL_TREE; - /* We do not want to process the purpose of aggregate + /* We do not want to process the index of aggregate initializers as they are identifier nodes which will be looked up by digest_init. */ - purpose_p = !(type && IS_AGGR_TYPE (type)); - for (elts = CONSTRUCTOR_ELTS (t); - elts; - elts = TREE_CHAIN (elts)) - { - tree purpose = TREE_PURPOSE (elts); - tree value = TREE_VALUE (elts); + process_index_p = !(type && IS_AGGR_TYPE (type)); - if (purpose && purpose_p) - purpose = RECUR (purpose); - value = RECUR (value); - r = tree_cons (purpose, value, r); + n = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t)); + for (idx = 0; VEC_iterate (constructor_elt, n, idx, ce); idx++) + { + if (ce->index && process_index_p) + ce->index = RECUR (ce->index); + ce->value = RECUR (ce->value); } - r = build_constructor (NULL_TREE, nreverse (r)); + r = build_constructor (NULL_TREE, n); TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t); if (type) - return digest_init (type, r, 0); + return digest_init (type, r); return r; } diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index dd59f69..e006938 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -861,7 +861,7 @@ tinfo_base_init (tinfo_s *ti, tree target) init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); - init = build_constructor (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -879,7 +879,7 @@ generic_initializer (tinfo_s *ti, tree target) { tree init = tinfo_base_init (ti, target); - init = build_constructor (NULL_TREE, init); + init = build_constructor_from_list (NULL_TREE, init); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -905,7 +905,7 @@ ptr_initializer (tinfo_s *ti, tree target) get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), init); - init = build_constructor (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -937,8 +937,8 @@ ptm_initializer (tinfo_s *ti, tree target) init = tree_cons (NULL_TREE, get_tinfo_ptr (klass), init); - - init = build_constructor (NULL_TREE, nreverse (init)); + + init = build_constructor_from_list (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -955,7 +955,7 @@ class_initializer (tinfo_s *ti, tree target, tree trail) tree init = tinfo_base_init (ti, target); TREE_CHAIN (init) = trail; - init = build_constructor (NULL_TREE, init); + init = build_constructor_from_list (NULL_TREE, init); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; @@ -1066,10 +1066,10 @@ get_pseudo_ti_init (tree type, unsigned tk_index) build_int_cst (NULL_TREE, flags)); base_init = tree_cons (NULL_TREE, offset, base_init); base_init = tree_cons (NULL_TREE, tinfo, base_init); - base_init = build_constructor (NULL_TREE, base_init); + base_init = build_constructor_from_list (NULL_TREE, base_init); base_inits = tree_cons (NULL_TREE, base_init, base_inits); } - base_inits = build_constructor (NULL_TREE, base_inits); + base_inits = build_constructor_from_list (NULL_TREE, base_inits); base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE); /* Prepend the number of bases. */ base_inits = tree_cons (NULL_TREE, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3d99c5d..e935bb9 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2011,20 +2011,19 @@ finish_unary_op_expr (enum tree_code code, tree expr) the INITIALIZER_LIST is being cast. */ tree -finish_compound_literal (tree type, tree initializer_list) +finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) { tree compound_literal; /* Build a CONSTRUCTOR for the INITIALIZER_LIST. */ compound_literal = build_constructor (NULL_TREE, initializer_list); /* Mark it as a compound-literal. */ - TREE_HAS_CONSTRUCTOR (compound_literal) = 1; if (processing_template_decl) TREE_TYPE (compound_literal) = type; else { /* Check the initialization. */ - compound_literal = digest_init (type, compound_literal, NULL); + compound_literal = digest_init (type, compound_literal); /* If the TYPE was an array type with an unknown bound, then we can figure out the dimension now. For example, something like: @@ -2036,6 +2035,7 @@ finish_compound_literal (tree type, tree initializer_list) compound_literal, 1); } + TREE_HAS_CONSTRUCTOR (compound_literal) = 1; return compound_literal; } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 0cf6b4e..ddc0b51 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2241,7 +2241,7 @@ stabilize_init (tree init, tree *initp) if (TREE_CODE (t) == COMPOUND_EXPR) t = expr_last (t); if (TREE_CODE (t) == CONSTRUCTOR - && CONSTRUCTOR_ELTS (t) == NULL_TREE) + && EMPTY_CONSTRUCTOR_P (t)) { /* Default-initialization. */ *initp = NULL_TREE; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b13c8cf..9a14f48 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5640,6 +5640,7 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn) tree u = NULL_TREE; tree delta_field; tree pfn_field; + VEC(constructor_elt, gc) *v; /* Pull the FIELD_DECLs out of the type. */ pfn_field = TYPE_FIELDS (type); @@ -5649,9 +5650,10 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn) delta = convert_and_check (delta_type_node, delta); /* Finish creating the initializer. */ - u = tree_cons (pfn_field, pfn, - build_tree_list (delta_field, delta)); - u = build_constructor (type, u); + v = VEC_alloc(constructor_elt, gc, 2); + CONSTRUCTOR_APPEND_ELT(v, pfn_field, pfn); + CONSTRUCTOR_APPEND_ELT(v, delta_field, delta); + u = build_constructor (type, v); TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta); TREE_INVARIANT (u) = TREE_INVARIANT (pfn) & TREE_INVARIANT (delta); TREE_STATIC (u) = (TREE_CONSTANT (u) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 4244088..2564a05 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -39,7 +39,9 @@ Boston, MA 02110-1301, USA. */ #include "output.h" #include "diagnostic.h" -static tree process_init_constructor (tree, tree, tree *); +static tree +process_init_constructor (tree type, tree init); + /* Print an error message stemming from an attempt to use BASETYPE as a base class for TYPE. */ @@ -435,11 +437,12 @@ cxx_incomplete_type_error (tree value, tree type) static void split_nonconstant_init_1 (tree dest, tree init) { - tree *pelt, elt, type = TREE_TYPE (dest); - tree sub, code, inner_type = NULL; + unsigned HOST_WIDE_INT idx; + tree field_index, value; + tree type = TREE_TYPE (dest); + tree inner_type = NULL; bool array_type_p = false; - pelt = &CONSTRUCTOR_ELTS (init); switch (TREE_CODE (type)) { case ARRAY_TYPE: @@ -450,16 +453,21 @@ split_nonconstant_init_1 (tree dest, tree init) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - while ((elt = *pelt)) + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, + field_index, value) { - tree field_index = TREE_PURPOSE (elt); - tree value = TREE_VALUE (elt); + /* The current implementation of this algorithm assumes that + the field was set for all the elements. This is usually done + by process_init_constructor. */ + gcc_assert (field_index); if (!array_type_p) inner_type = TREE_TYPE (field_index); if (TREE_CODE (value) == CONSTRUCTOR) { + tree sub; + if (array_type_p) sub = build4 (ARRAY_REF, inner_type, dest, field_index, NULL_TREE, NULL_TREE); @@ -471,7 +479,19 @@ split_nonconstant_init_1 (tree dest, tree init) } else if (!initializer_constant_valid_p (value, inner_type)) { - *pelt = TREE_CHAIN (elt); + tree code; + tree sub; + + /* FIXME: Ordered removal is O(1) so the whole function is + worst-case quadratic. This could be fixed using an aside + bitmap to record which elements must be removed and remove + them all at the same time. Or by merging + split_non_constant_init into process_init_constructor_array, + that is separating constants from non-constants while building + the vector. */ + VEC_ordered_remove (constructor_elt, CONSTRUCTOR_ELTS (init), + idx); + --idx; if (array_type_p) sub = build4 (ARRAY_REF, inner_type, dest, field_index, @@ -485,14 +505,13 @@ split_nonconstant_init_1 (tree dest, tree init) add_stmt (code); continue; } - - pelt = &TREE_CHAIN (elt); } break; case VECTOR_TYPE: if (!initializer_constant_valid_p (init, type)) { + tree code; tree cons = copy_node (init); CONSTRUCTOR_ELTS (init) = NULL; code = build2 (MODIFY_EXPR, type, dest, cons); @@ -568,7 +587,7 @@ store_init_value (tree decl, tree init) { error ("constructor syntax used, but no constructor declared " "for type %qT", type); - init = build_constructor (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (NULL_TREE, nreverse (init)); } } else if (TREE_CODE (init) == TREE_LIST @@ -591,7 +610,7 @@ store_init_value (tree decl, tree init) /* End of special C++ code. */ /* Digest the specified initializer into an expression. */ - value = digest_init (type, init, (tree *) 0); + value = digest_init (type, init); /* If the initializer is not a constant, fill in DECL_INITIAL with the bits that are constant, and then return an expression that will perform the dynamic initialization. */ @@ -607,39 +626,22 @@ store_init_value (tree decl, tree init) } -/* Digest the parser output INIT as an initializer for type TYPE. - Return a C expression of type TYPE to represent the initial value. +/* Process the initializer INIT for a variable of type TYPE, emitting + diagnostics for invalid initializers and converting the initializer as + appropriate. - If TAIL is nonzero, it points to a variable holding a list of elements - of which INIT is the first. We update the list stored there by - removing from the head all the elements that we use. - Normally this is only one; we use more than one element only if - TYPE is an aggregate and INIT is not a constructor. */ + For aggregate types, it assumes that reshape_init has already run, thus the + initializer will have the right shape (brace elision has been undone). */ tree -digest_init (tree type, tree init, tree* tail) +digest_init (tree type, tree init) { enum tree_code code = TREE_CODE (type); - tree element = NULL_TREE; - tree old_tail_contents = NULL_TREE; - - /* By default, assume we use one element from a list. - We correct this later in the sole case where it is not true. */ - if (tail) - { - old_tail_contents = *tail; - *tail = TREE_CHAIN (*tail); - } - - if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST - && TREE_VALUE (init) == error_mark_node)) + if (init == error_mark_node) return error_mark_node; - if (TREE_CODE (init) == ERROR_MARK) - /* __PRETTY_FUNCTION__'s initializer is a bogus expression inside - a template function. This gets substituted during instantiation. */ - return init; + gcc_assert (init); /* We must strip the outermost array type when completing the type, because the its bounds might be incomplete at the moment. */ @@ -647,60 +649,38 @@ digest_init (tree type, tree init, tree* tail) ? TREE_TYPE (type) : type, NULL_TREE)) return error_mark_node; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue + (g++.old-deja/g++.law/casts2.C). */ if (TREE_CODE (init) == NON_LVALUE_EXPR) init = TREE_OPERAND (init, 0); - if (BRACE_ENCLOSED_INITIALIZER_P (init) - && CONSTRUCTOR_ELTS (init) != 0 - && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0) - { - element = TREE_VALUE (CONSTRUCTOR_ELTS (init)); - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - if (element && TREE_CODE (element) == NON_LVALUE_EXPR) - element = TREE_OPERAND (element, 0); - if (element == error_mark_node) - return element; - } - - /* Initialization of an array of chars from a string constant - optionally enclosed in braces. */ - + /* Initialization of an array of chars from a string constant. The initializer + can be optionally enclosed in braces, but reshape_init has already removed + them if they were present. */ if (code == ARRAY_TYPE) { - tree typ1; - - if (TREE_CODE (init) == TREE_LIST) - { - error ("initializing array with parameter list"); - return error_mark_node; - } - - typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); if (char_type_p (typ1) - && ((init && TREE_CODE (init) == STRING_CST) - || (element && TREE_CODE (element) == STRING_CST))) + /*&& init */ + && TREE_CODE (init) == STRING_CST) { - tree string = element ? element : init; + tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init))); - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) - != char_type_node) + if (char_type != char_type_node && TYPE_PRECISION (typ1) == BITS_PER_UNIT) { error ("char-array initialized from wide string"); return error_mark_node; } - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) - == char_type_node) + if (char_type == char_type_node && TYPE_PRECISION (typ1) != BITS_PER_UNIT) { error ("int-array initialized from non-wide string"); return error_mark_node; } - TREE_TYPE (string) = type; - if (TYPE_DOMAIN (type) != 0 - && TREE_CONSTANT (TYPE_SIZE (type))) + TREE_TYPE (init) = type; + if (TYPE_DOMAIN (type) != 0 && TREE_CONSTANT (TYPE_SIZE (type))) { int size = TREE_INT_CST_LOW (TYPE_SIZE (type)); size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; @@ -708,419 +688,372 @@ digest_init (tree type, tree init, tree* tail) because it's ok to ignore the terminating null char that is counted in the length of the constant, but in C++ this would be invalid. */ - if (size < TREE_STRING_LENGTH (string)) + if (size < TREE_STRING_LENGTH (init)) pedwarn ("initializer-string for array of chars is too long"); } - return string; + return init; } } /* Handle scalar types, including conversions, and signature pointers and references. */ - - if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE - || code == ENUMERAL_TYPE || code == REFERENCE_TYPE - || code == BOOLEAN_TYPE || code == COMPLEX_TYPE - || TYPE_PTR_TO_MEMBER_P (type)) + if (SCALAR_TYPE_P (type) + || code == REFERENCE_TYPE) + return convert_for_initialization (0, type, init, LOOKUP_NORMAL, + "initialization", NULL_TREE, 0); + + /* Come here only for aggregates: records, arrays, unions, complex numbers + and vectors. */ + gcc_assert (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == VECTOR_TYPE + || TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == COMPLEX_TYPE); + + if (BRACE_ENCLOSED_INITIALIZER_P (init)) + return process_init_constructor (type, init); + else { - if (BRACE_ENCLOSED_INITIALIZER_P (init)) + if (TREE_HAS_CONSTRUCTOR (init) + && TREE_CODE (type) == ARRAY_TYPE) { - if (element == 0) - { - error ("initializer for scalar variable requires one element"); - return error_mark_node; - } - init = element; - } - while (BRACE_ENCLOSED_INITIALIZER_P (init)) - { - pedwarn ("braces around scalar initializer for %qT", type); - init = CONSTRUCTOR_ELTS (init); - if (TREE_CHAIN (init)) - pedwarn ("ignoring extra initializers for %qT", type); - init = TREE_VALUE (init); - } + error ("cannot initialize aggregate of type %qT with " + "a compound literal", type); - return convert_for_initialization (0, type, init, LOOKUP_NORMAL, + return error_mark_node; + } + return convert_for_initialization (NULL_TREE, type, init, + LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING, "initialization", NULL_TREE, 0); } +} + + +/* Set of flags used within process_init_constructor to describe the + initializers. */ +#define PICFLAG_ERRONEOUS 1 +#define PICFLAG_NOT_ALL_CONSTANT 2 +#define PICFLAG_NOT_ALL_SIMPLE 4 + +/* Given an initializer INIT, return the flag (PICFLAG_*) which better + describe it. */ + +static int +picflag_from_initializer (tree init) +{ + if (init == error_mark_node) + return PICFLAG_ERRONEOUS; + else if (!TREE_CONSTANT (init)) + return PICFLAG_NOT_ALL_CONSTANT; + else if (!initializer_constant_valid_p (init, TREE_TYPE (init))) + return PICFLAG_NOT_ALL_SIMPLE; + return 0; +} - /* Come here only for records and arrays (and unions with constructors). */ +/* Subroutine of process_init_constructor, which will process an initializer + INIT for a array or vector of type TYPE. Returns the flags (PICFLAG_*) which + describe the initializers. */ - if (COMPLETE_TYPE_P (type) && ! TREE_CONSTANT (TYPE_SIZE (type))) +static int +process_init_constructor_array (tree type, tree init) +{ + unsigned HOST_WIDE_INT i, len = 0; + int flags = 0; + bool unbounded = false; + constructor_elt *ce; + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (init); + + gcc_assert (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == VECTOR_TYPE); + + if (TREE_CODE (type) == ARRAY_TYPE) { - error ("variable-sized object of type %qT may not be initialized", - type); - return error_mark_node; + tree domain = TYPE_DOMAIN (type); + if (domain) + len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)) + - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)) + + 1); + else + unbounded = true; /* Take as many as there are. */ } + else + /* Vectors are like simple fixed-size arrays. */ + len = TYPE_VECTOR_SUBPARTS (type); - if (code == ARRAY_TYPE || code == VECTOR_TYPE || IS_AGGR_TYPE_CODE (code)) + /* There cannot be more initializers than needed (or reshape_init would + detect this before we do. */ + if (!unbounded) + gcc_assert (VEC_length (constructor_elt, v) <= len); + + for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i) { - if (BRACE_ENCLOSED_INITIALIZER_P (init)) - { - if (TYPE_NON_AGGREGATE_CLASS (type)) - { - error ("subobject of type %qT must be initialized by " - "constructor, not by %qE", - type, init); - return error_mark_node; - } - return process_init_constructor (type, init, (tree *)0); - } - else if (can_convert_arg (type, TREE_TYPE (init), init) - || TYPE_NON_AGGREGATE_CLASS (type)) - /* These are never initialized from multiple constructor elements. */; - else if (tail != 0) + if (ce->index) { - *tail = old_tail_contents; - return process_init_constructor (type, 0, tail); + gcc_assert (TREE_CODE (ce->index) == INTEGER_CST); + if (compare_tree_int (ce->index, i) != 0) + sorry ("non-trivial designated initializers not supported"); } + else + ce->index = size_int (i); + gcc_assert (ce->value); + ce->value = digest_init (TREE_TYPE (type), ce->value); - if (code != ARRAY_TYPE) - { - int flags = LOOKUP_NORMAL; - /* Initialization from { } is copy-initialization. */ - if (tail) - flags |= LOOKUP_ONLYCONVERTING; + if (ce->value != error_mark_node) + gcc_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (type), TREE_TYPE (ce->value))); - return convert_for_initialization (NULL_TREE, type, init, flags, - "initialization", NULL_TREE, 0); - } + flags |= picflag_from_initializer (ce->value); } - error ("invalid initializer"); - return error_mark_node; -} - -/* Process a constructor for a variable of type TYPE. - The constructor elements may be specified either with INIT or with ELTS, - only one of which should be non-null. + /* No more initializers. If the array is unbounded, we are done. Otherwise, + we must add initializers ourselves. */ + if (!unbounded) + for (; i < len; ++i) + { + tree next; + + if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) + { + /* If this type needs constructors run for default-initialization, + we can't rely on the backend to do it for us, so build up + TARGET_EXPRs. If the type in question is a class, just build + one up; if it's an array, recurse. */ + if (IS_AGGR_TYPE (TREE_TYPE (type))) + next = build_functional_cast (TREE_TYPE (type), NULL_TREE); + else + next = build_constructor (NULL_TREE, NULL); + next = digest_init (TREE_TYPE (type), next); + } + else if (!zero_init_p (TREE_TYPE (type))) + next = build_zero_init (TREE_TYPE (type), + /*nelts=*/NULL_TREE, + /*static_storage_p=*/false); + else + /* The default zero-initialization is fine for us; don't + add anything to the CONSTRUCTOR. */ + break; - If INIT is specified, it is a CONSTRUCTOR node which is specifically - and solely for initializing this datum. + flags |= picflag_from_initializer (next); + CONSTRUCTOR_APPEND_ELT (v, size_int (i), next); + } - If ELTS is specified, it is the address of a variable containing - a list of expressions. We take as many elements as we need - from the head of the list and update the list. + CONSTRUCTOR_ELTS (init) = v; + return flags; +} - In the resulting constructor, TREE_CONSTANT is set if all elts are - constant, and TREE_STATIC is set if, in addition, all elts are simple enough - constants that the assembler and linker can compute them. */ +/* Subroutine of process_init_constructor, which will process an initializer + INIT for a class of type TYPE. Returns the flags (PICFLAG_*) which describe + the initializers. */ -static tree -process_init_constructor (tree type, tree init, tree* elts) +static int +process_init_constructor_record (tree type, tree init) { - tree tail; - /* List of the elements of the result constructor, - in reverse order. */ - tree members = NULL; - tree next1; - tree result; - int allconstant = 1; - int allsimple = 1; - int erroneous = 0; - - /* Make TAIL be the list of elements to use for the initialization, - no matter how the data was given to us. */ - - if (elts) - { - if (warn_missing_braces) - warning (0, "aggregate has a partly bracketed initializer"); - tail = *elts; - } - else - tail = CONSTRUCTOR_ELTS (init); - - /* Gobble as many elements as needed, and make a constructor or initial value - for each element of this aggregate. Chain them together in result. - If there are too few, use 0 for each scalar ultimate component. */ - - if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE) + VEC(constructor_elt,gc) *v = NULL; + int flags = 0; + tree field; + unsigned HOST_WIDE_INT idx = 0; + + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + gcc_assert (!CLASSTYPE_VBASECLASSES (type)); + gcc_assert (!TYPE_BINFO (type) + || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type))); + gcc_assert (!TYPE_POLYMORPHIC_P (type)); + + /* Generally, we will always have an index for each initializer (which is + a FIELD_DECL, put by reshape_init), but compound literals don't go trough + reshape_init. So we need to handle both cases. */ + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { - long len; - int i; + tree next; - if (TREE_CODE (type) == ARRAY_TYPE) + if (!DECL_NAME (field) && DECL_C_BIT_FIELD (field)) { - tree domain = TYPE_DOMAIN (type); - if (domain) - len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)) - - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)) - + 1); - else - len = -1; /* Take as many as there are. */ - } - else - { - /* Vectors are like simple fixed-size arrays. */ - len = TYPE_VECTOR_SUBPARTS (type); + flags |= picflag_from_initializer (integer_zero_node); + CONSTRUCTOR_APPEND_ELT (v, field, integer_zero_node); + continue; } - for (i = 0; len < 0 || i < len; i++) + if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) + continue; + + if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init))) { - if (tail) + constructor_elt *ce = VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (init), idx); + if (ce->index) { - if (TREE_PURPOSE (tail) - && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST - || compare_tree_int (TREE_PURPOSE (tail), i) != 0)) - sorry ("non-trivial labeled initializers"); - - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; - next1 = digest_init (TREE_TYPE (type), - TREE_VALUE (tail), &tail1); - if (next1 == error_mark_node) - return next1; - gcc_assert (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (type), TREE_TYPE (next1))); - gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST); - if (tail == tail1 && len < 0) - { - error ("non-empty initializer for array of empty elements"); - /* Just ignore what we were supposed to use. */ - tail1 = NULL_TREE; - } - tail = tail1; - } - else - { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); - } + /* We can have either a FIELD_DECL or an IDENTIFIER_NODE. The + latter case can happen in templates where lookup has to be + deferred. */ + gcc_assert (TREE_CODE (ce->index) == FIELD_DECL + || TREE_CODE (ce->index) == IDENTIFIER_NODE); + if (ce->index != field + && ce->index != DECL_NAME (field)) + sorry ("non-trivial designated initializers not supported"); } - else if (len < 0) - /* We're done. */ - break; - else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) - { - /* If this type needs constructors run for - default-initialization, we can't rely on the backend to do it - for us, so build up TARGET_EXPRs. If the type in question is - a class, just build one up; if it's an array, recurse. */ - if (IS_AGGR_TYPE (TREE_TYPE (type))) - next1 = build_functional_cast (TREE_TYPE (type), NULL_TREE); - else - next1 = build_constructor (NULL_TREE, NULL_TREE); - next1 = digest_init (TREE_TYPE (type), next1, 0); - } - else if (! zero_init_p (TREE_TYPE (type))) - next1 = build_zero_init (TREE_TYPE (type), - /*nelts=*/NULL_TREE, - /*static_storage_p=*/false); + gcc_assert (ce->value); + next = digest_init (TREE_TYPE (field), ce->value); + ++idx; + } + else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) + { + /* If this type needs constructors run for + default-initialization, we can't rely on the backend to do it + for us, so build up TARGET_EXPRs. If the type in question is + a class, just build one up; if it's an array, recurse. */ + if (IS_AGGR_TYPE (TREE_TYPE (field))) + next = build_functional_cast (TREE_TYPE (field), NULL_TREE); + else + next = build_constructor (NULL_TREE, NULL); + + next = digest_init (TREE_TYPE (field), next); + + /* Warn when some struct elements are implicitly initialized. */ + warning (OPT_Wmissing_field_initializers, + "missing initializer for member %qD", field); + } + else + { + if (TREE_READONLY (field)) + error ("uninitialized const member %qD", field); + else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field))) + error ("member %qD with uninitialized const fields", field); + else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) + error ("member %qD is uninitialized reference", field); + + /* Warn when some struct elements are implicitly initialized + to zero. */ + warning (OPT_Wmissing_field_initializers, + "missing initializer for member %qD", field); + + if (!zero_init_p (TREE_TYPE (field))) + next = build_zero_init (TREE_TYPE (field), /*nelts=*/NULL_TREE, + /*static_storage_p=*/false); else /* The default zero-initialization is fine for us; don't - add anything to the CONSTRUCTOR. */ - break; - - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) - allsimple = 0; - members = tree_cons (size_int (i), next1, members); + add anything to the CONSTRUCTOR. */ + continue; } + + flags |= picflag_from_initializer (next); + CONSTRUCTOR_APPEND_ELT (v, field, next); } - else if (TREE_CODE (type) == RECORD_TYPE) - { - tree field; - if (tail) - { - gcc_assert (!CLASSTYPE_VBASECLASSES (type)); - gcc_assert (!TYPE_BINFO (type) - || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type))); - gcc_assert (!TYPE_POLYMORPHIC_P (type)); - } + CONSTRUCTOR_ELTS (init) = v; + return flags; +} - for (field = TYPE_FIELDS (type); field; - field = TREE_CHAIN (field)) - { - if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field)) - { - members = tree_cons (field, integer_zero_node, members); - continue; - } +/* Subroutine of process_init_constructor, which will process a single + initializer INIT for an union of type TYPE. Returns the flags (PICFLAG_*) + which describe the initializer. */ - if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) - continue; +static int +process_init_constructor_union (tree type, tree init) +{ + constructor_elt *ce; - if (tail) - { - if (TREE_PURPOSE (tail) - && TREE_PURPOSE (tail) != field - && TREE_PURPOSE (tail) != DECL_NAME (field)) - sorry ("non-trivial labeled initializers"); - - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; - - next1 = digest_init (TREE_TYPE (field), - TREE_VALUE (tail), &tail1); - gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST); - tail = tail1; - } - else - { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); - } - } - else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) - { - /* If this type needs constructors run for - default-initialization, we can't rely on the backend to do it - for us, so build up TARGET_EXPRs. If the type in question is - a class, just build one up; if it's an array, recurse. */ - - if (IS_AGGR_TYPE (TREE_TYPE (field))) - next1 = build_functional_cast (TREE_TYPE (field), - NULL_TREE); - else - { - next1 = build_constructor (NULL_TREE, NULL_TREE); - if (init) - TREE_HAS_CONSTRUCTOR (next1) - = TREE_HAS_CONSTRUCTOR (init); - } - next1 = digest_init (TREE_TYPE (field), next1, 0); - - /* Warn when some struct elements are implicitly initialized. */ - if (warn_missing_field_initializers - && (!init || BRACE_ENCLOSED_INITIALIZER_P (init))) - warning (0, "missing initializer for member %qD", field); - } - else + /* If the initializer was empty, use default zero initialization. */ + if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init))) + return 0; + + gcc_assert (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) == 1); + ce = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (init), 0); + + /* If this element specifies a field, initialize via that field. */ + if (ce->index) + { + if (TREE_CODE (ce->index) == FIELD_DECL) + ; + else if (TREE_CODE (ce->index) == IDENTIFIER_NODE) + { + /* This can happen within a cast, see g++.dg/opt/cse2.C. */ + tree name = ce->index; + tree field; + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (DECL_NAME (field) == name) + break; + if (!field) { - if (TREE_READONLY (field)) - error ("uninitialized const member %qD", field); - else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field))) - error ("member %qD with uninitialized const fields", field); - else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) - error ("member %qD is uninitialized reference", field); - - /* Warn when some struct elements are implicitly initialized - to zero. */ - if (warn_missing_field_initializers - && (!init || BRACE_ENCLOSED_INITIALIZER_P (init))) - warning (0, "missing initializer for member %qD", field); - - if (! zero_init_p (TREE_TYPE (field))) - next1 = build_zero_init (TREE_TYPE (field), - /*nelts=*/NULL_TREE, - /*static_storage_p=*/false); - else - /* The default zero-initialization is fine for us; don't - add anything to the CONSTRUCTOR. */ - continue; + error ("no field %qD found in union being initialized", field); + ce->value = error_mark_node; } - - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) - allsimple = 0; - members = tree_cons (field, next1, members); + ce->index = field; + } + else + { + gcc_assert (TREE_CODE (ce->index) == INTEGER_CST + || TREE_CODE (ce->index) == RANGE_EXPR); + error ("index value instead of field name in union initializer"); + ce->value = error_mark_node; } } - else if (TREE_CODE (type) == UNION_TYPE - /* If the initializer was empty, use default zero initialization. */ - && tail) + else { - tree field = TYPE_FIELDS (type); - /* Find the first named field. ANSI decided in September 1990 that only named fields count here. */ + tree field = TYPE_FIELDS (type); while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL)) field = TREE_CHAIN (field); - - /* If this element specifies a field, initialize via that field. */ - if (TREE_PURPOSE (tail) != NULL_TREE) - { - int win = 0; - - if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL) - /* Handle the case of a call by build_c_cast. */ - field = TREE_PURPOSE (tail), win = 1; - else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE) - error ("index value instead of field name in union initializer"); - else - { - tree temp; - for (temp = TYPE_FIELDS (type); - temp; - temp = TREE_CHAIN (temp)) - if (DECL_NAME (temp) == TREE_PURPOSE (tail)) - break; - if (temp) - field = temp, win = 1; - else - error ("no field %qD in union being initialized", - TREE_PURPOSE (tail)); - } - if (!win) - TREE_VALUE (tail) = error_mark_node; - } - else if (field == 0) + if (!field) { error ("union %qT with no named members cannot be initialized", type); - TREE_VALUE (tail) = error_mark_node; + ce->value = error_mark_node; } + ce->index = field; + } - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; + if (ce->value && ce->value != error_mark_node) + ce->value = digest_init (TREE_TYPE (ce->index), ce->value); - next1 = digest_init (TREE_TYPE (field), - TREE_VALUE (tail), &tail1); - gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST); - tail = tail1; - } - else - { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); - } + return picflag_from_initializer (ce->value); +} - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) - allsimple = 0; - members = tree_cons (field, next1, members); - } +/* Process INIT, a constructor for a variable of aggregate type TYPE. The + constructor is a brace-enclosed initializer, and will be modified in-place. + + Each element is converted to the right type through digest_init, and + missing initializers are added following the language rules (zero-padding, + etc.). - /* If arguments were specified as a list, just remove the ones we used. */ - if (elts) - *elts = tail; - /* If arguments were specified as a constructor, - complain unless we used all the elements of the constructor. */ - else if (tail) - pedwarn ("excess elements in aggregate initializer"); + After the execution, the initializer will have TREE_CONSTANT if all elts are + constant, and TREE_STATIC set if, in addition, all elts are simple enough + constants that the assembler and linker can compute them. + + The function returns the initializer itself, or error_mark_node in case + of error. */ + +static tree +process_init_constructor (tree type, tree init) +{ + int flags; + + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); + + if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE) + flags = process_init_constructor_array (type, init); + else if (TREE_CODE (type) == RECORD_TYPE) + flags = process_init_constructor_record (type, init); + else if (TREE_CODE (type) == UNION_TYPE) + flags = process_init_constructor_union (type, init); + else + gcc_unreachable (); - if (erroneous) + if (flags & PICFLAG_ERRONEOUS) return error_mark_node; - result = build_constructor (type, nreverse (members)); + TREE_TYPE (init) = type; if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE) - cp_complete_array_type (&TREE_TYPE (result), result, /*do_default=*/0); - if (init) - TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init); - if (allconstant) + cp_complete_array_type (&TREE_TYPE (init), init, /*do_default=*/0); + if (!(flags & PICFLAG_NOT_ALL_CONSTANT)) { - TREE_CONSTANT (result) = 1; - TREE_INVARIANT (result) = 1; - if (allsimple) - TREE_STATIC (result) = 1; + TREE_CONSTANT (init) = 1; + TREE_INVARIANT (init) = 1; + if (!(flags & PICFLAG_NOT_ALL_SIMPLE)) + TREE_STATIC (init) = 1; } - return result; + return init; } /* Given a structure or union value DATUM, construct and return @@ -1396,7 +1329,7 @@ build_functional_cast (tree exp, tree parms) if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type) && TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) { - exp = build_constructor (type, NULL_TREE); + exp = build_constructor (type, NULL); return get_target_expr (exp); } |