Commit de520661 by Richard Stallman

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
parent 8380e2f2
...@@ -55,13 +55,14 @@ static tree unary_complex_lvalue (); ...@@ -55,13 +55,14 @@ static tree unary_complex_lvalue ();
static tree process_init_constructor (); static tree process_init_constructor ();
static tree convert_arguments (); static tree convert_arguments ();
static char *get_spelling (); static char *get_spelling ();
tree digest_init (); static tree digest_init ();
static void pedantic_lvalue_warning (); static void pedantic_lvalue_warning ();
tree truthvalue_conversion (); tree truthvalue_conversion ();
void incomplete_type_error (); void incomplete_type_error ();
void readonly_warning (); void readonly_warning ();
static tree internal_build_compound_expr (); static tree internal_build_compound_expr ();
void process_init_element ();
/* Do `exp = require_complete_type (exp);' to make sure exp /* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) */ does not have an incomplete type. (That includes void types.) */
...@@ -4831,25 +4832,15 @@ static tree free_tree_list = NULL_TREE; ...@@ -4831,25 +4832,15 @@ static tree free_tree_list = NULL_TREE;
(That is true for all nested calls to digest_init.) */ (That is true for all nested calls to digest_init.) */
tree tree
digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) digest_init (type, init, tail, require_constant, constructor_constant)
tree type, init, *tail; tree type, init, *tail;
int require_constant, constructor_constant; int require_constant, constructor_constant;
char *ofwhat;
{ {
enum tree_code code = TREE_CODE (type); enum tree_code code = TREE_CODE (type);
tree element = 0; tree element = 0;
tree old_tail_contents; 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; 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. /* By default, assume we use one element from a list.
We correct this later in the cases where it is not true. 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) ...@@ -4876,16 +4867,6 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
if (TREE_CODE (init) == NON_LVALUE_EXPR) if (TREE_CODE (init) == NON_LVALUE_EXPR)
inside_init = TREE_OPERAND (init, 0); 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 /* Initialization of an array of chars from a string constant
optionally enclosed in braces. */ optionally enclosed in braces. */
...@@ -4907,7 +4888,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -4907,7 +4888,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
&& TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node)) && TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
{ {
error_init ("char-array%s initialized from wide string", error_init ("char-array%s initialized from wide string",
" `%s'", ofwhat); " `%s'", NULL);
return error_mark_node; return error_mark_node;
} }
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
...@@ -4915,7 +4896,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -4915,7 +4896,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
&& TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)) && TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
{ {
error_init ("int-array%s initialized from non-wide string", error_init ("int-array%s initialized from non-wide string",
" `%s'", ofwhat); " `%s'", NULL);
return error_mark_node; return error_mark_node;
} }
...@@ -4934,15 +4915,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -4934,15 +4915,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
: 1)) : 1))
pedwarn_init ( pedwarn_init (
"initializer-string for array of chars%s is too long", "initializer-string for array of chars%s is too long",
" `%s'", ofwhat); " `%s'", NULL);
} }
return string; return string;
} }
} }
/* Any type except an array can be initialized /* Any type can be initialized
from an expression of the same type, optionally with braces. from an expression of the same type, optionally with braces. */
For an array, this is allowed only for a string constant. */
if (inside_init && TREE_TYPE (inside_init) != 0 if (inside_init && TREE_TYPE (inside_init) != 0
&& ((TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)) && ((TYPE_MAIN_VARIANT (TREE_TYPE (inside_init))
...@@ -4959,10 +4939,11 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -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)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE)) || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE))
inside_init = default_conversion (inside_init); 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", error_init ("array%s initialized from non-constant array expression",
" `%s'", ofwhat); " `%s'", NULL);
return error_mark_node; return error_mark_node;
} }
...@@ -4973,14 +4954,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -4973,14 +4954,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
if (require_constant && ! TREE_CONSTANT (inside_init)) if (require_constant && ! TREE_CONSTANT (inside_init))
{ {
error_init ("initializer element%s is not constant", error_init ("initializer element%s is not constant",
" for `%s'", ofwhat); " for `%s'", NULL);
inside_init = error_mark_node; inside_init = error_mark_node;
} }
else if (require_constant else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0) && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{ {
error_init ("initializer element%s is not computable at load time", error_init ("initializer element%s is not computable at load time",
" for `%s'", ofwhat); " for `%s'", NULL);
inside_init = error_mark_node; inside_init = error_mark_node;
} }
...@@ -4994,7 +4975,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -4994,7 +4975,7 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
if (code == ARRAY_TYPE) if (code == ARRAY_TYPE)
{ {
error_init ("array%s initialized from non-constant array expression", error_init ("array%s initialized from non-constant array expression",
" `%s'", ofwhat); " `%s'", NULL);
return error_mark_node; return error_mark_node;
} }
if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE)) if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE))
...@@ -5005,108 +4986,32 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -5005,108 +4986,32 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
if (require_constant && ! TREE_CONSTANT (element)) if (require_constant && ! TREE_CONSTANT (element))
{ {
error_init ("initializer element%s is not constant", error_init ("initializer element%s is not constant",
" for `%s'", ofwhat); " for `%s'", NULL);
element = error_mark_node; element = error_mark_node;
} }
else if (require_constant else if (require_constant
&& initializer_constant_valid_p (element, TREE_TYPE (element)) == 0) && initializer_constant_valid_p (element, TREE_TYPE (element)) == 0)
{ {
error_init ("initializer element%s is not computable at load time", error_init ("initializer element%s is not computable at load time",
" for `%s'", ofwhat); " for `%s'", NULL);
element = error_mark_node; element = error_mark_node;
} }
return element; 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. */ /* Handle scalar types, including conversions. */
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == COMPLEX_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 SAVE_SPELLING_DEPTH
({ ({
if (ofwhat)
push_string (ofwhat);
if (!raw_constructor)
inside_init = init;
/* Note that convert_for_assignment calls default_conversion /* Note that convert_for_assignment calls default_conversion
for arrays and functions. We must not call it in the for arrays and functions. We must not call it in the
case where inside_init is a null pointer constant. */ case where inside_init is a null pointer constant. */
inside_init inside_init
= convert_for_assignment (type, inside_init, = convert_for_assignment (type, init,
&initialization_message, &initialization_message,
NULL_TREE, NULL_TREE, 0); NULL_TREE, NULL_TREE, 0);
}); });
...@@ -5114,14 +5019,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -5114,14 +5019,14 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
if (require_constant && ! TREE_CONSTANT (inside_init)) if (require_constant && ! TREE_CONSTANT (inside_init))
{ {
error_init ("initializer element%s is not constant", error_init ("initializer element%s is not constant",
" for `%s'", ofwhat); " for `%s'", NULL);
inside_init = error_mark_node; inside_init = error_mark_node;
} }
else if (require_constant else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0) && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{ {
error_init ("initializer element%s is not computable at load time", error_init ("initializer element%s is not computable at load time",
" for `%s'", ofwhat); " for `%s'", NULL);
inside_init = error_mark_node; inside_init = error_mark_node;
} }
...@@ -5133,582 +5038,1071 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat) ...@@ -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) if (TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{ {
error_init ("variable-sized object%s may not be initialized", error_init ("variable-sized object%s may not be initialized",
" `%s'", ofwhat); " `%s'", NULL);
return error_mark_node; return error_mark_node;
} }
if (code == ARRAY_TYPE || code == RECORD_TYPE) error_init ("invalid initializer%s", " for `%s'", NULL);
{
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);
return error_mark_node; return error_mark_node;
} }
/* Process a constructor for a variable of type TYPE. /* Handle initializers that use braces. */
The constructor elements may be specified either with INIT or with ELTS,
only one of which should be non-null.
If INIT is specified, it is a CONSTRUCTOR node which is specifically static void output_pending_init_elements ();
and solely for initializing this datum. static void check_init_type_bitfields ();
If ELTS is specified, it is the address of a variable containing /* Type of object we are accumulating a constructor for.
a list of expressions. We take as many elements as we need This type is always a RECORD_TYPE, UNION_TYPE or ARRAY_TYPE. */
from the head of the list and update the list. static tree constructor_type;
In the resulting constructor, TREE_CONSTANT is set if all elts are /* For a RECORD_TYPE or UNION_TYPE, this is the chain of fields
constant, and TREE_STATIC is set if, in addition, all elts are simple enough left to fill. */
constants that the assembler and linker can compute them. static tree constructor_fields;
The argument CONSTANT_VALUE says to print an error if either the /* For an ARRAY_TYPE, this is the specified index
value or any element is not a constant. 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 /* For an ARRAY_TYPE, this is the end index of the range
of an aggregate is not constant. It does not apply to a value to intitialize with the next element, or NULL in the ordinary case
which is not a constructor. where the element is used just once. */
static tree constructor_range_end;
OFWHAT is a character string describing the object being initialized, /* For an ARRAY_TYPE, this is the maximum index. */
for error messages. It might be "variable" or "variable.member" static tree constructor_max_index;
or "variable[17].member[5]".
If OFWHAT is null, the description string is stored on the spelling /* For a RECORD_TYPE, this is the first field not yet written out. */
stack. That is always true for recursive calls. */ static tree constructor_unfilled_fields;
static tree /* For an ARRAY_TYPE, this is the index of the first element
process_init_constructor (type, init, elts, constant_value, constant_element, not yet written out.
ofwhat) This is a special INTEGER_CST node that we modify in place. */
tree type, init, *elts; static tree constructor_unfilled_index;
int constant_value, constant_element;
char *ofwhat; /* 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; struct constructor_stack *next;
/* List of the elements of the result constructor, tree type;
in reverse order. */ tree fields;
register tree members = NULL; tree index;
tree result; tree range_end;
int allconstant = 1; tree max_index;
int allsimple = 1; tree unfilled_index;
int erroneous = 0; tree unfilled_fields;
int depth = SPELLING_DEPTH (); tree elements;
int offset;
tree pending_elts;
int depth;
char constant;
char simple;
char implicit;
char incremental;
char erroneous;
char outer;
};
if (ofwhat) struct constructor_stack *constructor_stack;
push_string (ofwhat);
/* Make TAIL be the list of elements to use for the initialization, /* This stack records separate initializers that are nested.
no matter how the data was given to us. */ Nested initializers can't happen in ANSI C, but GNU C allows them
in cases like { ... (struct foo) { ... } ... }. */
if (elts) struct initializer_stack
{ {
if (warn_missing_braces) struct initializer_stack *next;
{ tree decl;
if (! partial_bracket_mentioned) char *asmspec;
warning ("aggregate has a partly bracketed initializer"); struct constructor_stack *constructor_stack;
partial_bracket_mentioned = 1; struct spelling *spelling;
} struct spelling *spelling_base;
tail = *elts; int spelling_size;
} char top_level;
else char incremental;
tail = CONSTRUCTOR_ELTS (init); char require_constant_value;
char require_constant_elements;
char deferred;
};
/* Gobble as many elements as needed, and make a constructor or initial value struct initializer_stack *initializer_stack;
for each element of this aggregate. Chain them together in result.
If there are too few, use 0 for each scalar ultimate component. */
if (TREE_CODE (type) == ARRAY_TYPE) /* Prepare to parse and output the initializer for variable DECL. */
{
tree min_index, max_index; void
/* These are non-zero only within a range initializer. */ start_init (decl, asmspec, top_level)
tree start_index = 0, end_index = 0; tree decl;
/* Within a range, this is the value for the elts in the range. */ char *asmspec;
tree range_val = 0; int top_level;
/* Do arithmetic using double integers, but don't use fold/build, {
because these allocate a new tree object everytime they are called, char *locus;
thus resulting in gcc using too much memory for large struct initializer_stack *p
initializers. */ = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
union tree_node current_index_node, members_index_node;
tree current_index = &current_index_node; p->decl = constructor_decl;
tree members_index = &members_index_node; p->asmspec = constructor_asmspec;
TREE_TYPE (current_index) = integer_type_node; p->incremental = constructor_incremental;
TREE_TYPE (members_index) = integer_type_node; p->require_constant_value = require_constant_value;
p->require_constant_elements = require_constant_elements;
/* If we have array bounds, set our bounds from that. Otherwise, p->constructor_stack = constructor_stack;
we have a lower bound of zero and an unknown upper bound. */ p->spelling = spelling;
if (TYPE_DOMAIN (type)) p->spelling_base = spelling_base;
{ p->spelling_size = spelling_size;
min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); p->deferred = constructor_subconstants_deferred;
max_index = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); 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)
{
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 else
{ {
min_index = integer_zero_node; require_constant_value = 0;
max_index = 0; require_constant_elements = 0;
} locus = "(anonymous)";
}
TREE_INT_CST_LOW (members_index) = TREE_INT_CST_LOW (min_index);
TREE_INT_CST_HIGH (members_index) = TREE_INT_CST_HIGH (min_index); constructor_stack = 0;
/* Don't leave the loop based on index if the next item has an explicit spelling_base = 0;
index value that will override it. */ spelling_size = 0;
RESTORE_SPELLING_DEPTH (0);
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); if (locus)
tail != 0 || end_index; push_string (locus);
add_double (TREE_INT_CST_LOW (current_index), }
TREE_INT_CST_HIGH (current_index), 1, 0,
&TREE_INT_CST_LOW (current_index), void
&TREE_INT_CST_HIGH (current_index))) finish_init ()
{ {
register tree next1 = 0; struct initializer_stack *p = initializer_stack;
/* Handle the case where we are inside of a range. /* Output subconstants (string constants, usually)
current_index increments through the range, that were referenced within this initializer and saved up.
so just keep reusing the same element of TAIL Must do this if and only if we called defer_addressed_constants. */
until the end of the range. */ if (constructor_subconstants_deferred)
if (end_index != 0) output_deferred_addressed_constants ();
{
next1 = range_val; /* Free the whole constructor stack of this initializer. */
if (!tree_int_cst_lt (current_index, end_index)) while (constructor_stack)
end_index = 0; {
} struct constructor_stack *q = constructor_stack;
constructor_stack = q->next;
/* If this element specifies an index, free (q);
move to that index before storing it in the new list. */ }
else if (TREE_PURPOSE (tail) != 0)
{ /* Pop back to the data of the outer initializer (if any). */
int win = 0; constructor_decl = p->decl;
tree index = TREE_PURPOSE (tail); constructor_asmspec = p->asmspec;
constructor_incremental = p->incremental;
if (index && (TREE_CODE (index) == NON_LVALUE_EXPR require_constant_value = p->require_constant_value;
|| TREE_CODE (index) == NOP_EXPR)) require_constant_elements = p->require_constant_elements;
index = TREE_OPERAND (index, 0); constructor_stack = p->constructor_stack;
spelling = p->spelling;
/* Begin a range. */ spelling_base = p->spelling_base;
if (TREE_CODE (index) == TREE_LIST) spelling_size = p->spelling_size;
{ constructor_subconstants_deferred = p->deferred;
start_index = TREE_PURPOSE (index); constructor_top_level = p->top_level;
end_index = TREE_PURPOSE (TREE_CHAIN (index)); initializer_stack = p->next;
free (p);
/* Expose constants. It Doesn't matter if we change }
the mode.*/
if (end_index /* Call here when we see the initializer is surrounded by braces.
&& (TREE_CODE (end_index) == NON_LVALUE_EXPR This is instead of a call to push_init_level;
|| TREE_CODE (end_index) == NOP_EXPR)) it is matched by a call to pop_init_level.
end_index = TREE_OPERAND (end_index, 0);
if (start_index TYPE is the type to initialize, for a constructor expression.
&& (TREE_CODE (start_index) == NON_LVALUE_EXPR For an initializer for a decl, TYPE is zero. */
|| TREE_CODE (start_index) == NOP_EXPR))
start_index = TREE_OPERAND (start_index, 0); void
really_start_incremental_init (type)
constant_expression_warning (start_index); tree type;
constant_expression_warning (end_index); {
struct constructor_stack *p
if ((TREE_CODE (start_index) == IDENTIFIER_NODE) = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
|| (TREE_CODE (end_index) == IDENTIFIER_NODE))
error ("field name used as index in array initializer"); if (type == 0)
else if ((TREE_CODE (start_index) != INTEGER_CST) type = TREE_TYPE (constructor_decl);
|| (TREE_CODE (end_index) != INTEGER_CST))
error ("non-constant or non-integer array index in initializer"); /* Turn off constructor_incremental if type is a struct with bitfields.
else if (tree_int_cst_lt (start_index, min_index) Do this before the first push, so that the corrected value
|| (max_index && tree_int_cst_lt (max_index, start_index)) is available in finish_init. */
|| tree_int_cst_lt (end_index, min_index) check_init_type_bitfields (type);
|| (max_index && tree_int_cst_lt (max_index, end_index)))
error ("array index out of range in initializer"); p->type = constructor_type;
else if (tree_int_cst_lt (end_index, start_index)) p->fields = constructor_fields;
{ p->index = constructor_index;
/* If the range is empty, don't initialize any elements, p->range_end = constructor_range_end;
but do reset current_index for the next initializer p->max_index = constructor_max_index;
element. */ p->unfilled_index = constructor_unfilled_index;
warning ("empty array initializer range"); p->unfilled_fields = constructor_unfilled_fields;
tail = TREE_CHAIN (tail); p->elements = 0;
TREE_INT_CST_LOW (current_index) p->constant = constructor_constant;
= TREE_INT_CST_LOW (end_index); p->simple = constructor_simple;
TREE_INT_CST_HIGH (current_index) p->erroneous = constructor_erroneous;
= TREE_INT_CST_HIGH (end_index); p->pending_elts = constructor_pending_elts;
continue; 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 else
{ {
TREE_INT_CST_LOW (current_index) /* Handle the case of int x = {5}; */
= TREE_INT_CST_LOW (start_index); constructor_fields = constructor_type;
TREE_INT_CST_HIGH (current_index) constructor_unfilled_fields = constructor_type;
= 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;
} }
if (!win) if (constructor_incremental)
{ {
/* If there was an error, end the current range. */ int momentary = suspend_momentary ();
end_index = 0; push_obstacks_nochange ();
TREE_VALUE (tail) = error_mark_node; 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 (constructor_incremental)
{
defer_addressed_constants ();
constructor_subconstants_deferred = 1;
} }
}
if (max_index && tree_int_cst_lt (max_index, current_index)) /* Push down into a subobject, for initialization.
break; /* Stop if we've indeed run out of elements. */ 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. */ void
if (next1 != 0) push_init_level (implicit)
; int implicit;
else if (TREE_VALUE (tail) != 0) {
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));
}
/* Turn off constructor_incremental if type is a struct with bitfields. */
check_init_type_bitfields (constructor_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
{ {
tree tail1 = tail; error_init ("braces where a scalar is expected%s", " for `%s'", NULL);
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
}
/* Build the element of this array, with "[]" notation. For /* Don't read a struct incrementally if it has any bitfields,
error messages, we assume that the index fits within a because the incremental reading code doesn't know how to
host int. */ handle bitfields yet. */
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) static void
abort (); check_init_type_bitfields (type)
if (tail == tail1 && TYPE_DOMAIN (type) == 0) 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))
{ {
error_init ( constructor_incremental = 0;
"non-empty initializer for array%s of empty elements", break;
" `%s'", NULL_PTR);
/* Just ignore what we were supposed to use. */
tail1 = 0;
} }
tail = tail1;
} }
else }
/* 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)
{ {
next1 = error_mark_node; /* When we come to an explicit close brace,
tail = TREE_CHAIN (tail); pop any inner levels that didn't have explicit braces. */
while (constructor_stack->implicit)
process_init_element (pop_init_level (1));
} }
if (end_index != 0) p = constructor_stack;
range_val = next1; size = int_size_in_bytes (constructor_type);
/* Now output all pending elements. */
output_pending_init_elements (1);
if (next1 == error_mark_node) /* Pad out the end of the structure. */
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*. if (! constructor_incremental)
Make the list longer if necessary. */
while (! tree_int_cst_lt (current_index, members_index))
{ {
if (free_tree_list) if (constructor_erroneous)
constructor = error_mark_node;
else
{ {
TREE_CHAIN (free_tree_list) = members; int momentary = suspend_momentary ();
TREE_PURPOSE (free_tree_list) = NULL_TREE;
TREE_VALUE (free_tree_list) = NULL_TREE; constructor = build (CONSTRUCTOR, constructor_type, NULL_TREE,
members = free_tree_list; nreverse (constructor_elements));
free_tree_list = NULL_TREE; if (constructor_constant)
TREE_CONSTANT (constructor) = 1;
if (constructor_constant && constructor_simple)
TREE_STATIC (constructor) = 1;
resume_momentary (momentary);
} }
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));
} }
else
{
tree filled;
int momentary = suspend_momentary ();
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)
{ {
tree temp; tree maxindex
union tree_node idx_node; = size_binop (MINUS_EXPR,
tree idx = &idx_node; constructor_unfilled_index,
TREE_TYPE (idx) = integer_type_node; 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 ();
temp = members; if (pedantic
for (add_double (TREE_INT_CST_LOW (members_index), && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)),
TREE_INT_CST_HIGH (members_index), -1, -1, integer_zero_node))
&TREE_INT_CST_LOW (idx), error_with_decl (constructor_decl, "zero-size array `%s'");
&TREE_INT_CST_HIGH (idx)); layout_type (constructor_type);
tree_int_cst_lt (current_index, idx); size = int_size_in_bytes (constructor_type);
add_double (TREE_INT_CST_LOW (idx), pop_obstacks ();
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;
} }
filled = size_binop (MULT_EXPR, constructor_unfilled_index,
size_in_bytes (TREE_TYPE (constructor_type)));
} }
else
filled = 0;
if (filled != 0)
assemble_zeros (size - TREE_INT_CST_LOW (filled));
resume_momentary (momentary);
} }
if (TREE_CODE (type) == RECORD_TYPE)
{
register tree field;
int members_length = 0;
int i;
/* Don't leave the loop based on field just yet; see if next item
overrides the expected field first. */
for (field = TYPE_FIELDS (type), i = 0; tail; constructor_type = p->type;
field = TREE_CHAIN (field), i++) constructor_fields = p->fields;
{ constructor_index = p->index;
register tree next1; 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);
/* If this element specifies a field, constructor_stack = p->next;
move to that field before storing it in the new list. */ free (p);
if (TREE_PURPOSE (tail) != 0)
if (constructor == 0)
{ {
int win = 0; if (constructor_stack == 0)
return error_mark_node;
return NULL_TREE;
}
return constructor;
}
if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE) /* Within an array initializer, specify the next index to be initialized.
error ("index value instead of field name in structure initializer"); 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 else
{ {
tree temp; TREE_INT_CST_LOW (constructor_index)
int j; = TREE_INT_CST_LOW (first);
for (temp = TYPE_FIELDS (type), j = 0; TREE_INT_CST_HIGH (constructor_index)
temp; = TREE_INT_CST_HIGH (first);
temp = TREE_CHAIN (temp), j++)
if (DECL_NAME (temp) == TREE_PURPOSE (tail)) if (last != 0 && tree_int_cst_lt (last, first))
break; error_init ("empty index range in initializer%s", " for `%s'", NULL);
if (temp)
field = temp, i = j, win = 1;
else else
error ("no field `%s' in structure being initialized", constructor_range_end = last;
IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
} }
if (!win) }
TREE_VALUE (tail) = error_mark_node;
/* 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 (field == 0) if (tail == 0)
break; /* No more fields to init. */ 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.) */
if (! DECL_NAME (field)) void
output_init_element (value, type, field, pending)
tree value, type, field;
int pending;
{
int duplicate = 0;
if (require_constant_value && ! TREE_CONSTANT (value))
{ {
next1 = integer_zero_node; error_init ("initializer element%s is not constant",
" for `%s'", NULL);
value = error_mark_node;
} }
else if (TREE_VALUE (tail) != 0) else if (require_constant_elements
&& initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
{ {
tree tail1 = tail; error_init ("initializer element%s is not computable at load time",
" for `%s'", NULL);
/* Build the name of this member, with a "." for membership. */ value = error_mark_node;
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 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; error_init ("duplicate initializer%s", " for `%s'", NULL);
tail = TREE_CHAIN (tail); 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) if (tail != 0)
erroneous = 1; {
else if (!TREE_CONSTANT (next1)) error_init ("duplicate initializer%s", " for `%s'", NULL);
allconstant = 0; duplicate = 1;
else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) }
allsimple = 0; }
}
/* Now store NEXT1 in the list, I elements from the *end*. /* If this element doesn't come next in sequence,
Make the list longer if necessary. */ put it on constructor_pending_elts. */
while (i >= members_length) if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& !tree_int_cst_equal (field, constructor_unfilled_index))
{ {
if (free_tree_list) 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)
{ {
TREE_CHAIN (free_tree_list) = members; if (!duplicate)
TREE_PURPOSE (free_tree_list) = NULL_TREE; constructor_pending_elts
TREE_VALUE (free_tree_list) = NULL_TREE; = tree_cons (field,
members = free_tree_list; digest_init (type, value, (tree *)NULL,
free_tree_list = NULL_TREE; require_constant_value,
require_constant_elements),
constructor_pending_elts);
} }
else else
members = tree_cons (NULL_TREE, NULL_TREE, members);
members_length++;
}
{ {
tree temp; /* Otherwise, output this element either to
int j; constructor_elements or to the assembler file. */
temp = members; if (!duplicate)
for (j = members_length - 1; j > i; j--) {
temp = TREE_CHAIN (temp); if (! constructor_incremental)
TREE_VALUE (temp) = next1; constructor_elements
TREE_PURPOSE (temp) = field; = 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));
} }
/* Advance the variable that indicates sequential elements output. */
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
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 (type) == UNION_TYPE) }
{
register tree field = TYPE_FIELDS (type);
register tree next1;
/* Find the first named field. ANSI decided in September 1990 /* Output any pending elements which have become next.
that only named fields count here. */ As we output elements, constructor_unfilled_{fields,index}
while (field && DECL_NAME (field) == 0) advances, which may cause other elements to become next;
field = TREE_CHAIN (field); if so, they too are output.
/* For a union, get the initializer for 1 fld. */ If ALL is 0, we return when there are
no more pending elements to output now.
if (tail == 0) 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))
{ {
error ("empty initializer for union"); output_init_element (TREE_VALUE (tail), TREE_TYPE (constructor_type),
tail = build_tree_list (0, 0); 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;
}
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);
}
} }
/* If this element specifies a field, initialize via that field. */ /* Ordinarily return, but not if we want to output all
if (TREE_PURPOSE (tail) != 0) and there are elements left. */
if (! (all && next != 0))
return;
/* Generate space up to the position of NEXT. */
if (constructor_incremental)
{ {
int win = 0; tree filled;
tree nextpos_tree;
if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL) if (TREE_CODE (constructor_type) == RECORD_TYPE
/* Handle the case of a call by build_c_cast. */ || TREE_CODE (constructor_type) == UNION_TYPE)
field = TREE_PURPOSE (tail), win = 1;
else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE)
error ("index value instead of field name in union initializer");
else
{ {
tree temp; /* Find the last field written out. */
for (temp = TYPE_FIELDS (type); for (tail = TYPE_FIELDS (constructor_type); tail;
temp; tail = TREE_CHAIN (tail))
temp = TREE_CHAIN (temp)) if (TREE_CHAIN (tail) == constructor_unfilled_fields)
if (DECL_NAME (temp) == TREE_PURPOSE (tail))
break; break;
if (temp) /* Find the offset of the end of that field. */
field = temp, win = 1; filled = size_binop (CEIL_DIV_EXPR,
else size_binop (PLUS_EXPR,
error ("no field `%s' in union being initialized", DECL_FIELD_BITPOS (tail),
IDENTIFIER_POINTER (TREE_PURPOSE (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;
} }
if (!win) else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
TREE_VALUE (tail) = error_mark_node; {
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 (TREE_VALUE (tail) != 0) if (filled)
{ {
tree tail1 = tail; int nextpos = TREE_INT_CST_LOW (nextpos_tree);
/* Build the name of this member, with a "." for membership. */ assemble_zeros (nextpos - TREE_INT_CST_LOW (filled));
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;
} }
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 else
break;
}
while (1)
{
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{ {
next1 = error_mark_node; tree fieldtype;
tail = TREE_CHAIN (tail); enum tree_code fieldcode;
if (constructor_fields == 0)
{
pedwarn_init ("excess elements in struct initializer%s",
" after `%s'", NULL_PTR);
break;
} }
if (next1 == error_mark_node) fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
erroneous = 1; fieldcode = TREE_CODE (fieldtype);
else if (!TREE_CONSTANT (next1))
allconstant = 0; if (value != 0 && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
allsimple = 0; || fieldcode == UNION_TYPE))
if (free_tree_list)
{ {
TREE_CHAIN (free_tree_list) = members; push_init_level (1);
TREE_PURPOSE (free_tree_list) = field; continue;
TREE_VALUE (free_tree_list) = next1;
members = free_tree_list;
free_tree_list = NULL_TREE;
} }
else
members = tree_cons (field, next1, members); 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);
/* If arguments were specified as a list, just remove the ones we used. */ constructor_fields = TREE_CHAIN (constructor_fields);
if (elts) break;
*elts = tail; }
/* If arguments were specified as a constructor, if (TREE_CODE (constructor_type) == UNION_TYPE)
complain unless we used all the elements of the constructor. */
else if (tail)
{ {
if (TREE_CODE (type) == UNION_TYPE) tree fieldtype;
enum tree_code fieldcode;
if (constructor_fields == 0)
{ {
pedwarn_init ("excess elements in union initializer%s", pedwarn_init ("excess elements in union initializer%s",
" after `%s'", NULL_PTR); " 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 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 aggregate initializer%s", pedwarn_init ("excess elements in array initializer%s",
" after `%s'", NULL_PTR); " after `%s'", NULL_PTR);
break;
} }
/* Now output the actual element.
Ordinarily, output once.
If there is a range, repeat it till we advance past the range. */
do
{
tree tem;
if (value)
{
push_array_bounds (TREE_INT_CST_LOW (constructor_index));
output_init_element (value, elttype, constructor_index, 1);
RESTORE_SPELLING_DEPTH (constructor_depth);
} }
/* It might be possible to use SAVE_SPELLING_DEPTH, but I suspect that tem = size_binop (PLUS_EXPR, constructor_index,
some preprocessor somewhere won't accept that much text as an argument. integer_one_node);
It's also likely to make debugging difficult. */ TREE_INT_CST_LOW (constructor_index)
= TREE_INT_CST_LOW (tem);
TREE_INT_CST_HIGH (constructor_index)
= TREE_INT_CST_HIGH (tem);
RESTORE_SPELLING_DEPTH (depth); 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 (erroneous) break;
return error_mark_node; }
if (elts) /* Handle the sole element allowed in a braced initializer
result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members)); for a scalar variable. */
else if (constructor_fields == 0)
{ {
result = init; pedwarn_init ("excess elements in scalar initializer%s",
CONSTRUCTOR_ELTS (result) = nreverse (members); " after `%s'", NULL_PTR);
TREE_TYPE (result) = type; break;
TREE_CONSTANT (result) = 0;
TREE_STATIC (result) = 0;
} }
if (allconstant) TREE_CONSTANT (result) = 1;
if (allconstant && allsimple) TREE_STATIC (result) = 1; if (value)
return result; output_init_element (value, constructor_type, NULL_TREE, 1);
constructor_fields = 0;
break;
}
/* 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 /* Expand an ASM statement with operands, handling output operands
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment