[Bug middle-end/93582] [10 Regression] -Warray-bounds gives error: array subscript 0 is outside array bounds of struct E[1]
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Feb 7 14:37:00 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93582
--- Comment #15 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
With
struct S {
unsigned int s1:1;
unsigned int s2:1;
unsigned int s3:1;
unsigned int s4:1;
unsigned int s5:4;
unsigned char s6;
unsigned short s7;
unsigned short s8;
};
struct T {
int t1;
int t2;
};
static inline int
bar (struct S *x)
{
if (x->s4)
return ((struct T *)(x + 1))->t1 + ((struct T *)(x + 1))->t2;
else
return 0;
}
int
foo (int x, int y)
{
struct S s;
s.s6 = x;
s.s7 = y & 0x1FFF;
s.s4 = 0;
return bar (&s);
}
static inline int
qux (struct S *x)
{
int s4 = x->s4;
if (s4)
return ((struct T *)(x + 1))->t1 + ((struct T *)(x + 1))->t2;
else
return 0;
}
int
baz (int x, int y)
{
struct S s;
s.s6 = x;
s.s7 = y & 0x1FFF;
s.s4 = 0;
return qux (&s);
}
we don't actually warn about the baz/qux case, the difference is just
separating in the source the bitfield load from comparison, so the premature
fold "optimization" doesn't trigger anymore. And with -fno-tree-sra that s.s4
= 0; _10 = s.s4; is optimized during FRE1 value numbering.
The BIT_FIELD_REF also prevents SRA... :(
Anyway, it is clear why BIT_FIELD_REF <s, 8, 0> vn can't work in this case, the
other bits are uninitialized, or e.g. could be non-constant etc.
My thoughts were that we could just special-case BIT_FIELD_REF <s, N, M> & C,
either just where C is power of two and thus we extract a single bit and
handle that as visit_reference_op_load of BIT_FIELD_REF with that single bit,
so in this case BIT_FIELD_REF <s, 1, 3>, or perhaps iteratively, trying to
capture the bits one by one.
This still doesn't work, as vn_reference_lookup_3 punts on anything
non-byte-ish:
/* 3) Assignment from a constant. We can use folds native encode/interpret
routines to extract the assigned bits. */
else if (known_eq (ref->size, maxsize)
&& is_gimple_reg_type (vr->type)
&& !contains_storage_order_barrier_p (vr->operands)
&& gimple_assign_single_p (def_stmt)
&& CHAR_BIT == 8 && BITS_PER_UNIT == 8
/* native_encode and native_decode operate on arrays of bytes
and so fundamentally need a compile-time size and offset. */
&& maxsize.is_constant (&maxsizei)
&& maxsizei % BITS_PER_UNIT == 0 <============= This
fails, maxsizei is 1
&& offset.is_constant (&offseti)
&& offseti % BITS_PER_UNIT == 0 <============= This
would fail too, offseti is 3
&& (is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt))
|| (TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
&& is_gimple_min_invariant (SSA_VAL (gimple_assign_rhs1
(def_stmt))))))
...
if (base2
&& !reverse
&& !storage_order_barrier_p (lhs)
&& known_eq (maxsize2, size2)
&& multiple_p (size2, BITS_PER_UNIT) <============= This
would fail too, size2 would be 1
&& multiple_p (offset2, BITS_PER_UNIT) <============= This
would fail too, offset2 would be 3
&& adjust_offsets_for_equal_base_address (base, &offset,
base2, &offset2)
&& offset.is_constant (&offseti)
&& offset2.is_constant (&offset2i)
&& size2.is_constant (&size2i))
So, even if we don't want to handle all the bitfield vs. bitfield details for
now, could we perhaps special case the non-BITS_PER_UNITish offsets/sizes if
offseti == offset2i && maxsizei == size2i and perhaps don't use
native_encode/interpret in that case, but just handle INTEGER_CST and
fold_convert it to the right type?
These bitfields really ought to be integral types...
More information about the Gcc-bugs
mailing list