This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] handle constant size VLAs in -Warray-bounds (PR 82608, 92333)
- From: Martin Sebor <msebor at gmail dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 4 Nov 2019 20:26:45 -0700
- Subject: [PATCH] handle constant size VLAs in -Warray-bounds (PR 82608, 92333)
-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);
+}