This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR c/25805: DECL_SIZE of initialised flexible arrays


While working on the section anchor patch, I noticed that DECL_SIZE
is not set correctly for decls that have an initialised flexible array
field.  One symptom of this is that we will only allocate one int for:

    struct { int a; int x[]; } d1 = { 0, 0 };

when -fzero-initialized-in-bss is in effect.  A testcase is attached
below, and passes if compiled with -fno-zero-initialized-in-bss.

Bootstrapped & regression tested on i686-pc-linux-gnu.  OK to install?
Andrew Pinski says that this is a regression from 3.2.3, so if it's
OK for trunk, is it also OK for all active branches?

Richard


	* c-decl.c (add_flexible_array_elts_to_size): New function.
	(finish_decl): Use it.

testsuite/
	* gcc.dg/pr25805.c: New file.

Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 109745)
+++ gcc/c-decl.c	(working copy)
@@ -3054,6 +3054,35 @@ set_array_declarator_inner (struct c_dec
     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.  */
 
@@ -3353,6 +3382,9 @@ finish_decl (tree decl, tree init, 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);
Index: gcc/testsuite/gcc.dg/pr25805.c
===================================================================
--- gcc/testsuite/gcc.dg/pr25805.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr25805.c	(revision 0)
@@ -0,0 +1,20 @@
+/* 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);
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]