diff options
author | Richard Biener <rguenther@suse.de> | 2017-08-21 07:37:59 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2017-08-21 07:37:59 +0000 |
commit | 8322b607d60d721542792af78b84e9069ea1a662 (patch) | |
tree | f862273caec95a27fb0f0dffcb2344c356018a6c /gcc/tree-ssa-alias.c | |
parent | 5164293abdea95879f97d4ad711aee010cdbbc95 (diff) | |
download | gcc-8322b607d60d721542792af78b84e9069ea1a662.zip gcc-8322b607d60d721542792af78b84e9069ea1a662.tar.gz gcc-8322b607d60d721542792af78b84e9069ea1a662.tar.bz2 |
re PR tree-optimization/81884 (Invalid code generation with zero size arrays or flexible array members)
2017-08-21 Richard Biener <rguenther@suse.de>
PR middle-end/81884
* tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses
at struct end conservatively when comparing common bases.
* g++.dg/torture/pr81884.C: New testcase.
From-SVN: r251217
Diffstat (limited to 'gcc/tree-ssa-alias.c')
-rw-r--r-- | gcc/tree-ssa-alias.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 5794d22..9bbc163 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -2416,6 +2416,7 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref) if (ref->ref) { tree base = ref->ref; + tree innermost_dropped_array_ref = NULL_TREE; if (handled_component_p (base)) { tree saved_lhs0 = NULL_TREE; @@ -2435,6 +2436,11 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref) TREE_OPERAND (base, 0) = saved_base0; if (res) break; + /* Remember if we drop an array-ref that we need to + double-check not being at struct end. */ + if (TREE_CODE (base) == ARRAY_REF + || TREE_CODE (base) == ARRAY_RANGE_REF) + innermost_dropped_array_ref = base; /* Otherwise drop handled components of the access. */ base = saved_base0; } @@ -2443,15 +2449,22 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref) TREE_OPERAND (lhs, 0) = saved_lhs0; } /* Finally check if the lhs has the same address and size as the - base candidate of the access. */ - if (lhs == base - || (((TYPE_SIZE (TREE_TYPE (lhs)) - == TYPE_SIZE (TREE_TYPE (base))) - || (TYPE_SIZE (TREE_TYPE (lhs)) - && TYPE_SIZE (TREE_TYPE (base)) - && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)), - TYPE_SIZE (TREE_TYPE (base)), 0))) - && operand_equal_p (lhs, base, OEP_ADDRESS_OF))) + base candidate of the access. Watch out if we have dropped + an array-ref that was at struct end, this means ref->ref may + be outside of the TYPE_SIZE of its base. */ + if ((! innermost_dropped_array_ref + || ! array_at_struct_end_p (innermost_dropped_array_ref)) + && (lhs == base + || (((TYPE_SIZE (TREE_TYPE (lhs)) + == TYPE_SIZE (TREE_TYPE (base))) + || (TYPE_SIZE (TREE_TYPE (lhs)) + && TYPE_SIZE (TREE_TYPE (base)) + && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)), + TYPE_SIZE (TREE_TYPE (base)), + 0))) + && operand_equal_p (lhs, base, + OEP_ADDRESS_OF + | OEP_MATCH_SIDE_EFFECTS)))) return true; } |