This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Zero-length arrays


This patch implements the changes to static initialization
of flexible array members and zero length arrays mentioned
earlier in this thread.

In addition, it checks the constraints that c99 places on
the placement and context of flexible array members.

Sanity bootstrapped on alphaev6-linux.



r~

        * c-decl.c (finish_struct): Detect flexible array members
        used in an inappropriate context.
        * c-typeck.c (really_start_incremental_init): Special case
        constructor_max_index for zero length arrays.
        (pop_init_level): Allow initialization of flexible array
        members.  Deprecate initialization of zero length arrays.
        Don't issue missing initializer warning for flexible array
        members or zero length arrays.
        (process_init_element): Don't dereference null DECL_SIZE.
        * varasm.c (array_size_for_constructor): Return a HOST_WIDE_INT.
        Don't abort for empty constructors.  Use size_binop
        (output_constructor): Add commentary regarding zero length 
        array futures.  Abort if we try to initialize an array of
        unspecified length with a non-empty constructor in the middle
        of a structure.

        * extend.texi (Zero Length): Update and clarify documentation
        on static initialization.

        * gcc.dg/20000926-1.c: Update expected warnings.
        * gcc.dg/array-2.c: Likewise.
        * gcc.dg/array-4.c: Also validate flexible array members.
        * gcc.dg/c99-flex-array-1.c: New.

Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.197
diff -c -p -d -r1.197 c-decl.c
*** c-decl.c	2001/01/04 01:14:14	1.197
--- c-decl.c	2001/01/05 05:44:10
*************** finish_struct (t, fieldlist, attributes)
*** 5338,5343 ****
--- 5338,5344 ----
  {
    register tree x;
    int toplevel = global_binding_level == current_binding_level;
+   int saw_named_field;
  
    /* If this type was previously laid out as a forward reference,
       make sure we lay it out again.  */
*************** finish_struct (t, fieldlist, attributes)
*** 5376,5381 ****
--- 5377,5383 ----
       Store 0 there, except for ": 0" fields (so we can find them
       and delete them, below).  */
  
+   saw_named_field = 0;
    for (x = fieldlist; x; x = TREE_CHAIN (x))
      {
        DECL_CONTEXT (x) = t;
*************** finish_struct (t, fieldlist, attributes)
*** 5509,5514 ****
--- 5511,5532 ----
  	}
  
        DECL_INITIAL (x) = 0;
+ 
+       /* Detect flexible array member in an invalid context.  */
+       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+ 	  && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+ 	  && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
+ 	  && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
+ 	{
+ 	  if (TREE_CODE (t) == UNION_TYPE)
+ 	    error_with_decl (x, "flexible array member in union");
+ 	  else if (TREE_CHAIN (x) != NULL_TREE)
+ 	    error_with_decl (x, "flexible array member not at end of struct");
+ 	  else if (! saw_named_field)
+ 	    error_with_decl (x, "flexible array member in otherwise empty struct");
+ 	}
+       if (DECL_NAME (x))
+ 	saw_named_field = 1;
      }
  
    /* Delete all duplicate fields from the fieldlist */
*************** finish_struct (t, fieldlist, attributes)
*** 5554,5561 ****
  	fieldlistp = &TREE_CHAIN (*fieldlistp);
    }
  
!   /*  Now we have the truly final field list.
!       Store it in this type and in the variants.  */
  
    TYPE_FIELDS (t) = fieldlist;
  
--- 5572,5579 ----
  	fieldlistp = &TREE_CHAIN (*fieldlistp);
    }
  
