From: Martin Sebor Date: Sun, 23 Dec 2018 16:00:45 +0000 (+0000) Subject: builtins.h (c_strlen_data): Add new fields and comments. X-Git-Tag: upstream/12.2.0~27144 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b71bbbe2b22460ff9200613784e631496fcfc054;p=platform%2Fupstream%2Fgcc.git 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 From-SVN: r267378 --- 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 Jeff Law + * 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; }