aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorGiovanni Bajo <giovannibajo@libero.it>2005-07-20 03:19:59 +0200
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>2005-07-20 01:19:59 +0000
commit4038c495fc9685efdb400b36848627daab979e78 (patch)
treecee4baf52782472c6ce30e28249d2a5df154551f /gcc/cp
parentf37d7c6065a4f64b7af059bc8cbd05c3e7f2e9cf (diff)
downloadgcc-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/ChangeLog51
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/class.c10
-rw-r--r--gcc/cp/cp-tree.h11
-rw-r--r--gcc/cp/decl.c499
-rw-r--r--gcc/cp/decl2.c48
-rw-r--r--gcc/cp/error.c21
-rw-r--r--gcc/cp/init.c56
-rw-r--r--gcc/cp/parser.c23
-rw-r--r--gcc/cp/pt.c40
-rw-r--r--gcc/cp/rtti.c16
-rw-r--r--gcc/cp/semantics.c6
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/cp/typeck.c8
-rw-r--r--gcc/cp/typeck2.c767
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);
}