mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-11 04:14:31 +08:00
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
This commit is contained in:
parent
ead553a1d9
commit
6f642f9852
@ -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>
|
2005-01-26 Steven Bosscher <stevenb@suse.de>
|
||||||
|
|
||||||
PR middle-end/19616
|
PR middle-end/19616
|
||||||
|
56
gcc/expr.c
56
gcc/expr.c
@ -4272,12 +4272,15 @@ store_expr (tree exp, rtx target, int call_param_p)
|
|||||||
* how many scalar fields are set to non-constant values,
|
* how many scalar fields are set to non-constant values,
|
||||||
and place it in *P_NC_ELTS; and
|
and place it in *P_NC_ELTS; and
|
||||||
* how many scalar fields in total are in CTOR,
|
* 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
|
static void
|
||||||
categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
|
categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
|
||||||
HOST_WIDE_INT *p_nc_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;
|
HOST_WIDE_INT nz_elts, nc_elts, elt_count;
|
||||||
tree list;
|
tree list;
|
||||||
@ -4307,11 +4310,11 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
|
|||||||
{
|
{
|
||||||
case CONSTRUCTOR:
|
case CONSTRUCTOR:
|
||||||
{
|
{
|
||||||
HOST_WIDE_INT nz = 0, nc = 0, count = 0;
|
HOST_WIDE_INT nz = 0, nc = 0, ic = 0;
|
||||||
categorize_ctor_elements_1 (value, &nz, &nc, &count);
|
categorize_ctor_elements_1 (value, &nz, &nc, &ic, p_must_clear);
|
||||||
nz_elts += mult * nz;
|
nz_elts += mult * nz;
|
||||||
nc_elts += mult * nc;
|
nc_elts += mult * nc;
|
||||||
elt_count += mult * count;
|
elt_count += mult * ic;
|
||||||
}
|
}
|
||||||
break;
|
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_nz_elts += nz_elts;
|
||||||
*p_nc_elts += nc_elts;
|
*p_nc_elts += nc_elts;
|
||||||
*p_elt_count += elt_count;
|
*p_elt_count += elt_count;
|
||||||
@ -4364,12 +4397,15 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
|
|||||||
void
|
void
|
||||||
categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
|
categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
|
||||||
HOST_WIDE_INT *p_nc_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_nz_elts = 0;
|
||||||
*p_nc_elts = 0;
|
*p_nc_elts = 0;
|
||||||
*p_elt_count = 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
|
/* 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;
|
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));
|
elts = count_type_elements (TREE_TYPE (exp));
|
||||||
|
|
||||||
return nz_elts < elts / 4;
|
return nz_elts < elts / 4;
|
||||||
|
@ -2599,11 +2599,12 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
|
|||||||
|
|
||||||
categorize_ctor_elements (ctor, &num_nonzero_elements,
|
categorize_ctor_elements (ctor, &num_nonzero_elements,
|
||||||
&num_nonconstant_elements,
|
&num_nonconstant_elements,
|
||||||
&num_ctor_elements);
|
&num_ctor_elements, &cleared);
|
||||||
|
|
||||||
/* If a const aggregate variable is being initialized, then it
|
/* If a const aggregate variable is being initialized, then it
|
||||||
should never be a lose to promote the variable to be static. */
|
should never be a lose to promote the variable to be static. */
|
||||||
if (num_nonconstant_elements == 0
|
if (num_nonconstant_elements == 0
|
||||||
|
&& num_nonzero_elements > 1
|
||||||
&& TREE_READONLY (object)
|
&& TREE_READONLY (object)
|
||||||
&& TREE_CODE (object) == VAR_DECL)
|
&& 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));
|
num_type_elements = count_type_elements (TREE_TYPE (ctor));
|
||||||
|
|
||||||
/* If there are "lots" of zeros, then block clear the object first. */
|
/* If there are "lots" of zeros, then block clear the object first. */
|
||||||
cleared = false;
|
|
||||||
if (num_type_elements - num_nonzero_elements > CLEAR_RATIO
|
if (num_type_elements - num_nonzero_elements > CLEAR_RATIO
|
||||||
&& num_nonzero_elements < num_type_elements/4)
|
&& num_nonzero_elements < num_type_elements/4)
|
||||||
cleared = true;
|
cleared = true;
|
||||||
|
17
gcc/testsuite/gcc.c-torture/execute/pr19515.c
Normal file
17
gcc/testsuite/gcc.c-torture/execute/pr19515.c
Normal file
@ -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 bool initializer_zerop (tree);
|
||||||
|
|
||||||
extern void categorize_ctor_elements (tree, HOST_WIDE_INT *,
|
extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
|
||||||
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);
|
||||||
|
|
||||||
/* add_var_to_bind_expr (bind_expr, var) binds var to bind_expr. */
|
/* add_var_to_bind_expr (bind_expr, var) binds var to bind_expr. */
|
||||||
|
Loading…
Reference in New Issue
Block a user