aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-08-23 09:28:26 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2005-08-23 09:28:26 +0200
commit73ed17ff80da57d02cdb33b0035d5e718ed39fa2 (patch)
treef384afa06e592a553c6af6af04e511b95114c8d8 /gcc
parent18b10a7276e8d33f3f77ff80225adc4df16619d9 (diff)
downloadgcc-73ed17ff80da57d02cdb33b0035d5e718ed39fa2.zip
gcc-73ed17ff80da57d02cdb33b0035d5e718ed39fa2.tar.gz
gcc-73ed17ff80da57d02cdb33b0035d5e718ed39fa2.tar.bz2
re PR middle-end/22043 (Fields not initialized for automatic structs with flexible array members)
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. * gcc.c-torture/execute/20050613-1.c: New test. From-SVN: r103389
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/expr.c29
-rw-r--r--gcc/gimplify.c13
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20050613-1.c27
-rw-r--r--gcc/tree-sra.c2
-rw-r--r--gcc/tree.h2
7 files changed, 79 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3aff7ed..1f3f538 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/expr.c b/gcc/expr.c
index 5961e27..6cfe2d1 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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;
}
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index a4ff3d2..9b34970 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f18a9bd..42002e9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..f1b4e94
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20050613-1.c
@@ -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;
+}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index bd3a3c3..940f7a9 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -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
diff --git a/gcc/tree.h b/gcc/tree.h
index 91b3827..dba6ed5 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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. */