From 73ed17ff80da57d02cdb33b0035d5e718ed39fa2 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 23 Aug 2005 09:28:26 +0200 Subject: 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 --- gcc/ChangeLog | 14 ++++++++++++ gcc/expr.c | 29 ++++++++++++++++++------ gcc/gimplify.c | 13 +++++++---- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.c-torture/execute/20050613-1.c | 27 ++++++++++++++++++++++ gcc/tree-sra.c | 2 +- gcc/tree.h | 2 +- 7 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20050613-1.c (limited to 'gcc') 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 + + 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 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 + + PR tree-optimization/22043 + * gcc.c-torture/execute/20050613-1.c: New test. + 2005-08-23 Ben Elliston * 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. */ -- cgit v1.1