The new gimple_parm_array_size() function computes the size
of an array function parameter implied by its upper bound.
The code that does this strips one too many layers of array
types from the parameter, returning a smaller size than
implied by the second most significant bound.  (I must have
copied the code from somewhere else and not tested it very
well.)

The attached fix removes the additional peeling.  I'll commit
this obvious patch shortly.

Martin

PS The test exposes two minor bugs/limitations in the warning.
One is xfailed in the test itself and the other is pr97425.
PR middle-end/97391 - bogus -Warray-bounds accessing a multidimensional array parameter

	PR middle-end/97391
	* builtins.c (gimple_parm_array_size): Peel off one less layer
	of array types.

gcc/testsuite/ChangeLog:

	PR middle-end/97391
	* gcc.dg/Warray-bounds-68.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 3f799e54d5f..72627b5b859 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4493,12 +4493,9 @@ gimple_parm_array_size (tree ptr, wide_int rng[2],
 
   rng[0] = wi::zero (prec);
   rng[1] = wi::uhwi (access->minsize, prec);
-  /* If the PTR argument points to an array multiply MINSIZE by the size
-     of array element type.  Otherwise, multiply it by the size of what
-     the pointer points to.  */
+  /* Multiply the array bound encoded in the attribute by the size
+     of what the pointer argument to which it decays points to.  */
   tree eltype = TREE_TYPE (TREE_TYPE (ptr));
-  if (TREE_CODE (eltype) == ARRAY_TYPE)
-    eltype = TREE_TYPE (eltype);
   tree size = TYPE_SIZE_UNIT (eltype);
   if (!size || TREE_CODE (size) != INTEGER_CST)
     return NULL_TREE;
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-68.c b/gcc/testsuite/gcc.dg/Warray-bounds-68.c
new file mode 100644
index 00000000000..d6616695471
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-68.c
@@ -0,0 +1,118 @@
+/* PR middle-end/97391 - bogus -Warray-bounds accessing a multidimensional
+   array parameter
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+
+void nowarn_access_loop_idx (char a[3][5])
+{
+  for (int i = 0; i < 3; i++)
+    for (int j = 0; j < 5; j++)
+      a[i][j] = 0;
+}
+
+void warn_access_loop_idx (char a[3][5])
+{
+  for (int i = 0; i < 3; i++)
+    for (int j = 0; j < 5; j++)
+      a[j][i] = 0;            // { dg-warning "\\\[-Warray-bounds" }
+}
+
+
+void nowarn_access_cst_idx (int a[5][7][9])
+{
+  a[0][0][0] = __LINE__;
+  a[0][0][8] = __LINE__;
+
+  a[0][6][0] = __LINE__;
+  a[0][6][8] = __LINE__;
+
+  a[4][0][0] = __LINE__;
+  a[4][0][8] = __LINE__;
+  a[4][6][8] = __LINE__;
+}
+
+
+void test_ptr_access_cst_idx (int a[5][7][9])
+{
+  int *p = &a[0][0][0];
+
+  p[0] = __LINE__;
+  p[8] = __LINE__;
+
+  /* The following access should trigger a warning but it's represented
+     the same  as the valid access in
+       p = a[0][1][0];
+       p[1] = __LINE__;
+     both as
+       MEM[(int *)a_1(D) + 36B] = __LINE__;  */
+
+  p[9] = __LINE__;            // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  p[315] = __LINE__;
+  // { dg-warning "subscript 315 is outside array bounds of 'int\\\[5]\\\[7]\\\[9]'" "pr97425" { xfail *-*-* } .-1 }
+  // { dg-warning "subscript 315 is outside array bounds " "" { target *-*-* } .-2 }
+
+  p = &a[0][6][0];
+  p[0] = __LINE__;
+  p[8] = __LINE__;
+
+  p = &a[4][6][0];
+  p[0] = __LINE__;
+  p[8] = __LINE__;
+}
+
+
+void warn_access_cst_idx (int a[5][7][9])
+{
+  a[0][0][9] = __LINE__;      // { dg-warning "subscript 9 is above array bounds of 'int\\\[9]'" }
+  a[0][7][0] = __LINE__;      // { dg-warning "subscript 7 is above array bounds of 'int\\\[7]\\\[9]'" }
+  a[5][0][0] = __LINE__;
+  // { dg-warning "subscript 5 is outside array bounds of 'int\\\[5]\\\[7]\\\[9]'" "pr97425" { xfail *-*-* } .-1 }
+  // { dg-warning "subscript \\d+ is outside array bounds" "" { target *-*-* } .-2 }
+}
+
+
+void test_ptrarray_access_cst_idx (int (*pa)[5][7][9])
+{
+  (*pa)[0][0][0] = __LINE__;
+  (*pa)[0][0][8] = __LINE__;
+  (*pa)[0][0][9] = __LINE__;  // { dg-warning "subscript 9 is above array bounds of 'int\\\[9]'" }
+
+  (*pa)[0][6][0] = __LINE__;
+  (*pa)[0][7][0] = __LINE__;  // { dg-warning "subscript 7 is above array bounds of 'int\\\[7]\\\[9]'" }
+  (*pa)[0][8][0] = __LINE__;  // { dg-warning "subscript 8 is above array bounds of 'int\\\[7]\\\[9]'" }
+
+  (*pa)[4][6][8] = __LINE__;
+  (*pa)[5][0][0] = __LINE__;  // { dg-warning "subscript 5 is above array bounds of 'int\\\[5]\\\[7]\\\[9]'" }
+}
+
+
+void test_ptr_ptrarray_access_cst_idx (int (*pa)[5][7][9])
+{
+  int *p = &(*pa)[0][0][0];
+
+  p[0] = __LINE__;
+  p[8] = __LINE__;
+
+  /* The following access should trigger a warning but it's represented
+     the same  as the valid access in
+       p = a[0][1][0];
+       p[1] = __LINE__;
+     both as
+       MEM[(int *)a_1(D) + 36B] = __LINE__;  */
+
+  p[9] = __LINE__;            // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  p[315] = __LINE__;          // { dg-warning "\\\[-Warray-bounds" "pr97429" { xfail *-*-* } }
+
+  p = &(*pa)[0][6][0];
+  p[0] = __LINE__;
+  p[8] = __LINE__;
+
+  p = &(*pa)[4][6][0];
+  p[0] = __LINE__;
+  p[8] = __LINE__;
+}
+
+

Reply via email to