Blame SOURCES/gcc48-pr28865.patch

25c7f1
2014-01-16  Nick Clifton  <nickc@redhat.com>
25c7f1
25c7f1
	PR middle-end/28865
25c7f1
	* varasm.c (output_constant): Return the number of bytes actually
25c7f1
	emitted.
25c7f1
	(output_constructor_array_range): Update the field size with the
25c7f1
	number of bytes emitted by output_constant.
25c7f1
	(output_constructor_regular_field): Likewise.  Also do not
25c7f1
	complain if the total number of bytes emitted is now greater
25c7f1
	than the expected fieldpos.
25c7f1
	* output.h (output_constant): Update prototype and descriptive
25c7f1
	comment.
25c7f1
25c7f1
	* gcc.c-torture/compile/pr28865.c: New.
25c7f1
	* gcc.c-torture/execute/pr28865.c: New.
25c7f1
25c7f1
--- gcc/varasm.c	(revision 206660)
25c7f1
+++ gcc/varasm.c	(revision 206661)
25c7f1
@@ -4474,8 +4474,10 @@ static unsigned HOST_WIDE_INT
25c7f1
    This includes the pseudo-op such as ".int" or ".byte", and a newline.
25c7f1
    Assumes output_addressed_constants has been done on EXP already.
25c7f1
 
25c7f1
-   Generate exactly SIZE bytes of assembler data, padding at the end
25c7f1
-   with zeros if necessary.  SIZE must always be specified.
25c7f1
+   Generate at least SIZE bytes of assembler data, padding at the end
25c7f1
+   with zeros if necessary.  SIZE must always be specified.  The returned
25c7f1
+   value is the actual number of bytes of assembler data generated, which
25c7f1
+   may be bigger than SIZE if the object contains a variable length field.
25c7f1
 
25c7f1
    SIZE is important for structure constructors,
25c7f1
    since trailing members may have been omitted from the constructor.
25c7f1
@@ -4490,14 +4492,14 @@ static unsigned HOST_WIDE_INT
25c7f1
 
25c7f1
    ALIGN is the alignment of the data in bits.  */
25c7f1
 
25c7f1
-void
25c7f1
+unsigned HOST_WIDE_INT
25c7f1
 output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
