aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-12-23 16:00:45 +0000
committerJeff Law <law@gcc.gnu.org>2018-12-23 09:00:45 -0700
commitb71bbbe2b22460ff9200613784e631496fcfc054 (patch)
treea1a6d61bb5147081c7b610d4d5bd12d3a48a9814 /gcc
parente09aa5bd6df9ec0003f230ba29b8b5545c1b533e (diff)
downloadgcc-b71bbbe2b22460ff9200613784e631496fcfc054.zip
gcc-b71bbbe2b22460ff9200613784e631496fcfc054.tar.gz
gcc-b71bbbe2b22460ff9200613784e631496fcfc054.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/builtins.c8
-rw-r--r--gcc/builtins.h40
-rw-r--r--gcc/gimple-fold.c4
-rw-r--r--gcc/gimple-ssa-sprintf.c6
5 files changed, 54 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f1f9d70..cd2a294 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 0eb3df9..b56577e 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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;
}
diff --git a/gcc/builtins.h b/gcc/builtins.h
index cf4f9b1..472a86d 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -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;
};
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 0ba1514..b1dd441 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -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;
}
}
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index d627830..8284c76 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -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;
}