From: rth Date: Sun, 19 Nov 2000 23:40:37 +0000 (+0000) Subject: * c-decl.c (grokdeclarator): Support flexible array members. X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=1b82e8583b1e092e52d07a9a8b8abbfecc16e99f * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37576 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e84572495bd..1e9c1c0afc4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2000-11-19 Richard Henderson + + * 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 * config.gcc, invoke.texi: Fix errors in spelling of "deprecated". @@ -116,8 +128,7 @@ 2000-11-17 Neil Booth - * 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 diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 8868a11b39e..9da1923adee 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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 diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index edf73ea00be..ada69a8e395 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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 diff --git a/gcc/extend.texi b/gcc/extend.texi index 573b36cd331..0d88bdf175e 100644 --- a/gcc/extend.texi +++ b/gcc/extend.texi @@ -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 diff --git a/gcc/tree.c b/gcc/tree.c index 7652052662e..7910449bd34 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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)) diff --git a/gcc/varasm.c b/gcc/varasm.c index 170cf09ab1c..799beeb14ee 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -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) } -/* 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));