diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 23f37b0f7804bbc33766636bd840d883191daa45..6fd7bfd6c18763492186ad8038cc7e3d8c056a3b 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 a3b56c0b63451fe97651c3e4956cb704ae1a69a8..8320acaf6514668d51a547477ef967493d5c40e6 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 62deedaff30ae00b544737fe262328c7ca15e1ca..ca243bcbd860dc4501018196864802b190515c96 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 0000000000000000000000000000000000000000..1060a96cfe24b40acf746c341e249bfba496b80d
--- /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);
+}