diff options
author | Jakub Jelinek <jakub@redhat.com> | 2005-08-23 09:28:26 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2005-08-23 09:28:26 +0200 |
commit | 73ed17ff80da57d02cdb33b0035d5e718ed39fa2 (patch) | |
tree | f384afa06e592a553c6af6af04e511b95114c8d8 /gcc | |
parent | 18b10a7276e8d33f3f77ff80225adc4df16619d9 (diff) | |
download | gcc-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/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/expr.c | 29 | ||||
-rw-r--r-- | gcc/gimplify.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20050613-1.c | 27 | ||||
-rw-r--r-- | gcc/tree-sra.c | 2 | ||||
-rw-r--r-- | gcc/tree.h | 2 |
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 @@ -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 @@ -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. */ |