diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-decl.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr25805.c | 40 |
4 files changed, 83 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 23f37b0..6fd7bfd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2006-01-19 Richard Sandiford <richard@codesourcery.com> + + PR c/25805 + * c-decl.c (add_flexible_array_elts_to_size): New function. + (finish_decl): Use it. + 2006-01-18 Andrew Pinski <pinskia@physics.uc.edu> * diagnostic.h: Include options.h. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index a3b56c0..8320aca 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -3068,6 +3068,35 @@ set_array_declarator_inner (struct c_declarator *decl, error ("static or type qualifiers in abstract declarator"); return decl; } + +/* INIT is a constructor that forms DECL's initializer. If the final + element initializes a flexible array field, add the size of that + initializer to DECL's size. */ + +static void +add_flexible_array_elts_to_size (tree decl, tree init) +{ + unsigned int size; + tree elt, type; + + size = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)); + if (size == 0) + return; + + elt = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (init), size - 1)->value; + type = TREE_TYPE (elt); + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) == NULL_TREE + && TYPE_DOMAIN (type) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + { + complete_array_type (&type, elt, false); + DECL_SIZE (decl) + = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type)); + DECL_SIZE_UNIT (decl) + = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type)); + } +} /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ @@ -3367,6 +3396,9 @@ finish_decl (tree decl, tree init, tree asmspec_tree) if (TREE_CODE (decl) == VAR_DECL) { + if (init && TREE_CODE (init) == CONSTRUCTOR) + add_flexible_array_elts_to_size (decl, init); + if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node && COMPLETE_TYPE_P (TREE_TYPE (decl))) layout_decl (decl, 0); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 62deeda..ca243bc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-01-19 Richard Sandiford <richard@codesourcery.com> + + PR c/25805 + * gcc.dg/pr25805.c: New file. + 2006-01-18 Mark Mitchell <mark@codesourcery.com> PR c++/25836 diff --git a/gcc/testsuite/gcc.dg/pr25805.c b/gcc/testsuite/gcc.dg/pr25805.c new file mode 100644 index 0000000..1060a96 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr25805.c @@ -0,0 +1,40 @@ +/* When -fzero-initialized-in-bss was in effect, we used to only allocate + storage for d1.a. */ +/* { dg-do run } */ +/* { dg-options "" } */ +extern void abort (void); +extern void exit (int); + +struct { int a; int x[]; } d1 = { 0, 0 }; +int d2 = 0; + +int +main () +{ + d2 = 1; + if (sizeof (d1) != sizeof (int)) + abort (); + if (d1.x[0] != 0) + abort (); + exit (0); +} +/* When -fzero-initialized-in-bss was in effect, we used to only allocate + storage for d1.a. */ +/* { dg-do run } */ +/* { dg-options "" } */ +extern void abort (void); +extern void exit (int); + +struct { int a; int x[]; } d1 = { 0, 0 }; +int d2 = 0; + +int +main () +{ + d2 = 1; + if (sizeof (d1) != sizeof (int)) + abort (); + if (d1.x[0] != 0) + abort (); + exit (0); +} |