static tree process_init_constructor ();
static tree convert_arguments ();
static char *get_spelling ();
-tree digest_init ();
+static tree digest_init ();
static void pedantic_lvalue_warning ();
tree truthvalue_conversion ();
void incomplete_type_error ();
void readonly_warning ();
static tree internal_build_compound_expr ();
+void process_init_element ();
\f
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) */
(That is true for all nested calls to digest_init.) */
tree
-digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
+digest_init (type, init, tail, require_constant, constructor_constant)
tree type, init, *tail;
int require_constant, constructor_constant;
- char *ofwhat;
{
enum tree_code code = TREE_CODE (type);
tree element = 0;
tree old_tail_contents;
- /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
- tree node which has no TREE_TYPE. */
- int raw_constructor
- = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
tree inside_init = init;
- /* Make sure there is just one "partially bracketed" message
- per top-level initializer or constructor. */
- if (ofwhat != 0)
- partial_bracket_mentioned = 0;
-
/* By default, assume we use one element from a list.
We correct this later in the cases where it is not true.
if (TREE_CODE (init) == NON_LVALUE_EXPR)
inside_init = TREE_OPERAND (init, 0);
- if (inside_init && raw_constructor
- && CONSTRUCTOR_ELTS (inside_init) != 0
- && TREE_CHAIN (CONSTRUCTOR_ELTS (inside_init)) == 0)
- {
- element = TREE_VALUE (CONSTRUCTOR_ELTS (inside_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);
- }
-
/* Initialization of an array of chars from a string constant
optionally enclosed in braces. */
&& TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
{
error_init ("char-array%s initialized from wide string",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
&& TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
{
error_init ("int-array%s initialized from non-wide string",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
: 1))
pedwarn_init (
"initializer-string for array of chars%s is too long",
- " `%s'", ofwhat);
+ " `%s'", NULL);
}
return string;
}
}
- /* Any type except an array can be initialized
- from an expression of the same type, optionally with braces.
- For an array, this is allowed only for a string constant. */
+ /* Any type can be initialized
+ from an expression of the same type, optionally with braces. */
if (inside_init && TREE_TYPE (inside_init) != 0
&& ((TYPE_MAIN_VARIANT (TREE_TYPE (inside_init))
&& (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE))
inside_init = default_conversion (inside_init);
- else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST)
+ else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
+ && TREE_CODE (inside_init) != CONSTRUCTOR)
{
error_init ("array%s initialized from non-constant array expression",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
if (require_constant && ! TREE_CONSTANT (inside_init))
{
error_init ("initializer element%s is not constant",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
inside_init = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
error_init ("initializer element%s is not computable at load time",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
inside_init = error_mark_node;
}
if (code == ARRAY_TYPE)
{
error_init ("array%s initialized from non-constant array expression",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE))
if (require_constant && ! TREE_CONSTANT (element))
{
error_init ("initializer element%s is not constant",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
element = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (element, TREE_TYPE (element)) == 0)
{
error_init ("initializer element%s is not computable at load time",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
element = error_mark_node;
}
return element;
}
- /* Check for initializing a union by its first field.
- Such an initializer must use braces. */
-
- if (code == UNION_TYPE)
- {
- tree result;
- tree field = TYPE_FIELDS (type);
-
- /* Find the first named field. ANSI decided in September 1990
- that only named fields count here. */
- while (field && DECL_NAME (field) == 0)
- field = TREE_CHAIN (field);
-
- if (field == 0)
- {
- error_init ("union%s with no named members cannot be initialized",
- " `%s'", ofwhat);
- return error_mark_node;
- }
-
- if (raw_constructor)
- result = process_init_constructor (type, inside_init, NULL_PTR,
- require_constant,
- constructor_constant, ofwhat);
- else if (tail != 0)
- {
- *tail = old_tail_contents;
- free_tree_list = NULL_TREE;
- result = process_init_constructor (type, NULL_TREE, tail,
- require_constant,
- constructor_constant, ofwhat);
- }
- else
- result = 0;
-
- if (result)
- return result;
- }
-
/* Handle scalar types, including conversions. */
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == COMPLEX_TYPE)
{
- if (raw_constructor)
- {
- if (element == 0)
- {
- error_init (
- "initializer for scalar%s requires one element",
- " `%s'", ofwhat);
- return error_mark_node;
- }
- else
- {
- /* Deal with extra levels of {...}. */
- if (TREE_CODE (element) == CONSTRUCTOR
- && TREE_TYPE (element) == 0)
- {
- error_init (
- "initializer for scalar%s requires one element",
- " `%s'", ofwhat);
- return error_mark_node;
- }
- inside_init = element;
- }
- }
-
-#if 0 /* A non-raw constructor is an actual expression. */
- if (TREE_CODE (inside_init) == CONSTRUCTOR)
- {
- error_init ("initializer for scalar%s has extra braces",
- " `%s'", ofwhat);
- return error_mark_node;
- }
-#endif
-
SAVE_SPELLING_DEPTH
({
- if (ofwhat)
- push_string (ofwhat);
- if (!raw_constructor)
- inside_init = init;
/* Note that convert_for_assignment calls default_conversion
for arrays and functions. We must not call it in the
case where inside_init is a null pointer constant. */
inside_init
- = convert_for_assignment (type, inside_init,
+ = convert_for_assignment (type, init,
&initialization_message,
NULL_TREE, NULL_TREE, 0);
});
if (require_constant && ! TREE_CONSTANT (inside_init))
{
error_init ("initializer element%s is not constant",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
inside_init = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
error_init ("initializer element%s is not computable at load time",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
inside_init = error_mark_node;
}
if (TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
error_init ("variable-sized object%s may not be initialized",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
- if (code == ARRAY_TYPE || code == RECORD_TYPE)
- {
- if (raw_constructor)
- return process_init_constructor (type, inside_init,
- NULL_PTR, constructor_constant,
- constructor_constant, ofwhat);
- else if (tail != 0)
- {
- *tail = old_tail_contents;
- free_tree_list = NULL_TREE;
- return process_init_constructor (type, NULL_TREE, tail,
- constructor_constant,
- constructor_constant, ofwhat);
- }
- else if (flag_traditional)
- /* Traditionally one can say `char x[100] = 0;'. */
- return process_init_constructor (type,
- build_nt (CONSTRUCTOR, NULL_TREE,
- tree_cons (NULL_TREE,
- inside_init,
- NULL_TREE)),
- NULL_PTR, constructor_constant,
- constructor_constant, ofwhat);
- }
-
- error_init ("invalid initializer%s", " for `%s'", ofwhat);
+ error_init ("invalid initializer%s", " for `%s'", NULL);
return error_mark_node;
}
\f
-/* Process a constructor for a variable of type TYPE.
- The constructor elements may be specified either with INIT or with ELTS,
- only one of which should be non-null.
+/* Handle initializers that use braces. */
- If INIT is specified, it is a CONSTRUCTOR node which is specifically
- and solely for initializing this datum.
+static void output_pending_init_elements ();
+static void check_init_type_bitfields ();
- 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.
+/* Type of object we are accumulating a constructor for.
+ This type is always a RECORD_TYPE, UNION_TYPE or ARRAY_TYPE. */
+static tree constructor_type;
- 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.
+/* For a RECORD_TYPE or UNION_TYPE, this is the chain of fields
+ left to fill. */
+static tree constructor_fields;
- The argument CONSTANT_VALUE says to print an error if either the
- value or any element is not a constant.
+/* For an ARRAY_TYPE, this is the specified index
+ at which to store the next element we get.
+ This is a special INTEGER_CST node that we modify in place. */
+static tree constructor_index;
- The argument CONSTANT_ELEMENT says to print an error if an element
- of an aggregate is not constant. It does not apply to a value
- which is not a constructor.
+/* For an ARRAY_TYPE, this is the end index of the range
+ to intitialize with the next element, or NULL in the ordinary case
+ where the element is used just once. */
+static tree constructor_range_end;
- OFWHAT is a character string describing the object being initialized,
- for error messages. It might be "variable" or "variable.member"
- or "variable[17].member[5]".
+/* For an ARRAY_TYPE, this is the maximum index. */
+static tree constructor_max_index;
- If OFWHAT is null, the description string is stored on the spelling
- stack. That is always true for recursive calls. */
+/* For a RECORD_TYPE, this is the first field not yet written out. */
+static tree constructor_unfilled_fields;
-static tree
-process_init_constructor (type, init, elts, constant_value, constant_element,
- ofwhat)
- tree type, init, *elts;
- int constant_value, constant_element;
- char *ofwhat;
+/* For an ARRAY_TYPE, this is the index of the first element
+ not yet written out.
+ This is a special INTEGER_CST node that we modify in place. */
+static tree constructor_unfilled_index;
+
+/* If we are saving up the elements rather than allocating them,
+ this is the list of elements so far (in reverse order,
+ most recent first). */
+static tree constructor_elements;
+
+/* 1 if so far this constructor's elements are all compile-time constants. */
+static int constructor_constant;
+
+/* 1 if so far this constructor's elements are all valid address constants. */
+static int constructor_simple;
+
+/* 1 if this constructor is erroneous so far. */
+static int constructor_erroneous;
+
+/* 1 if have called defer_addressed_constants. */
+static int constructor_subconstants_deferred;
+
+/* List of pending elements at this constructor level.
+ These are elements encountered out of order
+ which belong at places we haven't reached yet in actually
+ writing the output. */
+static tree constructor_pending_elts;
+
+/* The SPELLING_DEPTH of this constructor. */
+static int constructor_depth;
+
+/* 1 if this constructor level was entered implicitly. */
+static int constructor_implicit;
+
+static int require_constant_value;
+static int require_constant_elements;
+
+/* 1 if it is ok to output this constructor as we read it.
+ 0 means must accumulate a CONSTRUCTOR expression. */
+static int constructor_incremental;
+
+/* DECL node for which an initializer is being read.
+ 0 means we are reading a constructor expression
+ such as (struct foo) {...}. */
+static tree constructor_decl;
+
+/* start_init saves the ASMSPEC arg here for really_start_incremental_init. */
+static char *constructor_asmspec;
+
+/* Nonzero if this is an initializer for a top-level decl. */
+static int constructor_top_level;
+
+/* When we finish reading a constructor expression
+ (constructor_decl is 0), the CONSTRUCTOR goes here. */
+static tree constructor_result;
+
+struct constructor_stack
{
- register tree tail;
- /* List of the elements of the result constructor,
- in reverse order. */
- register tree members = NULL;
- tree result;
- int allconstant = 1;
- int allsimple = 1;
- int erroneous = 0;
- int depth = SPELLING_DEPTH ();
+ struct constructor_stack *next;
+ tree type;
+ tree fields;
+ tree index;
+ tree range_end;
+ tree max_index;
+ tree unfilled_index;
+ tree unfilled_fields;
+ tree elements;
+ int offset;
+ tree pending_elts;
+ int depth;
+ char constant;
+ char simple;
+ char implicit;
+ char incremental;
+ char erroneous;
+ char outer;
+};
- if (ofwhat)
- push_string (ofwhat);
+struct constructor_stack *constructor_stack;
- /* Make TAIL be the list of elements to use for the initialization,
- no matter how the data was given to us. */
+/* This stack records separate initializers that are nested.
+ Nested initializers can't happen in ANSI C, but GNU C allows them
+ in cases like { ... (struct foo) { ... } ... }. */
- if (elts)
+struct initializer_stack
+{
+ struct initializer_stack *next;
+ tree decl;
+ char *asmspec;
+ struct constructor_stack *constructor_stack;
+ struct spelling *spelling;
+ struct spelling *spelling_base;
+ int spelling_size;
+ char top_level;
+ char incremental;
+ char require_constant_value;
+ char require_constant_elements;
+ char deferred;
+};
+
+struct initializer_stack *initializer_stack;
+\f
+/* Prepare to parse and output the initializer for variable DECL. */
+
+void
+start_init (decl, asmspec, top_level)
+ tree decl;
+ char *asmspec;
+ int top_level;
+{
+ char *locus;
+ struct initializer_stack *p
+ = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
+
+ p->decl = constructor_decl;
+ p->asmspec = constructor_asmspec;
+ p->incremental = constructor_incremental;
+ p->require_constant_value = require_constant_value;
+ p->require_constant_elements = require_constant_elements;
+ p->constructor_stack = constructor_stack;
+ p->spelling = spelling;
+ p->spelling_base = spelling_base;
+ p->spelling_size = spelling_size;
+ p->deferred = constructor_subconstants_deferred;
+ p->top_level = constructor_top_level;
+ p->next = 0;
+ initializer_stack = p;
+
+ constructor_decl = decl;
+ constructor_incremental = top_level;
+ constructor_asmspec = asmspec;
+ constructor_subconstants_deferred = 0;
+ constructor_top_level = top_level;
+
+ if (decl != 0)
{
- if (warn_missing_braces)
- {
- if (! partial_bracket_mentioned)
- warning ("aggregate has a partly bracketed initializer");
- partial_bracket_mentioned = 1;
- }
- tail = *elts;
+ require_constant_value = TREE_STATIC (decl);
+ require_constant_elements = TREE_STATIC (decl) || pedantic;
+ locus = IDENTIFIER_POINTER (DECL_NAME (decl));
+ constructor_incremental |= TREE_STATIC (decl);
}
else
- tail = CONSTRUCTOR_ELTS (init);
+ {
+ require_constant_value = 0;
+ require_constant_elements = 0;
+ locus = "(anonymous)";
+ }
- /* 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. */
+ constructor_stack = 0;
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree min_index, max_index;
- /* These are non-zero only within a range initializer. */
- tree start_index = 0, end_index = 0;
- /* Within a range, this is the value for the elts in the range. */
- tree range_val = 0;
- /* Do arithmetic using double integers, but don't use fold/build,
- because these allocate a new tree object everytime they are called,
- thus resulting in gcc using too much memory for large
- initializers. */
- union tree_node current_index_node, members_index_node;
- tree current_index = ¤t_index_node;
- tree members_index = &members_index_node;
- TREE_TYPE (current_index) = integer_type_node;
- TREE_TYPE (members_index) = integer_type_node;
-
- /* If we have array bounds, set our bounds from that. Otherwise,
- we have a lower bound of zero and an unknown upper bound. */
- if (TYPE_DOMAIN (type))
- {
- min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
- max_index = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
- }
- else
- {
- min_index = integer_zero_node;
- max_index = 0;
- }
+ spelling_base = 0;
+ spelling_size = 0;
+ RESTORE_SPELLING_DEPTH (0);
- TREE_INT_CST_LOW (members_index) = TREE_INT_CST_LOW (min_index);
- TREE_INT_CST_HIGH (members_index) = TREE_INT_CST_HIGH (min_index);
+ if (locus)
+ push_string (locus);
+}
- /* Don't leave the loop based on index if the next item has an explicit
- index value that will override it. */
+void
+finish_init ()
+{
+ struct initializer_stack *p = initializer_stack;
- for (TREE_INT_CST_LOW (current_index) = TREE_INT_CST_LOW (min_index),
- TREE_INT_CST_HIGH (current_index) = TREE_INT_CST_HIGH (min_index);
- tail != 0 || end_index;
- add_double (TREE_INT_CST_LOW (current_index),
- TREE_INT_CST_HIGH (current_index), 1, 0,
- &TREE_INT_CST_LOW (current_index),
- &TREE_INT_CST_HIGH (current_index)))
- {
- register tree next1 = 0;
+ /* Output subconstants (string constants, usually)
+ that were referenced within this initializer and saved up.
+ Must do this if and only if we called defer_addressed_constants. */
+ if (constructor_subconstants_deferred)
+ output_deferred_addressed_constants ();
- /* Handle the case where we are inside of a range.
- current_index increments through the range,
- so just keep reusing the same element of TAIL
- until the end of the range. */
- if (end_index != 0)
- {
- next1 = range_val;
- if (!tree_int_cst_lt (current_index, end_index))
- end_index = 0;
- }
+ /* Free the whole constructor stack of this initializer. */
+ while (constructor_stack)
+ {
+ struct constructor_stack *q = constructor_stack;
+ constructor_stack = q->next;
+ free (q);
+ }
- /* If this element specifies an index,
- move to that index before storing it in the new list. */
- else if (TREE_PURPOSE (tail) != 0)
- {
- int win = 0;
- tree index = TREE_PURPOSE (tail);
+ /* Pop back to the data of the outer initializer (if any). */
+ constructor_decl = p->decl;
+ constructor_asmspec = p->asmspec;
+ constructor_incremental = p->incremental;
+ require_constant_value = p->require_constant_value;
+ require_constant_elements = p->require_constant_elements;
+ constructor_stack = p->constructor_stack;
+ spelling = p->spelling;
+ spelling_base = p->spelling_base;
+ spelling_size = p->spelling_size;
+ constructor_subconstants_deferred = p->deferred;
+ constructor_top_level = p->top_level;
+ initializer_stack = p->next;
+ free (p);
+}
+\f
+/* Call here when we see the initializer is surrounded by braces.
+ This is instead of a call to push_init_level;
+ it is matched by a call to pop_init_level.
- if (index && (TREE_CODE (index) == NON_LVALUE_EXPR
- || TREE_CODE (index) == NOP_EXPR))
- index = TREE_OPERAND (index, 0);
+ TYPE is the type to initialize, for a constructor expression.
+ For an initializer for a decl, TYPE is zero. */
- /* Begin a range. */
- if (TREE_CODE (index) == TREE_LIST)
- {
- start_index = TREE_PURPOSE (index);
- end_index = TREE_PURPOSE (TREE_CHAIN (index));
-
- /* Expose constants. It Doesn't matter if we change
- the mode.*/
- if (end_index
- && (TREE_CODE (end_index) == NON_LVALUE_EXPR
- || TREE_CODE (end_index) == NOP_EXPR))
- end_index = TREE_OPERAND (end_index, 0);
- if (start_index
- && (TREE_CODE (start_index) == NON_LVALUE_EXPR
- || TREE_CODE (start_index) == NOP_EXPR))
- start_index = TREE_OPERAND (start_index, 0);
-
- constant_expression_warning (start_index);
- constant_expression_warning (end_index);
-
- if ((TREE_CODE (start_index) == IDENTIFIER_NODE)
- || (TREE_CODE (end_index) == IDENTIFIER_NODE))
- error ("field name used as index in array initializer");
- else if ((TREE_CODE (start_index) != INTEGER_CST)
- || (TREE_CODE (end_index) != INTEGER_CST))
- error ("non-constant or non-integer array index in initializer");
- else if (tree_int_cst_lt (start_index, min_index)
- || (max_index && tree_int_cst_lt (max_index, start_index))
- || tree_int_cst_lt (end_index, min_index)
- || (max_index && tree_int_cst_lt (max_index, end_index)))
- error ("array index out of range in initializer");
- else if (tree_int_cst_lt (end_index, start_index))
- {
- /* If the range is empty, don't initialize any elements,
- but do reset current_index for the next initializer
- element. */
- warning ("empty array initializer range");
- tail = TREE_CHAIN (tail);
- TREE_INT_CST_LOW (current_index)
- = TREE_INT_CST_LOW (end_index);
- TREE_INT_CST_HIGH (current_index)
- = TREE_INT_CST_HIGH (end_index);
- continue;
- }
- else
- {
- TREE_INT_CST_LOW (current_index)
- = TREE_INT_CST_LOW (start_index);
- TREE_INT_CST_HIGH (current_index)
- = TREE_INT_CST_HIGH (start_index);
- win = 1;
- /* See if the first element is also the last. */
- if (!tree_int_cst_lt (current_index, end_index))
- end_index = 0;
- }
- }
- else if (TREE_CODE (index) == IDENTIFIER_NODE)
- error ("field name used as index in array initializer");
- else if (TREE_CODE (index) != INTEGER_CST)
- error ("non-constant array index in initializer");
- else if (tree_int_cst_lt (index, min_index)
- || (max_index && tree_int_cst_lt (max_index, index)))
- error ("array index out of range in initializer");
- else
- {
- constant_expression_warning (index);
- TREE_INT_CST_LOW (current_index) = TREE_INT_CST_LOW (index);
- TREE_INT_CST_HIGH (current_index)
- = TREE_INT_CST_HIGH (index);
- win = 1;
- }
+void
+really_start_incremental_init (type)
+ tree type;
+{
+ struct constructor_stack *p
+ = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
+
+ if (type == 0)
+ type = TREE_TYPE (constructor_decl);
+
+ /* Turn off constructor_incremental if type is a struct with bitfields.
+ Do this before the first push, so that the corrected value
+ is available in finish_init. */
+ check_init_type_bitfields (type);
+
+ p->type = constructor_type;
+ p->fields = constructor_fields;
+ p->index = constructor_index;
+ p->range_end = constructor_range_end;
+ p->max_index = constructor_max_index;
+ p->unfilled_index = constructor_unfilled_index;
+ p->unfilled_fields = constructor_unfilled_fields;
+ p->elements = 0;
+ p->constant = constructor_constant;
+ p->simple = constructor_simple;
+ p->erroneous = constructor_erroneous;
+ p->pending_elts = constructor_pending_elts;
+ p->depth = constructor_depth;
+ p->implicit = 0;
+ p->incremental = constructor_incremental;
+ p->outer = 0;
+ p->next = 0;
+ constructor_stack = p;
+
+ constructor_constant = 1;
+ constructor_simple = 1;
+ constructor_depth = SPELLING_DEPTH ();
+ constructor_elements = 0;
+ constructor_pending_elts = 0;
+ constructor_type = type;
+
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ constructor_fields = TYPE_FIELDS (constructor_type);
+ constructor_unfilled_fields = constructor_fields;
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ constructor_index = copy_node (integer_zero_node);
+ constructor_range_end = 0;
+ constructor_unfilled_index = copy_node (integer_zero_node);
+ if (TYPE_DOMAIN (constructor_type))
+ constructor_max_index
+ = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+ }
+ else
+ {
+ /* Handle the case of int x = {5}; */
+ constructor_fields = constructor_type;
+ constructor_unfilled_fields = constructor_type;
+ }
- if (!win)
- {
- /* If there was an error, end the current range. */
- end_index = 0;
- TREE_VALUE (tail) = error_mark_node;
- }
- }
+ if (constructor_incremental)
+ {
+ int momentary = suspend_momentary ();
+ push_obstacks_nochange ();
+ if (TREE_PERMANENT (constructor_decl))
+ end_temporary_allocation ();
+ make_decl_rtl (constructor_decl, constructor_asmspec,
+ constructor_top_level);
+ assemble_variable (constructor_decl, constructor_top_level, 0, 1);
+ pop_obstacks ();
+ resume_momentary (momentary);
+ }
- if (max_index && tree_int_cst_lt (max_index, current_index))
- break; /* Stop if we've indeed run out of elements. */
+ if (constructor_incremental)
+ {
+ defer_addressed_constants ();
+ constructor_subconstants_deferred = 1;
+ }
+}
+\f
+/* Push down into a subobject, for initialization.
+ If this is for an explicit set of braces, IMPLICIT is 0.
+ If it is because the next element belongs at a lower level,
+ IMPLICIT is 1. */
- /* Now digest the value specified. */
- if (next1 != 0)
- ;
- else if (TREE_VALUE (tail) != 0)
- {
- tree tail1 = tail;
-
- /* Build the element of this array, with "[]" notation. For
- error messages, we assume that the index fits within a
- host int. */
- SAVE_SPELLING_DEPTH
- ({
- push_array_bounds (TREE_INT_CST_LOW (current_index));
- next1 = digest_init (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
- TREE_VALUE (tail), &tail1,
- /* Both of these are the same because
- a value here is an elt overall. */
- constant_element, constant_element,
- NULL_PTR);
- });
-
- if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
- abort ();
- if (tail == tail1 && TYPE_DOMAIN (type) == 0)
- {
- error_init (
- "non-empty initializer for array%s of empty elements",
- " `%s'", NULL_PTR);
- /* Just ignore what we were supposed to use. */
- tail1 = 0;
- }
- tail = tail1;
- }
- else
- {
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
- }
+void
+push_init_level (implicit)
+ int implicit;
+{
+ struct constructor_stack *p
+ = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
+ p->type = constructor_type;
+ p->fields = constructor_fields;
+ p->index = constructor_index;
+ p->range_end = constructor_range_end;
+ p->max_index = constructor_max_index;
+ p->unfilled_index = constructor_unfilled_index;
+ p->unfilled_fields = constructor_unfilled_fields;
+ p->elements = constructor_elements;
+ p->constant = constructor_constant;
+ p->simple = constructor_simple;
+ p->erroneous = constructor_erroneous;
+ p->pending_elts = constructor_pending_elts;
+ p->depth = constructor_depth;
+ p->implicit = implicit;
+ p->incremental = constructor_incremental;
+ p->outer = 0;
+ p->next = constructor_stack;
+ constructor_stack = p;
+
+ constructor_constant = 1;
+ constructor_simple = 1;
+ constructor_depth = SPELLING_DEPTH ();
+ constructor_elements = 0;
+ constructor_pending_elts = 0;
+
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ constructor_type = TREE_TYPE (constructor_fields);
+ push_member_name (IDENTIFIER_POINTER (DECL_NAME (constructor_fields)));
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ constructor_type = TREE_TYPE (constructor_type);
+ push_array_bounds (TREE_INT_CST_LOW (constructor_index));
+ }
- if (end_index != 0)
- range_val = next1;
+ /* Turn off constructor_incremental if type is a struct with bitfields. */
+ check_init_type_bitfields (constructor_type);
- 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;
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ constructor_fields = TYPE_FIELDS (constructor_type);
+ constructor_unfilled_fields = constructor_fields;
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ constructor_index = copy_node (integer_zero_node);
+ constructor_range_end = 0;
+ constructor_unfilled_index = copy_node (integer_zero_node);
+ if (TYPE_DOMAIN (constructor_type))
+ constructor_max_index
+ = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+ }
+ else
+ {
+ error_init ("braces where a scalar is expected%s", " for `%s'", NULL);
+ constructor_fields = constructor_type;
+ constructor_unfilled_fields = constructor_type;
+ }
+}
- /* Now store NEXT1 in the list, I elements from the *end*.
- Make the list longer if necessary. */
- while (! tree_int_cst_lt (current_index, members_index))
- {
- if (free_tree_list)
- {
- TREE_CHAIN (free_tree_list) = members;
- TREE_PURPOSE (free_tree_list) = NULL_TREE;
- TREE_VALUE (free_tree_list) = NULL_TREE;
- members = free_tree_list;
- free_tree_list = NULL_TREE;
- }
- else
- members = tree_cons (NULL_TREE, NULL_TREE, members);
- add_double (TREE_INT_CST_LOW (members_index),
- TREE_INT_CST_HIGH (members_index), 1, 0,
- &TREE_INT_CST_LOW (members_index),
- &TREE_INT_CST_HIGH (members_index));
- }
+/* Don't read a struct incrementally if it has any bitfields,
+ because the incremental reading code doesn't know how to
+ handle bitfields yet. */
+static void
+check_init_type_bitfields (type)
+ tree type;
+{
+ if (TREE_CODE (type) == RECORD_TYPE)
+ {
+ tree tail;
+ for (tail = TYPE_FIELDS (type); tail;
+ tail = TREE_CHAIN (tail))
+ if (DECL_BIT_FIELD (tail))
{
- tree temp;
- union tree_node idx_node;
- tree idx = &idx_node;
- TREE_TYPE (idx) = integer_type_node;
-
- temp = members;
- for (add_double (TREE_INT_CST_LOW (members_index),
- TREE_INT_CST_HIGH (members_index), -1, -1,
- &TREE_INT_CST_LOW (idx),
- &TREE_INT_CST_HIGH (idx));
- tree_int_cst_lt (current_index, idx);
- add_double (TREE_INT_CST_LOW (idx),
- TREE_INT_CST_HIGH (idx), -1, -1,
- &TREE_INT_CST_LOW (idx),
- &TREE_INT_CST_HIGH (idx)))
- temp = TREE_CHAIN (temp);
- TREE_VALUE (temp) = next1;
+ constructor_incremental = 0;
+ break;
}
- }
}
- if (TREE_CODE (type) == RECORD_TYPE)
+}
+
+/* At the end of an implicit or explicit brace level,
+ finish up that level of constructor.
+ If we were outputting the elements as they are read, return 0
+ from inner levels (process_init_element ignores that),
+ but return error_mark_node from the outermost level
+ (that's what we want to put in DECL_INITIAL).
+ Otherwise, return a CONSTRUCTOR expression. */
+
+tree
+pop_init_level (implicit)
+ int implicit;
+{
+ struct constructor_stack *p;
+ int size;
+ tree constructor = 0;
+
+ if (implicit == 0)
{
- register tree field;
- int members_length = 0;
- int i;
+ /* When we come to an explicit close brace,
+ pop any inner levels that didn't have explicit braces. */
+ while (constructor_stack->implicit)
+ process_init_element (pop_init_level (1));
+ }
- /* Don't leave the loop based on field just yet; see if next item
- overrides the expected field first. */
+ p = constructor_stack;
+ size = int_size_in_bytes (constructor_type);
- for (field = TYPE_FIELDS (type), i = 0; tail;
- field = TREE_CHAIN (field), i++)
+ /* Now output all pending elements. */
+ output_pending_init_elements (1);
+
+ /* Pad out the end of the structure. */
+
+ if (! constructor_incremental)
+ {
+ if (constructor_erroneous)
+ constructor = error_mark_node;
+ else
{
- register tree next1;
+ int momentary = suspend_momentary ();
+
+ constructor = build (CONSTRUCTOR, constructor_type, NULL_TREE,
+ nreverse (constructor_elements));
+ if (constructor_constant)
+ TREE_CONSTANT (constructor) = 1;
+ if (constructor_constant && constructor_simple)
+ TREE_STATIC (constructor) = 1;
+ resume_momentary (momentary);
+ }
+ }
+ else
+ {
+ tree filled;
+ int momentary = suspend_momentary ();
- /* If this element specifies a field,
- move to that field before storing it in the new list. */
- if (TREE_PURPOSE (tail) != 0)
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ tree tail;
+ /* Find the last field written out. */
+ for (tail = TYPE_FIELDS (constructor_type); tail;
+ tail = TREE_CHAIN (tail))
+ if (TREE_CHAIN (tail) == constructor_unfilled_fields)
+ break;
+ /* Find the offset of the end of that field. */
+ filled = size_binop (CEIL_DIV_EXPR,
+ size_binop (PLUS_EXPR,
+ DECL_FIELD_BITPOS (tail),
+ DECL_SIZE (tail)),
+ size_int (BITS_PER_UNIT));
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ /* If initializing an array of unknown size,
+ determine the size now. */
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && TYPE_DOMAIN (constructor_type) == 0)
{
- int win = 0;
+ tree maxindex
+ = size_binop (MINUS_EXPR,
+ constructor_unfilled_index,
+ integer_one_node);
+
+ push_obstacks_nochange ();
+ if (TREE_PERMANENT (constructor_type))
+ end_temporary_allocation ();
+ maxindex = copy_node (maxindex);
+ TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
+ TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
+
+ /* We shouldn't have an incomplete array type within
+ some other type. */
+ if (constructor_stack->next)
+ abort ();
- if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE)
- error ("index value instead of field name in structure initializer");
- else
- {
- tree temp;
- int j;
- for (temp = TYPE_FIELDS (type), j = 0;
- temp;
- temp = TREE_CHAIN (temp), j++)
- if (DECL_NAME (temp) == TREE_PURPOSE (tail))
- break;
- if (temp)
- field = temp, i = j, win = 1;
- else
- error ("no field `%s' in structure being initialized",
- IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
- }
- if (!win)
- TREE_VALUE (tail) = error_mark_node;
+ if (pedantic
+ && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)),
+ integer_zero_node))
+ error_with_decl (constructor_decl, "zero-size array `%s'");
+ layout_type (constructor_type);
+ size = int_size_in_bytes (constructor_type);
+ pop_obstacks ();
}
- if (field == 0)
- break; /* No more fields to init. */
+ filled = size_binop (MULT_EXPR, constructor_unfilled_index,
+ size_in_bytes (TREE_TYPE (constructor_type)));
+ }
+ else
+ filled = 0;
- if (! DECL_NAME (field))
- {
- next1 = integer_zero_node;
- }
- else if (TREE_VALUE (tail) != 0)
- {
- tree tail1 = tail;
-
- /* Build the name of this member, with a "." for membership. */
- SAVE_SPELLING_DEPTH
- ({
- push_member_name (IDENTIFIER_POINTER (DECL_NAME (field)));
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1,
- constant_element, constant_element,
- NULL_PTR);
- });
- if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
- abort ();
- tail = tail1;
- }
- else
+ if (filled != 0)
+ assemble_zeros (size - TREE_INT_CST_LOW (filled));
+
+ resume_momentary (momentary);
+ }
+
+
+ constructor_type = p->type;
+ constructor_fields = p->fields;
+ constructor_index = p->index;
+ constructor_range_end = p->range_end;
+ constructor_max_index = p->max_index;
+ constructor_unfilled_index = p->unfilled_index;
+ constructor_unfilled_fields = p->unfilled_fields;
+ constructor_elements = p->elements;
+ constructor_constant = p->constant;
+ constructor_simple = p->simple;
+ constructor_erroneous = p->erroneous;
+ constructor_pending_elts = p->pending_elts;
+ constructor_depth = p->depth;
+ constructor_incremental = p->incremental;
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+
+ constructor_stack = p->next;
+ free (p);
+
+ if (constructor == 0)
+ {
+ if (constructor_stack == 0)
+ return error_mark_node;
+ return NULL_TREE;
+ }
+ return constructor;
+}
+
+/* Within an array initializer, specify the next index to be initialized.
+ FIRST is that index. If LAST is nonzero, then initialize a range
+ of indices, running from FIRST through LAST. */
+
+void
+set_init_index (first, last)
+ tree first, last;
+{
+ if (tree_int_cst_lt (first, constructor_unfilled_index))
+ error_init ("duplicate array index in initializer%s", " for `%s'", NULL);
+ else
+ {
+ TREE_INT_CST_LOW (constructor_index)
+ = TREE_INT_CST_LOW (first);
+ TREE_INT_CST_HIGH (constructor_index)
+ = TREE_INT_CST_HIGH (first);
+
+ if (last != 0 && tree_int_cst_lt (last, first))
+ error_init ("empty index range in initializer%s", " for `%s'", NULL);
+ else
+ constructor_range_end = last;
+ }
+}
+
+/* Within a struct initializer, specify the next field to be initialized. */
+
+void
+set_init_label (fieldname)
+ tree fieldname;
+{
+ tree tail;
+ int passed = 0;
+
+ for (tail = TYPE_FIELDS (constructor_type); tail;
+ tail = TREE_CHAIN (tail))
+ {
+ if (tail == constructor_unfilled_fields)
+ passed = 1;
+ if (DECL_NAME (tail) == fieldname)
+ break;
+ }
+
+ if (tail == 0)
+ error ("unknown field `%s' specified in initializer",
+ IDENTIFIER_POINTER (fieldname));
+ else if (!passed)
+ error ("field `%s' already initialized",
+ IDENTIFIER_POINTER (fieldname));
+ else
+ constructor_fields = tail;
+}
+\f
+/* "Output" the next constructor element.
+ At top level, really output it to assembler code now.
+ Otherwise, collect it in a list from which we will make a CONSTRUCTOR.
+ TYPE is the data type that the containing data type wants here.
+ FIELD is the field (a FIELD_DECL) or the index that this element fills.
+
+ PENDING if non-nil means output pending elements that belong
+ right after this element. (PENDING is normally 1;
+ it is 0 while outputting pending elements, to avoid recursion.) */
+
+void
+output_init_element (value, type, field, pending)
+ tree value, type, field;
+ int pending;
+{
+ int duplicate = 0;
+
+ if (require_constant_value && ! TREE_CONSTANT (value))
+ {
+ error_init ("initializer element%s is not constant",
+ " for `%s'", NULL);
+ value = error_mark_node;
+ }
+ else if (require_constant_elements
+ && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
+ {
+ error_init ("initializer element%s is not computable at load time",
+ " for `%s'", NULL);
+ value = error_mark_node;
+ }
+
+ /* If this element duplicates one on constructor_pending_elts,
+ print a message and ignore it. Don't do this when we're
+ processing elements taken off constructor_pending_elts,
+ because we'd always get spurious errors. */
+ if (pending)
+ {
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ if (purpose_member (field, constructor_pending_elts))
{
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
+ error_init ("duplicate initializer%s", " for `%s'", NULL);
+ duplicate = 1;
}
+ }
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ tree tail;
+ for (tail = constructor_pending_elts; tail;
+ tail = TREE_CHAIN (tail))
+ if (TREE_PURPOSE (tail) != 0
+ && TREE_CODE (TREE_PURPOSE (tail)) == INTEGER_CST
+ && tree_int_cst_equal (TREE_PURPOSE (tail), constructor_index))
+ 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)) == 0)
- allsimple = 0;
-
- /* Now store NEXT1 in the list, I elements from the *end*.
- Make the list longer if necessary. */
- while (i >= members_length)
+ if (tail != 0)
{
- if (free_tree_list)
- {
- TREE_CHAIN (free_tree_list) = members;
- TREE_PURPOSE (free_tree_list) = NULL_TREE;
- TREE_VALUE (free_tree_list) = NULL_TREE;
- members = free_tree_list;
- free_tree_list = NULL_TREE;
- }
- else
- members = tree_cons (NULL_TREE, NULL_TREE, members);
- members_length++;
+ error_init ("duplicate initializer%s", " for `%s'", NULL);
+ duplicate = 1;
}
- {
- tree temp;
- int j;
-
- temp = members;
- for (j = members_length - 1; j > i; j--)
- temp = TREE_CHAIN (temp);
- TREE_VALUE (temp) = next1;
- TREE_PURPOSE (temp) = field;
- }
}
}
- if (TREE_CODE (type) == UNION_TYPE)
- {
- register tree field = TYPE_FIELDS (type);
- register tree next1;
-
- /* Find the first named field. ANSI decided in September 1990
- that only named fields count here. */
- while (field && DECL_NAME (field) == 0)
- field = TREE_CHAIN (field);
- /* For a union, get the initializer for 1 fld. */
+ /* If this element doesn't come next in sequence,
+ put it on constructor_pending_elts. */
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && !tree_int_cst_equal (field, constructor_unfilled_index))
+ {
+ if (! duplicate)
+ constructor_pending_elts
+ = tree_cons (field,
+ digest_init (type, value, (tree *)NULL,
+ require_constant_value,
+ require_constant_elements),
+ constructor_pending_elts);
+ }
+ else if ((TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ && field != constructor_unfilled_fields)
+ {
+ if (!duplicate)
+ constructor_pending_elts
+ = tree_cons (field,
+ digest_init (type, value, (tree *)NULL,
+ require_constant_value,
+ require_constant_elements),
+ constructor_pending_elts);
+ }
+ else
+ {
+ /* Otherwise, output this element either to
+ constructor_elements or to the assembler file. */
- if (tail == 0)
+ if (!duplicate)
{
- error ("empty initializer for union");
- tail = build_tree_list (0, 0);
+ if (! constructor_incremental)
+ constructor_elements
+ = tree_cons ((TREE_CODE (constructor_type) != ARRAY_TYPE
+ ? field : NULL),
+ digest_init (type, value, (tree *)NULL,
+ require_constant_value,
+ require_constant_elements),
+ constructor_elements);
+ else
+ output_constant (value, int_size_in_bytes (type));
}
- /* If this element specifies a field, initialize via that field. */
- if (TREE_PURPOSE (tail) != 0)
+ /* Advance the variable that indicates sequential elements output. */
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
- int win = 0;
+ tree tem = size_binop (PLUS_EXPR, constructor_unfilled_index,
+ integer_one_node);
+ TREE_INT_CST_LOW (constructor_unfilled_index)
+ = TREE_INT_CST_LOW (tem);
+ TREE_INT_CST_HIGH (constructor_unfilled_index)
+ = TREE_INT_CST_HIGH (tem);
+ }
+ else if (TREE_CODE (constructor_type) == RECORD_TYPE)
+ constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
+ else if (TREE_CODE (constructor_type) == UNION_TYPE)
+ constructor_unfilled_fields = 0;
+
+ /* Now output any pending elements which have become next. */
+ if (pending)
+ output_pending_init_elements (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
+/* Output any pending elements which have become next.
+ As we output elements, constructor_unfilled_{fields,index}
+ advances, which may cause other elements to become next;
+ if so, they too are output.
+
+ If ALL is 0, we return when there are
+ no more pending elements to output now.
+
+ If ALL is 1, we output space as necessary so that
+ we can output all the pending elements. */
+
+static void
+output_pending_init_elements (all)
+ int all;
+{
+ tree tail;
+ tree next;
+
+ retry:
+
+ /* Look thru the whole pending list.
+ If we find an element that should be output now,
+ output it. Otherwise, set NEXT to the element
+ that comes first among those still pending. */
+
+ next = 0;
+ for (tail = constructor_pending_elts; tail;
+ tail = TREE_CHAIN (tail))
+ {
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ if (tree_int_cst_equal (TREE_PURPOSE (tail),
+ constructor_unfilled_index))
{
- 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 `%s' in union being initialized",
- IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
+ output_init_element (TREE_VALUE (tail), TREE_TYPE (constructor_type),
+ constructor_unfilled_index, 0);
+ goto retry;
+ }
+ else if (tree_int_cst_lt (TREE_PURPOSE (tail),
+ constructor_unfilled_index))
+ ;
+ else if (next == 0
+ || tree_int_cst_lt (TREE_PURPOSE (tail),
+ next))
+ next = TREE_PURPOSE (tail);
+ }
+ else if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ if (TREE_PURPOSE (tail) == constructor_unfilled_fields)
+ {
+ output_init_element (TREE_VALUE (tail),
+ TREE_TYPE (constructor_unfilled_fields),
+ constructor_unfilled_fields,
+ 0);
+ goto retry;
}
- if (!win)
- TREE_VALUE (tail) = error_mark_node;
+ else if (tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)),
+ DECL_FIELD_BITPOS (constructor_unfilled_fields)))
+ ;
+ else if (next == 0
+ || tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)),
+ DECL_FIELD_BITPOS (next)))
+ next = TREE_PURPOSE (tail);
}
+ }
+
+ /* Ordinarily return, but not if we want to output all
+ and there are elements left. */
+ if (! (all && next != 0))
+ return;
+
+ /* Generate space up to the position of NEXT. */
+ if (constructor_incremental)
+ {
+ tree filled;
+ tree nextpos_tree;
- if (TREE_VALUE (tail) != 0)
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
{
- tree tail1 = tail;
-
- /* Build the name of this member, with a "." for membership. */
- SAVE_SPELLING_DEPTH
- ({
- push_member_name (IDENTIFIER_POINTER (DECL_NAME (field)));
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1,
- constant_value, constant_element, NULL_PTR);
- });
- if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
- abort ();
- tail = tail1;
+ /* Find the last field written out. */
+ for (tail = TYPE_FIELDS (constructor_type); tail;
+ tail = TREE_CHAIN (tail))
+ if (TREE_CHAIN (tail) == constructor_unfilled_fields)
+ break;
+ /* Find the offset of the end of that field. */
+ filled = size_binop (CEIL_DIV_EXPR,
+ size_binop (PLUS_EXPR,
+ DECL_FIELD_BITPOS (tail),
+ DECL_SIZE (tail)),
+ size_int (BITS_PER_UNIT));
+ nextpos_tree = size_binop (CEIL_DIV_EXPR,
+ DECL_FIELD_BITPOS (next),
+ size_int (BITS_PER_UNIT));
+ constructor_unfilled_fields = next;
}
- else
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
+ filled = size_binop (MULT_EXPR, constructor_unfilled_index,
+ size_in_bytes (TREE_TYPE (constructor_type)));
+ nextpos_tree
+ = size_binop (MULT_EXPR, next,
+ size_in_bytes (TREE_TYPE (constructor_type)));
+ TREE_INT_CST_LOW (constructor_unfilled_index)
+ = TREE_INT_CST_LOW (next);
+ TREE_INT_CST_HIGH (constructor_unfilled_index)
+ = TREE_INT_CST_HIGH (next);
}
+ else
+ filled = 0;
- 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;
- if (free_tree_list)
+ if (filled)
{
- TREE_CHAIN (free_tree_list) = members;
- TREE_PURPOSE (free_tree_list) = field;
- TREE_VALUE (free_tree_list) = next1;
- members = free_tree_list;
- free_tree_list = NULL_TREE;
+ int nextpos = TREE_INT_CST_LOW (nextpos_tree);
+
+ assemble_zeros (nextpos - TREE_INT_CST_LOW (filled));
}
+ }
+
+ goto retry;
+}
+\f
+/* Add one non-braced element to the current constructor level.
+ This adjusts the current position within the constructor's type.
+ This may also start or terminate implicit levels
+ to handle a partly-braced initializer.
+
+ Once this has found the correct level for the new element,
+ it calls output_init_element.
+
+ Note: if we are incrementally outputting this constructor,
+ this function may be called with a null argument
+ representing a sub-constructor that was already incrementally output.
+ When that happens, we output nothing, but we do the bookkeeping
+ to skip past that element of the current constructor. */
+
+void
+process_init_element (value)
+ tree value;
+{
+ if (value != 0)
+ value = default_conversion (value);
+
+ if (value == 0)
+ ;
+ else if (value == error_mark_node)
+ constructor_erroneous = 1;
+ else if (!TREE_CONSTANT (value))
+ constructor_constant = 0;
+ else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
+ constructor_simple = 0;
+
+ /* If we've exhausted any levels that didn't have braces,
+ pop them now. */
+ while (constructor_stack->implicit)
+ {
+ if ((TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ && constructor_fields == 0)
+ process_init_element (pop_init_level (1));
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && tree_int_cst_lt (constructor_max_index, constructor_index))
+ process_init_element (pop_init_level (1));
else
- members = tree_cons (field, next1, members);
+ break;
}
- /* 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)
+ while (1)
{
- if (TREE_CODE (type) == UNION_TYPE)
+ if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
- pedwarn_init ("excess elements in union initializer%s",
- " after `%s'", NULL_PTR);
+ tree fieldtype;
+ enum tree_code fieldcode;
+
+ if (constructor_fields == 0)
+ {
+ pedwarn_init ("excess elements in struct initializer%s",
+ " after `%s'", NULL_PTR);
+ break;
+ }
+
+ fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
+ fieldcode = TREE_CODE (fieldtype);
+
+ if (value != 0 && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
+ && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
+ || fieldcode == UNION_TYPE))
+ {
+ push_init_level (1);
+ continue;
+ }
+
+ if (value)
+ {
+ push_member_name (IDENTIFIER_POINTER (DECL_NAME (constructor_fields)));
+ output_init_element (value, fieldtype, constructor_fields, 1);
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+ }
+ else
+ /* If we are doing the bookkeeping for an element that was
+ directly output as a constructor,
+ we must update constructor_unfilled_fields. */
+ constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+
+ constructor_fields = TREE_CHAIN (constructor_fields);
+ break;
}
- else
+ if (TREE_CODE (constructor_type) == UNION_TYPE)
{
- pedwarn_init ("excess elements in aggregate initializer%s",
- " after `%s'", NULL_PTR);
+ tree fieldtype;
+ enum tree_code fieldcode;
+
+ if (constructor_fields == 0)
+ {
+ pedwarn_init ("excess elements in union initializer%s",
+ " after `%s'", NULL_PTR);
+ break;
+ }
+
+ fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
+ fieldcode = TREE_CODE (fieldtype);
+
+ if (value != 0 && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
+ && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
+ || fieldcode == UNION_TYPE))
+ {
+ push_init_level (1);
+ continue;
+ }
+
+ if (value)
+ {
+ push_member_name (IDENTIFIER_POINTER (DECL_NAME (constructor_fields)));
+ output_init_element (value, fieldtype, constructor_fields, 1);
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+ }
+ else
+ /* If we are doing the bookkeeping for an element that was
+ directly output as a constructor,
+ we must update constructor_unfilled_fields. */
+ constructor_unfilled_fields = 0;
+
+ constructor_fields = 0;
+ break;
}
- }
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+ enum tree_code eltcode = TREE_CODE (elttype);
+
+ if (value != 0 && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype
+ && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
+ || eltcode == UNION_TYPE))
+ {
+ push_init_level (1);
+ continue;
+ }
+
+ if (constructor_max_index != 0
+ && tree_int_cst_lt (constructor_max_index, constructor_index))
+ {
+ pedwarn_init ("excess elements in array initializer%s",
+ " after `%s'", NULL_PTR);
+ break;
+ }
- /* It might be possible to use SAVE_SPELLING_DEPTH, but I suspect that
- some preprocessor somewhere won't accept that much text as an argument.
- It's also likely to make debugging difficult. */
+ /* Now output the actual element.
+ Ordinarily, output once.
+ If there is a range, repeat it till we advance past the range. */
+ do
+ {
+ tree tem;
- RESTORE_SPELLING_DEPTH (depth);
+ if (value)
+ {
+ push_array_bounds (TREE_INT_CST_LOW (constructor_index));
+ output_init_element (value, elttype, constructor_index, 1);
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+ }
- if (erroneous)
- return error_mark_node;
+ tem = size_binop (PLUS_EXPR, constructor_index,
+ integer_one_node);
+ TREE_INT_CST_LOW (constructor_index)
+ = TREE_INT_CST_LOW (tem);
+ TREE_INT_CST_HIGH (constructor_index)
+ = TREE_INT_CST_HIGH (tem);
+
+ if (!value)
+ /* If we are doing the bookkeeping for an element that was
+ directly output as a constructor,
+ we must update constructor_unfilled_index. */
+ {
+ TREE_INT_CST_LOW (constructor_unfilled_index)
+ = TREE_INT_CST_LOW (constructor_index);
+ TREE_INT_CST_HIGH (constructor_unfilled_index)
+ = TREE_INT_CST_HIGH (constructor_index);
+ }
+ }
+ while (! (constructor_range_end == 0
+ || tree_int_cst_lt (constructor_range_end,
+ constructor_index)));
- if (elts)
- result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members));
- else
- {
- result = init;
- CONSTRUCTOR_ELTS (result) = nreverse (members);
- TREE_TYPE (result) = type;
- TREE_CONSTANT (result) = 0;
- TREE_STATIC (result) = 0;
+ break;
+ }
+
+ /* Handle the sole element allowed in a braced initializer
+ for a scalar variable. */
+ if (constructor_fields == 0)
+ {
+ pedwarn_init ("excess elements in scalar initializer%s",
+ " after `%s'", NULL_PTR);
+ break;
+ }
+
+ if (value)
+ output_init_element (value, constructor_type, NULL_TREE, 1);
+ constructor_fields = 0;
+ break;
}
- if (allconstant) TREE_CONSTANT (result) = 1;
- if (allconstant && allsimple) TREE_STATIC (result) = 1;
- return result;
+
+ /* If the (lexically) previous elments are not now saved,
+ we can discard the storage for them. */
+ if (constructor_incremental && constructor_pending_elts == 0)
+ clear_momentary ();
}
\f
/* Expand an ASM statement with operands, handling output operands