OSDN Git Service

PR tree-optimization/22043
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 Aug 2005 07:28:26 +0000 (07:28 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 Aug 2005 07:28:26 +0000 (07:28 +0000)
* tree.h (count_type_elements): Add ALLOW_FLEXARR argument.
* expr.c (count_type_elements): Add ALLOW_FLEXARR argument.
If ALLOW_FLEXARR, handle types ending with flexible array member.
Pass false as second argument to recursive count_type_elements calls.
(categorize_ctor_elements_1, mostly_zeros_p): Pass false as second
argument to count_type_elements call.
* tree-sra.c (decide_block_copy): Likewise.
* gimplify.c (gimplify_init_constructor): If num_type_elements < 0
for a constant-sized object, set cleared as well.  Pass true as
second argument to count_type_elements call.

* gcc.c-torture/execute/20050613-1.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@103389 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20050613-1.c [new file with mode: 0644]
gcc/tree-sra.c
gcc/tree.h

index 3aff7ed..1f3f538 100644 (file)
@@ -1,3 +1,17 @@
+2005-08-23  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/22043
+       * tree.h (count_type_elements): Add ALLOW_FLEXARR argument.
+       * expr.c (count_type_elements): Add ALLOW_FLEXARR argument.
+       If ALLOW_FLEXARR, handle types ending with flexible array member.
+       Pass false as second argument to recursive count_type_elements calls.
+       (categorize_ctor_elements_1, mostly_zeros_p): Pass false as second
+       argument to count_type_elements call.
+       * tree-sra.c (decide_block_copy): Likewise.
+       * gimplify.c (gimplify_init_constructor): If num_type_elements < 0
+       for a constant-sized object, set cleared as well.  Pass true as
+       second argument to count_type_elements call.
+
 2005-08-23  Alan Modra  <amodra@bigpond.net.au>
 
        PR target/21571
index 5961e27..6cfe2d1 100644 (file)
@@ -4504,7 +4504,7 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
              /* And now we have to find out if the element itself is fully
                 constructed.  E.g. for union { struct { int a, b; } s; } u
                 = { .s = { .a = 1 } }.  */
-             if (elt_count == count_type_elements (init_sub_type))
+             if (elt_count == count_type_elements (init_sub_type, false))
                clear_this = false;
            }
        }
@@ -4532,10 +4532,11 @@ categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
 }
 
 /* Count the number of scalars in TYPE.  Return -1 on overflow or
-   variable-sized.  */
+   variable-sized.  If ALLOW_FLEXARR is true, don't count flexible
+   array member at the end of the structure.  */
 
 HOST_WIDE_INT
