From: Richard Stallman Date: Fri, 23 Jul 1993 18:49:55 +0000 (+0000) Subject: Output most constructors an element at a time. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=de5206613ed98eac1e9b142079458314b66ada83;p=gcc.git Output most constructors an element at a time. (digest_init): Deleted code for raw constructors. (process_init_constructor): Function deleted. (start_init, finish_init): New functions. (really_start_incremental_init) (push_init_level, check_init_type_bitfields, pop_init_level) (set_init_index, set_init_label, process_init_element) (output_init_element, output_pending_init_elements): New functions. From-SVN: r4973 --- diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index ab2b9216533..8c88dbb3452 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -55,13 +55,14 @@ static tree unary_complex_lvalue (); 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 (); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) */ @@ -4831,25 +4832,15 @@ static tree free_tree_list = NULL_TREE; (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. @@ -4876,16 +4867,6 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) 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. */ @@ -4907,7 +4888,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) && 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))) @@ -4915,7 +4896,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) && 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; } @@ -4934,15 +4915,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) : 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)) @@ -4959,10 +4939,11 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) && (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; } @@ -4973,14 +4954,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) 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; } @@ -4994,7 +4975,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) 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)) @@ -5005,108 +4986,32 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) 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); }); @@ -5114,14 +5019,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) 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; } @@ -5133,582 +5038,1071 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) 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; } -/* 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; + +/* 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); +} + +/* 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; + } +} + +/* 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; +} + +/* "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; +} + +/* 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 (); } /* Expand an ASM statement with operands, handling output operands