On 2/17/21 6:56 AM, Jakub Jelinek wrote:
On Tue, Feb 16, 2021 at 08:34:41PM -0700, Martin Sebor via Gcc-patches wrote:
+ if (integer_all_onesp (nelts))
+ /* Zero length array. */
+ eltsize = 0;
+ else
{
- tree bnds[] = { TYPE_MIN_VALUE (dom), TYPE_MAX_VALUE (dom) };
- if (TREE_CODE (arg) == COMPONENT_REF)
- {
- offset_int size = maxobjsize;
- if (tree fldsize = component_ref_size (arg))
- size = wi::to_offset (fldsize);
- arrbounds[1] = wi::lrshift (size, eltsizelog2);
- }
- else if (array_at_struct_end_p (arg) || !bnds[0] || !bnds[1])
- arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
- else
- arrbounds[1] = (wi::to_offset (bnds[1]) - wi::to_offset
(bnds[0])
- + 1) * eltsize;
+ tree esz = TYPE_SIZE_UNIT (TREE_TYPE (reftype));
+ if (TREE_CODE (esz) == INTEGER_CST)
+ /* Array element is not a VLA. */
+ eltsize = wi::to_offset (esz);
}
+
+ if (!array_at_struct_end_p (arg)
+ && TREE_CODE (nelts) == INTEGER_CST)
+ arrbounds[1] = (wi::to_offset (nelts) + 1) * eltsize;
else
- arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
+ {
+ /* Use log2 of size to convert the array byte size in to its
+ upper bound in elements. */
+ const offset_int eltsizelog2 = wi::floor_log2 (eltsize);
+ arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
So, what will this do for zero length arrays at the end of struct?
eltsize will be 0 and wi::floor_log2 (eltsize) is -1, and shifting by -1,
while maybe not UB in wide_int computations, is certainly just weird.
Why do you use eltsize = 0 for the [0] arrays? They can still have their
element size and if array_at_struct_end_p and the element type is not a variable
length type, using the actual eltsize seems better.
Only when !array_at_struct_end_p we should ensure arrbounds[1] will be 0
and indeed that (wi::to_offset (nelts) + 1) * eltsize would likely not do
that because wi::to_offset is -1ULL or so, not -1.
The code is only entered for references to declared objects so
the array_at_struct_end_p() test is unnecessary. I've removed
it in the attached revision.
Also, I'm not sure I understand the right shift by floor_log2 of eltsize,
why can't you simply divide maxobjsize by eltsize (if eltsize is not 0).
I'm pretty sure that's because wide_int doesn't have division and
I assumed offset_int didn't either when I originally wrote the code.
I've changed it to use division.
Attached is a revised patch.
Martin
PR tree-optimization/99121 - ICE in -Warray-bounds on a VLA of zero-length array
gcc/ChangeLog:
PR tree-optimization/99121
* gimple-array-bounds.cc (array_bounds_checker::check_mem_ref):
Avoid assuming array element size is constant. Handle zero-length
arrays of VLAs.
gcc/testsuite/ChangeLog:
PR tree-optimization/99121
* c-c++-common/Warray-bounds-9.c: New test.
* gcc.dg/Warray-bounds-71.c: New test.
diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 2576556f76b..046b78d463e 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -594,34 +594,31 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
|| (DECL_EXTERNAL (arg) && array_at_struct_end_p (ref))))
return false;
- /* FIXME: Should this be 1 for Fortran? */
arrbounds[0] = 0;
if (TREE_CODE (reftype) == ARRAY_TYPE)
{
- /* Set to the size of the array element (and adjust below). */
- eltsize = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (reftype)));
- /* Use log2 of size to convert the array byte size in to its
- upper bound in elements. */
- const offset_int eltsizelog2 = wi::floor_log2 (eltsize);
- if (tree dom = TYPE_DOMAIN (reftype))
+ tree nelts = array_type_nelts (reftype);
+ if (integer_all_onesp (nelts))
+ /* Zero length array. */
+ arrbounds[1] = 0;
+ else
{
- tree bnds[] = { TYPE_MIN_VALUE (dom), TYPE_MAX_VALUE (dom) };
- if (TREE_CODE (arg) == COMPONENT_REF)
- {
- offset_int size = maxobjsize;
- if (tree fldsize = component_ref_size (arg))
- size = wi::to_offset (fldsize);
- arrbounds[1] = wi::lrshift (size, eltsizelog2);
- }
- else if (array_at_struct_end_p (arg) || !bnds[0] || !bnds[1])
- arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
+ tree esz = TYPE_SIZE_UNIT (TREE_TYPE (reftype));
+ if (TREE_CODE (esz) == INTEGER_CST)
+ /* Array element is either not a VLA or it's a VLA with
+ zero size (such as int A[n][n][0];). */
+ eltsize = wi::to_offset (esz);
else
- arrbounds[1] = (wi::to_offset (bnds[1]) - wi::to_offset (bnds[0])
- + 1) * eltsize;
+ return false;
+
+ if (TREE_CODE (nelts) == INTEGER_CST)
+ arrbounds[1] = (wi::to_offset (nelts) + 1) * eltsize;
+ else if (eltsize == 0)
+ arrbounds[1] = 0;
+ else
+ arrbounds[1] = maxobjsize / eltsize;
}
- else
- arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
/* Determine a tighter bound of the non-array element type. */
tree eltype = TREE_TYPE (reftype);
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-9.c b/gcc/testsuite/c-c++-common/Warray-bounds-9.c
new file mode 100644
index 00000000000..8ff592b363c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-9.c
@@ -0,0 +1,144 @@
+/* PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
+ VLA
+ { dg-do compile }
+ { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
+
+#define NOIPA __attribute__ ((noipa))
+
+void sink (void*, ...);
+#define T(a, x) sink (a, x)
+
+
+NOIPA void a_0_n (int n)
+{
+ int a[0][n];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_0 (int n)
+{
+ int a[n][0];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+
+NOIPA void a_1_n_0 (int n)
+{
+ int a[1][n][0];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_1_0_n (int n)
+{
+ int a[1][0][n];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_0_1_n (int n)
+{
+ int a[0][1][n];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_0_n_1 (int n)
+{
+ int a[0][n][1];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_0_n (int n)
+{
+ int a[n][0][n];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_n_0 (int n)
+{
+ int a[n][n][0];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_0_n_n (int n)
+{
+ int a[0][n][n];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_0_0_n (int n)
+{
+ int a[0][0][n];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_0_0 (int n)
+{
+ int a[n][0][0];
+
+ sink (a);
+
+ T (a, ((int *) a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((char *) a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (a, ((float *) a)[n]); // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_n_n (int n)
+{
+ int a[n][n][n];
+
+ sink (a);
+
+ T (a, ((int *) a)[-1]); // { dg-warning "\\\[-Warray-bounds" "pr99140" { xfail *-*-* } }
+ T (a, ((int *) a)[0]);
+ T (a, ((char *) a)[1]);
+ T (a, ((float *) a)[n]);
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.c b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
new file mode 100644
index 00000000000..c2af9bef78c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
@@ -0,0 +1,53 @@
+/* PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
+ VLA
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-strict-aliasing -ftrack-macro-expansion=0" } */
+
+#define NOIPA __attribute__ ((noipa))
+
+void sink (void*, ...);
+#define T(a, x) sink (a, x)
+
+
+NOIPA void ma_0_n (int n)
+{
+ struct {
+ int a[0][n];
+ } s;
+
+ sink (&s);
+
+ T (&s, ((int *) s.a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (&s, ((char *) s.a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (&s, ((float *) s.a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+
+ T (&s, ((int *) s.a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (&s, ((char *) s.a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (&s, ((float *) s.a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+
+ T (&s, ((int *) s.a)[n]); // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+ T (&s, ((char *) s.a)[n]); // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+ T (&s, ((float *) s.a)[n]); // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+}
+
+
+NOIPA void ma_n_0 (int n)
+{
+ struct {
+ int a[n][0];
+ } s;
+
+ sink (&s);
+
+ T (&s, ((int *) s.a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (&s, ((char *) s.a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+ T (&s, ((float *) s.a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+
+ T (&s, ((int *) s.a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (&s, ((char *) s.a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+ T (&s, ((float *) s.a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+
+ T (&s, ((int *) s.a)[n]); // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+ T (&s, ((char *) s.a)[n]); // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+ T (&s, ((float *) s.a)[n]); // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+}