Commit 8b6a5902 by Jakub Jelinek Committed by Jakub Jelinek

c-typeck.c (store_init_value): Don't require constant initializer elements with -pedantic -std=c99.

	* c-typeck.c (store_init_value): Don't require constant initializer
	elements with -pedantic -std=c99.
	(digest_init): Change error about non-constant initializer elements
	into pedwarn.
	(constructor_range_end): Remove.
	(constructor_incremental, designator_depth,
	designator_errorneous): New variables.
	(struct constructor_stack): Remove range_end, add incremental.
	(struct constructor_range_stack, constructor_range_stack): New.
	(struct initializer_stack): Add constructor_range_stack.
	(finish_init): Set it.
	(start_init): Likewise.  require_constant_elements for non-static
	trees only if not flag_isoc99.
	(really_start_incremental_init): Remove constructor_range_end, add
	constructor_incremental.
	(pop_init_level): Likewise.
	(push_init_level): Likewise.  If implicit and the subobject had some
	value set already, preinitialize the level with it.
	Warn about missing braces only if not pushing due to designators.
	(set_designator, push_range_stack): New functions.
	(set_init_label): Use them.
	(set_init_index): Likewise.  Remove constructor_range_end.
	Error if designator index is outside of array bounds.
	(add_pending_init): Compare values of purpose index trees, not the
	trees themselves.  Allow overwriting of already initialized element.
	Issue a warning if it had side-effects.
	(set_nonincremental_init, set_nonincremental_init_from_string): New
	functions.
	(pending_init_member): Rename to...
	(find_init_member): ...this function.  Call set_nonincremental_init
	if necessary.  Compare values of purpose index trees, not the trees
	themselves.  Return the actual value, not just non-zero if something
	is found.
	(output_init_element): Remove checks for duplicates.
	If field has zero size, only check the initializer for correctness.
	Call set_nonincremental_init if necessary.  Push RECORD/ARRAY into AVL
	if constructor_incremental is zero.  Change error about initializers
	not computable at load time into pedwarn.
	(output_pending_init_elements): Compare bit positions, not
	FIELD_DECLs to take into account zero-sized fields.
	(process_init_element): Use constructor_range_stack to fill all
	ranges in the designator lists from current level up.
	* extend.texi: Update documentation for labeled elements.

	* gcc.c-torture/execute/20000801-3.x: Remove.
	* gcc.dg/c90-init-1.c: New test.
	* gcc.dg/c99-init-1.c: New test.
	* gcc.dg/c99-init-2.c: New test.
	* gcc.dg/gnu99-init-1.c: New test.