!   /* Now we have the truly final field list.
!      Store it in this type and in the variants.  */
  
    TYPE_FIELDS (t) = fieldlist;
  
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-typeck.c,v
retrieving revision 1.107
diff -c -p -d -r1.107 c-typeck.c
*** c-typeck.c	2001/01/04 01:14:14	1.107
--- c-typeck.c	2001/01/05 05:44:10
*************** really_start_incremental_init (type)
*** 5162,5167 ****
--- 5162,5172 ----
  	{
  	  constructor_max_index
  	    = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+ 
+ 	  /* Detect non-empty initializations of zero-length arrays.  */
+ 	  if (constructor_max_index == NULL_TREE)
+ 	    constructor_max_index = build_int_2 (-1, -1);
+ 
  	  constructor_index
  	    = convert (bitsizetype,
  		       TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
*************** push_init_level (implicit)
*** 5292,5297 ****
--- 5297,5307 ----
  	  constructor_index
  	    = convert (bitsizetype, 
  		       TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+ 
+ 	  /* ??? For GCC 3.1, remove special case initialization of
+ 	     zero-length array members from pop_init_level and set
+ 	     constructor_max_index such that we get the normal
+ 	     "excess elements" warning.  */
  	}
        else
  	constructor_index = bitsize_zero_node;
*************** pop_init_level (implicit)
*** 5337,5356 ****
  
    /* 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.  */
--- 5347,5388 ----
  
    /* Error for initializing a flexible array member, or a zero-length
       array member in an inappropriate context.  */
!   if (constructor_type && constructor_fields
        && TREE_CODE (constructor_type) == ARRAY_TYPE
        && TYPE_DOMAIN (constructor_type)
        && ! TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
      {
!       /* Silently discard empty initializations.  The parser will
! 	 already have pedwarned for empty brackets.  */
!       if (integer_zerop (constructor_unfilled_index))
! 	constructor_type = NULL_TREE;
!       else if (! TYPE_SIZE (constructor_type))
! 	{
! 	  if (constructor_depth > 2)
! 	    error_init ("initialization of flexible array member in a nested context");
! 	  else if (pedantic)
! 	    pedwarn_init ("initialization of a flexible array member");
! 
!           /* We have already issued an error message for the existance
! 	     of a flexible array member not at the end of the structure.
! 	     Discard the initializer so that we do not abort later.  */
! 	  if (TREE_CHAIN (constructor_fields) != NULL_TREE)
! 	    constructor_type = NULL_TREE;
! 	}
!       else
! 	{
! 	  warning_init ("deprecated initialization of zero-length array");
! 
!           /* We must be initializing the last member of a top-level struct.  */
! 	  if (TREE_CHAIN (constructor_fields) != NULL_TREE)
! 	    {
! 	      error_init ("initialization of zero-length array before end of structure");
! 	      /* Discard the initializer so that we do not abort later.  */
! 	      constructor_type = NULL_TREE;
! 	    }
! 	  else if (constructor_depth > 2)
! 	    error_init ("initialization of zero-length array inside a nested context");
! 	}
      }
  
    /* Warn when some struct elements are implicitly initialized to zero.  */
*************** pop_init_level (implicit)
*** 5359,5367 ****
        && TREE_CODE (constructor_type) == RECORD_TYPE
        && constructor_unfilled_fields)
      {
!       push_member_name (constructor_unfilled_fields);
!       warning_init ("missing initializer");
!       RESTORE_SPELLING_DEPTH (constructor_depth);
      }
  
    /* Now output all pending elements.  */
--- 5391,5408 ----
        && TREE_CODE (constructor_type) == RECORD_TYPE
        && constructor_unfilled_fields)
      {
!       /* Do not warn for flexible array members or zero-length arrays.  */
!       while (constructor_unfilled_fields
! 	     && (! DECL_SIZE (constructor_unfilled_fields)
! 		 || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
! 	constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
! 
!       if (constructor_unfilled_fields)
! 	{
! 	  push_member_name (constructor_unfilled_fields);
! 	  warning_init ("missing initializer");
! 	  RESTORE_SPELLING_DEPTH (constructor_depth);
! 	}
      }
  
    /* Now output all pending elements.  */
*************** process_init_element (value)
*** 6129,6138 ****
  	       directly output as a constructor.  */
  	    {
  	      /* For a record, keep track of end position of last field.  */
! 	      constructor_bit_index
! 		= size_binop (PLUS_EXPR,
! 			      bit_position (constructor_fields),
! 			      DECL_SIZE (constructor_fields));
  
  	      constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
  	      /* Skip any nameless bit fields.  */
--- 6170,6180 ----
  	       directly output as a constructor.  */
  	    {
  	      /* For a record, keep track of end position of last field.  */
! 	      if (DECL_SIZE (constructor_fields))
! 	        constructor_bit_index
! 		  = size_binop (PLUS_EXPR,
! 			        bit_position (constructor_fields),
! 			        DECL_SIZE (constructor_fields));
  
  	      constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
  	      /* Skip any nameless bit fields.  */
Index: extend.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/extend.texi,v
retrieving revision 1.81
diff -c -p -d -r1.81 extend.texi
*** extend.texi	2001/01/04 01:14:14	1.81
--- extend.texi	2001/01/05 05:44:10
*************** extension for floating-point constants o
*** 868,873 ****
--- 868,874 ----
  @cindex arrays of length zero
  @cindex zero-length arrays
  @cindex length-zero arrays
+ @cindex flexible array members
  
  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 anywhere.  You may en
*** 907,932 ****
  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 y = @{ @{ 3, @{ 'b', 'a', 'd' @} @} @};
  
! /* Legal.  */
! struct bar z = @{ @{ 0, @{ @} @} @};
  @end example
- @end itemize
  
  @node Variable Length
  @section Arrays of Variable Length
--- 908,959 ----
  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.
+ @end itemize
  
! GCC versions before 3.0 allowed zero-length arrays to be statically
! initialized.  In addition to those cases that were useful, it also
! allowed initializations in situations that would corrupt later data.
! Non-empty initialization of zero-length arrays is now deprecated.
  
+ Instead GCC allows static initialization of flexible array members.
+ This is equivalent to defining a new structure containing the original
+ structure followed by an array of sufficient size to contain the data.
+ I.e. in the following, @code{f1} is constructed as if it were declared
+ like @code{f2}.
+ 
  @example
! struct f1 @{
!   int x; int y[];
! @} f1 = @{ 1, @{ 2, 3, 4 @} @};
  
! struct f2 @{
!   struct f1 f1; int data[3];
! @} f2 = @{ @{ 1 @}, @{ 2, 3, 4 @} @};
! @end example
  
! @noindent
! The convenience of this extension is that @code{f1} has the desired
! type, eliminating the need to consistently refer to @code{f2.f1}.
  
! This has symmetry with normal static arrays, in that an array of
! unknown size is also written with @code{[]}.
! 
! Of course, this extension only makes sense if the extra data comes at
! the end of a top-level object, as otherwise we would be overwriting
! data at subsequent offsets.  To avoid undue complication and confusion
! with initialization of deeply nested arrays, we simply disallow any
! non-empty initialization except when the structure is the top-level
! object.  For example:
! 
! @example
! struct foo @{ int x; int y[]; @};
! struct bar @{ struct foo z; @};
! 
! struct foo a = @{ 1, @{ 2, 3, 4 @} @};        // Legal.
! struct bar b = @{ @{ 1, @{ 2, 3, 4 @} @} @};    // Illegal.
! struct bar c = @{ @{ 1, @{ @} @} @};            // Legal.
! struct foo d[1] = @{ @{ 1 @{ 2, 3, 4 @} @} @};  // Illegal.
  @end example
  
  @node Variable Length
  @section Arrays of Variable Length
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/varasm.c,v
retrieving revision 1.152
diff -c -p -d -r1.152 varasm.c
*** varasm.c	2001/01/04 20:58:20	1.152
--- varasm.c	2001/01/05 05:44:10
*************** struct varasm_status
*** 108,114 ****
    struct pool_constant *x_first_pool, *x_last_pool;
  
    /* Current offset in constant pool (does not include any machine-specific
!      header.  */
    int x_pool_offset;
  
    /* Chain of all CONST_DOUBLE rtx's constructed for the current function.
--- 108,114 ----
    struct pool_constant *x_first_pool, *x_last_pool;
  
    /* Current offset in constant pool (does not include any machine-specific
!      header).  */
    int x_pool_offset;
  
    /* Chain of all CONST_DOUBLE rtx's constructed for the current function.
*************** static void mark_constant_pool		PARAMS (
*** 171,177 ****
  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 *));
--- 171,177 ----
  static void mark_constants		PARAMS ((rtx));
  static int output_addressed_constants	PARAMS ((tree));
  static void output_after_function_constants PARAMS ((void));
! static unsigned HOST_WIDE_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 *));
*************** output_constant (exp, size)
*** 4446,4464 ****
     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))
      {
--- 4446,4457 ----
     arrays of unspecified length.  VAL must be a CONSTRUCTOR of an array
     type with an unspecified upper bound.  */
  
! static unsigned HOST_WIDE_INT
  array_size_for_constructor (val)
       tree val;
  {
    tree max_index, i;
  
    max_index = NULL_TREE;
    for (i = CONSTRUCTOR_ELTS (val); i ; i = TREE_CHAIN (i))
      {
*************** array_size_for_constructor (val)
*** 4470,4489 ****
  	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);
  }
--- 4463,4479 ----
  	max_index = index;
      }
  
    if (max_index == NULL_TREE)
!     return 0;
  
    /* Compute the total number of array elements.  */
!   i = size_binop (MINUS_EXPR, convert (sizetype, max_index), 
! 		  convert (sizetype,
! 			   TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)))));
!   i = size_binop (PLUS_EXPR, i, convert (sizetype, integer_one_node));
  
    /* Multiply by the array element unit size to find number of bytes.  */
!   i = size_binop (MULT_EXPR, i, TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
  
    return tree_low_cst (i, 1);
  }
*************** output_constructor (exp, size)
*** 4607,4624 ****
  	  /* Determine size this element should occupy.  */
  	  if (field)
  	    {
! 	      /* If the last field is an array with an unspecified upper
! 		 bound, the initializer determines the size.  */
! 	      if (TREE_CHAIN (field) == 0
! 		  && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
! 		  && TYPE_DOMAIN (TREE_TYPE (field)) != 0
! 		  && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))) == 0)
  		  fieldsize = array_size_for_constructor (val);
