Commit ff61c5bd by Martin Sebor

PR middle-end/94940 - spurious -Warray-bounds for a zero length array member of union

gcc/testsuite/ChangeLog:

	PR middle-end/94940
	* gcc.dg/Warray-bounds-61.c: New test.

gcc/ChangeLog:

	PR middle-end/94940
	* tree-vrp.c (vrp_prop::check_mem_ref): Remove unreachable code.
	* tree.c (component_ref_size): Correct the handling or array members
	of unions.
	Drop a pointless test.
	Rename a local variable.
parent e9bfb06b
2020-05-18 Martin Sebor <msebor@redhat.com>
PR middle-end/94940
* tree-vrp.c (vrp_prop::check_mem_ref): Remove unreachable code.
* tree.c (component_ref_size): Correct the handling or array members
of unions.
Drop a pointless test.
Rename a local variable.
2020-05-12 Richard Biener <rguenther@suse.de>
Backport from mainline
......
2020-05-18 Martin Sebor <msebor@redhat.com>
PR middle-end/94940
* gcc.dg/Warray-bounds-61.c: New test.
2020-05-18 Doug Rupp <rupp@adacore.com>
* gcc.target/powerpc/pr71763.c: Require powerpc_vsx_ok.
......
/* PR middle-end/94940 - spurious -Warray-bounds for a zero length array
member of union
{ dg-do compile }
{ dg-options "-O2 -Wall" } */
extern int n;
extern union Ua3_a0 {
int a3[3];
int a2[2]; // can only alias a3[0 - 2]
int a1[1]; // can alias all of the union
int a0[0]; // ditto
} ua3_a0;
void test_ua3_ua0_a0 (int i)
{
ua3_a0.a0[0] = 0; // { dg-bogus "\\\[-Warray-bounds" }
ua3_a0.a0[1] = 0; // { dg-bogus "\\\[-Warray-bounds" }
ua3_a0.a0[2] = 0; // { dg-bogus "\\\[-Warray-bounds" }
ua3_a0.a0[3] = 0; // { dg-warning "\\\[-Warray-bounds" }
ua3_a0.a0[4] = 0; // { dg-warning "\\\[-Warray-bounds" }
ua3_a0.a0[i] = 0; // { dg-bogus "\\\[-Warray-bounds" }
if (i < __LINE__)
i = 5;
ua3_a0.a0[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
if (i > -1)
i = -1;
ua3_a0.a0[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
}
void test_ua3_ua0_a1 (int i)
{
/* Abusing one-element array members the same way as those of
length zero is discouraged but so far acceted without warnings.
This should change at some point. */
ua3_a0.a1[0] = 0;
ua3_a0.a1[1] = 0;
ua3_a0.a1[2] = 0;
ua3_a0.a1[3] = 0; // { dg-warning "\\\[-Warray-bounds" }
ua3_a0.a1[i] = 0;
if (i > -1)
i = -1;
ua3_a0.a1[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
if (i < 7)
i = 7;
ua3_a0.a1[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
}
void test_ua3_ua0_a2 (int i)
{
ua3_a0.a2[0] = 0;
ua3_a0.a2[1] = 0;
ua3_a0.a2[2] = 0; // { dg-warning "\\\[-Warray-bounds" }
ua3_a0.a2[i] = 0;
if (i < __LINE__)
i = __LINE__;
ua3_a0.a2[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
if (i > -1)
i = -1;
ua3_a0.a2[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
}
extern union Ua2_a3 {
int a2[2]; // can only alias a3[0 - 1]
int a3[3];
} ua2_a3;
void test_ua2_ua3 (int i)
{
ua2_a3.a2[0] = 0; // { dg-bogus "\\\[-Warray-bounds" }
ua2_a3.a2[1] = 0; // { dg-bogus "\\\[-Warray-bounds" }
ua2_a3.a2[2] = 0; // { dg-warning "\\\[-Warray-bounds" }
ua2_a3.a2[i] = 0;
if (i < __LINE__)
i = __LINE__;
ua2_a3.a2[i] = 0; // { dg-warning "\\\[-Warray-bounds" }
}
extern struct SUa2_a0 {
union Ua2_a0 {
int a2[2];
int a0[0];
} u;
} sua2_a0;
void test_sua2_sua0 (int i)
{
n += sua2_a0.u.a0[0];
n += sua2_a0.u.a0[1];
n += sua2_a0.u.a0[2]; // { dg-warning "\\\[-Warray-bounds" }
n += sua2_a0.u.a0[i];
if (i < __LINE__)
i = __LINE__;
n += sua2_a0.u.a0[i]; // { dg-warning "\\\[-Warray-bounds" }
}
void test_sua2_sua0_ptr (int i)
{
union Ua2_a0 *p = &sua2_a0.u;
n += p->a0[0];
n += p->a0[1];
n += p->a0[2]; // { dg-warning "\\\[-Warray-bounds" }
n += p->a0[i];
}
extern struct SUSa3_a0 {
union USa3_a0 {
struct {
int a3[3];
} s;
int a2[2]; // can alias s.a3[0 - 2]
int a1[1]; // can alias s.a3[0 - 2]
int a0[0]; // can alias s.a3[0]
} u;
} susa3_ua0;
void test_susa3_sua0 (int i, int j)
{
n += susa3_ua0.u.a0[0];
n += susa3_ua0.u.a0[1];
n += susa3_ua0.u.a0[2];
n += susa3_ua0.u.a0[3]; // { dg-warning "\\\[-Warray-bounds" }
}
void test_susa3_sua0_ptr (int i, int j)
{
union USa3_a0 *p = &susa3_ua0.u;
n += p->a0[0];
n += p->a0[1];
n += p->a0[2];
n += p->a0[3]; // { dg-warning "\\\[-Warray-bounds" }
}
void test_susa3_sua1 (int i)
{
n += susa3_ua0.u.a1[0];
n += susa3_ua0.u.a1[1];
n += susa3_ua0.u.a1[2];
n += susa3_ua0.u.a1[3]; // { dg-warning "\\\[-Warray-bounds" }
if (i < __LINE__)
i = __LINE__;
n += susa3_ua0.u.a1[i]; // { dg-warning "\\\[-Warray-bounds" }
}
void test_susa3_sua2 (void)
{
n += susa3_ua0.u.a2[0];
n += susa3_ua0.u.a2[1];
n += susa3_ua0.u.a2[2]; // { dg-warning "\\\[-Warray-bounds" }
n += susa3_ua0.u.a2[3]; // { dg-warning "\\\[-Warray-bounds" }
}
extern struct {
union {
struct {
int a3[3];
} s1;
struct {
int a0[0];
} s2;
} u;
} susa3_usa0;
void test_susi3_susi0 (int i)
{
n += susa3_usa0.u.s2.a0[0];
n += susa3_usa0.u.s2.a0[1];
n += susa3_usa0.u.s2.a0[2];
n += susa3_usa0.u.s2.a0[3]; // { dg-warning "\\\[-Warray-bounds" }
n += susa3_usa0.u.s2.a0[i];
if (i < __LINE__)
i = __LINE__;
n += susa3_usa0.u.s2.a0[i]; // { dg-warning "\\\[-Warray-bounds" }
}
......@@ -3843,15 +3843,11 @@ vrp_prop::check_mem_ref (location_t location, tree ref,
else
arrbounds[1] = wi::lrshift (maxobjsize, wi::floor_log2 (eltsize));
if (TREE_CODE (ref) == MEM_REF)
{
/* For MEM_REF determine a tighter bound of the non-array
element type. */
tree eltype = TREE_TYPE (reftype);
while (TREE_CODE (eltype) == ARRAY_TYPE)
eltype = TREE_TYPE (eltype);
eltsize = wi::to_offset (TYPE_SIZE_UNIT (eltype));
}
/* Determine a tighter bound of the non-array element type. */
tree eltype = TREE_TYPE (reftype);
while (TREE_CODE (eltype) == ARRAY_TYPE)
eltype = TREE_TYPE (eltype);
eltsize = wi::to_offset (TYPE_SIZE_UNIT (eltype));
}
else
{
......@@ -3884,27 +3880,17 @@ vrp_prop::check_mem_ref (location_t location, tree ref,
if (TREE_CODE (reftype) != ARRAY_TYPE)
reftype = build_array_type_nelts (reftype, 1);
if (TREE_CODE (ref) == MEM_REF)
{
/* Extract the element type out of MEM_REF and use its size
to compute the index to print in the diagnostic; arrays
in MEM_REF don't mean anything. A type with no size like
void is as good as having a size of 1. */
tree type = TREE_TYPE (ref);
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
if (tree size = TYPE_SIZE_UNIT (type))
{
offrange[0] = offrange[0] / wi::to_offset (size);
offrange[1] = offrange[1] / wi::to_offset (size);
}
}
else
/* Extract the element type out of MEM_REF and use its size
to compute the index to print in the diagnostic; arrays
in MEM_REF don't mean anything. A type with no size like
void is as good as having a size of 1. */
tree type = TREE_TYPE (ref);
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
if (tree size = TYPE_SIZE_UNIT (type))
{
/* For anything other than MEM_REF, compute the index to
print in the diagnostic as the offset over element size. */
offrange[0] = offrange[0] / eltsize;
offrange[1] = offrange[1] / eltsize;
offrange[0] = offrange[0] / wi::to_offset (size);
offrange[1] = offrange[1] / wi::to_offset (size);
}
bool warned;
......
......@@ -13645,6 +13645,10 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
if (!interior_zero_length)
interior_zero_length = &int_0_len;
/* The object/argument referenced by the COMPONENT_REF and its type. */
tree arg = TREE_OPERAND (ref, 0);
tree argtype = TREE_TYPE (arg);
/* The referenced member. */
tree member = TREE_OPERAND (ref, 1);
tree memsize = DECL_SIZE_UNIT (member);
......@@ -13656,7 +13660,7 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
bool trailing = array_at_struct_end_p (ref);
bool zero_length = integer_zerop (memsize);
if (!trailing && (!interior_zero_length || !zero_length))
if (!trailing && !zero_length)
/* MEMBER is either an interior array or is an array with
more than one element. */
return memsize;
......@@ -13675,9 +13679,14 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
offset_int minidx = wi::to_offset (min);
offset_int maxidx = wi::to_offset (max);
if (maxidx - minidx > 0)
/* MEMBER is an array with more than 1 element. */
/* MEMBER is an array with more than one element. */
return memsize;
}
/* For a refernce to a zero- or one-element array member of a union
use the size of the union instead of the size of the member. */
if (TREE_CODE (argtype) == UNION_TYPE)
memsize = TYPE_SIZE_UNIT (argtype);
}
/* MEMBER is either a bona fide flexible array member, or a zero-length
......@@ -13692,28 +13701,27 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
if (!*interior_zero_length)
return NULL_TREE;
if (TREE_CODE (TREE_OPERAND (ref, 0)) != COMPONENT_REF)
if (TREE_CODE (arg) != COMPONENT_REF)
return NULL_TREE;
base = TREE_OPERAND (ref, 0);
base = arg;
while (TREE_CODE (base) == COMPONENT_REF)
base = TREE_OPERAND (base, 0);
baseoff = tree_to_poly_int64 (byte_position (TREE_OPERAND (ref, 1)));
}
/* BASE is the declared object of which MEMBER is either a member
or that is cast to REFTYPE (e.g., a char buffer used to store
a REFTYPE object). */
tree reftype = TREE_TYPE (TREE_OPERAND (ref, 0));
or that is cast to ARGTYPE (e.g., a char buffer used to store
an ARGTYPE object). */
tree basetype = TREE_TYPE (base);
/* Determine the base type of the referenced object. If it's
the same as REFTYPE and MEMBER has a known size, return it. */
the same as ARGTYPE and MEMBER has a known size, return it. */
tree bt = basetype;
if (!*interior_zero_length)
while (TREE_CODE (bt) == ARRAY_TYPE)
bt = TREE_TYPE (bt);
bool typematch = useless_type_conversion_p (reftype, bt);
bool typematch = useless_type_conversion_p (argtype, bt);
if (memsize && typematch)
return memsize;
......@@ -13729,7 +13737,7 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
if (init)
{
memsize = TYPE_SIZE_UNIT (TREE_TYPE (init));
if (tree refsize = TYPE_SIZE_UNIT (reftype))
if (tree refsize = TYPE_SIZE_UNIT (argtype))
{
/* Use the larger of the initializer size and the tail
padding in the enclosing struct. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment