aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c64
1 files changed, 48 insertions, 16 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 945b3a9..e248f59 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-iterator.h"
#include "gimple-walk.h"
#include "tree-cfg.h"
+#include "tree-dfa.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa-loop-niter.h"
#include "tree-ssa-loop.h"
@@ -65,6 +66,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
#include "vr-values.h"
+#include "builtins.h"
/* Set of SSA names found live during the RPO traversal of the function
for still active basic-blocks. */
@@ -4781,26 +4783,51 @@ vrp_prop::check_array_ref (location_t location, tree ref,
low_sub = up_sub = TREE_OPERAND (ref, 1);
up_bound = array_ref_up_bound (ref);
- /* Can not check flexible arrays. */
if (!up_bound
- || TREE_CODE (up_bound) != INTEGER_CST)
- return;
+ || TREE_CODE (up_bound) != INTEGER_CST
+ || (warn_array_bounds < 2
+ && array_at_struct_end_p (ref)))
+ {
+ /* Accesses to trailing arrays via pointers may access storage
+ beyond the types array bounds. For such arrays, or for flexible
+ array members, as well as for other arrays of an unknown size,
+ replace the upper bound with a more permissive one that assumes
+ the size of the largest object is PTRDIFF_MAX. */
+ tree eltsize = array_ref_element_size (ref);
+
+ /* FIXME: Handle VLAs. */
+ if (TREE_CODE (eltsize) != INTEGER_CST)
+ return;
- /* Accesses to trailing arrays via pointers may access storage
- beyond the types array bounds. */
- if (warn_array_bounds < 2
- && array_at_struct_end_p (ref))
- return;
+ tree maxbound = TYPE_MAX_VALUE (ptrdiff_type_node);
+
+ up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
+
+ tree arg = TREE_OPERAND (ref, 0);
+
+ HOST_WIDE_INT off;
+ if (get_addr_base_and_unit_offset (arg, &off))
+ up_bound_p1 = wide_int_to_tree (sizetype,
+ wi::sub (wi::to_wide (up_bound_p1),
+ off));
+
+ up_bound = int_const_binop (MINUS_EXPR, up_bound_p1,
+ build_int_cst (ptrdiff_type_node, 1));
+ }
+ else
+ up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
+ build_int_cst (TREE_TYPE (up_bound), 1));
low_bound = array_ref_low_bound (ref);
- up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
- build_int_cst (TREE_TYPE (up_bound), 1));
+
+ tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
/* Empty array. */
if (tree_int_cst_equal (low_bound, up_bound_p1))
{
warning_at (location, OPT_Warray_bounds,
- "array subscript is above array bounds");
+ "array subscript %E is above array bounds of %qT",
+ low_bound, artype);
TREE_NO_WARNING (ref) = 1;
}
@@ -4824,7 +4851,8 @@ vrp_prop::check_array_ref (location_t location, tree ref,
&& tree_int_cst_le (low_sub, low_bound))
{
warning_at (location, OPT_Warray_bounds,
- "array subscript is outside array bounds");
+ "array subscript [%E, %E] is outside array bounds of %qT",
+ low_sub, up_sub, artype);
TREE_NO_WARNING (ref) = 1;
}
}
@@ -4840,7 +4868,8 @@ vrp_prop::check_array_ref (location_t location, tree ref,
fprintf (dump_file, "\n");
}
warning_at (location, OPT_Warray_bounds,
- "array subscript is above array bounds");
+ "array subscript %E is above array bounds of %qT",
+ up_sub, artype);
TREE_NO_WARNING (ref) = 1;
}
else if (TREE_CODE (low_sub) == INTEGER_CST
@@ -4853,7 +4882,8 @@ vrp_prop::check_array_ref (location_t location, tree ref,
fprintf (dump_file, "\n");
}
warning_at (location, OPT_Warray_bounds,
- "array subscript is below array bounds");
+ "array subscript %E is below array bounds of %qT",
+ low_sub, artype);
TREE_NO_WARNING (ref) = 1;
}
}
@@ -4908,7 +4938,8 @@ vrp_prop::search_for_addr_array (tree t, location_t location)
fprintf (dump_file, "\n");
}
warning_at (location, OPT_Warray_bounds,
- "array subscript is below array bounds");
+ "array subscript %wi is below array bounds of %qT",
+ idx.to_shwi (), TREE_TYPE (tem));
TREE_NO_WARNING (t) = 1;
}
else if (idx > (wi::to_offset (up_bound)
@@ -4921,7 +4952,8 @@ vrp_prop::search_for_addr_array (tree t, location_t location)
fprintf (dump_file, "\n");
}
warning_at (location, OPT_Warray_bounds,
- "array subscript is above array bounds");
+ "array subscript %wu is above array bounds of %qT",
+ idx.to_uhwi (), TREE_TYPE (tem));
TREE_NO_WARNING (t) = 1;
}
}