diff options
author | Martin Sebor <msebor@redhat.com> | 2017-02-03 16:38:15 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2017-02-03 09:38:15 -0700 |
commit | 3f3430400b2ce552a5dbdae49a3a482687b96afa (patch) | |
tree | c78749d08d207350d71edfc1c5b9871d422a1f1c /gcc/gimple-fold.c | |
parent | 46a2ab580a762b0fc3e64dc4ab24d459a4bd1fd2 (diff) | |
download | gcc-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.c | 44 |
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); |