* 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
+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.
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)
{
/* 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.
{
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;
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
/* 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. */
@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
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
+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
/* { 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)" } */
--- /dev/null
+/* { 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" } */
--- /dev/null
+/* { 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" } */
--- /dev/null
+/* { 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);
+}
/* 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.
/* 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));