Constrain conservative string lengths to array sizes [PR104119].

Resolves:
PR tree-optimization/104119 - unexpected -Wformat-overflow after strlen in ILP32 since Ranger integration

gcc/ChangeLog:

	PR tree-optimization/104119
	* gimple-ssa-sprintf.cc (struct directive): Change argument type.
	(format_none): Same.
	(format_percent): Same.
	(format_integer): Same.
	(format_floating): Same.
	(get_string_length): Same.
	(format_character): Same.
	(format_string): Same.
	(format_plain): Same.
	(format_directive): Same.
	(compute_format_length): Same.
	(handle_printf_call): Same.
	* tree-ssa-strlen.cc (get_range_strlen_dynamic): Same.   Call
	get_maxbound.
	(get_range_strlen_phi): Same.
	(get_maxbound): New function.
	(strlen_pass::get_len_or_size): Adjust to parameter change.
	* tree-ssa-strlen.h (get_range_strlen_dynamic): Change argument type.

gcc/testsuite/ChangeLog:

	PR tree-optimization/104119
	* gcc.dg/tree-ssa/builtin-snprintf-13.c: New test.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-29.c: New test.
This commit is contained in:
Martin Sebor 2022-02-03 13:27:16 -07:00
parent 4e4252db03
commit 3c9f762ad0
5 changed files with 412 additions and 41 deletions

View File

