aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-02-03 16:38:15 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-02-03 09:38:15 -0700
commit3f3430400b2ce552a5dbdae49a3a482687b96afa (patch)
treec78749d08d207350d71edfc1c5b9871d422a1f1c /gcc/gimple-fold.c
parent46a2ab580a762b0fc3e64dc4ab24d459a4bd1fd2 (diff)
downloadgcc-3f3430400b2ce552a5dbdae49a3a482687b96afa.zip
gcc-3f3430400b2ce552a5dbdae49a3a482687b96afa.tar.gz
gcc-3f3430400b2ce552a5dbdae49a3a482687b96afa.tar.bz2
PR tree-optimization/79352 - -fprintf-return-value doesn't handle flexible-like array members properly
gcc/ChangeLog: PR tree-optimization/79352 * gimple-fold.c (get_range_strlen): Add argument. (get_range_strlen): Change return type to bool. (get_maxval_strlen): Pass in a dummy argument. * gimple-fold.h (get_range_strlen): Change return type to bool. * gimple-ssa-sprintf.c (get_string_length): Set unlikely counter. * tree.h (array_at_struct_end_p): Add argument. * tree.c (array_at_struct_end_p): Handle it. gcc/testsuite/ChangeLog: PR tree-optimization/79352 * gcc.dg/tree-ssa/pr79352.c: New test. From-SVN: r245156
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index ef1afd1..1cd22a8 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1177,11 +1177,15 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
length and 2 for maximum value ARG can have.
When FUZZY is set and the length of a string cannot be determined,
the function instead considers as the maximum possible length the
- size of a character array it may refer to. */
+ size of a character array it may refer to.
+ Set *FLEXP to true if the range of the string lengths has been
+ obtained from the upper bound of an array at the end of a struct.
+ Such an array may hold a string that's longer than its upper bound
+ due to it being used as a poor-man's flexible array member. */
static bool
get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
- bool fuzzy)
+ bool fuzzy, bool *flexp)
{
tree var, val;
gimple *def_stmt;
@@ -1202,7 +1206,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
if (TREE_CODE (aop0) == INDIRECT_REF
&& TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
return get_range_strlen (TREE_OPERAND (aop0, 0),
- length, visited, type, fuzzy);
+ length, visited, type, fuzzy, flexp);
}
if (type == 2)
@@ -1219,7 +1223,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
{
if (TREE_CODE (arg) == ADDR_EXPR)
return get_range_strlen (TREE_OPERAND (arg, 0), length,
- visited, type, fuzzy);
+ visited, type, fuzzy, flexp);
if (TREE_CODE (arg) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1))) == ARRAY_TYPE)
@@ -1228,7 +1232,12 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
bound on the length of the array. This may be overly
optimistic if the array itself isn't NUL-terminated and
the caller relies on the subsequent member to contain
- the NUL. */
+ 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))
+ *flexp = true;
+
arg = TREE_OPERAND (arg, 1);
val = TYPE_SIZE_UNIT (TREE_TYPE (arg));
if (!val || integer_zerop (val))
@@ -1295,14 +1304,14 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|| gimple_assign_unary_nop_p (def_stmt))
{
tree rhs = gimple_assign_rhs1 (def_stmt);
- return get_range_strlen (rhs, length, visited, type, fuzzy);
+ return get_range_strlen (rhs, length, visited, type, fuzzy, flexp);
}
else if (gimple_assign_rhs_code (def_stmt) == COND_EXPR)
{
tree op2 = gimple_assign_rhs2 (def_stmt);
tree op3 = gimple_assign_rhs3 (def_stmt);
- return get_range_strlen (op2, length, visited, type, fuzzy)
- && get_range_strlen (op3, length, visited, type, fuzzy);
+ return get_range_strlen (op2, length, visited, type, fuzzy, flexp)
+ && get_range_strlen (op3, length, visited, type, fuzzy, flexp);
}
return false;
@@ -1325,7 +1334,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
if (arg == gimple_phi_result (def_stmt))
continue;
- if (!get_range_strlen (arg, length, visited, type, fuzzy))
+ if (!get_range_strlen (arg, length, visited, type, fuzzy, flexp))
{
if (fuzzy)
*maxlen = build_all_ones_cst (size_type_node);
@@ -1349,19 +1358,26 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
and array declared as 'char array[8]', MINMAXLEN[0] will be set
to 3 and MINMAXLEN[1] to 7, the longest string that could be
stored in array.
-*/
+ Return true if the range of the string lengths has been obtained
+ from the upper bound of an array at the end of a struct. Such
+ an array may hold a string that's longer than its upper bound
+ due to it being used as a poor-man's flexible array member. */
-void get_range_strlen (tree arg, tree minmaxlen[2])
+bool
+get_range_strlen (tree arg, tree minmaxlen[2])
{
bitmap visited = NULL;
minmaxlen[0] = NULL_TREE;
minmaxlen[1] = NULL_TREE;
- get_range_strlen (arg, minmaxlen, &visited, 1, true);
+ bool flexarray = false;
+ get_range_strlen (arg, minmaxlen, &visited, 1, true, &flexarray);
if (visited)
BITMAP_FREE (visited);
+
+ return flexarray;
}
tree
@@ -1369,7 +1385,9 @@ get_maxval_strlen (tree arg, int type)
{
bitmap visited = NULL;
tree len[2] = { NULL_TREE, NULL_TREE };
- if (!get_range_strlen (arg, len, &visited, type, false))
+
+ bool dummy;
+ if (!get_range_strlen (arg, len, &visited, type, false, &dummy))
len[1] = NULL_TREE;
if (visited)
BITMAP_FREE (visited);