! 	      else if (DECL_SIZE_UNIT (field)
! 		  && host_integerp (DECL_SIZE_UNIT (field), 1))
! 		fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
! 	      else
! 		fieldsize = 0;
  	    }
  	  else
  	    fieldsize = int_size_in_bytes (TREE_TYPE (type));
--- 4597,4626 ----
  	  /* Determine size this element should occupy.  */
  	  if (field)
  	    {
! 	      fieldsize = 0;
! 
! 	      /* If this is an array with an unspecified upper bound,
! 		 the initializer determines the size.  */
! 	      /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
! 		 but we cannot do this until the deprecated support for
! 		 initializing zero-length array members is removed.  */
! 	      if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
! 		  && TYPE_DOMAIN (TREE_TYPE (field))
! 		  && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
! 		{
  		  fieldsize = array_size_for_constructor (val);
! 		  /* Given a non-empty initialization, this field had
! 		     better be last.  */
! 		  if (fieldsize != 0 && TREE_CHAIN (field) != NULL_TREE)
! 		    abort ();
! 		}
! 	      else if (DECL_SIZE_UNIT (field))
! 		{
! 		  /* ??? This can't be right.  If the decl size overflows
! 		     a host integer we will silently emit no data.  */
! 		  if (host_integerp (DECL_SIZE_UNIT (field), 1))
! 		    fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
! 		}
  	    }
  	  else
  	    fieldsize = int_size_in_bytes (TREE_TYPE (type));
