From: Richard Henderson Date: Thu, 4 Jan 2001 01:14:16 +0000 (-0800) Subject: c-decl.c (grokdeclarator): Give zero-length arrays size zero. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=584ef5fea573e2e0966c068ec8c5dd6dce493663;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 697f42a061f..ec1565dcd75 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2000-01-03 Richard Henderson + + * 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 * configure.in (tm.h): Include isns-codes.h last. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 0521aa77936..826608ba4c1 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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) { diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index d7efc2d56f7..6a57eed24bd 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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. */ diff --git a/gcc/extend.texi b/gcc/extend.texi index 811a423e7db..1a0b0e14c73 100644 --- a/gcc/extend.texi +++ b/gcc/extend.texi @@ -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: + +@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. -GCC allows static initialization of the zero-length array if -the structure is not nested inside another structure. I.e. +@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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6bf11589d66..204efd1cc3f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2001-01-03 Richard Henderson + + * 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 * lib/target-supports.exp (check_alias_available): Modified to diff --git a/gcc/testsuite/gcc.dg/940510-1.c b/gcc/testsuite/gcc.dg/940510-1.c index 5f241f57c94..a734c8f80d7 100644 --- a/gcc/testsuite/gcc.dg/940510-1.c +++ b/gcc/testsuite/gcc.dg/940510-1.c @@ -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)" } */ diff --git a/gcc/testsuite/gcc.dg/array-2.c b/gcc/testsuite/gcc.dg/array-2.c new file mode 100644 index 00000000000..aa6f0c67397 --- /dev/null +++ b/gcc/testsuite/gcc.dg/array-2.c @@ -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" } */ diff --git a/gcc/testsuite/gcc.dg/array-3.c b/gcc/testsuite/gcc.dg/array-3.c new file mode 100644 index 00000000000..f0709d22064 --- /dev/null +++ b/gcc/testsuite/gcc.dg/array-3.c @@ -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" } */ diff --git a/gcc/testsuite/gcc.dg/array-4.c b/gcc/testsuite/gcc.dg/array-4.c new file mode 100644 index 00000000000..9396dec3aa7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/array-4.c @@ -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); +} diff --git a/gcc/varasm.c b/gcc/varasm.c index 0ebcbd9da2a..b87d9beeaca 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -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));