From-SVN: r38968
parent fafc249b
2001-01-12 Jakub Jelinek <jakub@redhat.com>
* c-typeck.c (store_init_value): Don't require constant initializer
elements with -pedantic -std=c99.
(digest_init): Change error about non-constant initializer elements
into pedwarn.
(constructor_range_end): Remove.
(constructor_incremental, designator_depth,
designator_errorneous): New variables.
(struct constructor_stack): Remove range_end, add incremental.
(struct constructor_range_stack, constructor_range_stack): New.
(struct initializer_stack): Add constructor_range_stack.
(finish_init): Set it.
(start_init): Likewise. require_constant_elements for non-static
trees only if not flag_isoc99.
(really_start_incremental_init): Remove constructor_range_end, add
constructor_incremental.
(pop_init_level): Likewise.
(push_init_level): Likewise. If implicit and the subobject had some
value set already, preinitialize the level with it.
Warn about missing braces only if not pushing due to designators.
(set_designator, push_range_stack): New functions.
(set_init_label): Use them.
(set_init_index): Likewise. Remove constructor_range_end.
Error if designator index is outside of array bounds.
(add_pending_init): Compare values of purpose index trees, not the
trees themselves. Allow overwriting of already initialized element.
Issue a warning if it had side-effects.
(set_nonincremental_init, set_nonincremental_init_from_string): New
functions.
(pending_init_member): Rename to...
(find_init_member): ...this function. Call set_nonincremental_init
if necessary. Compare values of purpose index trees, not the trees
themselves. Return the actual value, not just non-zero if something
is found.
(output_init_element): Remove checks for duplicates.
If field has zero size, only check the initializer for correctness.
Call set_nonincremental_init if necessary. Push RECORD/ARRAY into AVL
if constructor_incremental is zero. Change error about initializers
not computable at load time into pedwarn.
(output_pending_init_elements): Compare bit positions, not
FIELD_DECLs to take into account zero-sized fields.
(process_init_element): Use constructor_range_stack to fill all
ranges in the designator lists from current level up.
* extend.texi: Update documentation for labeled elements.
2001-01-12 Alexandre Oliva <aoliva@redhat.com> 2001-01-12 Alexandre Oliva <aoliva@redhat.com>
* calls.c (emit_library_call_value_1): Add USEs and CLOBBERs * calls.c (emit_library_call_value_1): Add USEs and CLOBBERs
......
...@@ -76,8 +76,12 @@ static void warning_init PARAMS ((const char *)); ...@@ -76,8 +76,12 @@ static void warning_init PARAMS ((const char *));
static tree digest_init PARAMS ((tree, tree, int, int)); static tree digest_init PARAMS ((tree, tree, int, int));
static void output_init_element PARAMS ((tree, tree, tree, int)); static void output_init_element PARAMS ((tree, tree, tree, int));
static void output_pending_init_elements PARAMS ((int)); static void output_pending_init_elements PARAMS ((int));
static int set_designator PARAMS ((int));
static void push_range_stack PARAMS ((tree));
static void add_pending_init PARAMS ((tree, tree)); static void add_pending_init PARAMS ((tree, tree));
static int pending_init_member PARAMS ((tree)); static void set_nonincremental_init PARAMS ((void));
static void set_nonincremental_init_from_string PARAMS ((tree));
static tree find_init_member PARAMS ((tree));
/* 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.) */
...@@ -4410,7 +4414,7 @@ store_init_value (decl, init) ...@@ -4410,7 +4414,7 @@ store_init_value (decl, init)
/* Digest the specified initializer into an expression. */ /* Digest the specified initializer into an expression. */
value = digest_init (type, init, TREE_STATIC (decl), value = digest_init (type, init, TREE_STATIC (decl),
TREE_STATIC (decl) || pedantic); TREE_STATIC (decl) || (pedantic && !flag_isoc99));
/* Store the expression if valid; else report error. */ /* Store the expression if valid; else report error. */
...@@ -4769,10 +4773,7 @@ digest_init (type, init, require_constant, constructor_constant) ...@@ -4769,10 +4773,7 @@ digest_init (type, init, require_constant, constructor_constant)
} }
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)
{ pedwarn ("initializer element is not computable at load time");
error_init ("initializer element is not computable at load time");
inside_init = error_mark_node;
}
return inside_init; return inside_init;
} }
...@@ -4868,11 +4869,6 @@ static tree constructor_fields; ...@@ -4868,11 +4869,6 @@ static tree constructor_fields;
at which to store the next element we get. */ at which to store the next element we get. */
static tree constructor_index; static tree constructor_index;
/* For an ARRAY_TYPE, this is the end index of the range
to initialize with the next element, or NULL in the ordinary case
where the element is used just once. */
static tree constructor_range_end;
/* For an ARRAY_TYPE, this is the maximum index. */ /* For an ARRAY_TYPE, this is the maximum index. */
static tree constructor_max_index; static tree constructor_max_index;
...@@ -4892,6 +4888,10 @@ static tree constructor_bit_index; ...@@ -4892,6 +4888,10 @@ static tree constructor_bit_index;
most recent first). */ most recent first). */
static tree constructor_elements; static tree constructor_elements;
/* 1 if constructor should be incrementally stored into a constructor chain,
0 if all the elements should be kept in AVL tree. */
static int constructor_incremental;
/* 1 if so far this constructor's elements are all compile-time constants. */ /* 1 if so far this constructor's elements are all compile-time constants. */
static int constructor_constant; static int constructor_constant;
...@@ -4943,6 +4943,12 @@ static const char *constructor_asmspec; ...@@ -4943,6 +4943,12 @@ static const char *constructor_asmspec;
/* Nonzero if this is an initializer for a top-level decl. */ /* Nonzero if this is an initializer for a top-level decl. */
static int constructor_top_level; static int constructor_top_level;
/* Nesting depth of designator list. */
static int designator_depth;
/* Nonzero if there were diagnosed errors in this designator list. */
static int designator_errorneous;
/* This stack has a level for each implicit or explicit level of /* This stack has a level for each implicit or explicit level of
structuring in the initializer, including the outermost one. It structuring in the initializer, including the outermost one. It
...@@ -4954,7 +4960,6 @@ struct constructor_stack ...@@ -4954,7 +4960,6 @@ struct constructor_stack
tree type; tree type;
tree fields; tree fields;
tree index; tree index;
tree range_end;
tree max_index; tree max_index;
tree unfilled_index; tree unfilled_index;
tree unfilled_fields; tree unfilled_fields;
...@@ -4971,10 +4976,26 @@ struct constructor_stack ...@@ -4971,10 +4976,26 @@ struct constructor_stack
char implicit; char implicit;
char erroneous; char erroneous;
char outer; char outer;
char incremental;
}; };
struct constructor_stack *constructor_stack; struct constructor_stack *constructor_stack;
/* This stack represents designators from some range designator up to
the last designator in the list. */
struct constructor_range_stack
{
struct constructor_range_stack *next, *prev;
struct constructor_stack *stack;
tree range_start;
tree index;
tree range_end;
tree fields;
};
struct constructor_range_stack *constructor_range_stack;
/* This stack records separate initializers that are nested. /* This stack records separate initializers that are nested.
Nested initializers can't happen in ANSI C, but GNU C allows them Nested initializers can't happen in ANSI C, but GNU C allows them
in cases like { ... (struct foo) { ... } ... }. */ in cases like { ... (struct foo) { ... } ... }. */
...@@ -4985,6 +5006,7 @@ struct initializer_stack ...@@ -4985,6 +5006,7 @@ struct initializer_stack
tree decl; tree decl;
const char *asmspec; const char *asmspec;
struct constructor_stack *constructor_stack; struct constructor_stack *constructor_stack;
struct constructor_range_stack *constructor_range_stack;
tree elements; tree elements;
struct spelling *spelling; struct spelling *spelling;
struct spelling *spelling_base; struct spelling *spelling_base;
...@@ -5018,6 +5040,7 @@ start_init (decl, asmspec_tree, top_level) ...@@ -5018,6 +5040,7 @@ start_init (decl, asmspec_tree, top_level)
p->require_constant_value = require_constant_value; p->require_constant_value = require_constant_value;
p->require_constant_elements = require_constant_elements; p->require_constant_elements = require_constant_elements;
p->constructor_stack = constructor_stack; p->constructor_stack = constructor_stack;
p->constructor_range_stack = constructor_range_stack;
p->elements = constructor_elements; p->elements = constructor_elements;
p->spelling = spelling; p->spelling = spelling;
p->spelling_base = spelling_base; p->spelling_base = spelling_base;
...@@ -5036,7 +5059,7 @@ start_init (decl, asmspec_tree, top_level) ...@@ -5036,7 +5059,7 @@ start_init (decl, asmspec_tree, top_level)
{ {
require_constant_value = TREE_STATIC (decl); require_constant_value = TREE_STATIC (decl);
require_constant_elements require_constant_elements
= ((TREE_STATIC (decl) || pedantic) = ((TREE_STATIC (decl) || (pedantic && !flag_isoc99))
/* For a scalar, you can always use any value to initialize, /* For a scalar, you can always use any value to initialize,
even within braces. */ even within braces. */
&& (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE && (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
...@@ -5053,6 +5076,7 @@ start_init (decl, asmspec_tree, top_level) ...@@ -5053,6 +5076,7 @@ start_init (decl, asmspec_tree, top_level)
} }
constructor_stack = 0; constructor_stack = 0;
constructor_range_stack = 0;
missing_braces_mentioned = 0; missing_braces_mentioned = 0;
...@@ -5083,12 +5107,16 @@ finish_init () ...@@ -5083,12 +5107,16 @@ finish_init ()
free (q); free (q);
} }
if (constructor_range_stack)
abort ();
/* Pop back to the data of the outer initializer (if any). */ /* Pop back to the data of the outer initializer (if any). */
constructor_decl = p->decl; constructor_decl = p->decl;
constructor_asmspec = p->asmspec; constructor_asmspec = p->asmspec;
require_constant_value = p->require_constant_value; require_constant_value = p->require_constant_value;
require_constant_elements = p->require_constant_elements; require_constant_elements = p->require_constant_elements;
constructor_stack = p->constructor_stack; constructor_stack = p->constructor_stack;
constructor_range_stack = p->constructor_range_stack;
constructor_elements = p->elements; constructor_elements = p->elements;
spelling = p->spelling; spelling = p->spelling;
spelling_base = p->spelling_base; spelling_base = p->spelling_base;
...@@ -5119,7 +5147,6 @@ really_start_incremental_init (type) ...@@ -5119,7 +5147,6 @@ really_start_incremental_init (type)
p->type = constructor_type; p->type = constructor_type;
p->fields = constructor_fields; p->fields = constructor_fields;
p->index = constructor_index; p->index = constructor_index;
p->range_end = constructor_range_end;
p->max_index = constructor_max_index; p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index; p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields; p->unfilled_fields = constructor_unfilled_fields;
...@@ -5133,6 +5160,7 @@ really_start_incremental_init (type) ...@@ -5133,6 +5160,7 @@ really_start_incremental_init (type)
p->replacement_value = 0; p->replacement_value = 0;
p->implicit = 0; p->implicit = 0;
p->outer = 0; p->outer = 0;
p->incremental = constructor_incremental;
p->next = 0; p->next = 0;
constructor_stack = p; constructor_stack = p;
...@@ -5142,6 +5170,9 @@ really_start_incremental_init (type) ...@@ -5142,6 +5170,9 @@ really_start_incremental_init (type)
constructor_elements = 0; constructor_elements = 0;
constructor_pending_elts = 0; constructor_pending_elts = 0;
constructor_type = type; constructor_type = type;
constructor_incremental = 1;
designator_depth = 0;
designator_errorneous = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE) || TREE_CODE (constructor_type) == UNION_TYPE)
...@@ -5157,7 +5188,6 @@ really_start_incremental_init (type) ...@@ -5157,7 +5188,6 @@ really_start_incremental_init (type)
} }
else if (TREE_CODE (constructor_type) == ARRAY_TYPE) else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{ {
constructor_range_end = 0;
if (TYPE_DOMAIN (constructor_type)) if (TYPE_DOMAIN (constructor_type))
{ {
constructor_max_index constructor_max_index
...@@ -5187,13 +5217,14 @@ really_start_incremental_init (type) ...@@ -5187,13 +5217,14 @@ really_start_incremental_init (type)
/* Push down into a subobject, for initialization. /* Push down into a subobject, for initialization.
If this is for an explicit set of braces, IMPLICIT is 0. If this is for an explicit set of braces, IMPLICIT is 0.
If it is because the next element belongs at a lower level, If it is because the next element belongs at a lower level,
IMPLICIT is 1. */ IMPLICIT is 1 (or 2 if the push is because of designator list). */
void void
push_init_level (implicit) push_init_level (implicit)
int implicit; int implicit;
{ {
struct constructor_stack *p; struct constructor_stack *p;
tree value = NULL_TREE;
/* If we've exhausted any levels that didn't have braces, /* If we've exhausted any levels that didn't have braces,
pop them now. */ pop them now. */
...@@ -5210,11 +5241,22 @@ push_init_level (implicit) ...@@ -5210,11 +5241,22 @@ push_init_level (implicit)
break; break;
} }
/* Unless this is an explicit brace, we need to preserve previous
content if any. */
if (implicit)
{
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields)
value = find_init_member (constructor_fields);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
value = find_init_member (constructor_index);
}
p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack)); p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
p->type = constructor_type; p->type = constructor_type;
p->fields = constructor_fields; p->fields = constructor_fields;
p->index = constructor_index; p->index = constructor_index;
p->range_end = constructor_range_end;
p->max_index = constructor_max_index; p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index; p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields; p->unfilled_fields = constructor_unfilled_fields;
...@@ -5228,6 +5270,7 @@ push_init_level (implicit) ...@@ -5228,6 +5270,7 @@ push_init_level (implicit)
p->replacement_value = 0; p->replacement_value = 0;
p->implicit = implicit; p->implicit = implicit;
p->outer = 0; p->outer = 0;
p->incremental = constructor_incremental;
p->next = constructor_stack; p->next = constructor_stack;
constructor_stack = p; constructor_stack = p;
...@@ -5235,7 +5278,13 @@ push_init_level (implicit) ...@@ -5235,7 +5278,13 @@ push_init_level (implicit)
constructor_simple = 1; constructor_simple = 1;
constructor_depth = SPELLING_DEPTH (); constructor_depth = SPELLING_DEPTH ();
constructor_elements = 0; constructor_elements = 0;
constructor_incremental = 1;
constructor_pending_elts = 0; constructor_pending_elts = 0;
if (!implicit)
{
designator_depth = 0;
designator_errorneous = 0;
}
/* Don't die if an entire brace-pair level is superfluous /* Don't die if an entire brace-pair level is superfluous
in the containing level. */ in the containing level. */
...@@ -5269,7 +5318,18 @@ push_init_level (implicit) ...@@ -5269,7 +5318,18 @@ push_init_level (implicit)
return; return;
} }
if (implicit && warn_missing_braces && !missing_braces_mentioned) if (value && TREE_CODE (value) == CONSTRUCTOR)
{
constructor_constant = TREE_CONSTANT (value);
constructor_simple = TREE_STATIC (value);
constructor_elements = TREE_OPERAND (value, 1);
if (constructor_elements
&& (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == ARRAY_TYPE))
set_nonincremental_init ();
}
if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
{ {
missing_braces_mentioned = 1; missing_braces_mentioned = 1;
warning_init ("missing braces around initializer"); warning_init ("missing braces around initializer");
...@@ -5289,7 +5349,6 @@ push_init_level (implicit) ...@@ -5289,7 +5349,6 @@ push_init_level (implicit)
} }
else if (TREE_CODE (constructor_type) == ARRAY_TYPE) else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{ {
constructor_range_end = 0;
if (TYPE_DOMAIN (constructor_type)) if (TYPE_DOMAIN (constructor_type))
{ {
constructor_max_index constructor_max_index
...@@ -5307,6 +5366,13 @@ push_init_level (implicit) ...@@ -5307,6 +5366,13 @@ push_init_level (implicit)
constructor_index = bitsize_zero_node; constructor_index = bitsize_zero_node;
constructor_unfilled_index = constructor_index; constructor_unfilled_index = constructor_index;
if (value && TREE_CODE (value) == STRING_CST)
{
/* We need to split the char/wchar array into individual
characters, so that we don't have to special case it
everywhere. */
set_nonincremental_init_from_string (value);
}
} }
else else
{ {
...@@ -5406,6 +5472,7 @@ pop_init_level (implicit) ...@@ -5406,6 +5472,7 @@ pop_init_level (implicit)
} }
/* Now output all pending elements. */ /* Now output all pending elements. */
constructor_incremental = 1;
output_pending_init_elements (1); output_pending_init_elements (1);
/* Pad out the end of the structure. */ /* Pad out the end of the structure. */
...@@ -5423,6 +5490,7 @@ pop_init_level (implicit) ...@@ -5423,6 +5490,7 @@ pop_init_level (implicit)
the element, after verifying there is just one. */ the element, after verifying there is just one. */
if (constructor_elements == 0) if (constructor_elements == 0)
{ {
if (!constructor_erroneous)
error_init ("empty scalar initializer"); error_init ("empty scalar initializer");
constructor = error_mark_node; constructor = error_mark_node;
} }
...@@ -5452,7 +5520,6 @@ pop_init_level (implicit) ...@@ -5452,7 +5520,6 @@ pop_init_level (implicit)
constructor_type = p->type; constructor_type = p->type;
constructor_fields = p->fields; constructor_fields = p->fields;
constructor_index = p->index; constructor_index = p->index;
constructor_range_end = p->range_end;
constructor_max_index = p->max_index; constructor_max_index = p->max_index;
constructor_unfilled_index = p->unfilled_index; constructor_unfilled_index = p->unfilled_index;
constructor_unfilled_fields = p->unfilled_fields; constructor_unfilled_fields = p->unfilled_fields;
...@@ -5461,6 +5528,7 @@ pop_init_level (implicit) ...@@ -5461,6 +5528,7 @@ pop_init_level (implicit)
constructor_constant = p->constant; constructor_constant = p->constant;
constructor_simple = p->simple; constructor_simple = p->simple;
constructor_erroneous = p->erroneous; constructor_erroneous = p->erroneous;
constructor_incremental = p->incremental;
constructor_pending_elts = p->pending_elts; constructor_pending_elts = p->pending_elts;
constructor_depth = p->depth; constructor_depth = p->depth;
RESTORE_SPELLING_DEPTH (constructor_depth); RESTORE_SPELLING_DEPTH (constructor_depth);
...@@ -5477,6 +5545,97 @@ pop_init_level (implicit) ...@@ -5477,6 +5545,97 @@ pop_init_level (implicit)
return constructor; return constructor;
} }
/* Common handling for both array range and field name designators.
ARRAY argument is non-zero for array ranges. Returns zero for success. */
static int
set_designator (array)
int array;
{
tree subtype;
enum tree_code subcode;
/* Don't die if an entire brace-pair level is superfluous
in the containing level. */
if (constructor_type == 0)
return 1;
/* If there were errors in this designator list already, bail out silently. */
if (designator_errorneous)
return 1;
if (!designator_depth)
{
if (constructor_range_stack)
abort ();
/* Designator list starts at the level of closest explicit
braces. */
while (constructor_stack->implicit)
process_init_element (pop_init_level (1));
return 0;
}
if (constructor_no_implicit)
{
error_init ("initialization designators may not nest");
return 1;
}
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
subtype = TREE_TYPE (constructor_fields);
if (subtype != error_mark_node)
subtype = TYPE_MAIN_VARIANT (subtype);
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
}
else
abort ();
subcode = TREE_CODE (subtype);
if (array && subcode != ARRAY_TYPE)
{
error_init ("array index in non-array initializer");
return 1;
}
else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
{
error_init ("field name not in record or union initializer");
return 1;
}
push_init_level (2);
return 0;
}
/* If there are range designators in designator list, push a new designator
to constructor_range_stack. RANGE_END is end of such stack range or
NULL_TREE if there is no range designator at this level. */
static void
push_range_stack (range_end)
tree range_end;
{
struct constructor_range_stack *p;
p = (struct constructor_range_stack *)
ggc_alloc (sizeof (struct constructor_range_stack));
p->prev = constructor_range_stack;
p->next = 0;
p->fields = constructor_fields;
p->range_start = constructor_index;
p->index = constructor_index;
p->stack = constructor_stack;
p->range_end = range_end;
if (constructor_range_stack)
constructor_range_stack->next = p;
constructor_range_stack = p;
}
/* Within an array initializer, specify the next index to be initialized. /* Within an array initializer, specify the next index to be initialized.
FIRST is that index. If LAST is nonzero, then initialize a range FIRST is that index. If LAST is nonzero, then initialize a range
of indices, running from FIRST through LAST. */ of indices, running from FIRST through LAST. */
...@@ -5485,6 +5644,11 @@ void ...@@ -5485,6 +5644,11 @@ void
set_init_index (first, last) set_init_index (first, last)
tree first, last; tree first, last;
{ {
if (set_designator (1))
return;
designator_errorneous = 1;
while ((TREE_CODE (first) == NOP_EXPR while ((TREE_CODE (first) == NOP_EXPR
|| TREE_CODE (first) == CONVERT_EXPR || TREE_CODE (first) == CONVERT_EXPR
|| TREE_CODE (first) == NON_LVALUE_EXPR) || TREE_CODE (first) == NON_LVALUE_EXPR)
...@@ -5504,18 +5668,34 @@ set_init_index (first, last) ...@@ -5504,18 +5668,34 @@ set_init_index (first, last)
error_init ("nonconstant array index in initializer"); error_init ("nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST) else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
error_init ("nonconstant array index in initializer"); error_init ("nonconstant array index in initializer");
else if (! constructor_unfilled_index) else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
error_init ("array index in non-array initializer"); error_init ("array index in non-array initializer");
else if (tree_int_cst_lt (first, constructor_unfilled_index)) else if (constructor_max_index
error_init ("duplicate array index in initializer"); && tree_int_cst_lt (constructor_max_index, first))
error_init ("array index in initializer exceeds array bounds");
else else
{ {
constructor_index = convert (bitsizetype, first); constructor_index = convert (bitsizetype, first);
if (last != 0 && tree_int_cst_lt (last, first)) if (last != 0 && tree_int_cst_lt (last, first))
{
error_init ("empty index range in initializer"); error_init ("empty index range in initializer");
else last = 0;
constructor_range_end = last ? convert (bitsizetype, last) : 0; }
else if (last)
{
last = convert (bitsizetype, last);
if (constructor_max_index != 0
&& tree_int_cst_lt (constructor_max_index, last))
{
error_init ("array index range in initializer exceeds array bounds");
last = 0;
}
}
designator_depth++;
designator_errorneous = 0;
if (constructor_range_stack || last)
push_range_stack (last);
} }
} }
...@@ -5526,18 +5706,22 @@ set_init_label (fieldname) ...@@ -5526,18 +5706,22 @@ set_init_label (fieldname)
tree fieldname; tree fieldname;
{ {
tree tail; tree tail;
int passed = 0;
/* Don't die if an entire brace-pair level is superfluous if (set_designator (0))
in the containing level. */
if (constructor_type == 0)
return; return;
designator_errorneous = 1;
if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != UNION_TYPE)
{
error_init ("field name not in record or union initializer");
return;
}
for (tail = TYPE_FIELDS (constructor_type); tail; for (tail = TYPE_FIELDS (constructor_type); tail;
tail = TREE_CHAIN (tail)) tail = TREE_CHAIN (tail))
{ {
if (tail == constructor_unfilled_fields)
passed = 1;
if (DECL_NAME (tail) == fieldname) if (DECL_NAME (tail) == fieldname)
break; break;
} }
...@@ -5545,11 +5729,14 @@ set_init_label (fieldname) ...@@ -5545,11 +5729,14 @@ set_init_label (fieldname)
if (tail == 0) if (tail == 0)
error ("unknown field `%s' specified in initializer", error ("unknown field `%s' specified in initializer",
IDENTIFIER_POINTER (fieldname)); IDENTIFIER_POINTER (fieldname));
else if (!passed)
error ("field `%s' already initialized",
IDENTIFIER_POINTER (fieldname));
else else
{
constructor_fields = tail; constructor_fields = tail;
designator_depth++;
designator_errorneous = 0;
if (constructor_range_stack)
push_range_stack (NULL_TREE);
}
} }
/* Add a new initializer to the tree of pending initializers. PURPOSE /* Add a new initializer to the tree of pending initializers. PURPOSE
...@@ -5572,24 +5759,36 @@ add_pending_init (purpose, value) ...@@ -5572,24 +5759,36 @@ add_pending_init (purpose, value)
p = *q; p = *q;
if (tree_int_cst_lt (purpose, p->purpose)) if (tree_int_cst_lt (purpose, p->purpose))
q = &p->left; q = &p->left;
else if (p->purpose != purpose) else if (tree_int_cst_lt (p->purpose, purpose))
q = &p->right; q = &p->right;
else else
abort (); {
if (TREE_SIDE_EFFECTS (p->value))
warning_init ("initialized field with side-effects overwritten");
p->value = value;
return;
}
} }
} }
else else
{ {
tree bitpos;
bitpos = bit_position (purpose);
while (*q != NULL) while (*q != NULL)
{ {
p = *q; p = *q;
if (tree_int_cst_lt (bit_position (purpose), if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
bit_position (p->purpose)))
q = &p->left; q = &p->left;
else if (p->purpose != purpose) else if (p->purpose != purpose)
q = &p->right; q = &p->right;
else else
abort (); {
if (TREE_SIDE_EFFECTS (p->value))
warning_init ("initialized field with side-effects overwritten");
p->value = value;
return;
}
} }
} }
...@@ -5758,41 +5957,178 @@ add_pending_init (purpose, value) ...@@ -5758,41 +5957,178 @@ add_pending_init (purpose, value)
} }
} }
/* Return nonzero if FIELD is equal to the index of a pending initializer. */ /* Build AVL tree from a sorted chain. */
static int static void
pending_init_member (field) set_nonincremental_init ()
{
tree chain;
if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != ARRAY_TYPE)
return;
for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain))
add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain));
constructor_elements = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
constructor_unfilled_fields = TYPE_FIELDS (constructor_type);
/* Skip any nameless bit fields at the beginning. */
while (constructor_unfilled_fields != 0
&& DECL_C_BIT_FIELD (constructor_unfilled_fields)
&& DECL_NAME (constructor_unfilled_fields) == 0)
constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (constructor_type))
constructor_unfilled_index
= convert (bitsizetype,
TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
else
constructor_unfilled_index = bitsize_zero_node;
}
constructor_incremental = 0;
}
/* Build AVL tree from a string constant. */
static void
set_nonincremental_init_from_string (str)
tree str;
{
tree value, purpose, type;
HOST_WIDE_INT val[2];
const char *p, *end;
int byte, wchar_bytes, charwidth, bitpos;
if (TREE_CODE (constructor_type) != ARRAY_TYPE)
abort ();
if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
== TYPE_PRECISION (char_type_node))
wchar_bytes = 1;
else if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
== TYPE_PRECISION (wchar_type_node))
wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
else
abort ();
charwidth = TYPE_PRECISION (char_type_node);
type = TREE_TYPE (constructor_type);
p = TREE_STRING_POINTER (str);
end = p + TREE_STRING_LENGTH (str);
for (purpose = bitsize_zero_node;
p < end && !tree_int_cst_lt (constructor_max_index, purpose);
purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node))
{
if (wchar_bytes == 1)
{
val[1] = (unsigned char) *p++;
val[0] = 0;
}
else
{
val[0] = 0;
val[1] = 0;
for (byte = 0; byte < wchar_bytes; byte++)
{
if (BYTES_BIG_ENDIAN)
bitpos = (wchar_bytes - byte - 1) * charwidth;
else
bitpos = byte * charwidth;
val[bitpos < HOST_BITS_PER_WIDE_INT]
|= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
<< (bitpos % HOST_BITS_PER_WIDE_INT);
}
}
if (!TREE_UNSIGNED (type))
{
bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
if (bitpos < HOST_BITS_PER_WIDE_INT)
{
if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
{
val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
val[0] = -1;
}
}
else if (bitpos == HOST_BITS_PER_WIDE_INT)
{
if (val[1] < 0)
val[0] = -1;
}
else if (val[0] & (((HOST_WIDE_INT) 1)
<< (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
val[0] |= ((HOST_WIDE_INT) -1)
<< (bitpos - HOST_BITS_PER_WIDE_INT);
}
value = build_int_2 (val[1], val[0]);
TREE_TYPE (value) = type;
add_pending_init (purpose, value);
}
constructor_incremental = 0;
}
/* Return value of FIELD in pending initializer or zero if the field was
not initialized yet. */
static tree
find_init_member (field)
tree field; tree field;
{ {
struct init_node *p; struct init_node *p;
p = constructor_pending_elts;
if (TREE_CODE (constructor_type) == ARRAY_TYPE) if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{ {
if (constructor_incremental
&& tree_int_cst_lt (field, constructor_unfilled_index))
set_nonincremental_init ();
p = constructor_pending_elts;
while (p) while (p)
{ {
if (field == p->purpose) if (tree_int_cst_lt (field, p->purpose))
return 1;
else if (tree_int_cst_lt (field, p->purpose))
p = p->left; p = p->left;
else else if (tree_int_cst_lt (p->purpose, field))
p = p->right; p = p->right;
else
return p->value;
} }
} }
else else if (TREE_CODE (constructor_type) == RECORD_TYPE)
{ {
tree bitpos = bit_position (field);
if (constructor_incremental
&& (!constructor_unfilled_fields
|| tree_int_cst_lt (bitpos,
bit_position (constructor_unfilled_fields))))
set_nonincremental_init ();
p = constructor_pending_elts;
while (p) while (p)
{ {
if (field == p->purpose) if (field == p->purpose)
return 1; return p->value;
else if (tree_int_cst_lt (bit_position (field), else if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
bit_position (p->purpose)))
p = p->left; p = p->left;
else else
p = p->right; p = p->right;
} }
} }
else if (TREE_CODE (constructor_type) == UNION_TYPE)
{
if (constructor_elements
&& TREE_PURPOSE (constructor_elements) == field)
return TREE_VALUE (constructor_elements);
}
return 0; return 0;
} }
...@@ -5811,8 +6147,6 @@ output_init_element (value, type, field, pending) ...@@ -5811,8 +6147,6 @@ output_init_element (value, type, field, pending)
tree value, type, field; tree value, type, field;
int pending; int pending;
{ {
int duplicate = 0;
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
|| (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
&& !(TREE_CODE (value) == STRING_CST && !(TREE_CODE (value) == STRING_CST
...@@ -5840,57 +6174,80 @@ output_init_element (value, type, field, pending) ...@@ -5840,57 +6174,80 @@ output_init_element (value, type, field, pending)
} }
else if (require_constant_elements else if (require_constant_elements
&& initializer_constant_valid_p (value, TREE_TYPE (value)) == 0) && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
{ pedwarn ("initializer element is not computable at load time");
error_init ("initializer element is not computable at load time");
value = error_mark_node; /* If this field is empty (and not at the end of structure),
} don't do anything other than checking the initializer. */
if (field
&& (TREE_TYPE (field) == error_mark_node
|| (COMPLETE_TYPE_P (TREE_TYPE (field))
&& integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
&& (TREE_CODE (constructor_type) == ARRAY_TYPE
|| TREE_CHAIN (field)))))
return;
/* If this element duplicates one on constructor_pending_elts, if (value == error_mark_node)
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
|| TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (pending_init_member (field))
{ {
error_init ("duplicate initializer"); constructor_erroneous = 1;
duplicate = 1; return;
}
}
} }
/* If this element doesn't come next in sequence, /* If this element doesn't come next in sequence,
put it on constructor_pending_elts. */ put it on constructor_pending_elts. */
if (TREE_CODE (constructor_type) == ARRAY_TYPE if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& ! tree_int_cst_equal (field, constructor_unfilled_index)) && (!constructor_incremental
|| !tree_int_cst_equal (field, constructor_unfilled_index)))
{ {
if (! duplicate) if (constructor_incremental
&& tree_int_cst_lt (field, constructor_unfilled_index))
set_nonincremental_init ();
add_pending_init (field, add_pending_init (field,
digest_init (type, value, require_constant_value, digest_init (type, value, require_constant_value,
require_constant_elements)); require_constant_elements));
return;
} }
else if (TREE_CODE (constructor_type) == RECORD_TYPE else if (TREE_CODE (constructor_type) == RECORD_TYPE
&& field != constructor_unfilled_fields) && (!constructor_incremental
|| field != constructor_unfilled_fields))
{ {
/* We do this for records but not for unions. In a union, /* We do this for records but not for unions. In a union,
no matter which field is specified, it can be initialized no matter which field is specified, it can be initialized
right away since it starts at the beginning of the union. */ right away since it starts at the beginning of the union. */
if (!duplicate) if (constructor_incremental)
{
if (!constructor_unfilled_fields)
set_nonincremental_init ();
else
{
tree bitpos, unfillpos;
bitpos = bit_position (field);
unfillpos = bit_position (constructor_unfilled_fields);
if (tree_int_cst_lt (bitpos, unfillpos))
set_nonincremental_init ();
}
}
add_pending_init (field, add_pending_init (field,
digest_init (type, value, require_constant_value, digest_init (type, value, require_constant_value,
require_constant_elements)); require_constant_elements));
return;
} }
else else if (TREE_CODE (constructor_type) == UNION_TYPE
&& constructor_elements)
{ {
if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements)))
warning_init ("initialized field with side-effects overwritten");
/* We can have just one union field set. */
constructor_elements = 0;
}
/* Otherwise, output this element either to /* Otherwise, output this element either to
constructor_elements or to the assembler file. */ constructor_elements or to the assembler file. */
if (!duplicate)
{
if (field && TREE_CODE (field) == INTEGER_CST) if (field && TREE_CODE (field) == INTEGER_CST)
field = copy_node (field); field = copy_node (field);
constructor_elements constructor_elements
...@@ -5898,7 +6255,6 @@ output_init_element (value, type, field, pending) ...@@ -5898,7 +6255,6 @@ output_init_element (value, type, field, pending)
require_constant_value, require_constant_value,
require_constant_elements), require_constant_elements),
constructor_elements); constructor_elements);
}
/* Advance the variable that indicates sequential elements output. */ /* Advance the variable that indicates sequential elements output. */
if (TREE_CODE (constructor_type) == ARRAY_TYPE) if (TREE_CODE (constructor_type) == ARRAY_TYPE)
...@@ -5923,7 +6279,6 @@ output_init_element (value, type, field, pending) ...@@ -5923,7 +6279,6 @@ output_init_element (value, type, field, pending)
/* Now output any pending elements which have become next. */ /* Now output any pending elements which have become next. */
if (pending) if (pending)
output_pending_init_elements (0); output_pending_init_elements (0);
}
} }
/* Output any pending elements which have become next. /* Output any pending elements which have become next.
...@@ -5999,18 +6354,23 @@ output_pending_init_elements (all) ...@@ -5999,18 +6354,23 @@ output_pending_init_elements (all)
else if (TREE_CODE (constructor_type) == RECORD_TYPE else if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE) || TREE_CODE (constructor_type) == UNION_TYPE)
{ {
tree ctor_unfilled_bitpos, elt_bitpos;
/* If the current record is complete we are done. */ /* If the current record is complete we are done. */
if (constructor_unfilled_fields == 0) if (constructor_unfilled_fields == 0)
break; break;
if (elt->purpose == constructor_unfilled_fields)
ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields);
elt_bitpos = bit_position (elt->purpose);
/* We can't compare fields here because there might be empty
fields in between. */
if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
{ {
output_init_element (elt->value, constructor_unfilled_fields = elt->purpose;
TREE_TYPE (constructor_unfilled_fields), output_init_element (elt->value, TREE_TYPE (elt->purpose),
constructor_unfilled_fields, elt->purpose, 0);
0);
} }
else if (tree_int_cst_lt (bit_position (constructor_unfilled_fields), else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
bit_position (elt->purpose)))
{ {
/* Advance to the next smaller node. */ /* Advance to the next smaller node. */
if (elt->left) if (elt->left)
...@@ -6036,8 +6396,7 @@ output_pending_init_elements (all) ...@@ -6036,8 +6396,7 @@ output_pending_init_elements (all)
elt = elt->parent; elt = elt->parent;
elt = elt->parent; elt = elt->parent;
if (elt if (elt
&& (tree_int_cst_lt && (tree_int_cst_lt (ctor_unfilled_bitpos,
(bit_position (constructor_unfilled_fields),
bit_position (elt->purpose)))) bit_position (elt->purpose))))
{ {
next = elt->purpose; next = elt->purpose;
...@@ -6081,6 +6440,9 @@ process_init_element (value) ...@@ -6081,6 +6440,9 @@ process_init_element (value)
tree orig_value = value; tree orig_value = value;
int string_flag = value != 0 && TREE_CODE (value) == STRING_CST; int string_flag = value != 0 && TREE_CODE (value) == STRING_CST;
designator_depth = 0;
designator_errorneous = 0;
/* Handle superfluous braces around string cst as in /* Handle superfluous braces around string cst as in
char x[] = {"foo"}; */ char x[] = {"foo"}; */
if (string_flag if (string_flag
...@@ -6123,6 +6485,10 @@ process_init_element (value) ...@@ -6123,6 +6485,10 @@ process_init_element (value)
break; break;
} }
/* In the case of [LO ... HI] = VALUE, only evaluate VALUE once. */
if (constructor_range_stack)
value = save_expr (value);
while (1) while (1)
{ {
if (TREE_CODE (constructor_type) == RECORD_TYPE) if (TREE_CODE (constructor_type) == RECORD_TYPE)
...@@ -6191,9 +6557,8 @@ process_init_element (value) ...@@ -6191,9 +6557,8 @@ process_init_element (value)
&& DECL_C_BIT_FIELD (constructor_fields) && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0) && DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields); constructor_fields = TREE_CHAIN (constructor_fields);
break;
} }
if (TREE_CODE (constructor_type) == UNION_TYPE) else if (TREE_CODE (constructor_type) == UNION_TYPE)
{ {
tree fieldtype; tree fieldtype;
enum tree_code fieldcode; enum tree_code fieldcode;
...@@ -6252,9 +6617,8 @@ process_init_element (value) ...@@ -6252,9 +6617,8 @@ process_init_element (value)
} }
constructor_fields = 0; constructor_fields = 0;
break;
} }
if (TREE_CODE (constructor_type) == ARRAY_TYPE) else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{ {
tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
enum tree_code eltcode = TREE_CODE (elttype); enum tree_code eltcode = TREE_CODE (elttype);
...@@ -6285,25 +6649,7 @@ process_init_element (value) ...@@ -6285,25 +6649,7 @@ process_init_element (value)
break; break;
} }
/* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */ /* Now output the actual element. */
if (constructor_range_end)
{
if (constructor_max_index != 0
&& tree_int_cst_lt (constructor_max_index,
constructor_range_end))
{
pedwarn_init ("excess elements in array initializer");
constructor_range_end = constructor_max_index;
}
value = save_expr (value);
}
/* Now output the actual element.
Ordinarily, output once.
If there is a range, repeat it till we advance past the range. */
do
{
if (value) if (value)
{ {
push_array_bounds (tree_low_cst (constructor_index, 0)); push_array_bounds (tree_low_cst (constructor_index, 0));
...@@ -6320,26 +6666,76 @@ process_init_element (value) ...@@ -6320,26 +6666,76 @@ process_init_element (value)
constructor_unfilled_index. */ constructor_unfilled_index. */
constructor_unfilled_index = constructor_index; constructor_unfilled_index = constructor_index;
} }
while (! (constructor_range_end == 0
|| tree_int_cst_lt (constructor_range_end,
constructor_index)));
break;
}
/* Handle the sole element allowed in a braced initializer /* Handle the sole element allowed in a braced initializer
for a scalar variable. */ for a scalar variable. */
if (constructor_fields == 0) else if (constructor_fields == 0)
{ {
pedwarn_init ("excess elements in scalar initializer"); pedwarn_init ("excess elements in scalar initializer");
break; break;
} }
else
{
if (value) if (value)
output_init_element (value, constructor_type, NULL_TREE, 1); output_init_element (value, constructor_type, NULL_TREE, 1);
constructor_fields = 0; constructor_fields = 0;
}
/* Handle range initializers either at this level or anywhere higher
in the designator stack. */
if (constructor_range_stack)
{
struct constructor_range_stack *p, *range_stack;
int finish = 0;
range_stack = constructor_range_stack;
constructor_range_stack = 0;
while (constructor_stack != range_stack->stack)
{
if (!constructor_stack->implicit)
abort ();
process_init_element (pop_init_level (1));
}
for (p = range_stack;
!p->range_end || tree_int_cst_equal (p->index, p->range_end);
p = p->prev)
{
if (!constructor_stack->implicit)
abort ();
process_init_element (pop_init_level (1));
}
p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
finish = 1;
while (1)
{
constructor_index = p->index;
constructor_fields = p->fields;
if (finish && p->range_end && p->index == p->range_start)
{
finish = 0;
p->prev = 0;
}
p = p->next;
if (!p)
break;
push_init_level (2);
p->stack = constructor_stack;
if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
p->index = p->range_start;
}
if (!finish)
constructor_range_stack = range_stack;
continue;
}
break; break;
} }
constructor_range_stack = 0;
} }
/* Build an asm-statement, whose components are a CV_QUALIFIER, a /* Build an asm-statement, whose components are a CV_QUALIFIER, a
......
...@@ -1261,6 +1261,10 @@ int widths[] = @{ [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 @}; ...@@ -1261,6 +1261,10 @@ int widths[] = @{ [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 @};
@end example @end example
@noindent @noindent
If the value in it has side-effects, the side-effects will happen only once,
not for each initialized field by the range initializer.
@noindent
Note that the length of the array is the highest value specified Note that the length of the array is the highest value specified
plus one. plus one.
...@@ -1345,6 +1349,12 @@ example, with the @samp{struct point} declaration above: ...@@ -1345,6 +1349,12 @@ example, with the @samp{struct point} declaration above:
struct point ptarray[10] = @{ [2].y = yv2, [2].x = xv2, [0].x = xv0 @}; struct point ptarray[10] = @{ [2].y = yv2, [2].x = xv2, [0].x = xv0 @};
@end example @end example
@noindent
If the same field is initialized multiple times, it will have value from
the last initialization. If any such overridden initialization has
side-effect, it is unspecified whether the side-effect happens or not.
Currently, gcc will discard them and issue a warning.
@node Case Ranges @node Case Ranges
@section Case Ranges @section Case Ranges
@cindex case ranges @cindex case ranges
......
2001-01-12 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/20000801-3.x: Remove.
* gcc.dg/c90-init-1.c: New test.
* gcc.dg/c99-init-1.c: New test.
* gcc.dg/c99-init-2.c: New test.
* gcc.dg/gnu99-init-1.c: New test.
2001-01-12 Richard Earnshaw <rearnsha@arm.com> 2001-01-12 Richard Earnshaw <rearnsha@arm.com>
* lib/f-torture.exp (f_torture_compile): Prune the warnings before * lib/f-torture.exp (f_torture_compile): Prune the warnings before
......
set torture_execute_xfail "*-*-*"
return 0
/* Test for C99 designated initializers */
/* Origin: Jakub Jelinek <jakub@redhat.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
struct A {
int B;
short C[2];
};
int a[10] = { 10, [4] = 15 }; /* { dg-error "ISO C89 forbids specifying subobject to initialize" } */
struct A b = { .B = 2 }; /* { dg-error "ISO C89 forbids specifying subobject to initialize" } */
struct A c[] = { [3].C[1] = 1 }; /* { dg-error "ISO C89 forbids specifying subobject to initialize" } */
struct A d[] = { [4 ... 6].C[0 ... 1] = 2 }; /* { dg-error "(forbids specifying range of elements to initialize)|(ISO C89 forbids specifying subobject to initialize)" } */
int e[] = { [2] 2 }; /* { dg-error "use of designated initializer without" } */
struct A f = { C: { 0, 1 } }; /* { dg-error "use of designated initializer with " } */
int g;
void foo (int *);
void bar (void)
{
int x[] = { g++, 2 }; /* { dg-error "is not computable at load time" } */
foo (x);
}
/* Test for C99 designated initializers */
/* Origin: Jakub Jelinek <jakub@redhat.com> */
/* { dg-do run } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
typedef __SIZE_TYPE__ size_t;
typedef __WCHAR_TYPE__ wchar_t;
extern int memcmp (const void *, const void *, size_t);
extern void abort (void);
extern void exit (int);
int a[10] = { 10, 0, 12, 13, 14, 0, 0, 17, 0, 0 };
int b[10] = { 10, [4] = 15, [2] = 12, [4] = 14, [7] = 17 };
int c[10] = { 10, [4] = 15, [2] = 12, [3] = 13, 14, [7] = 17 };
struct A {
int B;
short C[2];
};
struct A d[] = { { 0, { 1, 2 } }, { 0, { 0, 0 } }, { 10, { 11, 12 } } };
struct A e[] = { 0, 1, 2, [2] = 10, 11, 12 };
struct A f[] = { 0, 1, 2, [2].C = 11, 12, 13 };
struct A g[] = { 0, 1, 2, [2].C[1] = 12, 13, 14 };
struct A h[] = { 0, 1, 2, [2] = { .C[1] = 12 }, 13, 14 };
struct A i[] = { 0, 1, 2, [2] = { .C = { [1] = 12 } }, 13, 14 };
union D {
int E;
double F;
struct A G;
};
union D j[] = { [4] = 1, [4].F = 1.0, [1].G.C[1] = 4 };
struct H {
char I[6];
int J;
} k[] = { { { "foo" }, 1 }, [0].I[0] = 'b' };
struct K {
wchar_t L[6];
int M;
} l[] = { { { L"foo" }, 1 }, [0].L[2] = L'x', [0].L[4] = L'y' };
struct H m[] = { { { "foo" }, 1 }, [0] = { .I[0] = 'b' } };
struct H n[] = { { { "foo" }, 1 }, [0].I = { "a" }, [0].J = 2 };
int o = { 22 };
int main (void)
{
if (b[3])
abort ();
b[3] = 13;
if (memcmp (a, b, sizeof (a)) || memcmp (a, c, sizeof (a)))
abort ();
if (memcmp (d, e, sizeof (d)) || sizeof (d) != sizeof (e))
abort ();
if (f[2].B != 0 || g[2].B != 0 || g[2].C[0] != 0)
abort ();
if (memcmp (g, h, sizeof (g)) || memcmp (g, i, sizeof (g)))
abort ();
f[2].B = 10;
g[2].B = 10;
g[2].C[0] = 11;
if (memcmp (d, f, sizeof (d)) || memcmp (d, g, sizeof (d)))
abort ();
if (f[3].B != 13 || g[3].B != 13 || g[3].C[0] != 14)
abort ();
if (j[0].E || j[1].G.B || j[1].G.C[0] || j[1].G.C[1] != 4)
abort ();
if (j[2].E || j[3].E || j[4].F != 1.0)
abort ();
if (memcmp (k[0].I, "boo\0\0", 6) || k[0].J != 1)
abort ();
if (memcmp (l[0].L, L"fox\0y", 6 * sizeof(wchar_t)) || l[0].M != 1)
abort ();
if (memcmp (m[0].I, "b\0\0\0\0", 6) || m[0].J)
abort ();
if (memcmp (n[0].I, "a\0\0\0\0", 6) || n[0].J != 2)
abort ();
if (o != 22)
abort ();
exit (0);
}
/* Test for C99 designated initializer warnings and errors */
/* Origin: Jakub Jelinek <jakub@redhat.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -Wall -pedantic-errors" } */
typedef struct {
int B;
short C[2];
} A;
A a = { [2] = 1 }; /* { dg-error "(array index in non-array)|(near initialization)" } */
int b[] = { .B = 1 }; /* { dg-error "(field name not in record)|(near initialization)" } */
A c[] = { [0].D = 1 }; /* { dg-error "unknown field" } */
int d;
int e = { d++ }; /* { dg-error "(is not constant)|(near initialization)" } */
A f[2] = { [0].C[0] = 1, [2] = { 2, { 1, 2 } } };/* { dg-error "(array index in initializer exceeds array bounds)|(near initialization)" } */
int g[4] = { [1] = 1, 2, [6] = 5 }; /* { dg-error "(array index in initializer exceeds array bounds)|(near initialization)" } */
int h[] = { [0 ... 3] = 5 }; /* { dg-error "forbids specifying range of elements" } */
int i[] = { [2] 4 }; /* { dg-error "use of designated initializer without" } */
A j = { B: 2 }; /* { dg-error "use of designated initializer with " } */
void foo (int *, A *);
void bar (void)
{
int a[] = { d++, [0] = 1 }; /* { dg-warning "(initialized field with side-effects overwritten)|(near initialization)" } */
A b = { 1, { d++, 2 }, .C[0] = 3 };/* { dg-warning "(initialized field with side-effects overwritten)|(near initialization)" } */
A c = { d++, { 2, 3 }, .B = 4 }; /* { dg-warning "(initialized field with side-effects overwritten)|(near initialization)" } */
foo (a, d ? &b : &c);
}
/* Test for GNU extensions to C99 designated initializers */
/* Origin: Jakub Jelinek <jakub@redhat.com> */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
typedef __SIZE_TYPE__ size_t;
extern int memcmp (const void *, const void *, size_t);
extern void abort (void);
extern void exit (int);
int a[][2][4] = { [2 ... 4][0 ... 1][2 ... 3] = 1, [2] = 2, [2][0][2] = 3 };
struct E {};
struct F { struct E H; };
struct G { int I; struct E J; int K; };
struct H { int I; struct F J; int K; };
struct G k = { .J = {}, 1 };
struct H l = { .J.H = {}, 2 };
struct H m = { .J = {}, 3 };
struct I { int J; int K[3]; int L; };
struct M { int N; struct I O[3]; int P; };
struct M n[] = { [0 ... 5].O[1 ... 2].K[0 ... 1] = 4, 5, 6, 7 };
int main (void)
{
int x, y, z;
if (a[2][0][0] != 2 || a[2][0][2] != 3)
abort ();
a[2][0][0] = 0;
a[2][0][2] = 1;
for (x = 0; x <= 4; x++)
for (y = 0; y <= 1; y++)
for (z = 0; z <= 3; z++)
if (a[x][y][z] != (x >= 2 && z >= 2))
abort ();
if (k.I || l.I || m.I || k.K != 1 || l.K != 2 || m.K != 3)
abort ();
for (x = 0; x <= 5; x++)
{
if (n[x].N || n[x].O[0].J || n[x].O[0].L)
abort ();
for (y = 0; y <= 2; y++)
if (n[x].O[0].K[y])
abort ();
for (y = 1; y <= 2; y++)
{
if (n[x].O[y].J)
abort ();
if (n[x].O[y].K[0] != 4)
abort ();
if (n[x].O[y].K[1] != 4)
abort ();
if ((x < 5 || y < 2) && (n[x].O[y].K[2] || n[x].O[y].L))
abort ();
}
if (x < 5 && n[x].P)
abort ();
}
if (n[5].O[2].K[2] != 5 || n[5].O[2].L != 6 || n[5].P != 7)
abort ();
exit (0);
}
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