aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2018-12-07 00:28:04 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2018-12-07 00:28:04 +0100
commitb8a003c16567ccecffce256a2b35c9210db933a4 (patch)
treecd2b1d9b89ff3acda5dd2a6f6fa1e668e192e7fe /gcc/tree-vrp.c
parentff8ba86f447546c57e26bfab2a3437f14d6f2595 (diff)
downloadgcc-b8a003c16567ccecffce256a2b35c9210db933a4.zip
gcc-b8a003c16567ccecffce256a2b35c9210db933a4.tar.gz
gcc-b8a003c16567ccecffce256a2b35c9210db933a4.tar.bz2
re PR tree-optimization/88367 (-fno-delete-null-pointer-checks doesn't work properly)
PR c/88367 * tree-vrp.c (extract_range_from_binary_expr): For POINTER_PLUS_EXPR with -fno-delete-null-pointer-checks, set_nonnull only if the pointer is non-NULL and offset is known to have most significant bit clear. * vr-values.c (vr_values::vrp_stmt_computes_nonzero): For ADDR_EXPR of MEM_EXPR, return true if the MEM_EXPR has non-zero offset with most significant bit clear. If offset does have most significant bit set and -fno-delete-null-pointer-checks, don't return true even if the base pointer is non-NULL. * gcc.dg/tree-ssa/pr88367.c: New test. From-SVN: r266878
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 6fd1fd2..15ac65b 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1673,9 +1673,26 @@ extract_range_from_binary_expr (value_range_base *vr,
else if (code == POINTER_PLUS_EXPR)
{
/* For pointer types, we are really only interested in asserting
- whether the expression evaluates to non-NULL. */
- if (!range_includes_zero_p (&vr0)
- || !range_includes_zero_p (&vr1))
+ whether the expression evaluates to non-NULL.
+ With -fno-delete-null-pointer-checks we need to be more
+ conservative. As some object might reside at address 0,
+ then some offset could be added to it and the same offset
+ subtracted again and the result would be NULL.
+ E.g.
+ static int a[12]; where &a[0] is NULL and
+ ptr = &a[6];
+ ptr -= 6;
+ ptr will be NULL here, even when there is POINTER_PLUS_EXPR
+ where the first range doesn't include zero and the second one
+ doesn't either. As the second operand is sizetype (unsigned),
+ consider all ranges where the MSB could be set as possible
+ subtractions where the result might be NULL. */
+ if ((!range_includes_zero_p (&vr0)
+ || !range_includes_zero_p (&vr1))
+ && !TYPE_OVERFLOW_WRAPS (expr_type)
+ && (flag_delete_null_pointer_checks
+ || (range_int_cst_p (&vr1)
+ && !tree_int_cst_sign_bit (vr1.max ()))))
vr->set_nonnull (expr_type);
else if (range_is_null (&vr0) && range_is_null (&vr1))
vr->set_null (expr_type);