aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2019-01-02 06:17:54 +0000
committerJeff Law <law@gcc.gnu.org>2019-01-01 23:17:54 -0700
commiteef2da674ab7e8a9551e656e649359c2b27b026d (patch)
treef10d8250b17e84370021c55efc1683b25d2a446e /gcc/gimple-fold.c
parent2667a5d04a4a34d901d592028d98aea694fca523 (diff)
downloadgcc-eef2da674ab7e8a9551e656e649359c2b27b026d.zip
gcc-eef2da674ab7e8a9551e656e649359c2b27b026d.tar.gz
gcc-eef2da674ab7e8a9551e656e649359c2b27b026d.tar.bz2
gimple-fold.c (get_range_strlen_tree): Record if the computed length is optimistic.
* gimple-fold.c (get_range_strlen_tree): Record if the computed length is optimistic. If it is, then arrange to compute the conservative length as well. * gcc.dg/strlenopt-40.c: Update * gcc.dg/strlenopt-51.c: Likewise. * gcc.dg/tree-ssa/pr79376.c: Likewise. Co-Authored-By: Jeff Law <law@redhat.com> From-SVN: r267505
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c69
1 files changed, 60 insertions, 9 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 6185f98..cf19db2 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1291,6 +1291,12 @@ get_range_strlen_tree (tree arg, bitmap *visited,
/* The length computed by this invocation of the function. */
tree val = NULL_TREE;
+ /* True if VAL is an optimistic (tight) bound determined from
+ the size of the character array in which the string may be
+ stored. In that case, the computed VAL is used to set
+ PDATA->MAXBOUND. */
+ bool tight_bound = false;
+
/* We can end up with &(*iftmp_1)[0] here as well, so handle it. */
if (TREE_CODE (arg) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF)
@@ -1384,6 +1390,7 @@ get_range_strlen_tree (tree arg, bitmap *visited,
&& optype == TREE_TYPE (TREE_OPERAND (arg, 0))
&& array_at_struct_end_p (TREE_OPERAND (arg, 0)))
*flexp = true;
+ tight_bound = true;
}
else if (TREE_CODE (arg) == COMPONENT_REF
&& (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1)))
@@ -1419,17 +1426,24 @@ get_range_strlen_tree (tree arg, bitmap *visited,
/* Set the minimum size to zero since the string in
the array could have zero length. */
pdata->minlen = ssize_int (0);
- }
- if (VAR_P (arg))
- {
- tree type = TREE_TYPE (arg);
- if (POINTER_TYPE_P (type))
- type = TREE_TYPE (type);
-
- if (TREE_CODE (type) == ARRAY_TYPE)
+ /* The array size determined above is an optimistic bound
+ on the length. If the array isn't nul-terminated the
+ length computed by the library function would be greater.
+ Even though using strlen to cross the subobject boundary
+ is undefined, avoid drawing conclusions from the member
+ type about the length here. */
+ tight_bound = true;
+ }
+ else if (VAR_P (arg))
+ {
+ /* Avoid handling pointers to arrays. GCC might misuse
+ a pointer to an array of one bound to point to an array
+ object of a greater bound. */
+ tree argtype = TREE_TYPE (arg);
+ if (TREE_CODE (argtype) == ARRAY_TYPE)
{
- val = TYPE_SIZE_UNIT (type);
+ val = TYPE_SIZE_UNIT (argtype);
if (!val
|| TREE_CODE (val) != INTEGER_CST
|| integer_zerop (val))
@@ -1476,6 +1490,43 @@ get_range_strlen_tree (tree arg, bitmap *visited,
else
pdata->maxbound = val;
+ if (tight_bound)
+ {
+ /* VAL computed above represents an optimistically tight bound
+ on the length of the string based on the referenced object's
+ or subobject's type. Determine the conservative upper bound
+ based on the enclosing object's size if possible. */
+ if (rkind == SRK_LENRANGE || rkind == SRK_LENRANGE_2)
+ {
+ poly_int64 offset;
+ tree base = get_addr_base_and_unit_offset (arg, &offset);
+ if (!base)
+ {
+ /* When the call above fails due to a non-constant offset
+ assume the offset is zero and use the size of the whole
+ enclosing object instead. */
+ base = get_base_address (arg);
+ offset = 0;
+ }
+ /* If the base object is a pointer no upper bound on the length
+ can be determined. Otherwise the maximum length is equal to
+ the size of the enclosing object minus the offset of
+ the referenced subobject minus 1 (for the terminating nul). */
+ tree type = TREE_TYPE (base);
+ if (TREE_CODE (type) == POINTER_TYPE
+ || !VAR_P (base) || !(val = DECL_SIZE_UNIT (base)))
+ val = build_all_ones_cst (size_type_node);
+ else
+ {
+ val = DECL_SIZE_UNIT (base);
+ val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
+ size_int (offset + 1));
+ }
+ }
+ else
+ return false;
+ }
+
if (pdata->maxlen)
{
/* Adjust the more conservative bound if possible/necessary