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
{
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) require_constant_value = TREE_STATIC (decl);
{ require_constant_elements = TREE_STATIC (decl) || pedantic;
if (! partial_bracket_mentioned) locus = IDENTIFIER_POINTER (DECL_NAME (decl));
warning ("aggregate has a partly bracketed initializer"); constructor_incremental |= TREE_STATIC (decl);
partial_bracket_mentioned = 1;
}
tail = *elts;
} }
else 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 constructor_stack = 0;
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) spelling_base = 0;
{ spelling_size = 0;
tree min_index, max_index; RESTORE_SPELLING_DEPTH (0);
/* 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 = &current_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;
}
TREE_INT_CST_LOW (members_index) = TREE_INT_CST_LOW (min_index); if (locus)
TREE_INT_CST_HIGH (members_index) = TREE_INT_CST_HIGH (min_index); push_string (locus);
}
/* Don't leave the loop based on index if the next item has an explicit void
index value that will override it. */ finish_init ()
{
struct initializer_stack *p = initializer_stack;
for (TREE_INT_CST_LOW (current_index) = TREE_INT_CST_LOW (min_index), /* Output subconstants (string constants, usually)
TREE_INT_CST_HIGH (current_index) = TREE_INT_CST_HIGH (min_index); that were referenced within this initializer and saved up.
tail != 0 || end_index; Must do this if and only if we called defer_addressed_constants. */
add_double (TREE_INT_CST_LOW (current_index), if (constructor_subconstants_deferred)
TREE_INT_CST_HIGH (current_index), 1, 0, output_deferred_addressed_constants ();
&TREE_INT_CST_LOW (current_index),
&TREE_INT_CST_HIGH (current_index)))
{
register tree next1 = 0;
/* Handle the case where we are inside of a range. /* Free the whole constructor stack of this initializer. */
current_index increments through the range, while (constructor_stack)
so just keep reusing the same element of TAIL {
until the end of the range. */ struct constructor_stack *q = constructor_stack;
if (end_index != 0) constructor_stack = q->next;
{ free (q);
next1 = range_val; }
if (!tree_int_cst_lt (current_index, end_index))
end_index = 0;
}
/* If this element specifies an index, /* Pop back to the data of the outer initializer (if any). */
move to that index before storing it in the new list. */ constructor_decl = p->decl;
else if (TREE_PURPOSE (tail) != 0) constructor_asmspec = p->asmspec;
{ constructor_incremental = p->incremental;
int win = 0; require_constant_value = p->require_constant_value;
tree index = TREE_PURPOSE (tail); 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 TYPE is the type to initialize, for a constructor expression.
|| TREE_CODE (index) == NOP_EXPR)) For an initializer for a decl, TYPE is zero. */
index = TREE_OPERAND (index, 0);
/* Begin a range. */ void
if (TREE_CODE (index) == TREE_LIST) really_start_incremental_init (type)
{ tree type;
start_index = TREE_PURPOSE (index); {
end_index = TREE_PURPOSE (TREE_CHAIN (index)); struct constructor_stack *p
= (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
/* Expose constants. It Doesn't matter if we change
the mode.*/ if (type == 0)
if (end_index type = TREE_TYPE (constructor_decl);
&& (TREE_CODE (end_index) == NON_LVALUE_EXPR
|| TREE_CODE (end_index) == NOP_EXPR)) /* Turn off constructor_incremental if type is a struct with bitfields.
end_index = TREE_OPERAND (end_index, 0); Do this before the first push, so that the corrected value
if (start_index is available in finish_init. */
&& (TREE_CODE (start_index) == NON_LVALUE_EXPR check_init_type_bitfields (type);
|| TREE_CODE (start_index) == NOP_EXPR))
start_index = TREE_OPERAND (start_index, 0); p->type = constructor_type;
p->fields = constructor_fields;
constant_expression_warning (start_index); p->index = constructor_index;
constant_expression_warning (end_index); p->range_end = constructor_range_end;
p->max_index = constructor_max_index;
if ((TREE_CODE (start_index) == IDENTIFIER_NODE) p->unfilled_index = constructor_unfilled_index;
|| (TREE_CODE (end_index) == IDENTIFIER_NODE)) p->unfilled_fields = constructor_unfilled_fields;
error ("field name used as index in array initializer"); p->elements = 0;
else if ((TREE_CODE (start_index) != INTEGER_CST) p->constant = constructor_constant;
|| (TREE_CODE (end_index) != INTEGER_CST)) p->simple = constructor_simple;
error ("non-constant or non-integer array index in initializer"); p->erroneous = constructor_erroneous;
else if (tree_int_cst_lt (start_index, min_index) p->pending_elts = constructor_pending_elts;
|| (max_index && tree_int_cst_lt (max_index, start_index)) p->depth = constructor_depth;
|| tree_int_cst_lt (end_index, min_index) p->implicit = 0;
|| (max_index && tree_int_cst_lt (max_index, end_index))) p->incremental = constructor_incremental;
error ("array index out of range in initializer"); p->outer = 0;
else if (tree_int_cst_lt (end_index, start_index)) p->next = 0;
{ constructor_stack = p;
/* If the range is empty, don't initialize any elements,
but do reset current_index for the next initializer constructor_constant = 1;
element. */ constructor_simple = 1;
warning ("empty array initializer range"); constructor_depth = SPELLING_DEPTH ();
tail = TREE_CHAIN (tail); constructor_elements = 0;
TREE_INT_CST_LOW (current_index) constructor_pending_elts = 0;
= TREE_INT_CST_LOW (end_index); constructor_type = type;
TREE_INT_CST_HIGH (current_index)
= TREE_INT_CST_HIGH (end_index); if (TREE_CODE (constructor_type) == RECORD_TYPE
continue; || TREE_CODE (constructor_type) == UNION_TYPE)
} {
else constructor_fields = TYPE_FIELDS (constructor_type);
{ constructor_unfilled_fields = constructor_fields;
TREE_INT_CST_LOW (current_index) }
= TREE_INT_CST_LOW (start_index); else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
TREE_INT_CST_HIGH (current_index) {
= TREE_INT_CST_HIGH (start_index); constructor_index = copy_node (integer_zero_node);
win = 1; constructor_range_end = 0;
/* See if the first element is also the last. */ constructor_unfilled_index = copy_node (integer_zero_node);
if (!tree_int_cst_lt (current_index, end_index)) if (TYPE_DOMAIN (constructor_type))
end_index = 0; constructor_max_index
} = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
} }
else if (TREE_CODE (index) == IDENTIFIER_NODE) else
error ("field name used as index in array initializer"); {
else if (TREE_CODE (index) != INTEGER_CST) /* Handle the case of int x = {5}; */
error ("non-constant array index in initializer"); constructor_fields = constructor_type;
else if (tree_int_cst_lt (index, min_index) constructor_unfilled_fields = constructor_type;
|| (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 (max_index && tree_int_cst_lt (max_index, current_index)) if (constructor_incremental)
break; /* Stop if we've indeed run out of elements. */ {
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. */ void
if (next1 != 0) push_init_level (implicit)
; int implicit;
else if (TREE_VALUE (tail) != 0) {
{ struct constructor_stack *p
tree tail1 = tail; = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
p->type = constructor_type;
/* Build the element of this array, with "[]" notation. For p->fields = constructor_fields;
error messages, we assume that the index fits within a p->index = constructor_index;
host int. */ p->range_end = constructor_range_end;
SAVE_SPELLING_DEPTH p->max_index = constructor_max_index;
({ p->unfilled_index = constructor_unfilled_index;
push_array_bounds (TREE_INT_CST_LOW (current_index)); p->unfilled_fields = constructor_unfilled_fields;
next1 = digest_init (TYPE_MAIN_VARIANT (TREE_TYPE (type)), p->elements = constructor_elements;
TREE_VALUE (tail), &tail1, p->constant = constructor_constant;
/* Both of these are the same because p->simple = constructor_simple;
a value here is an elt overall. */ p->erroneous = constructor_erroneous;
constant_element, constant_element, p->pending_elts = constructor_pending_elts;
NULL_PTR); p->depth = constructor_depth;
}); p->implicit = implicit;
p->incremental = constructor_incremental;
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) p->outer = 0;
abort (); p->next = constructor_stack;
if (tail == tail1 && TYPE_DOMAIN (type) == 0) constructor_stack = p;
{
error_init ( constructor_constant = 1;
"non-empty initializer for array%s of empty elements", constructor_simple = 1;
" `%s'", NULL_PTR); constructor_depth = SPELLING_DEPTH ();
/* Just ignore what we were supposed to use. */ constructor_elements = 0;
tail1 = 0; constructor_pending_elts = 0;
}
tail = tail1; if (TREE_CODE (constructor_type) == RECORD_TYPE
} || TREE_CODE (constructor_type) == UNION_TYPE)
else {
{ constructor_type = TREE_TYPE (constructor_fields);
next1 = error_mark_node; push_member_name (IDENTIFIER_POINTER (DECL_NAME (constructor_fields)));
tail = TREE_CHAIN (tail); }
} 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) /* Turn off constructor_incremental if type is a struct with bitfields. */
range_val = next1; check_init_type_bitfields (constructor_type);
if (next1 == error_mark_node) if (TREE_CODE (constructor_type) == RECORD_TYPE
erroneous = 1; || TREE_CODE (constructor_type) == UNION_TYPE)
else if (!TREE_CONSTANT (next1)) {
allconstant = 0; constructor_fields = TYPE_FIELDS (constructor_type);
else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) constructor_unfilled_fields = constructor_fields;
allsimple = 0; }
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*. /* Don't read a struct incrementally if it has any bitfields,
Make the list longer if necessary. */ because the incremental reading code doesn't know how to
while (! tree_int_cst_lt (current_index, members_index)) handle bitfields yet. */
{
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));
}
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; constructor_incremental = 0;
union tree_node idx_node; break;
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;
} }
}
} }
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; /* When we come to an explicit close brace,
int members_length = 0; pop any inner levels that didn't have explicit braces. */
int i; 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 p = constructor_stack;
overrides the expected field first. */ size = int_size_in_bytes (constructor_type);
for (field = TYPE_FIELDS (type), i = 0; tail; /* Now output all pending elements. */
field = TREE_CHAIN (field), i++) 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, if (TREE_CODE (constructor_type) == RECORD_TYPE
move to that field before storing it in the new list. */ || TREE_CODE (constructor_type) == UNION_TYPE)
if (TREE_PURPOSE (tail) != 0) {
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) if (pedantic
error ("index value instead of field name in structure initializer"); && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)),
else integer_zero_node))
{ error_with_decl (constructor_decl, "zero-size array `%s'");
tree temp; layout_type (constructor_type);
int j; size = int_size_in_bytes (constructor_type);
for (temp = TYPE_FIELDS (type), j = 0; pop_obstacks ();
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 (field == 0) filled = size_binop (MULT_EXPR, constructor_unfilled_index,
break; /* No more fields to init. */ size_in_bytes (TREE_TYPE (constructor_type)));
}
else
filled = 0;
if (! DECL_NAME (field)) if (filled != 0)
{ assemble_zeros (size - TREE_INT_CST_LOW (filled));
next1 = integer_zero_node;
} resume_momentary (momentary);
else if (TREE_VALUE (tail) != 0) }
{
tree tail1 = tail;
constructor_type = p->type;
/* Build the name of this member, with a "." for membership. */ constructor_fields = p->fields;
SAVE_SPELLING_DEPTH constructor_index = p->index;
({ constructor_range_end = p->range_end;
push_member_name (IDENTIFIER_POINTER (DECL_NAME (field))); constructor_max_index = p->max_index;
next1 = digest_init (TREE_TYPE (field), constructor_unfilled_index = p->unfilled_index;
TREE_VALUE (tail), &tail1, constructor_unfilled_fields = p->unfilled_fields;
constant_element, constant_element, constructor_elements = p->elements;
NULL_PTR); constructor_constant = p->constant;
}); constructor_simple = p->simple;
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) constructor_erroneous = p->erroneous;
abort (); constructor_pending_elts = p->pending_elts;
tail = tail1; constructor_depth = p->depth;
} constructor_incremental = p->incremental;
else 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; 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))
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 (free_tree_list) error_init ("duplicate initializer%s", " for `%s'", NULL);
{ duplicate = 1;
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++;
} }
{
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"); if (! constructor_incremental)
tail = build_tree_list (0, 0); 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. */ /* Advance the variable that indicates sequential elements output. */
if (TREE_PURPOSE (tail) != 0) 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) /* Output any pending elements which have become next.
/* Handle the case of a call by build_c_cast. */ As we output elements, constructor_unfilled_{fields,index}
field = TREE_PURPOSE (tail), win = 1; advances, which may cause other elements to become next;
else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE) if so, they too are output.
error ("index value instead of field name in union initializer");
else 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; output_init_element (TREE_VALUE (tail), TREE_TYPE (constructor_type),
for (temp = TYPE_FIELDS (type); constructor_unfilled_index, 0);
temp; goto retry;
temp = TREE_CHAIN (temp)) }
if (DECL_NAME (temp) == TREE_PURPOSE (tail)) else if (tree_int_cst_lt (TREE_PURPOSE (tail),
break; constructor_unfilled_index))
if (temp) ;
field = temp, win = 1; else if (next == 0
else || tree_int_cst_lt (TREE_PURPOSE (tail),
error ("no field `%s' in union being initialized", next))
IDENTIFIER_POINTER (TREE_PURPOSE (tail))); 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) else if (tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)),
TREE_VALUE (tail) = error_mark_node; 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; /* Find the last field written out. */
for (tail = TYPE_FIELDS (constructor_type); tail;
/* Build the name of this member, with a "." for membership. */ tail = TREE_CHAIN (tail))
SAVE_SPELLING_DEPTH if (TREE_CHAIN (tail) == constructor_unfilled_fields)
({ break;
push_member_name (IDENTIFIER_POINTER (DECL_NAME (field))); /* Find the offset of the end of that field. */
next1 = digest_init (TREE_TYPE (field), filled = size_binop (CEIL_DIV_EXPR,
TREE_VALUE (tail), &tail1, size_binop (PLUS_EXPR,
constant_value, constant_element, NULL_PTR); DECL_FIELD_BITPOS (tail),
}); DECL_SIZE (tail)),
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) size_int (BITS_PER_UNIT));
abort (); nextpos_tree = size_binop (CEIL_DIV_EXPR,
tail = tail1; 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; filled = size_binop (MULT_EXPR, constructor_unfilled_index,
tail = TREE_CHAIN (tail); 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) if (filled)
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)
{ {
TREE_CHAIN (free_tree_list) = members; int nextpos = TREE_INT_CST_LOW (nextpos_tree);
TREE_PURPOSE (free_tree_list) = field;
TREE_VALUE (free_tree_list) = next1; assemble_zeros (nextpos - TREE_INT_CST_LOW (filled));
members = free_tree_list;
free_tree_list = NULL_TREE;
} }
}
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
members = tree_cons (field, next1, members); break;
} }
/* If arguments were specified as a list, just remove the ones we used. */ while (1)
if (elts)
*elts = tail;
/* If arguments were specified as a constructor,
complain unless we used all the elements of the constructor. */
else if (tail)
{ {
if (TREE_CODE (type) == UNION_TYPE) if (TREE_CODE (constructor_type) == RECORD_TYPE)
{ {
pedwarn_init ("excess elements in union initializer%s", tree fieldtype;
" after `%s'", NULL_PTR); 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", tree fieldtype;
" after `%s'", NULL_PTR); 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 /* Now output the actual element.
some preprocessor somewhere won't accept that much text as an argument. Ordinarily, output once.
It's also likely to make debugging difficult. */ 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) tem = size_binop (PLUS_EXPR, constructor_index,
return error_mark_node; 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) break;
result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members)); }
else
{ /* Handle the sole element allowed in a braced initializer
result = init; for a scalar variable. */
CONSTRUCTOR_ELTS (result) = nreverse (members); if (constructor_fields == 0)
TREE_TYPE (result) = type; {
TREE_CONSTANT (result) = 0; pedwarn_init ("excess elements in scalar initializer%s",
TREE_STATIC (result) = 0; " 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; /* If the (lexically) previous elments are not now saved,
return result; 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