Index: testsuite/gcc.dg/20000926-1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/gcc.dg/20000926-1.c,v
retrieving revision 1.2
diff -c -p -d -r1.2 20000926-1.c
*** 20000926-1.c	2000/11/28 22:25:51	1.2
--- 20000926-1.c	2001/01/05 05:44:11
***************
*** 1,5 ****
  /* Copyright (C) 2000  Free Software Foundation.
- 
     by William Cohen  <wcohen@redhat.com>  */
  
  /* { dg-do compile } */
--- 1,4 ----
*************** struct PLAYBOOK playbook  =
*** 23,27 ****
    "BookName",
    {
      { 1, "PName0" },
!   }
  };
--- 22,26 ----
    "BookName",
    {
      { 1, "PName0" },
!   } /* { dg-warning "(deprecated initialization)|(near initialization)" "" } */
  };
Index: testsuite/gcc.dg/array-2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/gcc.dg/array-2.c,v
retrieving revision 1.1
diff -c -p -d -r1.1 array-2.c
*** array-2.c	2001/01/04 01:14:16	1.1
--- array-2.c	2001/01/05 05:44:11
***************
*** 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" } */
--- 1,13 ----
  /* { dg-do compile } */
! /* { dg-options "-w" } */
  
  /* Verify that we can't do things to get ourselves in trouble
!    with GCC's initialized flexible array member extension.  */
  