@ -600,7 +600,7 @@ struct directive
/* Format conversion function that given a directive and an argument
returns the formatting result. */
fmtresult (*fmtfunc) (const directive &, tree, range_query *);
fmtresult (*fmtfunc) (const directive &, tree, pointer_query &);
/* Return True when the format flag CHR has been used. */
bool get_flag (char chr) const
@ -968,7 +968,7 @@ directive::set_precision (tree arg, range_query *query)
/* Return the result of formatting a no-op directive (such as '%n'). */
static fmtresult
format_none (const directive &, tree, range_query *)
format_none (const directive &, tree, pointer_query &)
{
fmtresult res (0);
return res;
@ -977,7 +977,7 @@ format_none (const directive &, tree, range_query *)
/* Return the result of formatting the '%%' directive. */
static fmtresult
format_percent (const directive &, tree, range_query *)
format_percent (const directive &, tree, pointer_query &)
{
fmtresult res (1);
return res;
@ -1199,7 +1199,7 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
used when the directive argument or its value isn't known. */
static fmtresult
format_integer (const directive &dir, tree arg, range_query *query)
format_integer (const directive &dir, tree arg, pointer_query &ptr_qry)
{
tree intmax_type_node;
tree uintmax_type_node;
@ -1383,7 +1383,7 @@ format_integer (const directive &dir, tree arg, range_query *query)
/* Try to determine the range of values of the integer argument
(range information is not available for pointers). */
value_range vr;
query->range_of_expr (vr, arg, dir.info->callstmt);
ptr_qry.rvals->range_of_expr (vr, arg, dir.info->callstmt);
if (!vr.varying_p () && !vr.undefined_p ())
{
@ -1414,7 +1414,7 @@ format_integer (const directive &dir, tree arg, range_query *query)
if (code == INTEGER_CST)
{
arg = gimple_assign_rhs1 (def);
return format_integer (dir, arg, query);
return format_integer (dir, arg, ptr_qry);
}
if (code == NOP_EXPR)
@ -1459,16 +1459,16 @@ format_integer (const directive &dir, tree arg, range_query *query)
/* For unsigned conversions/directives or signed when
the minimum is positive, use the minimum and maximum to compute
the shortest and longest output, respectively. */
res.range.min = format_integer (dir, argmin, query).range.min;
res.range.max = format_integer (dir, argmax, query).range.max;
res.range.min = format_integer (dir, argmin, ptr_qry).range.min;
res.range.max = format_integer (dir, argmax, ptr_qry).range.max;
}
else if (tree_int_cst_sgn (argmax) < 0)
{
/* For signed conversions/directives if maximum is negative,
use the minimum as the longest output and maximum as the
shortest output. */
res.range.min = format_integer (dir, argmax, query).range.min;
res.range.max = format_integer (dir, argmin, query).range.max;
res.range.min = format_integer (dir, argmax, ptr_qry).range.min;
res.range.max = format_integer (dir, argmin, ptr_qry).range.max;
}
else
{
@ -1477,11 +1477,11 @@ format_integer (const directive &dir, tree arg, range_query *query)
length of the output of both minimum and maximum and pick the
longer. */
unsigned HOST_WIDE_INT max1
= format_integer (dir, argmin, query).range.max;
= format_integer (dir, argmin, ptr_qry).range.max;
unsigned HOST_WIDE_INT max2
= format_integer (dir, argmax, query).range.max;
= format_integer (dir, argmax, ptr_qry).range.max;
res.range.min
= format_integer (dir, integer_zero_node, query).range.min;
= format_integer (dir, integer_zero_node, ptr_qry).range.min;
res.range.max = MAX (max1, max2);
}
@ -1830,7 +1830,7 @@ format_floating (const directive &dir, const HOST_WIDE_INT prec[2])
ARG. */
static fmtresult
format_floating (const directive &dir, tree arg, range_query *)
format_floating (const directive &dir, tree arg, pointer_query &)
{
HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] };
tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
@ -2025,7 +2025,7 @@ format_floating (const directive &dir, tree arg, range_query *)
static fmtresult
get_string_length (tree str, gimple *stmt, unsigned HOST_WIDE_INT max_size,
unsigned eltsize, range_query *query)
unsigned eltsize, pointer_query &ptr_qry)
{
if (!str)
return fmtresult ();
@ -2036,7 +2036,7 @@ get_string_length (tree str, gimple *stmt, unsigned HOST_WIDE_INT max_size,
c_strlen_data lendata = { };
lendata.maxbound = str;
if (eltsize == 1)
get_range_strlen_dynamic (str, stmt, &lendata, query);
get_range_strlen_dynamic (str, stmt, &lendata, ptr_qry);
else
{
/* Determine the length of the shortest and longest string referenced
@ -2084,17 +2084,30 @@ get_string_length (tree str, gimple *stmt, unsigned HOST_WIDE_INT max_size,
return res;
}
/* The minimum length of the string. */
HOST_WIDE_INT min
= (tree_fits_uhwi_p (lendata.minlen)
? tree_to_uhwi (lendata.minlen)
: 0);
/* The maximum length of the string; initially set to MAXBOUND which
may be less than MAXLEN, but may be adjusted up below. */
HOST_WIDE_INT max
= (lendata.maxbound && tree_fits_uhwi_p (lendata.maxbound)
? tree_to_uhwi (lendata.maxbound)
: HOST_WIDE_INT_M1U);
const bool unbounded = integer_all_onesp (lendata.maxlen);
/* True if either the maximum length is unknown or (conservatively)
the array bound is less than the maximum length. That can happen
when the length of the string is unknown but the array in which
the string is stored is a member of a struct. The warning uses
the size of the member as the upper bound but the optimization
doesn't. The optimization could still use the size of
enclosing object as the upper bound but that's not done here. */
const bool unbounded
= (integer_all_onesp (lendata.maxlen)
|| (lendata.maxbound
&& tree_int_cst_lt (lendata.maxbound, lendata.maxlen)));
/* Set the max/likely counters to unbounded when a minimum is known
but the maximum length isn't bounded. This implies that STR is
@ -2147,7 +2160,7 @@ get_string_length (tree str, gimple *stmt, unsigned HOST_WIDE_INT max_size,
vsprinf). */
static fmtresult
format_character (const directive &dir, tree arg, range_query *query)
format_character (const directive &dir, tree arg, pointer_query &ptr_qry)
{
fmtresult res;
@ -2160,7 +2173,8 @@ format_character (const directive &dir, tree arg, range_query *query)
res.range.min = 0;
HOST_WIDE_INT min, max;
if (get_int_range (arg, dir.info->callstmt, &min, &max, false, 0, query))
if (get_int_range (arg, dir.info->callstmt, &min, &max, false, 0,
ptr_qry.rvals))
{
if (min == 0 && max == 0)
{
@ -2457,7 +2471,7 @@ alias_offset (tree arg, HOST_WIDE_INT *arg_size,
vsprinf). */
static fmtresult
format_string (const directive &dir, tree arg, range_query *query)
format_string (const directive &dir, tree arg, pointer_query &ptr_qry)
{
fmtresult res;
@ -2495,7 +2509,7 @@ format_string (const directive &dir, tree arg, range_query *query)
}
fmtresult slen =
get_string_length (arg, dir.info->callstmt, arg_size, count_by, query);
get_string_length (arg, dir.info->callstmt, arg_size, count_by, ptr_qry);
if (slen.range.min == slen.range.max
&& slen.range.min < HOST_WIDE_INT_MAX)
{
@ -2667,7 +2681,7 @@ format_string (const directive &dir, tree arg, range_query *query)
/* Format plain string (part of the format string itself). */
static fmtresult
format_plain (const directive &dir, tree, range_query *)
format_plain (const directive &dir, tree, pointer_query &)
{
fmtresult res (dir.len);
return res;
@ -3063,7 +3077,7 @@ bytes_remaining (unsigned HOST_WIDE_INT navail, const format_result &res)
static bool
format_directive (const call_info &info,
format_result *res, const directive &dir,
range_query *query)
pointer_query &ptr_qry)
{
/* Offset of the beginning of the directive from the beginning
of the format string. */
@ -3088,7 +3102,7 @@ format_directive (const call_info &info,
return false;
/* Compute the range of lengths of the formatted output. */
fmtresult fmtres = dir.fmtfunc (dir, dir.arg, query);
fmtresult fmtres = dir.fmtfunc (dir, dir.arg, ptr_qry);
/* Record whether the output of all directives is known to be
bounded by some maximum, implying that their arguments are
@ -3990,7 +4004,8 @@ maybe_warn_overlap (call_info &info, format_result *res)
that caused the processing to be terminated early). */
static bool
compute_format_length (call_info &info, format_result *res, range_query *query)
compute_format_length (call_info &info, format_result *res,
pointer_query &ptr_qry)
{
if (dump_file)
{
@ -4027,10 +4042,10 @@ compute_format_length (call_info &info, format_result *res, range_query *query)
{
directive dir (&info, dirno);
size_t n = parse_directive (info, dir, res, pf, &argno, query);
size_t n = parse_directive (info, dir, res, pf, &argno, ptr_qry.rvals);
/* Return failure if the format function fails. */
if (!format_directive (info, res, dir, query))
if (!format_directive (info, res, dir, ptr_qry))
return false;
/* Return success when the directive is zero bytes long and it's
@ -4700,7 +4715,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
never set to true again). */
res.posunder4k = posunder4k && dstptr;
bool success = compute_format_length (info, &res, ptr_qry.rvals);
bool success = compute_format_length (info, &res, ptr_qry);
if (res.warned)
suppress_warning (info.callstmt, info.warnopt ());

View File

@ -0,0 +1,131 @@
/* PR tree-optimization/104119 - unexpected -Wformat-overflow after strlen
in ILP32 since Ranger integration
Verify that unlike -Wformat-overflow the sprintf optimization doesn't
assume the length of a string isn't bounded by the size of the array
member it's stored in.
{ dg-do compile }
{ dg-options "-O2 -Wall -fdump-tree-optimized" } */
typedef __SIZE_TYPE__ size_t;
void* memcpy (void*, const void*, size_t);
int snprintf (char*, size_t, const char*, ...);
char* strcpy (char*, const char*);
size_t strlen (const char*);
extern void keep_call_on_line (int);
extern void elim_call_on_line (int);
void sink (void*, ...);
struct __attribute__ ((packed)) S
{
char a4[4], b4[4], ax[];
};
extern struct S es;
void test_extern_decl_memcpy (void)
{
struct S *p = &es;
/* Set strlen (P->A4) to [3, PTRDIFF - 2]. */
memcpy (p->a4, "123", 3);
int i = snprintf (0, 0, "%s", p->a4);
if (i > 4)
keep_call_on_line (__LINE__);
}
void test_extern_decl_strcpy_3 (void)
{
struct S *p = &es;
/* Set strlen (P->A4) to 3. */
strcpy (p->a4, "123");
int i = snprintf (0, 0, "%s", p->a4);
if (i > 4)
elim_call_on_line (__LINE__);
}
void test_extern_decl_strcpy_X (const char *s)
{
struct S *p = &es;
/* Set strlen (P->A4) to [0, PTRDIFF_MAX - 2]. */
strcpy (p->a4, s);
int i = snprintf (0, 0, "%s", p->a4);
if (i > 4)
keep_call_on_line (__LINE__);
}
size_t test_extern_decl_strlen (void)
{
struct S *p = &es;
/* Set strlen (P->A4) to [0, PTRDIFF - 2]. */
size_t n = strlen (p->a4);
int i = snprintf (0, 0, "%s", p->a4);
if (i > 4)
keep_call_on_line (__LINE__);
return n;
}
static struct S ss;
/* Store and read SS to prevent optimizers from assuming it's unchanged. */
extern void set_ss (struct S *p)
{
if (ss.a4[(unsigned char)*p->a4])
__builtin_memcpy (&ss, p, sizeof ss);
}
void test_static_decl_memcpy (void)
{
struct S *p = &ss;
/* Set strlen (P->A4) to [3, PTRDIFF - 2]. */
memcpy (p->a4, "123", 3);
int i = snprintf (0, 0, "%s", p->a4);
if (i > 4)
keep_call_on_line (__LINE__);
}
void test_static_decl_strcpy_3 (void)
{
struct S *p = &ss;
/* Set strlen (P->A4) to 3. */
strcpy (p->a4, "123");
int i = snprintf (0, 0, "%s", p->a4);
if (i > 4)
elim_call_on_line (__LINE__);
}
void test_static_decl_strcpy_X (const char *s)
{
struct S *p = &ss;
/* Set strlen (P->A4) to [0, PTRDIFF_MAX - 2]. */
strcpy (p->a4, s);
int i = snprintf (0, 0, "%s", p->a4);
if (i > 4)
keep_call_on_line (__LINE__);
}
size_t test_static_decl_strlen (void)
{
struct S *p = &ss;
/* Set strlen (P->A4) to [0, PTRDIFF - 2]. */
size_t n = strlen (p->a4);
int i = snprintf (0, 0, "%s", p->a4);
if (i > 4)
keep_call_on_line (__LINE__);
return n;
}
/* { dg-final { scan-tree-dump-times "keep_call_on_line" 6 "optimized" } }
{ dg-final { scan-tree-dump-not "elim_call_on_line" "optimized" } } */

View File

@ -0,0 +1,179 @@
/* PR tree-optimization/104119 - unexpected -Wformat-overflow after strlen
in ILP32 since Ranger integration
{ dg-do compile }
{ dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
typedef __SIZE_TYPE__ size_t;
void* malloc (size_t);
int sprintf (char*, const char*, ...);
size_t strlen (const char*);
void sink (void*, ...);
struct __attribute__ ((packed)) S
{
char a3[3], a4[4], a5[5], a6[6], a7[7], a8[8], a9[9], ax[];
};
extern struct S s;
extern char a4[4], a7[7], a8[8];
void test_decl (void)
{
struct S *p = &s;
{
size_t n = strlen (p->a3);
sprintf (a4, "%s", p->a3); // { dg-bogus "-Wformat-overflow" }
sink (a4, n);
}
{
size_t n = strlen (p->a4);
sprintf (a4, "%s", p->a4); // { dg-bogus "-Wformat-overflow" }
sink (a4, n);
}
{
size_t n = strlen (p->a5);
sprintf (a4, "%s", p->a5); // { dg-warning "may write a terminating nul past the end" }
sink (a4, n);
}
{
size_t n = strlen (p->a7);
sprintf (a8, "%s", p->a7); // { dg-bogus "-Wformat-overflow" }
sink (a8, n);
}
{
size_t n = strlen (p->a8);
sprintf (a8, "%s", p->a8); // { dg-bogus "-Wformat-overflow" }
sink (a8, n);
}
{
size_t n = strlen (p->a9);
sprintf (a8, "%s", p->a9); // { dg-warning "may write a terminating nul past the end " }
sink (a8, n);
}
{
size_t n = strlen (p->ax);
sprintf (a7, "%s", p->ax); // { dg-bogus "-Wformat-overflow" "pr??????" { xfail ilp32 } }
sink (a7, n);
}
}
/* Verify the warning with a pointer to an allocated object with nonstant
size in known range. */
void test_alloc_5_8 (int n)
{
if (n < 5 || 8 < n)
n = 5;
struct S *p = (struct S*)malloc (sizeof *p + n);
sink (p); // initialize *p
{
size_t n = strlen (p->a3);
sprintf (a4, "%s", p->a3); // { dg-bogus "-Wformat-overflow" }
sink (a4, n);
}
{
size_t n = strlen (p->a4);
sprintf (a4, "%s", p->a4); // { dg-bogus "-Wformat-overflow" }
sink (a4, n);
}
{
size_t n = strlen (p->a5);
sprintf (a4, "%s", p->a5); // { dg-warning "may write a terminating nul past the end" }
sink (a4, n);
}
{
size_t n = strlen (p->a7);
sprintf (a8, "%s", p->a7); // { dg-bogus "-Wformat-overflow" }
sink (a8, n);
}
{
size_t n = strlen (p->a8);
sprintf (a8, "%s", p->a8); // { dg-bogus "-Wformat-overflow" }
sink (a8, n);
}
{
size_t n = strlen (p->a9);
sprintf (a8, "%s", p->a9); // { dg-warning "may write a terminating nul past the end " }
sink (a8, n);
}
{
/* The size of the flexible array member p->ax is between 5 and 8
bytes so the length of the string stored in it is at most 7.
Verify the warning triggers based on its size and also gets
the length right. */
size_t n = strlen (p->ax);
sprintf (a4, "%s", p->ax); // { dg-warning "writing up to 7 bytes " }
sink (a4, n);
}
{
size_t n = strlen (p->ax);
sprintf (a8, "%s", p->ax);
sink (a8, n);
}
}
void test_ptr (struct S *p)
{
{
size_t n = strlen (p->a3);
sprintf (a4, "%s", p->a3); // { dg-bogus "-Wformat-overflow" }
sink (a4, n);
}
{
size_t n = strlen (p->a4);
sprintf (a4, "%s", p->a4); // { dg-bogus "-Wformat-overflow" }
sink (a4, n);
}
{
size_t n = strlen (p->a5);
sprintf (a4, "%s", p->a5); // { dg-warning "may write a terminating nul past the end" }
sink (a4, n);
}
{
size_t n = strlen (p->a7);
sprintf (a8, "%s", p->a7); // { dg-bogus "-Wformat-overflow" }
sink (a8, n);
}
{
size_t n = strlen (p->a8);
sprintf (a8, "%s", p->a8); // { dg-bogus "-Wformat-overflow" }
sink (a8, n);
}
{
size_t n = strlen (p->a9);
sprintf (a8, "%s", p->a9); // { dg-warning "may write a terminating nul past the end " }
sink (a8, n);
}
{
size_t n = strlen (p->ax);
sprintf (a8, "%s", p->ax); // { dg-bogus "-Wformat-overflow" "pr??????" { xfail ilp32 } }
sink (a8, n);
}
}

View File

@ -193,8 +193,8 @@ struct laststmt_struct
} laststmt;
static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
static bool get_range_strlen_dynamic (tree, gimple *s, c_strlen_data *,
bitmap, range_query *, unsigned *);
static bool get_range_strlen_dynamic (tree, gimple *, c_strlen_data *,
bitmap, pointer_query *, unsigned *);
/* Sets MINMAX to either the constant value or the range VAL is in
and returns either the constant value or VAL on success or null
@ -1094,7 +1094,7 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals)
static bool
get_range_strlen_phi (tree src, gphi *phi,
c_strlen_data *pdata, bitmap visited,
range_query *rvals, unsigned *pssa_def_max)
pointer_query *ptr_qry, unsigned *pssa_def_max)
{
if (!bitmap_set_bit (visited, SSA_NAME_VERSION (src)))
return true;
@ -1113,7 +1113,7 @@ get_range_strlen_phi (tree src, gphi *phi,
continue;
c_strlen_data argdata = { };
if (!get_range_strlen_dynamic (arg, phi, &argdata, visited, rvals,
if (!get_range_strlen_dynamic (arg, phi, &argdata, visited, ptr_qry,
pssa_def_max))
{
pdata->maxlen = build_all_ones_cst (size_type_node);
@ -1159,6 +1159,48 @@ get_range_strlen_phi (tree src, gphi *phi,
return true;
}
/* Return the maximum possible length of the string PTR that's less
than MAXLEN given the size of the object of subobject it points
to at the given STMT. MAXLEN is the maximum length of the string
determined so far. Return null when no such maximum can be
determined. */
static tree
get_maxbound (tree ptr, gimple *stmt, offset_int maxlen,
pointer_query *ptr_qry)
{
access_ref aref;
if (!ptr_qry->get_ref (ptr, stmt, &aref))
return NULL_TREE;
offset_int sizrem = aref.size_remaining ();
if (sizrem <= 0)
return NULL_TREE;
if (sizrem < maxlen)
maxlen = sizrem - 1;
/* Try to determine the maximum from the subobject at the offset.
This handles MEM [&some-struct, member-offset] that's often
the result of folding COMPONENT_REF [some-struct, member]. */
tree reftype = TREE_TYPE (aref.ref);
if (!RECORD_OR_UNION_TYPE_P (reftype)
|| aref.offrng[0] != aref.offrng[1]
|| !wi::fits_shwi_p (aref.offrng[0]))
return wide_int_to_tree (size_type_node, maxlen);
HOST_WIDE_INT off = aref.offrng[0].to_shwi ();
tree fld = field_at_offset (reftype, NULL_TREE, off);
if (!fld || !DECL_SIZE_UNIT (fld))
return wide_int_to_tree (size_type_node, maxlen);
offset_int size = wi::to_offset (DECL_SIZE_UNIT (fld));
if (maxlen < size)
return wide_int_to_tree (size_type_node, maxlen);
return wide_int_to_tree (size_type_node, size - 1);
}
/* Attempt to determine the length of the string SRC. On success, store
the length in *PDATA and return true. Otherwise, return false.
VISITED is a bitmap of visited PHI nodes. RVALS points to the valuation
@ -1168,7 +1210,7 @@ get_range_strlen_phi (tree src, gphi *phi,
static bool
get_range_strlen_dynamic (tree src, gimple *stmt,
c_strlen_data *pdata, bitmap visited,
range_query *rvals, unsigned *pssa_def_max)
pointer_query *ptr_qry, unsigned *pssa_def_max)
{
int idx = get_stridx (src, stmt);
if (!idx)
@ -1177,7 +1219,7 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
{
gimple *def_stmt = SSA_NAME_DEF_STMT (src);
if (gphi *phi = dyn_cast<gphi *>(def_stmt))
return get_range_strlen_phi (src, phi, pdata, visited, rvals,
return get_range_strlen_phi (src, phi, pdata, visited, ptr_qry,
pssa_def_max);
}
@ -1206,7 +1248,7 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
else if (TREE_CODE (si->nonzero_chars) == SSA_NAME)
{
value_range vr;
rvals->range_of_expr (vr, si->nonzero_chars, si->stmt);
ptr_qry->rvals->range_of_expr (vr, si->nonzero_chars, si->stmt);
if (range_int_cst_p (&vr))
{
pdata->minlen = vr.min ();
@ -1250,12 +1292,16 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
else if (pdata->minlen && TREE_CODE (pdata->minlen) == SSA_NAME)
{
value_range vr;
rvals->range_of_expr (vr, si->nonzero_chars, stmt);
ptr_qry->rvals->range_of_expr (vr, si->nonzero_chars, stmt);
if (range_int_cst_p (&vr))
{
pdata->minlen = vr.min ();
pdata->maxlen = vr.max ();
pdata->maxbound = pdata->maxlen;
offset_int max = offset_int::from (vr.upper_bound (0), SIGNED);
if (tree maxbound = get_maxbound (si->ptr, stmt, max, ptr_qry))
pdata->maxbound = maxbound;
else
pdata->maxbound = pdata->maxlen;
}
else
{
@ -1293,13 +1339,13 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
void
get_range_strlen_dynamic (tree src, gimple *stmt, c_strlen_data *pdata,
range_query *rvals)
pointer_query &ptr_qry)
{
auto_bitmap visited;
tree maxbound = pdata->maxbound;
unsigned limit = param_ssa_name_def_chain_limit;
if (!get_range_strlen_dynamic (src, stmt, pdata, visited, rvals, &limit))
if (!get_range_strlen_dynamic (src, stmt, pdata, visited, &ptr_qry, &limit))
{
/* On failure extend the length range to an impossible maximum
(a valid MAXLEN must be less than PTRDIFF_MAX - 1). Other
@ -4030,7 +4076,7 @@ strlen_pass::get_len_or_size (gimple *stmt, tree arg, int idx,
/* Set MAXBOUND to an arbitrary non-null non-integer node as a request
to have it set to the length of the longest string in a PHI. */
lendata.maxbound = arg;
get_range_strlen_dynamic (arg, stmt, &lendata, ptr_qry.rvals);
get_range_strlen_dynamic (arg, stmt, &lendata, ptr_qry);
unsigned HOST_WIDE_INT maxbound = HOST_WIDE_INT_M1U;
if (tree_fits_uhwi_p (lendata.maxbound)

View File

@ -33,7 +33,7 @@ extern tree get_range (tree, gimple *, wide_int[2],
struct c_strlen_data;
extern void get_range_strlen_dynamic (tree, gimple *, c_strlen_data *,
class range_query *);
pointer_query &);
/* APIs internal to strlen pass. Defined in gimple-ssa-sprintf.cc. */
extern bool handle_printf_call (gimple_stmt_iterator *, pointer_query &);