aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard@codesourcery.com>2006-01-19 07:35:47 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2006-01-19 07:35:47 +0000
commit1f0f7cebf9eccfa3c9bac5c2602a261c487c86d2 (patch)
tree887b3e85fac5c0dbaab29803fab659be8bc0ce7a /gcc
parentc888c93b290aeb3f7eb556bd5b7ed4f7564c822a (diff)
downloadgcc-1f0f7cebf9eccfa3c9bac5c2602a261c487c86d2.zip
gcc-1f0f7cebf9eccfa3c9bac5c2602a261c487c86d2.tar.gz
gcc-1f0f7cebf9eccfa3c9bac5c2602a261c487c86d2.tar.bz2
re PR c/25805 (Incorrect handling of zero-initialized flexible arrays)
PR c/25805 * c-decl.c (add_flexible_array_elts_to_size): New function. (finish_decl): Use it. testsuite/ PR c/25805 * gcc.dg/pr25805.c: New file. From-SVN: r109946
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/c-decl.c32
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr25805.c40
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);
+}