c-decl.c (grokdeclarator): Give zero-length arrays size zero.

* c-decl.c (grokdeclarator): Give zero-length arrays size zero.
        Remove dead code.
        * c-typeck.c (push_init_level): Move checks for flexible array
        members and zero length arrays ...
        (pop_init_level): ... here.  Silently discard empty initializations.
        Remove dead code.
        * varasm.c (output_constructor): Update for sizeof change to
        zero-length arrays.

        * extend.texi (Zero Length): Clarify semantics.

        * gcc.dg/940510-1.c: Update expected error wording.
        * gcc.dg/array-2.c, gcc.dg/array-3.c, gcc.dg/array-4.c: New.

From-SVN: r38678
This commit is contained in:
Richard Henderson 2001-01-03 17:14:16 -08:00 committed by Richard Henderson
parent 04d430b8d0
commit 584ef5fea5
10 changed files with 134 additions and 51 deletions

View File

@ -1,3 +1,16 @@
2000-01-03 Richard Henderson <rth@redhat.com>
* c-decl.c (grokdeclarator): Give zero-length arrays size zero.
Remove dead code.
* c-typeck.c (push_init_level): Move checks for flexible array
members and zero length arrays ...
(pop_init_level): ... here. Silently discard empty initializations.
Remove dead code.
* varasm.c (output_constructor): Update for sizeof change to
zero-length arrays.
* extend.texi (Zero Length): Clarify semantics.
2001-01-03 Alexandre Oliva <aoliva@redhat.com>
* configure.in (tm.h): Include isns-codes.h last.

View File

@ -4518,14 +4518,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (type_quals)
type = c_build_qualified_type (type, type_quals);
#if 0
/* Don't clear these; leave them set so that the array type
or the variable is itself const or volatile. */
type_quals = TYPE_UNQUALIFIED;
#endif
if (size_varies)
C_TYPE_VARIABLE_SIZE (type) = 1;
/* The GCC extension for zero-length arrays differs from
ISO flexible array members in that sizeof yields zero. */
if (size && integer_zerop (size))
{
layout_type (type);
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
}
else if (TREE_CODE (declarator) == CALL_EXPR)
{

View File

@ -1,6 +1,6 @@
/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000 Free Software Foundation, Inc.
1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@ -5289,20 +5289,9 @@ 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
(TYPE_DOMAIN (constructor_type)));
TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
}
else
constructor_index = bitsize_zero_node;
@ -5346,6 +5335,24 @@ pop_init_level (implicit)
if (constructor_type != 0)
size = int_size_in_bytes (constructor_type);
/* Error for initializing a flexible array member, or a zero-length
array member in an inappropriate context. */
if (constructor_type
&& TREE_CODE (constructor_type) == ARRAY_TYPE
&& TYPE_DOMAIN (constructor_type)
&& ! TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
{
if (! TYPE_SIZE (constructor_type))
error_init ("initialization of a flexible array member");
/* Silently discard empty initializations of zero-length arrays. */
else if (integer_zerop (constructor_unfilled_index))
constructor_type = 0;
/* Otherwise we must be initializing a member of a top-level
structure. */
else if (constructor_depth != 2)
error_init ("initialization of zero-length array inside a nested structure");
}
/* Warn when some struct elements are implicitly initialized to zero. */
if (extra_warnings
&& constructor_type
@ -5360,17 +5367,7 @@ pop_init_level (implicit)
/* Now output all pending elements. */
output_pending_init_elements (1);
#if 0 /* c-parse.in warns about {}. */
/* In ANSI, each brace level must have at least one element. */
if (! implicit && pedantic
&& (TREE_CODE (constructor_type) == ARRAY_TYPE
? integer_zerop (constructor_unfilled_index)
: constructor_unfilled_fields == TYPE_FIELDS (constructor_type)))
pedwarn_init ("empty braces in initializer");
#endif
/* Pad out the end of the structure. */
if (p->replacement_value)
/* If this closes a superfluous brace pair,
just pass out the element between them. */

View File

@ -869,8 +869,8 @@ extension for floating-point constants of type @code{float}.
@cindex zero-length arrays
@cindex length-zero arrays
Zero-length arrays are allowed in GNU C. They are very useful as the last
element of a structure which is really a header for a variable-length
Zero-length arrays are allowed in GNU C. They are very useful as the
last element of a structure which is really a header for a variable-length
object:
@example
@ -879,32 +879,54 @@ struct line @{
char contents[0];
@};
@{
struct line *thisline = (struct line *)
malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
@}
struct line *thisline = (struct line *)
malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
@end example
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}.
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[]}.
In ISO C99, you would use a @dfn{flexible array member}, which is
slightly different in syntax and semantics:
GCC allows static initialization of the zero-length array if
the structure is not nested inside another structure. I.e.
@itemize @bullet
@item
Flexible array members are written as @code{contents[]} without
the @code{0}.
@item
Flexible array members have incomplete type, and so the @code{sizeof}
operator may not be applied. As a quirk of the original implementation
of zero-length arrays, @code{sizeof} evaluates to zero.
@item
Flexible array members may only appear as the last member of a
@code{struct} that is otherwise non-empty. GCC currently allows
zero-length arrays anywhere. You may encounter problems, however,
defining structures containing only a zero-length array. Such usage
is deprecated, and we recommend using zero-length arrays only in
places in which flexible array members would be allowed.
@item
GCC allows static initialization of the zero-length array if the structure
is not nested inside another structure. In addition, for backward
compatibility with an earlier versions of gcc, we allow a degenerate empty
initialization when nested inside another structure. I.e.
@example
struct bar @{ struct line a; @};
/* Legal. */
struct line x = @{ 4, @{ 'g', 'o', 'o', 'd' @} @};
/* Illegal. */
struct bar @{
struct line a;
@} y = @{ @{ 3, @{ 'b', 'a', 'd' @} @} @};
struct bar y = @{ @{ 3, @{ 'b', 'a', 'd' @} @} @};
/* Legal. */
struct bar z = @{ @{ 0, @{ @} @} @};
@end example
@end itemize
@node Variable Length
@section Arrays of Variable Length

