diff mbox series

correct formatting of function pointers in -Warray-bounds (PR 101601)

Message ID f6a82019-b699-a12a-f49d-e9081666f345@gmail.com
State New
Headers show
Series correct formatting of function pointers in -Warray-bounds (PR 101601) | expand

Commit Message

Martin Sebor July 27, 2021, 8:45 p.m. UTC
When mentioning the type of the accessed object -Warray-bounds
treats singleton objects as arrays of one element for simplicity.
But because the code doesn't distinguish between function and
object pointers, a warning for an out-of-bounds index into
a singleton function pointer object attempts to create an array
of one function.  Since arrays of functions are invalid,
the helper function the code calls fails with an error issued
to the user.

To avoid this the attached patch avoids this singleton-to-array
shortcut for function pointers.  Tested on x86_64-linux.

Martin

Comments

Jeff Law July 28, 2021, 2:08 p.m. UTC | #1
On 7/27/2021 2:45 PM, Martin Sebor via Gcc-patches wrote:
> When mentioning the type of the accessed object -Warray-bounds
> treats singleton objects as arrays of one element for simplicity.
> But because the code doesn't distinguish between function and
> object pointers, a warning for an out-of-bounds index into
> a singleton function pointer object attempts to create an array
> of one function.  Since arrays of functions are invalid,
> the helper function the code calls fails with an error issued
> to the user.
>
> To avoid this the attached patch avoids this singleton-to-array
> shortcut for function pointers.  Tested on x86_64-linux.
>
> Martin
>
>
> gcc-101601.diff
>
> PR middle-end/101601 - [12 Regression] -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.
OK
jeff
diff mbox series

Patch

PR middle-end/101601 - [12 Regression] -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.

diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 598c76bf52e..9ead2182519 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, ...\\\)'" }
+}