diff options
author | Richard Henderson <rth@redhat.com> | 2005-01-26 07:20:53 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-01-26 07:20:53 -0800 |
commit | 6f642f985272e36ec5bac248a65e912605727337 (patch) | |
tree | 2bf5d70375fa0bc54fd1069c76adcd376923ad97 /gcc | |
parent | ead553a1d9f9206c1f5a3b1a6799ea877fc9a845 (diff) | |
download | gcc-6f642f985272e36ec5bac248a65e912605727337.zip gcc-6f642f985272e36ec5bac248a65e912605727337.tar.gz gcc-6f642f985272e36ec5bac248a65e912605727337.tar.bz2 |
re PR middle-end/19515 (Violation of C99 6.7.8 ยง21 for unions)
PR middle-end/19515
* expr.c (categorize_ctor_elements): New argument p_must_clear.
(categorize_ctor_elements_1): Likewise. Detect a union that isn't
fully initialized.
(mostly_zeros_p): Update for new categorize_ctor_elements argument.
* gimplify.c (gimplify_init_constructor): Likewise. Only shove
objects into static storage if they have more than one non-zero value.
* tree.h (categorize_ctor_elements): Update decl.
From-SVN: r94266
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/expr.c | 56 | ||||
-rw-r--r-- | gcc/gimplify.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr19515.c | 17 | ||||
-rw-r--r-- | gcc/tree.h | 4 |
5 files changed, 80 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ef8f274..a7b83b8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2005-01-26 Richard Henderson <rth@redhat.com> + + PR middle-end/19515 + * expr.c (categorize_ctor_elements): New argument p_must_clear. + (categorize_ctor_elements_1): Likewise. Detect a union that isn't + fully initialized. + (mostly_zeros_p): Update for new categorize_ctor_elements argument. + * gimplify.c (gimplify_init_constructor): Likewise. Only shove + objects into static storage if they have more than one non-zero value. + * tree.h (categorize_ctor_elements): Update decl. + 2005-01-26 Steven Bosscher <stevenb@suse.de> PR middle-end/19616 @@ -4272,12 +4272,15 @@ store_expr (tree exp, rtx target, int call_param_p) * how many scalar fields are set to non-constant values, and place it in *P_NC_ELTS; and * how many scalar fields in total are in CTOR, - and place it in *P_ELT_COUNT. */ + and place it in *P_ELT_COUNT. + * if a type is a union, and the initializer from the constructor + is not the largest element in the union, then set *p_must_clear. */ static void categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, HOST_WIDE_INT *p_nc_elts, - HOST_WIDE_INT *p_elt_count) + HOST_WIDE_INT *p_elt_count, + bool *p_must_clear) { HOST_WIDE_INT nz_elts, nc_elts, elt_count; tree list; @@ -4307,11 +4310,11 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, { case CONSTRUCTOR: { - HOST_WIDE_INT nz = 0, nc = 0, count = 0; - categorize_ctor_elements_1 (value, &nz, &nc, &count); + HOST_WIDE_INT nz = 0, nc = 0, ic = 0; + categorize_ctor_elements_1 (value, &nz, &nc, &ic, p_must_clear); nz_elts += mult * nz; nc_elts += mult * nc; - elt_count += mult * count; + elt_count += mult * ic; } break; @@ -4356,6 +4359,36 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, } } + if (!*p_must_clear + && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE + || TREE_CODE (TREE_TYPE (ctor)) == QUAL_UNION_TYPE)) + { + tree init_sub_type; + + /* We don't expect more than one element of the union to be + initialized. Not sure what we should do otherwise... */ + list = CONSTRUCTOR_ELTS (ctor); + gcc_assert (TREE_CHAIN (list) == NULL); + + init_sub_type = TREE_TYPE (TREE_VALUE (list)); + + /* ??? We could look at each element of the union, and find the + largest element. Which would avoid comparing the size of the + initialized element against any tail padding in the union. + Doesn't seem worth the effort... */ + if (simple_cst_equal (TYPE_SIZE (TREE_TYPE (ctor)), + TYPE_SIZE (init_sub_type)) == 1) + { + /* 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)) + *p_must_clear = true; + } + else + *p_must_clear = true; + } + *p_nz_elts += nz_elts; *p_nc_elts += nc_elts; *p_elt_count += elt_count; @@ -4364,12 +4397,15 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts, void categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts, HOST_WIDE_INT *p_nc_elts, - HOST_WIDE_INT *p_elt_count) + HOST_WIDE_INT *p_elt_count, + bool *p_must_clear) { *p_nz_elts = 0; *p_nc_elts = 0; *p_elt_count = 0; - categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts, p_elt_count); + *p_must_clear = false; + categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts, p_elt_count, + p_must_clear); } /* Count the number of scalars in TYPE. Return -1 on overflow or @@ -4459,8 +4495,12 @@ mostly_zeros_p (tree exp) { HOST_WIDE_INT nz_elts, nc_elts, count, elts; + bool must_clear; + + categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count, &must_clear); + if (must_clear) + return 1; - categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count); elts = count_type_elements (TREE_TYPE (exp)); return nz_elts < elts / 4; diff --git a/gcc/gimplify.c b/gcc/gimplify.c index d77a3b3..ac9ae14 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2599,11 +2599,12 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, categorize_ctor_elements (ctor, &num_nonzero_elements, &num_nonconstant_elements, - &num_ctor_elements); + &num_ctor_elements, &cleared); /* If a const aggregate variable is being initialized, then it should never be a lose to promote the variable to be static. */ if (num_nonconstant_elements == 0 + && num_nonzero_elements > 1 && TREE_READONLY (object) && TREE_CODE (object) == VAR_DECL) { @@ -2685,7 +2686,6 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, num_type_elements = count_type_elements (TREE_TYPE (ctor)); /* If there are "lots" of zeros, then block clear the object first. */ - cleared = false; if (num_type_elements - num_nonzero_elements > CLEAR_RATIO && num_nonzero_elements < num_type_elements/4) cleared = true; diff --git a/gcc/testsuite/gcc.c-torture/execute/pr19515.c b/gcc/testsuite/gcc.c-torture/execute/pr19515.c new file mode 100644 index 0000000..df0e107 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr19515.c @@ -0,0 +1,17 @@ +/* PR 19515 */ + +typedef union { + char a2[8]; +}aun; + +void abort (void); + +int main(void) +{ + aun a = {{0}}; + + if (a.a2[2] != 0) + abort (); + return 0; +} + @@ -3235,8 +3235,8 @@ extern int fields_length (tree); extern bool initializer_zerop (tree); -extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, - HOST_WIDE_INT *, HOST_WIDE_INT *); +extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, + HOST_WIDE_INT *, bool *); extern HOST_WIDE_INT count_type_elements (tree); /* add_var_to_bind_expr (bind_expr, var) binds var to bind_expr. */ |