View File

@ -1,3 +1,8 @@
2001-01-03 Richard Henderson <rth@redhat.com>
* gcc.dg/940510-1.c: Update expected error wording.
* gcc.dg/array-2.c, gcc.dg/array-3.c, gcc.dg/array-4.c: New.
2001-01-03 Jeffrey Oldham <oldham@codesourcery.com>
* lib/target-supports.exp (check_alias_available): Modified to

View File

@ -1,3 +1,3 @@
/* { dg-do compile } */
/* { dg-options "-std=c89 -pedantic" } */
struct { int a[]; } x = { 0 }; /* { dg-error "(does not support)|(near initialization)" } */
struct { int a[]; } x = { 0 }; /* { dg-error "(flexible array member)|(near initialization)" } */

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "" } */
/* Verify that we can't do things to get ourselves in trouble
with GCC's zero-length array extension. */
struct f { int w; int x[0]; };
struct g { struct f f; };
struct g g1 = { { 0, { } } };
struct g g2 = { { 0, { 1 } } }; /* { dg-error "(nested structure)|(near initialization)" "nested" } */

View File

@ -0,0 +1,11 @@
/* { dg-do compile } */
/* { dg-options "" } */
/* ISO C99 flexible array members don't have a size. GCC's zero-length
array extension does. */
struct f { int w; int x[0]; } f;
struct g { int w; int x[]; } g;
char test_gcc[sizeof (f.x) ? -1 : 1];
char test_iso[sizeof (g.x) ? -1 : 1]; /* { dg-error "incomplete type" "iso" } */

View File

@ -0,0 +1,19 @@
/* { dg-do run } */
/* { dg-options "" } */
/* Verify that GCC's extension to initialize a zero-length array
member works properly. */
extern void abort(void);
extern void exit(int);
struct f { int w; int x[0]; } f = { 4, { 0, 1, 2, 3 } };
int main()
{
int i;
for (i = 0; i < f.w; ++i)
if (f.x[i] != i)
abort ();
exit(0);
}

View File

@ -1,6 +1,6 @@
/* Output variables, constants and external declarations, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000 Free Software Foundation, Inc.
1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@ -4607,16 +4607,19 @@ output_constructor (exp, size)
/* Determine size this element should occupy. */
if (field)
{
if (DECL_SIZE_UNIT (field))
if (DECL_SIZE_UNIT (field)
&& ! integer_zerop (DECL_SIZE_UNIT (field)))
fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
else
else if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
{
/* 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
/* If DECL_SIZE is not set or is zero, 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 = 0;
}
else
fieldsize = int_size_in_bytes (TREE_TYPE (type));