]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Correct -Warray-bounds handling if function pointers [PR101601].
authorMartin Sebor <msebor@redhat.com>
Wed, 28 Jul 2021 22:14:38 +0000 (16:14 -0600)
committerMartin Sebor <msebor@redhat.com>
Wed, 28 Jul 2021 22:14:38 +0000 (16:14 -0600)
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
gcc/testsuite/g++.dg/warn/Warray-bounds-25.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Warray-bounds-85.c [new file with mode: 0644]

index 3a5c2dd0be88b3e08d290a0b7d7913f4ff3408e3..0517e5ddd8e6370a094b6ac6aa4283c91c1b9cca 100644 (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
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 (file)
index 0000000..a93da03
--- /dev/null
@@ -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 (file)
index 0000000..0ee7120
--- /dev/null
@@ -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, ...\\\)'" }
+}