diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f978694a953..7f636b3c908 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2010-05-01 Richard Guenther + + PR tree-optimization/43949 + * tree-vrp.c (ssa_name_nonnegative_p): Return true for unsigned + types. + (extract_range_from_binary_expr): Handle *_MOD_EXPR. + 2010-05-01 Anatoly Sokolov * rtl.h (CONST_DOUBLE_P): Define. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8e1b484794c..39a8d977d6e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-01 Richard Guenther + + PR tree-optimization/43949 + * g++.dg/warn/Warray-bounds-5.C: New testcase. + 2010-05-01 H.J. Lu PR c++/43951 diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-5.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-5.C new file mode 100644 index 00000000000..06d776a400b --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-5.C @@ -0,0 +1,24 @@ +// { dg-do compile } +// { dg-options "-O2 -Warray-bounds" } + +void f(); + +int c[3]; +int result; + +struct Vector { + static int get(int i) { + if (i >= 3) + f(); + return c[i]; + } +}; + +void g() +{ + for (int i = 0; i < 3; ++i) { + const int index = i % 3; + result = Vector::get(index) + Vector::get(index); + } +} + diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index d8ebbe8f369..83ff665c61d 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1364,6 +1364,10 @@ ssa_name_nonnegative_p (const_tree t) { value_range_t *vr = get_value_range (t); + if (INTEGRAL_TYPE_P (t) + && TYPE_UNSIGNED (t)) + return true; + if (!vr) return false; @@ -2079,6 +2083,10 @@ extract_range_from_binary_expr (value_range_t *vr, && code != CEIL_DIV_EXPR && code != EXACT_DIV_EXPR && code != ROUND_DIV_EXPR + && code != TRUNC_MOD_EXPR + && code != FLOOR_MOD_EXPR + && code != CEIL_MOD_EXPR + && code != ROUND_MOD_EXPR && code != RSHIFT_EXPR && code != MIN_EXPR && code != MAX_EXPR @@ -2147,6 +2155,10 @@ extract_range_from_binary_expr (value_range_t *vr, && code != CEIL_DIV_EXPR && code != EXACT_DIV_EXPR && code != ROUND_DIV_EXPR + && code != TRUNC_MOD_EXPR + && code != FLOOR_MOD_EXPR + && code != CEIL_MOD_EXPR + && code != ROUND_MOD_EXPR && (vr0.type == VR_VARYING || vr1.type == VR_VARYING || vr0.type != vr1.type @@ -2497,6 +2509,28 @@ extract_range_from_binary_expr (value_range_t *vr, } } } + else if (code == TRUNC_MOD_EXPR + || code == FLOOR_MOD_EXPR + || code == CEIL_MOD_EXPR + || code == ROUND_MOD_EXPR) + { + bool sop = false; + if (vr0.type == VR_ANTI_RANGE + || vr1.type != VR_RANGE + || symbolic_range_p (&vr1) + || range_includes_zero_p (&vr1)) + { + set_value_range_to_varying (vr); + return; + } + type = VR_RANGE; + max = int_const_binop (MINUS_EXPR, vr1.max, integer_one_node, 0); + if (vrp_expr_computes_nonnegative (op0, &sop) + && vrp_expr_computes_nonnegative (op1, &sop) && !sop) + min = build_int_cst (TREE_TYPE (vr1.max), 0); + else + min = fold_unary (NEGATE_EXPR, TREE_TYPE (max), max); + } else if (code == MINUS_EXPR) { /* If we have a MINUS_EXPR with two VR_ANTI_RANGEs, drop to