-count_type_elements (tree type)
+count_type_elements (tree type, bool allow_flexarr)
 {
   const HOST_WIDE_INT max = ~((HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT-1));
   switch (TREE_CODE (type))
@@ -4546,7 +4547,7 @@ count_type_elements (tree type)
        if (telts && host_integerp (telts, 1))
          {
            HOST_WIDE_INT n = tree_low_cst (telts, 1) + 1;
-           HOST_WIDE_INT m = count_type_elements (TREE_TYPE (type));
+           HOST_WIDE_INT m = count_type_elements (TREE_TYPE (type), false);
            if (n == 0)
              return 0;
            else if (max / n > m)
@@ -4563,9 +4564,23 @@ count_type_elements (tree type)
        for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
          if (TREE_CODE (f) == FIELD_DECL)
            {
-             t = count_type_elements (TREE_TYPE (f));
+             t = count_type_elements (TREE_TYPE (f), false);
              if (t < 0)
-               return -1;
+               {
+                 /* Check for structures with flexible array member.  */
+                 tree tf = TREE_TYPE (f);
+                 if (allow_flexarr
+                     && TREE_CHAIN (f) == NULL
+                     && TREE_CODE (tf) == ARRAY_TYPE
+                     && TYPE_DOMAIN (tf)
+                     && TYPE_MIN_VALUE (TYPE_DOMAIN (tf))
+                     && integer_zerop (TYPE_MIN_VALUE (TYPE_DOMAIN (tf)))
+                     && !TYPE_MAX_VALUE (TYPE_DOMAIN (tf))
+                     && int_size_in_bytes (type) >= 0)
+                   break;
+
+                 return -1;
+               }
              n += t;
            }
 
@@ -4623,7 +4638,7 @@ mostly_zeros_p (tree exp)
       if (must_clear)
        return 1;
 
-      elts = count_type_elements (TREE_TYPE (exp));
+      elts = count_type_elements (TREE_TYPE (exp), false);
 
       return nz_elts < elts / 4;
     }
index a4ff3d2..9b34970 100644 (file)
@@ -2706,13 +2706,18 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
           parts in, then generate code for the non-constant parts.  */
        /* TODO.  There's code in cp/typeck.c to do this.  */
 
-       num_type_elements = count_type_elements (TREE_TYPE (ctor));
+       num_type_elements = count_type_elements (type, true);
 
+       /* If count_type_elements could not determine number of type elements
+          for a constant-sized object, assume clearing is needed.
+          Don't do this for variable-sized objects, as store_constructor
+          will ignore the clearing of variable-sized objects.  */
+       if (num_type_elements < 0 && int_size_in_bytes (type) >= 0)
+         cleared = true;
        /* If there are "lots" of zeros, then block clear the object first.  */
-       if (num_type_elements - num_nonzero_elements > CLEAR_RATIO
-           && num_nonzero_elements < num_type_elements/4)
+       else if (num_type_elements - num_nonzero_elements > CLEAR_RATIO
+                && num_nonzero_elements < num_type_elements/4)
          cleared = true;
-
        /* ??? This bit ought not be needed.  For any element not present
           in the initializer, we should simply set them to zero.  Except
           we'd need to *find* the elements that are not present, and that
index f18a9bd..42002e9 100644 (file)
@@ -1,3 +1,8 @@
+2005-08-23  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/22043
+       * gcc.c-torture/execute/20050613-1.c: New test.
+
 2005-08-23  Ben Elliston  <bje@au.ibm.com>
 
        * gcc.c-torture/execute/ieee/ieee.exp: Load gcc-dg.exp library.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20050613-1.c b/gcc/testsuite/gcc.c-torture/execute/20050613-1.c
new file mode 100644 (file)
index 0000000..f1b4e94
--- /dev/null
@@ -0,0 +1,27 @@
+/* PR tree-optimization/22043 */
+
+extern void abort (void);
+
+struct A { int i; int j; int k; int l; };
+struct B { struct A a; int r[1]; };
+struct C { struct A a; int r[0]; };
+struct D { struct A a; int r[]; };
+
+void
+foo (struct A *x)
+{
+  if (x->i != 0 || x->j != 5 || x->k != 0 || x->l != 0)
+    abort ();
+}
+
+int
+main ()
+{
+  struct B b = { .a.j = 5 };
+  struct C c = { .a.j = 5 };
+  struct D d = { .a.j = 5 };
+  foo (&b.a);
+  foo (&c.a);
+  foo (&d.a);
+  return 0;
+}
index bd3a3c3..940f7a9 100644 (file)
@@ -1338,7 +1338,7 @@ decide_block_copy (struct sra_elt *elt)
            : MOVE_RATIO;
 
          full_size = tree_low_cst (size_tree, 1);
-         full_count = count_type_elements (elt->type);
+         full_count = count_type_elements (elt->type, false);
          inst_count = sum_instantiated_sizes (elt, &inst_size);
 
          /* ??? What to do here.  If there are two fields, and we've only
index 91b3827..dba6ed5 100644 (file)
@@ -3555,7 +3555,7 @@ extern bool initializer_zerop (tree);
 
 extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
                                      HOST_WIDE_INT *, bool *);
-extern HOST_WIDE_INT count_type_elements (tree);
+extern HOST_WIDE_INT count_type_elements (tree, bool);
 
 /* add_var_to_bind_expr (bind_expr, var) binds var to bind_expr.  */