-Warray-bounds doesn't yet have the logic to detect out-of-bounds indices into dynamically allocated arrays like VLAs because it doesn't track allocation calls. But the warning could detect such errors in accesses to VLAs with constant sizes even without such tracking.
The attached patch adds this capability. Testing the warning revealed that the names and locations of VLAs with constant sizes are unavailable, making the warnings less useful than they could be otherwise. So the other part of the patch also arranges for the arrays backing the constant size VLAs to have names that reflect those of the VLAs, and the same location. Tested on x86_64-linux. Martin
PR middle-end/92333 - missing variable name referencing VLA in warnings PR middle-end/82608 - missing -Warray-bounds on an out-of-bounds VLA index gcc/testsuite/ChangeLog: PR middle-end/92333 PR middle-end/82608 * gcc.dg/Warray-bounds-53.c: New test. gcc/ChangeLog: PR middle-end/92333 PR middle-end/82608 * tree-vrp.c (vrp_prop::check_array_ref): Handle VLAs with constant size. * tree-ssa-ccp.c (fold_builtin_alloca_with_align): Use a meaninful name and location for a temporary variable. Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 277806) +++ gcc/tree-vrp.c (working copy) @@ -4154,6 +4154,9 @@ vrp_prop::check_array_ref (location_t location, tr low_sub = up_sub = TREE_OPERAND (ref, 1); up_bound = array_ref_up_bound (ref); + /* Referenced decl if one can be determined. */ + tree decl = NULL_TREE; + /* Set for accesses to interior zero-length arrays. */ bool interior_zero_len = false; @@ -4182,7 +4185,8 @@ vrp_prop::check_array_ref (location_t location, tr tree arg = TREE_OPERAND (ref, 0); poly_int64 off; - if (TREE_CODE (arg) == COMPONENT_REF) + const bool compref = TREE_CODE (arg) == COMPONENT_REF; + if (compref) { /* Try to determine the size of the trailing array from its initializer (if it has one). */ @@ -4191,12 +4195,27 @@ vrp_prop::check_array_ref (location_t location, tr maxbound = refsize; } - if (maxbound == ptrdiff_max - && get_addr_base_and_unit_offset (arg, &off) - && known_gt (off, 0)) - maxbound = wide_int_to_tree (sizetype, - wi::sub (wi::to_wide (maxbound), - off)); + if (maxbound == ptrdiff_max) + { + /* Try to determine the size of the base object. Avoid + COMPONENT_REF already tried above. Using its DECL_SIZE + size wouldn't necessarily be correct if the reference is + to its flexible array member initialized in a different + translation unit. */ + tree base = get_addr_base_and_unit_offset (arg, &off); + if (!compref && base && DECL_P (base)) + if (tree basesize = DECL_SIZE_UNIT (base)) + if (TREE_CODE (basesize) == INTEGER_CST) + { + maxbound = basesize; + decl = base; + } + + if (known_gt (off, 0)) + maxbound = wide_int_to_tree (sizetype, + wi::sub (wi::to_wide (maxbound), + off)); + } else maxbound = fold_convert (sizetype, maxbound); @@ -4281,7 +4300,7 @@ vrp_prop::check_array_ref (location_t location, tr fprintf (dump_file, "\n"); } - ref = TREE_OPERAND (ref, 0); + ref = decl ? decl : TREE_OPERAND (ref, 0); tree rec = NULL_TREE; if (TREE_CODE (ref) == COMPONENT_REF) Index: gcc/tree-ssa-ccp.c =================================================================== --- gcc/tree-ssa-ccp.c (revision 277806) +++ gcc/tree-ssa-ccp.c (working copy) @@ -2222,7 +2222,25 @@ fold_builtin_alloca_with_align (gimple *stmt) elem_type = build_nonstandard_integer_type (BITS_PER_UNIT, 1); n_elem = size * 8 / BITS_PER_UNIT; array_type = build_array_type_nelts (elem_type, n_elem); - var = create_tmp_var (array_type); + + if (tree ssa_name = SSA_NAME_IDENTIFIER (lhs)) + { + /* Give the temporary a name derived from the name of the VLA + declaration so it can be referenced in diagnostics. */ + const char *name = IDENTIFIER_POINTER (ssa_name); + var = create_tmp_var (array_type, name); + } + else + var = create_tmp_var (array_type); + + if (gimple *lhsdef = SSA_NAME_DEF_STMT (lhs)) + { + /* Set the temporary's location to that of the VLA declaration + so it can be pointed to in diagnostics. */ + location_t loc = gimple_location (lhsdef); + DECL_SOURCE_LOCATION (var) = loc; + } + SET_DECL_ALIGN (var, TREE_INT_CST_LOW (gimple_call_arg (stmt, 1))); if (uid != 0) SET_DECL_PT_UID (var, uid); Index: gcc/testsuite/gcc.dg/Warray-bounds-53.c =================================================================== --- gcc/testsuite/gcc.dg/Warray-bounds-53.c (nonexistent) +++ gcc/testsuite/gcc.dg/Warray-bounds-53.c (working copy) @@ -0,0 +1,50 @@ +/* PR middle-end/92333 - missing variable name referencing VLA in warnings + PR middle-end/82608 - missing -Warray-bounds on an out-of-bounds VLA index + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +void sink (void*); + +void test_char_vla_location (void) +{ + unsigned nelts = 7; + + char vla[nelts]; // { dg-message "declared here" } + + vla[0] = __LINE__; + vla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" } + + sink (vla); +} + +void test_int_vla_location (void) +{ + unsigned nelts = 7; + + int vla[nelts]; // { dg-message "declared here" } + + vla[0] = __LINE__; + vla[nelts] = 1; // { dg-warning "\\\[-Warray-bounds" } + + sink (vla); +} + +void test_struct_vla_location (void) +{ + unsigned nelts = 7; + + struct { + char cvla[nelts]; // { dg-message "declared here" } + int ivla[nelts]; // { dg-message "declared here" } + } s; + + s.cvla[0] = __LINE__; + s.cvla[nelts - 1] = 0; + s.cvla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" } + + s.ivla[0] = __LINE__; + s.ivla[nelts - 1] = 0; + s.ivla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" } + + sink (&s); +}