diff mbox series

handle constant size VLAs in -Warray-bounds (PR 82608, 92333)

Message ID fb3d4da3-dcc2-4e38-9267-4801d0e20c27@gmail.com
State New
Headers show
Series handle constant size VLAs in -Warray-bounds (PR 82608, 92333) | expand

Commit Message

Martin Sebor Nov. 5, 2019, 3:26 a.m. UTC
-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

Comments

Jeff Law Nov. 5, 2019, 4:35 a.m. UTC | #1
On 11/4/19 8:26 PM, Martin Sebor wrote:
> -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
> 
> gcc-92333.diff
> 
> 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.
OK
jeff
diff mbox series

Patch

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);
+}