Correct -Warray-bounds handling if function pointers [PR101601].

Resolves:
PR middle-end/101601 - -Warray-bounds triggers error: arrays of functions are not meaningful

	PR middle-end/101601

gcc/ChangeLog:

	* gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Remove
	a pointless test.
	Handle pointers to functions.

gcc/testsuite/ChangeLog:

	* g++.dg/warn/Warray-bounds-25.C: New test.
	* gcc.dg/Warray-bounds-85.c: New test.
This commit is contained in:
Martin Sebor 2021-07-28 16:14:38 -06:00
parent 2a837de28e
commit b9cbf8c9e0
3 changed files with 111 additions and 15 deletions

View File

@ -421,10 +421,9 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
/* The type and size of the access. */
tree axstype = TREE_TYPE (ref);
offset_int axssize = 0;
if (TREE_CODE (axstype) != UNION_TYPE)
if (tree access_size = TYPE_SIZE_UNIT (axstype))
if (TREE_CODE (access_size) == INTEGER_CST)
axssize = wi::to_offset (access_size);
if (tree access_size = TYPE_SIZE_UNIT (axstype))
if (TREE_CODE (access_size) == INTEGER_CST)
axssize = wi::to_offset (access_size);
access_ref aref;
if (!compute_objsize (ref, 0, &aref, ranges))
@ -451,20 +450,28 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
tree reftype = TREE_TYPE (aref.ref);
/* The size of the referenced array element. */
offset_int eltsize = 1;
/* The byte size of the array has already been determined above
based on a pointer ARG. Set ELTSIZE to the size of the type
it points to and REFTYPE to the array with the size, rounded
down as necessary. */
if (POINTER_TYPE_P (reftype))
reftype = TREE_TYPE (reftype);
if (TREE_CODE (reftype) == ARRAY_TYPE)
reftype = TREE_TYPE (reftype);
if (tree refsize = TYPE_SIZE_UNIT (reftype))
if (TREE_CODE (refsize) == INTEGER_CST)
eltsize = wi::to_offset (refsize);
const offset_int nelts = aref.sizrng[1] / eltsize;
reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
if (TREE_CODE (reftype) == FUNCTION_TYPE)
/* Restore the original (pointer) type and avoid trying to create
an array of functions (done below). */
reftype = TREE_TYPE (aref.ref);
else
{
/* The byte size of the array has already been determined above
based on a pointer ARG. Set ELTSIZE to the size of the type
it points to and REFTYPE to the array with the size, rounded
down as necessary. */
if (TREE_CODE (reftype) == ARRAY_TYPE)
reftype = TREE_TYPE (reftype);
if (tree refsize = TYPE_SIZE_UNIT (reftype))
if (TREE_CODE (refsize) == INTEGER_CST)
eltsize = wi::to_offset (refsize);
const offset_int nelts = aref.sizrng[1] / eltsize;
reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
}
/* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE
is set (when taking the address of the one-past-last element

View File

@ -0,0 +1,59 @@
/* PR middle-end/101601 - [12 Regression] -Warray-bounds triggers error:
arrays of functions are not meaningful
{ dg-do compile }
{ dg-options "-O2 -Wall" } */
typedef void Fvv (void);
extern Fvv* pf; // { dg-message "'pf'" }
void f (...);
void test_funptr (void)
{
f (&pf);
f (&pf + 1);
f (&pf + 2); // { dg-warning "subscript 2 is outside array bounds of 'void \\\(\\\* ?\\\[1]\\\)\\\(\\\)'" }
}
typedef int Fii_ (int, ...);
extern Fii_* pfa[3]; // { dg-message "'pfa'" }
void test_funptr_array (void)
{
f (pfa);
f (pfa + 1);
f (pfa + 2);
f (pfa + 3);
f (pfa + 4); // { dg-warning "subscript 4 is outside array bounds of 'int \\\(\\\* ?\\\[3]\\\)\\\(int, ...\\\)'" }
}
struct A;
typedef void (A::*MFvv)(void);
MFvv pmf;
void test_memfunptr (void)
{
f (&pmf);
f (&pmf + 1);
f (&pmf + 2); // { dg-warning "subscript 2 is outside array bounds of 'void \\\(A::\\\* ?\\\[1]\\\)\\\(\\\)'" }
}
typedef int (A::*MFii)(int);
MFii pmfa[4];
void test_memfunptr_array (void)
{
f (pmfa);
f (pmfa + 1);
f (pmfa + 2);
f (pmfa + 3);
f (pmfa + 4);
f (pmfa + 5); // { dg-warning "subscript 5 is outside array bounds of 'int \\\(A::\\\* ?\\\[4]\\\)\\\(int\\\)'" }
}

View File

@ -0,0 +1,30 @@
/* PR middle-end/101601 - [12 Regression] -Warray-bounds triggers error:
arrays of functions are not meaningful
{ dg-do compile }
{ dg-options "-O2 -Wall" } */
typedef void Fvv (void);
extern Fvv* pf; // { dg-message "'pf'" }
void f (void*);
void test_funptr (void)
{
f (&pf);
f (&pf + 1);
f (&pf + 2); // { dg-warning "subscript 2 is outside array bounds of 'void \\\(\\\*\\\[1]\\\)\\\(void\\\)'" }
}
typedef int Fii_ (int, ...);
extern Fii_* pfa[3]; // { dg-message "'pfa'" }
void test_funptr_array (void)
{
f (pfa);
f (pfa + 1);
f (pfa + 2);
f (pfa + 3);
f (pfa + 4); // { dg-warning "subscript 4 is outside array bounds of 'int \\\(\\\*\\\[3]\\\)\\\(int, ...\\\)'" }
}