The recent -Warray-bounds enhancement to detect past-the-end accesses to struct members has introduced the assumption that struct members have constant sizes. That assumption is not safe for the GCC VLA member extension. The attached change removes the assumption without attempting to handle past- the-end accesses to such VLA members.
Tested on x86_64-linux and committed in r277786. Martin
PR tree-optimization/92349 - ICE in -Warray-bounds of a VLA member gcc/testsuite/ChangeLog: PR tree-optimization/92349 * gcc.dg/Warray-bounds-50.c: New test. gcc/ChangeLog: PR tree-optimization/92349 * tree-vrp.c (vrp_prop::check_array_ref): Avoid assuming struct memebers have constant sizes. Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 277783) +++ gcc/tree-vrp.c (working copy) @@ -4164,7 +4164,8 @@ vrp_prop::check_array_ref (location_t location, tr /* Try to determine the size of the trailing array from its initializer (if it has one). */ if (tree refsize = component_ref_size (arg, &interior_zero_len)) - maxbound = refsize; + if (TREE_CODE (refsize) == INTEGER_CST) + maxbound = refsize; } if (maxbound == ptrdiff_max Index: gcc/testsuite/gcc.dg/Warray-bounds-50.c =================================================================== --- gcc/testsuite/gcc.dg/Warray-bounds-50.c (nonexistent) +++ gcc/testsuite/gcc.dg/Warray-bounds-50.c (working copy) @@ -0,0 +1,114 @@ +/* PR middle-end/92349 - ICE in -Warray-bounds on a VLA member + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +void sink (void*, ...); + +void mem_vla_cst_store_idx (void) +{ + int n = 3; + + struct { + char a[n], b; + } s; + + char *p = s.a; + + s.a[0] = 0; + s.b = 0; + + *++p = 1; + *++p = 2; + + sink (&s, p); +} + +void mem_vla_range_store_idx (int n) +{ + if (n < 3 || 4 < n) + n = 3; + + struct { + char a[n], b; + } s; + + char *p = s.a; + + s.a[0] = 0; + s.b = 0; + + *++p = 1; + *++p = 2; + + sink (&s, p); +} + +void mem_vla_var_store_idx (size_t n) +{ + struct { + char a[n], b; + } s; + + char *p = s.a; + + s.a[0] = 0; + s.b = 0; + + *++p = 1; + *++p = 2; + + sink (&s, p); +} + + +void mem_vla_cst_store_ptr (void) +{ + int n = 3; + + struct { + char a[n], b; + } s; + + char *p = s.a; + + *p++ = __LINE__; + *p++ = __LINE__; + *p++ = __LINE__; + + sink (&s, p); +} + +void mem_vla_range_store_ptr (int n) +{ + if (n < 3 || 4 < n) + n = 3; + + struct { + char a[n], b; + } s; + + char *p = s.a; + + *p++ = __LINE__; + *p++ = __LINE__; + *p++ = __LINE__; + + sink (&s, p); +} + +void mem_vla_var_store_ptr (size_t n) +{ + struct { + char a[n], b; + } s; + + char *p = s.a; + + *p++ = __LINE__; + *p++ = __LINE__; + *p++ = __LINE__; + + sink (&s, p); +}