OSDN Git Service

* c-decl.c (grokdeclarator): Support flexible array members.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 19 Nov 2000 23:40:37 +0000 (23:40 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 19 Nov 2000 23:40:37 +0000 (23:40 +0000)
        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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37576 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-decl.c
gcc/c-typeck.c
gcc/extend.texi
gcc/tree.c
gcc/varasm.c

index e845724..1e9c1c0 100644 (file)
@@ -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".
 
 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>
 
index 8868a11..9da1923 100644 (file)
@@ -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
index edf73ea..ada69a8 100644 (file)
@@ -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
index 573b36c..0d88bdf 100644 (file)
@@ -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
index 7652052..7910449 100644 (file)
@@ -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))
index 170cf09..799beeb 100644 (file)
@@ -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)
 }
 
 \f
-/* 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));