25c7f1
 {
25c7f1
   enum tree_code code;
25c7f1
   unsigned HOST_WIDE_INT thissize;
25c7f1
 
25c7f1
   if (size == 0 || flag_syntax_only)
25c7f1
-    return;
25c7f1
+    return size;
25c7f1
 
25c7f1
   /* See if we're trying to initialize a pointer in a non-default mode
25c7f1
      to the address of some declaration somewhere.  If the target says
25c7f1
@@ -4562,7 +4564,7 @@ output_constant (tree exp, unsigned HOST
25c7f1
       && vec_safe_is_empty (CONSTRUCTOR_ELTS (exp)))
25c7f1
     {
25c7f1
       assemble_zeros (size);
25c7f1
-      return;
25c7f1
+      return size;
25c7f1
     }
25c7f1
 
25c7f1
   if (TREE_CODE (exp) == FDESC_EXPR)
25c7f1
@@ -4574,7 +4576,7 @@ output_constant (tree exp, unsigned HOST
25c7f1
 #else
25c7f1
       gcc_unreachable ();
25c7f1
 #endif
25c7f1
-      return;
25c7f1
+      return size;
25c7f1
     }
25c7f1
 
25c7f1
   /* Now output the underlying data.  If we've handling the padding, return.
25c7f1
@@ -4612,8 +4614,7 @@ output_constant (tree exp, unsigned HOST
25c7f1
       switch (TREE_CODE (exp))
25c7f1
 	{
25c7f1
 	case CONSTRUCTOR:
25c7f1
-	    output_constructor (exp, size, align, NULL);
25c7f1
-	  return;
25c7f1
+	  return output_constructor (exp, size, align, NULL);
25c7f1
 	case STRING_CST:
25c7f1
 	  thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
25c7f1
 			  size);
25c7f1
@@ -4648,11 +4649,10 @@ output_constant (tree exp, unsigned HOST
25c7f1
     case RECORD_TYPE:
25c7f1
     case UNION_TYPE:
25c7f1
       gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
25c7f1
-      output_constructor (exp, size, align, NULL);
25c7f1
-      return;
25c7f1
+      return output_constructor (exp, size, align, NULL);
25c7f1
 
25c7f1
     case ERROR_MARK:
25c7f1
-      return;
25c7f1
+      return 0;
25c7f1
 
25c7f1
     default:
25c7f1
       gcc_unreachable ();
25c7f1
@@ -4660,6 +4660,8 @@ output_constant (tree exp, unsigned HOST
25c7f1
 
25c7f1
   if (size > thissize)
25c7f1
     assemble_zeros (size - thissize);
25c7f1
+
25c7f1
+  return size;
25c7f1
 }
25c7f1
 
25c7f1
 
25c7f1
@@ -4759,7 +4761,7 @@ output_constructor_array_range (oc_local
25c7f1
       if (local->val == NULL_TREE)
25c7f1
 	assemble_zeros (fieldsize);
25c7f1
       else
25c7f1
-	output_constant (local->val, fieldsize, align2);
25c7f1
+	fieldsize = output_constant (local->val, fieldsize, align2);
25c7f1
 
25c7f1
       /* Count its size.  */
25c7f1
       local->total_bytes += fieldsize;
25c7f1
@@ -4808,9 +4810,8 @@ output_constructor_regular_field (oc_loc
25c7f1
      Note no alignment needed in an array, since that is guaranteed
25c7f1
      if each element has the proper size.  */
25c7f1
   if ((local->field != NULL_TREE || local->index != NULL_TREE)
25c7f1
-      && fieldpos != local->total_bytes)
25c7f1
+      && fieldpos > local->total_bytes)
25c7f1
     {
25c7f1
-      gcc_assert (fieldpos >= local->total_bytes);
25c7f1
       assemble_zeros (fieldpos - local->total_bytes);
25c7f1
       local->total_bytes = fieldpos;
25c7f1
     }
25c7f1
@@ -4847,7 +4848,7 @@ output_constructor_regular_field (oc_loc
25c7f1
   if (local->val == NULL_TREE)
25c7f1
     assemble_zeros (fieldsize);
25c7f1
   else
25c7f1
-    output_constant (local->val, fieldsize, align2);
25c7f1
+    fieldsize = output_constant (local->val, fieldsize, align2);
25c7f1
 
25c7f1
   /* Count its size.  */
25c7f1
   local->total_bytes += fieldsize;
25c7f1
--- gcc/output.h	(revision 206660)
25c7f1
+++ gcc/output.h	(revision 206661)
25c7f1
@@ -294,11 +294,13 @@ extern void output_quoted_string (FILE *
25c7f1
    This includes the pseudo-op such as ".int" or ".byte", and a newline.
25c7f1
    Assumes output_addressed_constants has been done on EXP already.
25c7f1
 
25c7f1
-   Generate exactly SIZE bytes of assembler data, padding at the end
25c7f1
-   with zeros if necessary.  SIZE must always be specified.
25c7f1
+   Generate at least SIZE bytes of assembler data, padding at the end
25c7f1
+   with zeros if necessary.  SIZE must always be specified.  The returned
25c7f1
+   value is the actual number of bytes of assembler data generated, which
25c7f1
+   may be bigger than SIZE if the object contains a variable length field.
25c7f1
 
25c7f1
    ALIGN is the alignment in bits that may be assumed for the data.  */
25c7f1
-extern void output_constant (tree, unsigned HOST_WIDE_INT, unsigned int);
25c7f1
+extern unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT, unsigned int);
25c7f1
 
25c7f1
 /* When outputting delayed branch sequences, this rtx holds the
25c7f1
    sequence being output.  It is null when no delayed branch
25c7f1
--- gcc/testsuite/gcc.c-torture/execute/pr28865.c	(revision 0)
25c7f1
+++ gcc/testsuite/gcc.c-torture/execute/pr28865.c	(revision 206661)
25c7f1
@@ -0,0 +1,21 @@
25c7f1
+struct A { int a; char b[]; };
25c7f1
+union B { struct A a; char b[sizeof (struct A) + 31]; };
25c7f1
+union B b = { { 1, "123456789012345678901234567890" } };
25c7f1
+union B c = { { 2, "123456789012345678901234567890" } };
25c7f1
+
25c7f1
+__attribute__((noinline, noclone)) void
25c7f1
+foo (int *x[2])
25c7f1
+{
25c7f1
+  x[0] = &b.a.a;
25c7f1
+  x[1] = &c.a.a;
25c7f1
+}
25c7f1
+
25c7f1
+int
25c7f1
+main ()
25c7f1
+{
25c7f1
+  int *x[2];
25c7f1
+  foo (x);
25c7f1
+  if (*x[0] != 1 || *x[1] != 2)
25c7f1
+    __builtin_abort ();
25c7f1
+  return 0;
25c7f1
+}
25c7f1
--- gcc/testsuite/gcc.c-torture/compile/pr28865.c	(revision 0)
25c7f1
+++ gcc/testsuite/gcc.c-torture/compile/pr28865.c	(revision 206661)
25c7f1
@@ -0,0 +1,16 @@
25c7f1
+struct var_len
25c7f1
+{
25c7f1
+  int field1;
25c7f1
+  const char field2[];
25c7f1
+};
25c7f1
+
25c7f1
+/* Note - strictly speaking this array declaration is illegal
25c7f1
+   since each element has a variable length.  GCC allows it
25c7f1
+   (for the moment) because it is used in existing code, such
25c7f1
+   as glibc.  */
25c7f1
+static const struct var_len var_array[] = 
25c7f1
+{
25c7f1
+  { 1, "Long exposure noise reduction" },
25c7f1
+  { 2, "Shutter/AE lock buttons" },
25c7f1
+  { 3, "Mirror lockup" }
25c7f1
+};