From c3e46927e4504374677f4e17838e6e51b5d7b185 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 4 May 2017 09:08:01 +0000 Subject: [PATCH] tree.c (array_at_struct_end_p): Handle arrays at struct end with flexarrays more conservatively. 2017-05-04 Richard Biener * 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 --- gcc/ChangeLog | 11 +++++++++ gcc/emit-rtl.c | 2 +- gcc/gimple-fold.c | 2 +- gcc/tree-chkp.c | 2 +- gcc/tree.c | 63 +++++++++++++++++++++++++++++++++++------------ gcc/tree.h | 10 +++----- 6 files changed, 65 insertions(+), 25 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c690da95a26..1c01a1571c2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2017-05-04 Richard Biener + + * 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. + 2017-05-04 Richard Biener PR tree-optimization/31130 diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index d7aba8864be..041f2a71760 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -1957,7 +1957,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, || (TREE_CODE (t2) == COMPONENT_REF /* For trailing arrays t2 doesn't have a size that covers all valid accesses. */ - && ! array_at_struct_end_p (t, false))) + && ! array_at_struct_end_p (t))) { attrs.expr = t2; attrs.offset_known_p = false; diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 5ebdcdfd796..d58f62207fa 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1235,7 +1235,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type, the NUL. Set *FLEXP to true if the array whose bound is being used is at the end of a struct. */ - if (array_at_struct_end_p (arg, true)) + if (array_at_struct_end_p (arg)) *flexp = true; arg = TREE_OPERAND (arg, 1); diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c index b1ff21851c6..23f5af98ae3 100644 --- a/gcc/tree-chkp.c +++ b/gcc/tree-chkp.c @@ -3277,7 +3277,7 @@ chkp_may_narrow_to_field (tree ref, tree field) return DECL_SIZE (field) && TREE_CODE (DECL_SIZE (field)) == INTEGER_CST && tree_to_uhwi (DECL_SIZE (field)) != 0 && !(flag_chkp_flexible_struct_trailing_arrays - && array_at_struct_end_p (ref, true)) + && array_at_struct_end_p (ref)) && (!DECL_FIELD_OFFSET (field) || TREE_CODE (DECL_FIELD_OFFSET (field)) == INTEGER_CST) && (!DECL_FIELD_BIT_OFFSET (field) diff --git a/gcc/tree.c b/gcc/tree.c index d88c445d32b..3bc6f1c284d 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 diff --git a/gcc/tree.h b/gcc/tree.h index 21c72201110..1b7d86a5257 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4886,12 +4886,10 @@ extern tree array_ref_up_bound (tree); EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */ extern tree array_ref_low_bound (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 second argument is true considers - REF when it's a COMPONENT_REF in addition ARRAY_REF and - ARRAY_RANGE_REF. */ -extern bool array_at_struct_end_p (tree, bool = false); +/* 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. */ +extern bool array_at_struct_end_p (tree); /* Return a tree representing the offset, in bytes, of the field referenced by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */ -- 2.30.2