Commit 91eb5fa8 by Martin Sebor Committed by Martin Sebor

PR tree-optimization/92373 - ICE in -Warray-bounds on access to member array in…

PR tree-optimization/92373 - ICE in -Warray-bounds on access to member array in an initialized char buffer

gcc/testsuite/ChangeLog:

	PR tree-optimization/92373
	* gcc.dg/Warray-bounds-55.c: New test.
	* gcc.dg/Wzero-length-array-bounds-2.c: New test.

gcc/ChangeLog:

	PR tree-optimization/92373
	* tree.c (component_ref_size): Only consider initializers of objects
	of matching struct types.
	Return null for instances of interior zero-length arrays.

From-SVN: r277871
parent eebabc49
2019-11-05 Martin Sebor <msebor@redhat.com>
PR tree-optimization/92373
* tree.c (component_ref_size): Only consider initializers of objects
of matching struct types.
Return null for instances of interior zero-length arrays.
2019-11-05 Segher Boessenkool <segher@kernel.crashing.org> 2019-11-05 Segher Boessenkool <segher@kernel.crashing.org>
* doc/md.texi (Insn Splitting): Fix combiner documentation. * doc/md.texi (Insn Splitting): Fix combiner documentation.
2019-11-05 Martin Sebor <msebor@redhat.com>
PR tree-optimization/92373
* gcc.dg/Warray-bounds-55.c: New test.
* gcc.dg/Wzero-length-array-bounds-2.c: New test.
2019-11-05 Jim Wilson <jimw@sifive.com> 2019-11-05 Jim Wilson <jimw@sifive.com>
PR middle-end/92263 PR middle-end/92263
......
/* PR middle-end/92373 - ICE in -Warray-bounds on access to member array
in an initialized char buffer
{ dg-do compile }
{ dg-options "-O2 -Wall" } */
void sink (void*);
struct S
{
char data[1];
};
char a[6] = { };
int f (void)
{
struct S *p = (struct S*)a;
return p->data[4];
}
void g (void)
{
char b[6] = { };
struct S *p = (struct S*)b;
p->data[4] = 0;
sink (p);
}
/* Test to verify that -Wzero-length-bounds and not -Warray-bounds is
issued for accesses to interior zero-length array members that are
within the bounds of the enclosing struct.
{ dg-do compile }
{ dg-options "-O2 -Wall" } */
void sink (void*);
struct A { int i; };
struct B { int j; struct A a[0]; };
struct C
{
struct B b1;
struct B b2;
};
void test_B_ref (struct B *p)
{
// References with negative indices are always diagnosed by -Warray-bounds
// even though they could be considered the same as past the end accesses
// to trailing zero-length arrays.
p->a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->a[ 0].i = 0;
p->a[ 1].i = 0;
sink (p);
p[1].a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p[1].a[ 0].i = 0;
p[1].a[ 1].i = 0;
}
void test_C_ref (struct C *p)
{
p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
// Accesses to trailing zero-length arrays are not diagnosed (should
// they be?)
p->b2.a[ 0].i = 0;
p->b2.a[ 9].i = 0;
}
void test_C_decl (void)
{
struct C c, *p = &c;
p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
// c.b1.a[0].i overlaps c.b2.j.
p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
// c.b1.a[1].i is past the end of c...
p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
// ...and so are references to all elements of c.b2.a
p->b2.a[ 0].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b2.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
}
char cbuf1[1 * sizeof (struct C)];
char cbuf2[2 * sizeof (struct C)] = { };
void test_C_global_buf (void)
{
struct C *p = (struct C*)&cbuf1;
p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
p->b2.a[ 0].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b2.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
p = (struct C*)&cbuf2;
p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
sink (p);
p->b2.a[ 0].i = 0;
p->b2.a[ 1].i = 0;
p->b2.a[ 2].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b2.a[ 3].i = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
}
void test_C_local_buf (void)
{
char cbuf1[1 * sizeof (struct C)] = "";
char cbuf2[2 * sizeof (struct C)] = { };
struct C *p = (struct C*)&cbuf1;
p->b1.a[-1].i = 1; // { dg-warning "\\\[-Warray-bounds" }
p->b1.a[ 0].i = 2; // { dg-warning "\\\[-Wzero-length-bounds" }
p->b1.a[ 1].i = 3; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
p->b2.a[ 0].i = 4; // { dg-warning "\\\[-Warray-bounds" }
p->b2.a[ 1].i = 5; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
p = (struct C*)&cbuf2;
p->b1.a[-1].i = 6; // { dg-warning "\\\[-Warray-bounds" }
p->b1.a[ 0].i = 7; // { dg-warning "\\\[-Wzero-length-bounds" }
p->b1.a[ 1].i = 8; // { dg-warning "\\\[-Wzero-length-bounds" }
sink (p);
p->b2.a[ 0].i = 9;
p->b2.a[ 1].i = 10;
p->b2.a[ 2].i = 11; // { dg-warning "\\\[-Warray-bounds" }
p->b2.a[ 3].i = 12; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
}
...@@ -13635,6 +13635,8 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */) ...@@ -13635,6 +13635,8 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
return NULL_TREE; return NULL_TREE;
base = TREE_OPERAND (ref, 0); base = TREE_OPERAND (ref, 0);
while (TREE_CODE (base) == COMPONENT_REF)
base = TREE_OPERAND (base, 0);
baseoff = tree_to_poly_int64 (byte_position (TREE_OPERAND (ref, 1))); baseoff = tree_to_poly_int64 (byte_position (TREE_OPERAND (ref, 1)));
} }
...@@ -13656,27 +13658,28 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */) ...@@ -13656,27 +13658,28 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
memsize = NULL_TREE; memsize = NULL_TREE;
/* MEMBER is a true flexible array member. Compute its size from if (typematch)
the initializer of the BASE object if it has one. */ /* MEMBER is a true flexible array member. Compute its size from
if (tree init = DECL_P (base) ? DECL_INITIAL (base) : NULL_TREE) the initializer of the BASE object if it has one. */
{ if (tree init = DECL_P (base) ? DECL_INITIAL (base) : NULL_TREE)
init = get_initializer_for (init, member); {
if (init) init = get_initializer_for (init, member);
{ if (init)
memsize = TYPE_SIZE_UNIT (TREE_TYPE (init)); {
if (tree refsize = TYPE_SIZE_UNIT (reftype)) memsize = TYPE_SIZE_UNIT (TREE_TYPE (init));
{ if (tree refsize = TYPE_SIZE_UNIT (reftype))
/* Use the larger of the initializer size and the tail {
padding in the enclosing struct. */ /* Use the larger of the initializer size and the tail
poly_int64 rsz = tree_to_poly_int64 (refsize); padding in the enclosing struct. */
rsz -= baseoff; poly_int64 rsz = tree_to_poly_int64 (refsize);
if (known_lt (tree_to_poly_int64 (memsize), rsz)) rsz -= baseoff;
memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz); if (known_lt (tree_to_poly_int64 (memsize), rsz))
} memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz);
}
baseoff = 0; baseoff = 0;
} }
} }
if (!memsize) if (!memsize)
{ {
...@@ -13689,17 +13692,19 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */) ...@@ -13689,17 +13692,19 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
/* The size of a flexible array member of an extern struct /* The size of a flexible array member of an extern struct
with no initializer cannot be determined (it's defined with no initializer cannot be determined (it's defined
in another translation unit and can have an initializer in another translation unit and can have an initializer
witth an arbitrary number of elements). */ with an arbitrary number of elements). */
return NULL_TREE; return NULL_TREE;
/* Use the size of the base struct or, for interior zero-length /* Use the size of the base struct or, for interior zero-length
arrays, the size of the enclosing type. */ arrays, the size of the enclosing type. */
memsize = TYPE_SIZE_UNIT (bt); memsize = TYPE_SIZE_UNIT (bt);
} }
else else if (DECL_P (base))
/* Use the size of the BASE object (possibly an array of some /* Use the size of the BASE object (possibly an array of some
other type such as char used to store the struct). */ other type such as char used to store the struct). */
memsize = DECL_SIZE_UNIT (base); memsize = DECL_SIZE_UNIT (base);
else
return NULL_TREE;
} }
/* If the flexible array member has a known size use the greater /* If the flexible array member has a known size use the greater
......
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