A -Warray-bounds enhancement committed last year into GCC 9 introduced an assumption that the MEM_REF type argument has a size. The test case submitted in PR89662 does pointer addition on void*, in which the MEM_REF type is void*, which breaks the assumption.
The attached change removes this assumption and considers such types to have the size of 1. (The result is used to scale the offset in diagnostics after it has been determined to be out of bounds.) Martin
PR tree-optimization/89662 - -Warray-bounds ICE on void* arithmetic gcc/ChangeLog: PR tree-optimization/89662 * tree-vrp.c (vrp_prop::check_mem_ref): Avoid assuming every type has a size. gcc/testsuite/ChangeLog: PR tree-optimization/89662 * gcc.dg/Warray-bounds-41.c: New test. Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 269445) +++ gcc/tree-vrp.c (working copy) @@ -4718,13 +4718,16 @@ vrp_prop::check_mem_ref (location_t location, tree { /* Extract the element type out of MEM_REF and use its size to compute the index to print in the diagnostic; arrays - in MEM_REF don't mean anything. */ + in MEM_REF don't mean anything. A type with no size like + void is as good as having a size of 1. */ tree type = TREE_TYPE (ref); while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); - tree size = TYPE_SIZE_UNIT (type); - offrange[0] = offrange[0] / wi::to_offset (size); - offrange[1] = offrange[1] / wi::to_offset (size); + if (tree size = TYPE_SIZE_UNIT (type)) + { + offrange[0] = offrange[0] / wi::to_offset (size); + offrange[1] = offrange[1] / wi::to_offset (size); + } } else { Index: gcc/testsuite/gcc.dg/Warray-bounds-41.c =================================================================== --- gcc/testsuite/gcc.dg/Warray-bounds-41.c (nonexistent) +++ gcc/testsuite/gcc.dg/Warray-bounds-41.c (working copy) @@ -0,0 +1,33 @@ +/* PR tree-optimization/89662- -Warray-bounds ICE on void* arithmetic + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +void* vptr (void *c) +{ + return c; +} + +void sink (void*); + +void test_vptr_arith_vla_cst (void) +{ + int n = 1; + char c[n]; + sink (vptr (c) - 1); /* { dg-warning "\\\[-Warray-bounds" } */ +} + +void test_vptr_arith_vla_range (int n) +{ + if (n < 1 || 4 < n) + return; + + char c[n]; + sink (vptr (c) - 1); /* { dg-warning "\\\[-Warray-bounds" "pr82608" { xfail *-*-* } } */ +} + +void test_vptr_arith_vla_var (int n) +{ + char c[n]; + sink (vptr (c) - 1); /* { dg-warning "\\\[-Warray-bounds" "pr82608" { xfail *-*-* } } */ +} +