-Warray-bounds makes a couple of assumptions about arrays that hold neither for VLAs of zero-length arrays nor for zero-length arrays of VLAs. The attached patch removes these assumptions and simplifies the code that deals with them in the process.
This resolves a P2 GCC 9-11 regression so I'm looking for approval to commit this fix to both release branches as well as the trunk. Tested on x86_64-linux. 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..25b91f6e215 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -594,34 +594,32 @@ 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. */ + 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); + } /* 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..48ad16828f2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Warray-bounds-9.c @@ -0,0 +1,55 @@ +/* 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 f_2_n_0 (int n) +{ + int a[2][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 f_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" } +} 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 *-*-* } } +}