diff options
author | Richard Guenther <rguenther@suse.de> | 2011-09-28 13:47:12 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2011-09-28 13:47:12 +0000 |
commit | 206c3e102a4f90a27acf45ac0e6ffc87c94ae7e8 (patch) | |
tree | 76046af01f71445893ce54d6fbb350126b673570 /gcc/fold-const.c | |
parent | fbfb84e623787c68f78eb526b63efb3317a88306 (diff) | |
download | gcc-206c3e102a4f90a27acf45ac0e6ffc87c94ae7e8.tar.gz |
re PR middle-end/50460 (__builtin___strcpy_chk/__builtin_object_size don't work)
2011-09-28 Richard Guenther <rguenther@suse.de>
PR middle-end/50460
* fold-const.c (try_move_mult_to_index): Handle &a.array the
same as &a.array[0].
From-SVN: r179313
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 83 |
1 files changed, 77 insertions, 6 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 5807a5533ba..2726e018665 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6870,6 +6870,60 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1) break; } + else if (TREE_CODE (ref) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE) + { + tree domain; + + /* Remember if this was a multi-dimensional array. */ + if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF) + mdim = true; + + domain = TYPE_DOMAIN (TREE_TYPE (ref)); + if (! domain) + continue; + itype = TREE_TYPE (domain); + + step = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref))); + if (TREE_CODE (step) != INTEGER_CST) + continue; + + if (s) + { + if (! tree_int_cst_equal (step, s)) + continue; + } + else + { + /* Try if delta is a multiple of step. */ + tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step); + if (! tmp) + continue; + delta = tmp; + } + + /* Only fold here if we can verify we do not overflow one + dimension of a multi-dimensional array. */ + if (mdim) + { + tree tmp; + + if (!TYPE_MIN_VALUE (domain) + || !TYPE_MAX_VALUE (domain) + || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST) + continue; + + tmp = fold_binary_loc (loc, PLUS_EXPR, itype, + fold_convert_loc (loc, itype, + TYPE_MIN_VALUE (domain)), + fold_convert_loc (loc, itype, delta)); + if (TREE_CODE (tmp) != INTEGER_CST + || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp)) + continue; + } + + break; + } else mdim = false; @@ -6892,12 +6946,29 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1) pos = TREE_OPERAND (pos, 0); } - TREE_OPERAND (pos, 1) = fold_build2_loc (loc, PLUS_EXPR, itype, - fold_convert_loc (loc, itype, - TREE_OPERAND (pos, 1)), - fold_convert_loc (loc, itype, delta)); - - return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret); + if (TREE_CODE (ref) == ARRAY_REF) + { + TREE_OPERAND (pos, 1) + = fold_build2_loc (loc, PLUS_EXPR, itype, + fold_convert_loc (loc, itype, TREE_OPERAND (pos, 1)), + fold_convert_loc (loc, itype, delta)); + return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret); + } + else if (TREE_CODE (ref) == COMPONENT_REF) + { + gcc_assert (ret == pos); + ret = build4_loc (loc, ARRAY_REF, TREE_TYPE (TREE_TYPE (ref)), ret, + fold_build2_loc + (loc, PLUS_EXPR, itype, + fold_convert_loc (loc, itype, + TYPE_MIN_VALUE + (TYPE_DOMAIN (TREE_TYPE (ref)))), + fold_convert_loc (loc, itype, delta)), + NULL_TREE, NULL_TREE); + return build_fold_addr_expr_loc (loc, ret); + } + else + gcc_unreachable (); } |