Hi,

while compute_record_mode in stor-layout.c makes sure it assigns BLK
mode to structs with flexible arrays, it has no such provisions for
zero length arrays
(http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/Zero-Length.html).  I
think that in order to avoid problems and surprises like PR 57748
(where this triggered code that was intended for small structures that
fit into a scalar mode and ICEd), we should assign both variable array
possibilities the same mode.

Bootstrapped and tested on x86_64-linux without any problems.  OK for
trunk and the 4.8 branch?  (I'm not sure about the 4.7, this PR does
not happen there despite the wrong mode so I'd ignore it for now.)

Thanks,

Martin


2013-08-01  Martin Jambor  <mjam...@suse.cz>

        PR middle-end/57748
        * stor-layout.c (compute_record_mode): Treat zero-sized array fields
        like incomplete types.

testsuite/
        * gcc.dg/torture/pr57748.c: New test.


*** /tmp/lV6Ba8_stor-layout.c   Thu Aug  1 16:28:25 2013
--- gcc/stor-layout.c   Thu Aug  1 15:36:18 2013
*************** compute_record_mode (tree type)
*** 1604,1610 ****
                   && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))))
          || ! host_integerp (bit_position (field), 1)
          || DECL_SIZE (field) == 0
!         || ! host_integerp (DECL_SIZE (field), 1))
        return;
  
        /* If this field is the whole struct, remember its mode so
--- 1604,1612 ----
                   && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))))
          || ! host_integerp (bit_position (field), 1)
          || DECL_SIZE (field) == 0
!         || ! host_integerp (DECL_SIZE (field), 1)
!         || (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
!             && tree_low_cst (DECL_SIZE (field), 1) == 0))
        return;
  
        /* If this field is the whole struct, remember its mode so
*** /dev/null   Tue Jun  4 12:34:56 2013
--- gcc/testsuite/gcc.dg/torture/pr57748.c      Thu Aug  1 15:42:14 2013
***************
*** 0 ****
--- 1,45 ----
+ /* PR middle-end/57748 */
+ /* { dg-do run } */
+ 
+ #include <stdlib.h>
+ 
+ extern void abort (void);
+ 
+ typedef long long V
+   __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+ 
+ typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
+ 
+ struct __attribute__((packed)) T { char c; P s; };
+ 
+ void __attribute__((noinline, noclone))
+ check (struct T *t)
+ {
+   if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4)
+     abort ();
+ }
+ 
+ int __attribute__((noinline, noclone))
+ get_i (void)
+ {
+   return 0;
+ }
+ 
+ void __attribute__((noinline, noclone))
+ foo (P *p)
+ {
+   V a = { 3, 4 };
+   int i = get_i();
+   p->b[i] = a;
+ }
+ 
+ int
+ main ()
+ {
+   struct T *t = (struct T *) malloc (128);
+ 
+   foo (&t->s);
+   check (t);
+ 
+   return 0;
+ }

Reply via email to