diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-04-07 12:31:32 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-04-07 12:31:32 +0000 |
commit | c26ce8a90a7c8ef9b6587959083d12f6edbc5e01 (patch) | |
tree | 92208bc8d4ba4a670add9a969acc3e87e362914a /gcc/tree-vrp.c | |
parent | f086d5d699de69490287f3fb23a5281eb8252067 (diff) | |
download | gcc-c26ce8a90a7c8ef9b6587959083d12f6edbc5e01.tar.gz |
2010-04-07 Richard Guenther <rguenther@suse.de>
PR tree-optimization/43270
* tree-vrp.c (check_array_ref): Fix flexible array member
detection.
* tree-ssa-sccvn.h (fully_constant_vn_reference_p): Declare.
* tree-ssa-pre.c (phi_translate_1): Adjust.
(fully_constant_expression): Split out vn_reference handling to ...
* tree-ssa-sccvn.c (fully_constant_vn_reference_p): ... here.
Fold reads from constant strings.
(vn_reference_lookup): Handle fully constant references.
(vn_reference_lookup_pieces): Likewise.
* Makefile.in (expmed.o-warn): Add -Wno-error.
* g++.dg/warn/Warray-bounds-4.C: New testcase.
* gcc.dg/Warray-bounds-7.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158058 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index c84004e6be4..3b22948e39f 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -4998,23 +4998,46 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one) { value_range_t* vr = NULL; tree low_sub, up_sub; - tree low_bound, up_bound = array_ref_up_bound (ref); + tree low_bound, up_bound, up_bound_p1; + tree base; + + if (TREE_NO_WARNING (ref)) + return; low_sub = up_sub = TREE_OPERAND (ref, 1); + up_bound = array_ref_up_bound (ref); - if (!up_bound || TREE_NO_WARNING (ref) - || TREE_CODE (up_bound) != INTEGER_CST - /* Can not check flexible arrays. */ - || (TYPE_SIZE (TREE_TYPE (ref)) == NULL_TREE - && TYPE_DOMAIN (TREE_TYPE (ref)) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (ref))) == NULL_TREE) - /* Accesses after the end of arrays of size 0 (gcc - extension) and 1 are likely intentional ("struct - hack"). */ - || compare_tree_int (up_bound, 1) <= 0) + /* Can not check flexible arrays. */ + if (!up_bound + || TREE_CODE (up_bound) != INTEGER_CST) return; + /* Accesses to trailing arrays via pointers may access storage + beyond the types array bounds. */ + base = get_base_address (ref); + if (base + && INDIRECT_REF_P (base)) + { + tree cref, next = NULL_TREE; + + if (TREE_CODE (TREE_OPERAND (ref, 0)) != COMPONENT_REF) + return; + + cref = TREE_OPERAND (ref, 0); + if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref, 0))) == RECORD_TYPE) + for (next = TREE_CHAIN (TREE_OPERAND (cref, 1)); + next && TREE_CODE (next) != FIELD_DECL; + next = TREE_CHAIN (next)) + ; + + /* If this is the last field in a struct type or a field in a + union type do not warn. */ + if (!next) + return; + } + low_bound = array_ref_low_bound (ref); + up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, integer_one_node, 0); if (TREE_CODE (low_sub) == SSA_NAME) { @@ -5039,14 +5062,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one) } } else if (TREE_CODE (up_sub) == INTEGER_CST - && tree_int_cst_lt (up_bound, up_sub) - && !tree_int_cst_equal (up_bound, up_sub) - && (!ignore_off_by_one - || !tree_int_cst_equal (int_const_binop (PLUS_EXPR, - up_bound, - integer_one_node, - 0), - up_sub))) + && (ignore_off_by_one + ? (tree_int_cst_lt (up_bound, up_sub) + && !tree_int_cst_equal (up_bound_p1, up_sub)) + : (tree_int_cst_lt (up_bound, up_sub) + || tree_int_cst_equal (up_bound_p1, up_sub)))) { warning_at (location, OPT_Warray_bounds, "array subscript is above array bounds"); |