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>
* calls.c (emit_library_call_value_1): Add USEs and CLOBBERs
......
......@@ -76,8 +76,12 @@ static void warning_init PARAMS ((const char *));
static tree digest_init PARAMS ((tree, tree, int, int));
static void output_init_element PARAMS ((tree, tree, tree, 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 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
does not have an incomplete type. (That includes void types.) */
......@@ -4410,7 +4414,7 @@ store_init_value (decl, init)
/* Digest the specified initializer into an expression. */
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. */
......@@ -4769,10 +4773,7 @@ digest_init (type, init, require_constant, constructor_constant)
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
error_init ("initializer element is not computable at load time");
inside_init = error_mark_node;
}
pedwarn ("initializer element is not computable at load time");
return inside_init;
}
......@@ -4868,11 +4869,6 @@ static tree constructor_fields;
at which to store the next element we get. */
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. */
static tree constructor_max_index;
......@@ -4892,6 +4888,10 @@ static tree constructor_bit_index;
most recent first). */
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. */
static int constructor_constant;
......@@ -4943,6 +4943,12 @@ static const char *constructor_asmspec;
/* Nonzero if this is an initializer for a top-level decl. */
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
structuring in the initializer, including the outermost one. It
......@@ -4954,7 +4960,6 @@ struct constructor_stack
tree type;
tree fields;
tree index;
tree range_end;
tree max_index;
tree unfilled_index;
tree unfilled_fields;
......@@ -4971,10 +4976,26 @@ struct constructor_stack
char implicit;
char erroneous;
char outer;
char incremental;
};
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.
Nested initializers can't happen in ANSI C, but GNU C allows them
in cases like { ... (struct foo) { ... } ... }. */
......@@ -4985,6 +5006,7 @@ struct initializer_stack
tree decl;
const char *asmspec;
struct constructor_stack *constructor_stack;
struct constructor_range_stack *constructor_range_stack;
tree elements;
struct spelling *spelling;
struct spelling *spelling_base;
......@@ -5018,6 +5040,7 @@ start_init (decl, asmspec_tree, top_level)
p->require_constant_value = require_constant_value;
p->require_constant_elements = require_constant_elements;
p->constructor_stack = constructor_stack;
p->constructor_range_stack = constructor_range_stack;
p->elements = constructor_elements;
p->spelling = spelling;
p->spelling_base = spelling_base;
......@@ -5036,7 +5059,7 @@ start_init (decl, asmspec_tree, top_level)
{
require_constant_value = TREE_STATIC (decl);
require_constant_elements
= ((TREE_STATIC (decl) || pedantic)
= ((TREE_STATIC (decl) || (pedantic && !flag_isoc99))
/* For a scalar, you can always use any value to initialize,
even within braces. */
&& (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
......@@ -5053,6 +5076,7 @@ start_init (decl, asmspec_tree, top_level)
}
constructor_stack = 0;
constructor_range_stack = 0;
missing_braces_mentioned = 0;
......@@ -5083,12 +5107,16 @@ finish_init ()
free (q);
}
if (constructor_range_stack)
abort ();
/* Pop back to the data of the outer initializer (if any). */
constructor_decl = p->decl;
constructor_asmspec = p->asmspec;
require_constant_value = p->require_constant_value;
require_constant_elements = p->require_constant_elements;
constructor_stack = p->constructor_stack;
constructor_range_stack = p->constructor_range_stack;
constructor_elements = p->elements;
spelling = p->spelling;
spelling_base = p->spelling_base;
......@@ -5119,7 +5147,6 @@ really_start_incremental_init (type)
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
p->range_end = constructor_range_end;
p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
......@@ -5133,6 +5160,7 @@ really_start_incremental_init (type)
p->replacement_value = 0;
p->implicit = 0;
p->outer = 0;
p->incremental = constructor_incremental;
p->next = 0;
constructor_stack = p;
......@@ -5142,6 +5170,9 @@ really_start_incremental_init (type)
constructor_elements = 0;
constructor_pending_elts = 0;
constructor_type = type;
constructor_incremental = 1;
designator_depth = 0;
designator_errorneous = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
......@@ -5157,7 +5188,6 @@ really_start_incremental_init (type)
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
constructor_range_end = 0;
if (TYPE_DOMAIN (constructor_type))
{
constructor_max_index
......@@ -5187,13 +5217,14 @@ really_start_incremental_init (type)
/* 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. */
IMPLICIT is 1 (or 2 if the push is because of designator list). */
void
push_init_level (implicit)
int implicit;
{
struct constructor_stack *p;
tree value = NULL_TREE;
/* If we've exhausted any levels that didn't have braces,
pop them now. */
......@@ -5210,11 +5241,22 @@ push_init_level (implicit)
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->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
p->range_end = constructor_range_end;
p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
......@@ -5228,6 +5270,7 @@ push_init_level (implicit)
p->replacement_value = 0;
p->implicit = implicit;
p->outer = 0;
p->incremental = constructor_incremental;
p->next = constructor_stack;
constructor_stack = p;
......@@ -5235,7 +5278,13 @@ push_init_level (implicit)
constructor_simple = 1;
constructor_depth = SPELLING_DEPTH ();
constructor_elements = 0;
constructor_incremental = 1;
constructor_pending_elts = 0;
if (!implicit)
{
designator_depth = 0;
designator_errorneous = 0;
}
/* Don't die if an entire brace-pair level is superfluous
in the containing level. */
......@@ -5269,7 +5318,18 @@ push_init_level (implicit)
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;
warning_init ("missing braces around initializer");
......@@ -5289,7 +5349,6 @@ push_init_level (implicit)
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
constructor_range_end = 0;
if (TYPE_DOMAIN (constructor_type))
{
constructor_max_index
......@@ -5307,6 +5366,13 @@ push_init_level (implicit)
constructor_index = bitsize_zero_node;
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
{
......@@ -5406,6 +5472,7 @@ pop_init_level (implicit)
}
/* Now output all pending elements. */
constructor_incremental = 1;
output_pending_init_elements (1);
/* Pad out the end of the structure. */
......@@ -5423,6 +5490,7 @@ pop_init_level (implicit)
the element, after verifying there is just one. */
if (constructor_elements == 0)
{
if (!constructor_erroneous)
error_init ("empty scalar initializer");
constructor = error_mark_node;
}
......@@ -5452,7 +5520,6 @@ pop_init_level (implicit)
constructor_type = p->type;
constructor_fields = p->fields;
constructor_index = p->index;
constructor_range_end = p->range_end;
constructor_max_index = p->max_index;
constructor_unfilled_index = p->unfilled_index;
constructor_unfilled_fields = p->unfilled_fields;
......@@ -5461,6 +5528,7 @@ pop_init_level (implicit)
constructor_constant = p->constant;
constructor_simple = p->simple;
constructor_erroneous = p->erroneous;
constructor_incremental = p->incremental;
constructor_pending_elts = p->pending_elts;
constructor_depth = p->depth;
RESTORE_SPELLING_DEPTH (constructor_depth);
......@@ -5477,6 +5545,97 @@ pop_init_level (implicit)
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.
FIRST is that index. If LAST is nonzero, then initialize a range
of indices, running from FIRST through LAST. */
......@@ -5485,6 +5644,11 @@ void
set_init_index (first, last)
tree first, last;
{
if (set_designator (1))
return;
designator_errorneous = 1;
while ((TREE_CODE (first) == NOP_EXPR
|| TREE_CODE (first) == CONVERT_EXPR
|| TREE_CODE (first) == NON_LVALUE_EXPR)
......@@ -5504,18 +5668,34 @@ set_init_index (first, last)
error_init ("nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
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");
else if (tree_int_cst_lt (first, constructor_unfilled_index))
error_init ("duplicate array index in initializer");
else if (constructor_max_index
&& tree_int_cst_lt (constructor_max_index, first))
error_init ("array index in initializer exceeds array bounds");
else
{
constructor_index = convert (bitsizetype, first);
if (last != 0 && tree_int_cst_lt (last, first))
{
error_init ("empty index range in initializer");
else
constructor_range_end = last ? convert (bitsizetype, last) : 0;
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)
tree fieldname;
{
tree tail;
int passed = 0;
/* Don't die if an entire brace-pair level is superfluous
in the containing level. */
if (constructor_type == 0)
if (set_designator (0))
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;
tail = TREE_CHAIN (tail))
{
if (tail == constructor_unfilled_fields)
passed = 1;
if (DECL_NAME (tail) == fieldname)
break;
}
......@@ -5545,11 +5729,14 @@ set_init_label (fieldname)
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;
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
......@@ -5572,24 +5759,36 @@ add_pending_init (purpose, value)
p = *q;
if (tree_int_cst_lt (purpose, p->purpose))
q = &p->left;
else if (p->purpose != purpose)
else if (tree_int_cst_lt (p->purpose, purpose))
q = &p->right;
else
abort ();
{
if (TREE_SIDE_EFFECTS (p->value))
warning_init ("initialized field with side-effects overwritten");
p->value = value;
return;
}
}
}
else
{
tree bitpos;
bitpos = bit_position (purpose);
while (*q != NULL)
{
p = *q;
if (tree_int_cst_lt (bit_position (purpose),
bit_position (p->purpose)))
if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
q = &p->left;
else if (p->purpose != purpose)
q = &p->right;
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)
}
}
/* Return nonzero if FIELD is equal to the index of a pending initializer. */
/* Build AVL tree from a sorted chain. */
static int
pending_init_member (field)
static void
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;
{
struct init_node *p;
p = constructor_pending_elts;
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)
{
if (field == p->purpose)
return 1;
else if (tree_int_cst_lt (field, p->purpose))
if (tree_int_cst_lt (field, p->purpose))
p = p->left;
else
else if (tree_int_cst_lt (p->purpose, field))
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)
{
if (field == p->purpose)
return 1;
else if (tree_int_cst_lt (bit_position (field),
bit_position (p->purpose)))
return p->value;
else if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
p = p->left;
else
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;
}
......@@ -5811,8 +6147,6 @@ output_init_element (value, type, field, pending)
tree value, type, field;
int pending;
{
int duplicate = 0;
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
|| (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
&& !(TREE_CODE (value) == STRING_CST
......@@ -5840,57 +6174,80 @@ output_init_element (value, type, field, pending)
}
else if (require_constant_elements
&& initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
{
error_init ("initializer element is not computable at load time");
value = error_mark_node;
}
pedwarn ("initializer element is not computable at load time");
/* 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,
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))
if (value == error_mark_node)
{
error_init ("duplicate initializer");
duplicate = 1;
}
}
constructor_erroneous = 1;
return;
}
/* 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))
&& (!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,
digest_init (type, value, require_constant_value,
require_constant_elements));
return;
}
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,
no matter which field is specified, it can be initialized
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,
digest_init (type, value, require_constant_value,
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
constructor_elements or to the assembler file. */
if (!duplicate)
{
if (field && TREE_CODE (field) == INTEGER_CST)
field = copy_node (field);
constructor_elements
......@@ -5898,7 +6255,6 @@ output_init_element (value, type, field, pending)
require_constant_value,
require_constant_elements),
constructor_elements);
}
/* Advance the variable that indicates sequential elements output. */
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
......@@ -5923,7 +6279,6 @@ output_init_element (value, type, field, pending)
/* Now output any pending elements which have become next. */
if (pending)
output_pending_init_elements (0);
}
}
/* Output any pending elements which have become next.
......@@ -5999,18 +6354,23 @@ output_pending_init_elements (all)
else if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
tree ctor_unfilled_bitpos, elt_bitpos;
/* If the current record is complete we are done. */
if (constructor_unfilled_fields == 0)
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,
TREE_TYPE (constructor_unfilled_fields),
constructor_unfilled_fields,
0);
constructor_unfilled_fields = elt->purpose;
output_init_element (elt->value, TREE_TYPE (elt->purpose),
elt->purpose, 0);
}
else if (tree_int_cst_lt (bit_position (constructor_unfilled_fields),
bit_position (elt->purpose)))
else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
{
/* Advance to the next smaller node. */
if (elt->left)
......@@ -6036,8 +6396,7 @@ output_pending_init_elements (all)
elt = elt->parent;
elt = elt->parent;
if (elt
&& (tree_int_cst_lt
(bit_position (constructor_unfilled_fields),
&& (tree_int_cst_lt (ctor_unfilled_bitpos,
bit_position (elt->purpose))))
{
next = elt->purpose;
......@@ -6081,6 +6440,9 @@ process_init_element (value)
tree orig_value = value;
int string_flag = value != 0 && TREE_CODE (value) == STRING_CST;
designator_depth = 0;
designator_errorneous = 0;
/* Handle superfluous braces around string cst as in
char x[] = {"foo"}; */
if (string_flag
......@@ -6123,6 +6485,10 @@ process_init_element (value)
break;
}
/* In the case of [LO ... HI] = VALUE, only evaluate VALUE once. */
if (constructor_range_stack)
value = save_expr (value);
while (1)
{
if (TREE_CODE (constructor_type) == RECORD_TYPE)
......@@ -6191,9 +6557,8 @@ process_init_element (value)
&& DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
break;
}
if (TREE_CODE (constructor_type) == UNION_TYPE)
else if (TREE_CODE (constructor_type) == UNION_TYPE)
{
tree fieldtype;
enum tree_code fieldcode;
......@@ -6252,9 +6617,8 @@ process_init_element (value)
}
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));
enum tree_code eltcode = TREE_CODE (elttype);
......@@ -6285,25 +6649,7 @@ process_init_element (value)
break;
}
/* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */
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
{
/* Now output the actual element. */
if (value)
{
push_array_bounds (tree_low_cst (constructor_index, 0));
......@@ -6320,26 +6666,76 @@ process_init_element (value)
constructor_unfilled_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
for a scalar variable. */
if (constructor_fields == 0)
else if (constructor_fields == 0)
{
pedwarn_init ("excess elements in scalar initializer");
break;
}
else
{
if (value)
output_init_element (value, constructor_type, NULL_TREE, 1);
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;
}
constructor_range_stack = 0;
}
/* 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 @};
@end example
@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
plus one.
......@@ -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 @};
@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
@section 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>
* 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