! struct f { int w; int x[]; };
  struct g { struct f f; };
  struct g g1 = { { 0, { } } };
! struct g g2 = { { 0, { 1 } } }; /* { dg-error "(nested context)|(near initialization)" "nested" } */
! 
! struct h { int x[0]; int y; };
! struct h h1 = { { 0 }, 1 }; /* { dg-error "(before end)|(near initialization)" "before end" } */
Index: testsuite/gcc.dg/array-4.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/gcc.dg/array-4.c,v
retrieving revision 1.1
diff -c -p -d -r1.1 array-4.c
*** array-4.c	2001/01/04 01:14:16	1.1
--- array-4.c	2001/01/05 05:44:11
***************
*** 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);
  }
--- 1,28 ----
  /* { dg-do run } */
  /* { dg-options "" } */
  
! /* Verify that GCC's initialized flexible array member extension
!    works properly.  */
  
  extern void abort(void);
  extern void exit(int);
  
! struct f { int w; int x[]; };
! struct g { int w; int x[0]; };
  
+ static struct f f = { 4, { 0, 1, 2, 3 } };
+ static int junk1[] = { -1, -1, -1, -1 };
+ static struct g g = { 4, { 0, 1, 2, 3 } }; /* { dg-warning "(deprecated initialization)|(near initialization)" "" } */
+ static int junk2[] = { -1, -1, -1, -1 };
+ 
  int main()
  {
    int i;
    for (i = 0; i < f.w; ++i)
      if (f.x[i] != i)
+       abort ();
+   for (i = 0; i < g.w; ++i)
+     if (g.x[i] != i)
        abort ();
    exit(0);
  }
Index: testsuite/gcc.dg/c99-flex-array-1.c
===================================================================
RCS file: c99-flex-array-1.c
diff -N c99-flex-array-1.c
*** /dev/null	Tue May  5 13:32:27 1998
--- c99-flex-array-1.c	Thu Jan  4 21:44:11 2001
***************
*** 0 ****
--- 1,8 ----
+ /* Test for invalid uses of flexible array members.  */
+ /* { dg-do compile } */
+ /* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+ 
+ struct s1 { int x[]; }; /* { dg-error "empty struct" "empty" } */
+ struct s2 { int :1; int x[]; }; /* { dg-error "empty struct" "empty" } */
+ struct s3 { int x[]; int y; }; /* { dg-error "not at end" "not at end" } */
+ struct s4 { int x; int y[]; };

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]