builtins.h (c_strlen_data): Add new fields and comments.

* builtins.h (c_strlen_data): Add new fields and comments.
	* builtins.c (unterminated_array): Change field reference from
	"len" to "minlen" in c_strlen_data instance.
	* gimple-fold.c (get_range_strlen): Likewise.
	* gimple-ssa-sprintf.c (get_string_length): Likewise.

Co-Authored-By: Jeff Law <law@redhat.com>

From-SVN: r267378
This commit is contained in:
Martin Sebor 2018-12-23 16:00:45 +00:00 committed by Jeff Law
parent e09aa5bd6d
commit b71bbbe2b2
5 changed files with 54 additions and 10 deletions

View File

@ -1,6 +1,12 @@
2018-12-23 Martin Sebor <msebor@redhat.com>
Jeff Law <law@redhat.com>
* builtins.h (c_strlen_data): Add new fields and comments.
* builtins.c (unterminated_array): Change field reference from
"len" to "minlen" in c_strlen_data instance.
* gimple-fold.c (get_range_strlen): Likewise.
* gimple-ssa-sprintf.c (get_string_length): Likewise.
* builtins.c (unterminated_array): Rename "data" to "lendata". Fix
a few comments.
(expand_builtin_strnlen, expand_builtin_stpcpy_1): Likewise.

View File

@ -577,11 +577,11 @@ unterminated_array (tree exp, tree *size /* = NULL */, bool *exact /* = NULL */)
structure if EXP references a unterminated array. */
c_strlen_data lendata = { };
tree len = c_strlen (exp, 1, &lendata);
if (len == NULL_TREE && lendata.len && lendata.decl)
if (len == NULL_TREE && lendata.minlen && lendata.decl)
{
if (size)
{
len = lendata.len;
len = lendata.minlen;
if (lendata.off)
{
/* Constant offsets are already accounted for in LENDATA.MINLEN,
@ -720,7 +720,7 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
{
data->decl = decl;
data->off = byteoff;
data->len = ssize_int (len);
data->minlen = ssize_int (len);
return NULL_TREE;
}
@ -794,7 +794,7 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
{
data->decl = decl;
data->off = byteoff;
data->len = ssize_int (len);
data->minlen = ssize_int (len);
return NULL_TREE;
}

View File

@ -57,10 +57,48 @@ extern bool get_pointer_alignment_1 (tree, unsigned int *,
unsigned HOST_WIDE_INT *);
extern unsigned int get_pointer_alignment (tree);
extern unsigned string_length (const void*, unsigned, unsigned);
struct c_strlen_data
{
/* [MINLEN, MAXBOUND, MAXLEN] is a range describing the length of
one or more strings of possibly unknown length. For a single
string of known length the range is a constant where
MINLEN == MAXBOUND == MAXLEN holds.
For other strings, MINLEN is the length of the shortest known
string. MAXBOUND is the length of a string that could be stored
in the largest array referenced by the expression. MAXLEN is
the length of the longest sequence of non-zero bytes
in an object referenced by the expression. For such strings,
MINLEN <= MAXBOUND <= MAXLEN holds. For example, given:
struct A { char a[7], b[]; };
extern struct A *p;
n = strlen (p->a);
the computed range will be [0, 6, ALL_ONES].
However, for a conditional expression involving a string
of known length and an array of unknown bound such as
n = strlen (i ? p->b : "123");
the range will be [3, 3, ALL_ONES].
MINLEN != 0 && MAXLEN == ALL_ONES indicates that MINLEN is
the length of the shortest known string and implies that
the shortest possible string referenced by the expression may
actually be the empty string. This distinction is useful for
diagnostics. get_range_strlen() return value distinguishes
between these two cases.
As the tighter (and more optimistic) bound, MAXBOUND is suitable
for diagnostics but not for optimization.
As the more conservative bound, MAXLEN is intended to be used
for optimization. */
tree minlen;
tree maxlen;
tree maxbound;
/* When non-null, NONSTR refers to the declaration known to store
an unterminated constant character array, as in:
const char s[] = { 'a', 'b', 'c' };
It is used to diagnose uses of such arrays in functions such as
strlen() that expect a nul-terminated string as an argument. */
tree decl;
tree len;
/* Non-constant offset from the beginning of a string not accounted
for in the length range. Used to improve diagnostics. */
tree off;
};

View File

@ -1343,8 +1343,8 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
if (!val && lendata.decl)
{
*nonstr = lendata.decl;
*minlen = lendata.len;
*maxlen = lendata.len;
*minlen = lendata.minlen;
*maxlen = lendata.minlen;
return type == 0 ? false : true;
}
}

View File

@ -2015,12 +2015,12 @@ get_string_length (tree str, unsigned eltsize)
}
else if (!slen
&& data.decl
&& data.len
&& TREE_CODE (data.len) == INTEGER_CST)
&& data.minlen
&& TREE_CODE (data.minlen) == INTEGER_CST)
{
/* STR was not properly NUL terminated, but we have
length information about the unterminated string. */
fmtresult res (tree_to_shwi (data.len));
fmtresult res (tree_to_shwi (data.minlen));
res.nonstr = data.decl;
return res;
}