aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2017-05-04 09:08:01 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2017-05-04 09:08:01 +0000
commitc3e46927e4504374677f4e17838e6e51b5d7b185 (patch)
tree060bfa97ff1fe70567c51cb7685cdc78194aa1db /gcc/tree.c
parent99b68476de7635380de3480b83e852a38fe36f64 (diff)
downloadgcc-c3e46927e4504374677f4e17838e6e51b5d7b185.zip
gcc-c3e46927e4504374677f4e17838e6e51b5d7b185.tar.gz
gcc-c3e46927e4504374677f4e17838e6e51b5d7b185.tar.bz2
tree.c (array_at_struct_end_p): Handle arrays at struct end with flexarrays more conservatively.
2017-05-04 Richard Biener <rguenther@suse.de> * tree.c (array_at_struct_end_p): Handle arrays at struct end with flexarrays more conservatively. Refactor and treat arrays of arrays or aggregates more strict. Fix VIEW_CONVERT_EXPR handling. Remove allow_compref argument. * tree.c (array_at_struct_end_p): Adjust prototype. * emit-rtl.c (set_mem_attributes_minus_bitpos): Adjust. * gimple-fold.c (get_range_strlen): Likewise. * tree-chkp.c (chkp_may_narrow_to_field): Likewise. From-SVN: r247581
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c63
1 files changed, 47 insertions, 16 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index d88c445..3bc6f1c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13221,18 +13221,26 @@ array_ref_up_bound (tree exp)
return NULL_TREE;
}
-/* Returns true if REF is an array reference to an array at the end of
- a structure. If this is the case, the array may be allocated larger
- than its upper bound implies. When ALLOW_COMPREF is true considers
- REF when it's a COMPONENT_REF in addition ARRAY_REF and
- ARRAY_RANGE_REF. */
+/* Returns true if REF is an array reference or a component reference
+ to an array at the end of a structure.
+ If this is the case, the array may be allocated larger
+ than its upper bound implies. */
bool
-array_at_struct_end_p (tree ref, bool allow_compref)
+array_at_struct_end_p (tree ref)
{
- if (TREE_CODE (ref) != ARRAY_REF
- && TREE_CODE (ref) != ARRAY_RANGE_REF
- && (!allow_compref || TREE_CODE (ref) != COMPONENT_REF))
+ tree atype;
+
+ if (TREE_CODE (ref) == ARRAY_REF
+ || TREE_CODE (ref) == ARRAY_RANGE_REF)
+ {
+ atype = TREE_TYPE (TREE_OPERAND (ref, 0));
+ ref = TREE_OPERAND (ref, 0);
+ }
+ else if (TREE_CODE (ref) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE)
+ atype = TREE_TYPE (TREE_OPERAND (ref, 1));
+ else
return false;
while (handled_component_p (ref))
@@ -13240,19 +13248,42 @@ array_at_struct_end_p (tree ref, bool allow_compref)
/* If the reference chain contains a component reference to a
non-union type and there follows another field the reference
is not at the end of a structure. */
- if (TREE_CODE (ref) == COMPONENT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+ if (TREE_CODE (ref) == COMPONENT_REF)
{
- tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
- while (nextf && TREE_CODE (nextf) != FIELD_DECL)
- nextf = DECL_CHAIN (nextf);
- if (nextf)
- return false;
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+ {
+ tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
+ while (nextf && TREE_CODE (nextf) != FIELD_DECL)
+ nextf = DECL_CHAIN (nextf);
+ if (nextf)
+ return false;
+ }
}
+ /* If we have a multi-dimensional array we do not consider
+ a non-innermost dimension as flex array if the whole
+ multi-dimensional array is at struct end.
+ Same for an array of aggregates with a trailing array
+ member. */
+ else if (TREE_CODE (ref) == ARRAY_REF)
+ return false;
+ else if (TREE_CODE (ref) == ARRAY_RANGE_REF)
+ ;
+ /* If we view an underlying object as sth else then what we
+ gathered up to now is what we have to rely on. */
+ else if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
+ break;
+ else
+ gcc_unreachable ();
ref = TREE_OPERAND (ref, 0);
}
+ /* The array now is at struct end. Treat flexible arrays as
+ always subject to extend, even into just padding constrained by
+ an underlying decl. */
+ if (! TYPE_SIZE (atype))
+ return true;
+
tree size = NULL;
if (TREE_CODE (ref) == MEM_REF