mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-27 21:34:40 +08:00
c-decl.c (grokdeclarator): Support flexible array members.
* c-decl.c (grokdeclarator): Support flexible array members. Use open-ended ranges for these and zero-length arrays. * c-typeck.c (push_init_level): Validate the context of initialization of a zero-length array. * tree.c (int_fits_type_p): Be prepared for missing bounds. * varasm.c (array_size_for_constructor): New. (output_constructor): Use it for arrays of unspecified length. * extend.texi (Zero Length): Mention C99 flexible array members. Document initialization in a top-level struct as valid. From-SVN: r37576
This commit is contained in:
parent
2650255a57
commit
a25f12118f
@ -1,3 +1,15 @@
|
||||
2000-11-19 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* c-decl.c (grokdeclarator): Support flexible array members.
|
||||
Use open-ended ranges for these and zero-length arrays.
|
||||
* c-typeck.c (push_init_level): Validate the context of
|
||||
initialization of a zero-length array.
|
||||
* tree.c (int_fits_type_p): Be prepared for missing bounds.
|
||||
* varasm.c (array_size_for_constructor): New.
|
||||
(output_constructor): Use it for arrays of unspecified length.
|
||||
* extend.texi (Zero Length): Mention C99 flexible array members.
|
||||
Document initialization in a top-level struct as valid.
|
||||
|
||||
2000-11-19 Joseph S. Myers <jsm28@cam.ac.uk>
|
||||
|
||||
* config.gcc, invoke.texi: Fix errors in spelling of "deprecated".
|
||||
@ -116,8 +128,7 @@
|
||||
|
||||
2000-11-17 Neil Booth <neilb@earthling.net>
|
||||
|
||||
* cpperror.c (print_file_and_line): Don't display line number
|
||||
if 0.
|
||||
* cpperror.c (print_file_and_line): Don't display line number if 0.
|
||||
|
||||
2000-11-17 Zack Weinberg <zack@wolery.stanford.edu>
|
||||
|
||||
|
18
gcc/c-decl.c
18
gcc/c-decl.c
@ -4498,9 +4498,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
{
|
||||
/* A zero-length array cannot be represented with an
|
||||
unsigned index type, which is what we'll get with
|
||||
build_index_type. Create a signed range instead. */
|
||||
itype = build_range_type (index_type, size,
|
||||
build_int_2 (-1, -1));
|
||||
build_index_type. Create an open-ended range instead. */
|
||||
itype = build_range_type (sizetype, size, NULL_TREE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4530,6 +4529,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
itype = build_index_type (itype);
|
||||
}
|
||||
}
|
||||
else if (decl_context == FIELD)
|
||||
{
|
||||
/* ??? Need to check somewhere that this is a structure
|
||||
and not a union, that this field is last, and that
|
||||
this structure has at least one other named member. */
|
||||
|
||||
if (pedantic && !flag_isoc99 && !in_system_header)
|
||||
pedwarn ("ISO C89 does not support flexible array members");
|
||||
|
||||
/* ISO C99 Flexible array members are effectively identical
|
||||
to GCC's zero-length array extension. */
|
||||
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This had bad results for pointers to arrays, as in
|
||||
|
@ -5295,6 +5295,16 @@ push_init_level (implicit)
|
||||
{
|
||||
constructor_max_index
|
||||
= TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
|
||||
|
||||
if (constructor_max_index == NULL_TREE)
|
||||
{
|
||||
/* This is a zero-length array or flexible array member. */
|
||||
if (pedantic)
|
||||
pedwarn_init ("ISO C does not support initialization of flexible array members");
|
||||
if (constructor_depth != 2)
|
||||
error_init ("initialization of zero-length array inside a nested structure");
|
||||
}
|
||||
|
||||
constructor_index
|
||||
= convert (bitsizetype,
|
||||
TYPE_MIN_VALUE
|
||||
|
@ -886,12 +886,25 @@ struct line @{
|
||||
@}
|
||||
@end example
|
||||
|
||||
In standard C, you would have to give @code{contents} a length of 1, which
|
||||
In ISO C89, you would have to give @code{contents} a length of 1, which
|
||||
means either you waste space or complicate the argument to @code{malloc}.
|
||||
|
||||
Static initialization of the zero-length array is not allowed. A
|
||||
warning will be generated for each initializer attempting to initialize
|
||||
the zero-length array.
|
||||
In ISO C99, you would use a @dfn{flexible array member}, which uses a
|
||||
slightly different syntax: leave out the @code{0} and write
|
||||
@code{contents[]}.
|
||||
|
||||
GCC allows static initialization of the zero-length array if
|
||||
the structure is not nested inside another structure. I.e.
|
||||
|
||||
@example
|
||||
/* Legal. */
|
||||
struct line x = @{ 4, @{ 'g', 'o', 'o', 'd' @} @};
|
||||
|
||||
/* Illegal. */
|
||||
struct bar @{
|
||||
struct line a;
|
||||
@} y = @{ @{ 3, @{ 'b', 'a', 'd' @} @} @};
|
||||
@end example
|
||||
|
||||
@node Variable Length
|
||||
@section Arrays of Variable Length
|
||||
|
@ -4186,7 +4186,9 @@ int_fits_type_p (c, type)
|
||||
{
|
||||
/* If the bounds of the type are integers, we can check ourselves.
|
||||
Otherwise,. use force_fit_type, which checks against the precision. */
|
||||
if (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
|
||||
if (TYPE_MAX_VALUE (type) != NULL_TREE
|
||||
&& TYPE_MIN_VALUE (type) != NULL_TREE
|
||||
&& TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
|
||||
&& TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
|
||||
{
|
||||
if (TREE_UNSIGNED (type))
|
||||
|
63
gcc/varasm.c
63
gcc/varasm.c
@ -171,6 +171,7 @@ static void mark_constant_pool PARAMS ((void));
|
||||
static void mark_constants PARAMS ((rtx));
|
||||
static int output_addressed_constants PARAMS ((tree));
|
||||
static void output_after_function_constants PARAMS ((void));
|
||||
static int array_size_for_constructor PARAMS ((tree));
|
||||
static void output_constructor PARAMS ((tree, int));
|
||||
#ifdef ASM_WEAKEN_LABEL
|
||||
static void remove_from_pending_weak_list PARAMS ((const char *));
|
||||
@ -4413,8 +4414,53 @@ output_constant (exp, size)
|
||||
}
|
||||
|
||||
|
||||
/* Subroutine of output_constant, used for CONSTRUCTORs
|
||||
(aggregate constants).
|
||||
/* Subroutine of output_constructor, used for computing the size of
|
||||
arrays of unspecified length. VAL must be a CONSTRUCTOR of an array
|
||||
type with an unspecified upper bound. */
|
||||
|
||||
static int
|
||||
array_size_for_constructor (val)
|
||||
tree val;
|
||||
{
|
||||
tree max_index, i;
|
||||
|
||||
if (!val || TREE_CODE (val) != CONSTRUCTOR
|
||||
|| TREE_CODE (TREE_TYPE (val)) != ARRAY_TYPE
|
||||
|| TYPE_DOMAIN (TREE_TYPE (val)) == NULL_TREE
|
||||
|| TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (val))) != NULL_TREE
|
||||
|| TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val))) == NULL_TREE)
|
||||
abort ();
|
||||
|
||||
max_index = NULL_TREE;
|
||||
for (i = CONSTRUCTOR_ELTS (val); i ; i = TREE_CHAIN (i))
|
||||
{
|
||||
tree index = TREE_PURPOSE (i);
|
||||
|
||||
if (TREE_CODE (index) == RANGE_EXPR)
|
||||
index = TREE_OPERAND (index, 1);
|
||||
if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index))
|
||||
max_index = index;
|
||||
}
|
||||
|
||||
/* ??? I'm fairly certain if there were no elements, we shouldn't have
|
||||
created the constructor in the first place. */
|
||||
if (max_index == NULL_TREE)
|
||||
abort ();
|
||||
|
||||
/* Compute the total number of array elements. */
|
||||
i = fold (build (MINUS_EXPR, TREE_TYPE (max_index), max_index,
|
||||
TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)))));
|
||||
i = fold (build (PLUS_EXPR, TREE_TYPE (i), i,
|
||||
convert (TREE_TYPE (i), integer_one_node)));
|
||||
|
||||
/* Multiply by the array element unit size to find number of bytes. */
|
||||
i = fold (build (MULT_EXPR, TREE_TYPE (max_index), i,
|
||||
TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val)))));
|
||||
|
||||
return tree_low_cst (i, 1);
|
||||
}
|
||||
|
||||
/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
|
||||
Generate at least SIZE bytes, padding if necessary. */
|
||||
|
||||
static void
|
||||
@ -4532,7 +4578,18 @@ output_constructor (exp, size)
|
||||
|
||||
/* Determine size this element should occupy. */
|
||||
if (field)
|
||||
fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
|
||||
{
|
||||
if (DECL_SIZE_UNIT (field))
|
||||
fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
|
||||
else
|
||||
{
|
||||
/* If DECL_SIZE is not set, then this must be an array
|
||||
of unspecified length. The initialized value must
|
||||
be a CONSTRUCTOR, and we take the length from the
|
||||
last initialized element. */
|
||||
fieldsize = array_size_for_constructor (val);
|
||||
}
|
||||
}
|
||||
else
|
||||
fieldsize = int_size_in_bytes (TREE_TYPE (type));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user