From b9cbf8c9e0bc72f59b643165247fae646560aadd Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 28 Jul 2021 16:14:38 -0600 Subject: [PATCH] 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. --- gcc/gimple-array-bounds.cc | 37 +++++++----- gcc/testsuite/g++.dg/warn/Warray-bounds-25.C | 59 ++++++++++++++++++++ gcc/testsuite/gcc.dg/Warray-bounds-85.c | 30 ++++++++++ 3 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Warray-bounds-25.C create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-85.c diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index 3a5c2dd0be8..0517e5ddd8e 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -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 diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-25.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-25.C new file mode 100644 index 00000000000..a93da037560 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-25.C @@ -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\\\)'" } + +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-85.c b/gcc/testsuite/gcc.dg/Warray-bounds-85.c new file mode 100644 index 00000000000..0ee71200cbb --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-85.c @@ -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, ...\\\)'" } +}