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>
* 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>
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 */)
return NULL_TREE;
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)));
}
......@@ -13656,27 +13658,28 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
memsize = NULL_TREE;
/* MEMBER is a true flexible array member. Compute its size from
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)
{
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. */
poly_int64 rsz = tree_to_poly_int64 (refsize);
rsz -= baseoff;
if (known_lt (tree_to_poly_int64 (memsize), rsz))
memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz);
}
if (typematch)
/* MEMBER is a true flexible array member. Compute its size from
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)
{
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. */
poly_int64 rsz = tree_to_poly_int64 (refsize);
rsz -= baseoff;
if (known_lt (tree_to_poly_int64 (memsize), rsz))
memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz);
}
baseoff = 0;
}
}
baseoff = 0;
}
}
if (!memsize)
{
......@@ -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
with no initializer cannot be determined (it's defined
in another translation unit and can have an initializer
witth an arbitrary number of elements). */
with an arbitrary number of elements). */
return NULL_TREE;
/* Use the size of the base struct or, for interior zero-length
arrays, the size of the enclosing type. */
memsize = TYPE_SIZE_UNIT (bt);
}
else
else if (DECL_P (base))
/* Use the size of the BASE object (possibly an array of some
other type such as char used to store the struct). */
memsize = DECL_SIZE_UNIT (base);
else
return NULL_TREE;
}
/* 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