PR tree-optimization/83431 - -Wformat-truncation may incorrectly report truncation
gcc/ChangeLog: PR c++/83431 * gimple-ssa-sprintf.c (pass_data_sprintf_length): Remove object. (sprintf_dom_walker): Remove class. (get_int_range): Make argument const. (directive::fmtfunc, directive::set_precision): Same. (format_none): Same. (build_intmax_type_nodes): Same. (adjust_range_for_overflow): Same. (format_floating): Same. (format_character): Same. (format_string): Same. (format_plain): Same. (get_int_range): Cast away constness. (format_integer): Same. (get_string_length): Call get_range_strlen_dynamic. Handle null lendata.maxbound. (should_warn_p): Adjust argument scope qualifier. (maybe_warn): Same. (format_directive): Same. (parse_directive): Same. (is_call_safe): Same. (try_substitute_return_value): Same. (sprintf_dom_walker::handle_printf_call): Rename... (handle_printf_call): ...to this. Initialize target to host charmap here instead of in pass_sprintf_length::execute. (struct call_info): Make global. (sprintf_dom_walker::compute_format_length): Make global. (sprintf_dom_walker::handle_gimple_call): Same. * passes.def (pass_sprintf_length): Replace with pass_strlen. * print-rtl.c (print_pattern): Reduce the number of spaces to avoid -Wformat-truncation. * tree-pass.h (make_pass_warn_printf): New function. * tree-ssa-strlen.c (strlen_optimize): New variable. (get_string_length): Add comments. (get_range_strlen_dynamic): New function. (check_and_optimize_call): New function. (handle_integral_assign): New function. (strlen_check_and_optimize_stmt): Factor code out into strlen_check_and_optimize_call and handle_integral_assign. (strlen_dom_walker::evrp): New member. (strlen_dom_walker::before_dom_children): Use evrp member. (strlen_dom_walker::after_dom_children): Use evrp member. (printf_strlen_execute): New function. (pass_strlen::gate): Update to handle printf calls. (dump_strlen_info): New function. (pass_data_warn_printf): New variable. (pass_warn_printf): New class. * tree-ssa-strlen.h (get_range_strlen_dynamic): Declare. (handle_printf_call): Same. * tree-vrp.c (value_range_base::type): Adjust assertion. * vr-values.c (vr_values::update_value_range): Use type of the first argument rather than the second. gcc/testsuite/ChangeLog: PR c++/83431 * gcc.dg/strlenopt-63.c: New test. * gcc.dg/pr79538.c: Adjust text of expected warning. * gcc.dg/pr81292-1.c: Adjust pass name. * gcc.dg/pr81292-2.c: Same. * gcc.dg/pr81703.c: Same. * gcc.dg/strcmpopt_2.c: Same. * gcc.dg/strcmpopt_3.c: Same. * gcc.dg/strcmpopt_4.c: Same. * gcc.dg/strlenopt-1.c: Same. * gcc.dg/strlenopt-10.c: Same. * gcc.dg/strlenopt-11.c: Same. * gcc.dg/strlenopt-13.c: Same. * gcc.dg/strlenopt-14g.c: Same. * gcc.dg/strlenopt-14gf.c: Same. * gcc.dg/strlenopt-15.c: Same. * gcc.dg/strlenopt-16g.c: Same. * gcc.dg/strlenopt-17g.c: Same. * gcc.dg/strlenopt-18g.c: Same. * gcc.dg/strlenopt-19.c: Same. * gcc.dg/strlenopt-1f.c: Same. * gcc.dg/strlenopt-2.c: Same. * gcc.dg/strlenopt-20.c: Same. * gcc.dg/strlenopt-21.c: Same. * gcc.dg/strlenopt-22.c: Same. * gcc.dg/strlenopt-22g.c: Same. * gcc.dg/strlenopt-24.c: Same. * gcc.dg/strlenopt-25.c: Same. * gcc.dg/strlenopt-26.c: Same. * gcc.dg/strlenopt-27.c: Same. * gcc.dg/strlenopt-28.c: Same. * gcc.dg/strlenopt-29.c: Same. * gcc.dg/strlenopt-2f.c: Same. * gcc.dg/strlenopt-3.c: Same. * gcc.dg/strlenopt-30.c: Same. * gcc.dg/strlenopt-31g.c: Same. * gcc.dg/strlenopt-32.c: Same. * gcc.dg/strlenopt-33.c: Same. * gcc.dg/strlenopt-33g.c: Same. * gcc.dg/strlenopt-34.c: Same. * gcc.dg/strlenopt-35.c: Same. * gcc.dg/strlenopt-4.c: Same. * gcc.dg/strlenopt-48.c: Same. * gcc.dg/strlenopt-49.c: Same. * gcc.dg/strlenopt-4g.c: Same. * gcc.dg/strlenopt-4gf.c: Same. * gcc.dg/strlenopt-5.c: Same. * gcc.dg/strlenopt-50.c: Same. * gcc.dg/strlenopt-51.c: Same. * gcc.dg/strlenopt-52.c: Same. * gcc.dg/strlenopt-53.c: Same. * gcc.dg/strlenopt-54.c: Same. * gcc.dg/strlenopt-55.c: Same. * gcc.dg/strlenopt-56.c: Same. * gcc.dg/strlenopt-6.c: Same. * gcc.dg/strlenopt-61.c: Same. * gcc.dg/strlenopt-7.c: Same. * gcc.dg/strlenopt-8.c: Same. * gcc.dg/strlenopt-9.c: Same. * gcc.dg/strlenopt.h (snprintf, snprintf): Declare. * gcc.dg/tree-ssa/builtin-snprintf-6.c: New test. * gcc.dg/tree-ssa/builtin-snprintf-7.c: New test. * gcc.dg/tree-ssa/builtin-snprintf-8.c: New test. * gcc.dg/tree-ssa/builtin-snprintf-9.c: New test. * gcc.dg/tree-ssa/builtin-sprintf-warn-21.c: New test. * gcc.dg/tree-ssa/dump-4.c: New test. * gcc.dg/tree-ssa/pr83501.c: Adjust pass name. From-SVN: r274933
This commit is contained in:
parent
59bce4ad03
commit
22fca489ea
@ -1,3 +1,58 @@
|
||||
2019-08-23 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/83431
|
||||
* gimple-ssa-sprintf.c (pass_data_sprintf_length): Remove object.
|
||||
(sprintf_dom_walker): Remove class.
|
||||
(get_int_range): Make argument const.
|
||||
(directive::fmtfunc, directive::set_precision): Same.
|
||||
(format_none): Same.
|
||||
(build_intmax_type_nodes): Same.
|
||||
(adjust_range_for_overflow): Same.
|
||||
(format_floating): Same.
|
||||
(format_character): Same.
|
||||
(format_string): Same.
|
||||
(format_plain): Same.
|
||||
(get_int_range): Cast away constness.
|
||||
(format_integer): Same.
|
||||
(get_string_length): Call get_range_strlen_dynamic. Handle
|
||||
null lendata.maxbound.
|
||||
(should_warn_p): Adjust argument scope qualifier.
|
||||
(maybe_warn): Same.
|
||||
(format_directive): Same.
|
||||
(parse_directive): Same.
|
||||
(is_call_safe): Same.
|
||||
(try_substitute_return_value): Same.
|
||||
(sprintf_dom_walker::handle_printf_call): Rename...
|
||||
(handle_printf_call): ...to this. Initialize target to host charmap
|
||||
here instead of in pass_sprintf_length::execute.
|
||||
(struct call_info): Make global.
|
||||
(sprintf_dom_walker::compute_format_length): Make global.
|
||||
(sprintf_dom_walker::handle_gimple_call): Same.
|
||||
* passes.def (pass_sprintf_length): Replace with pass_strlen.
|
||||
* print-rtl.c (print_pattern): Reduce the number of spaces to
|
||||
avoid -Wformat-truncation.
|
||||
* tree-pass.h (make_pass_warn_printf): New function.
|
||||
* tree-ssa-strlen.c (strlen_optimize): New variable.
|
||||
(get_string_length): Add comments.
|
||||
(get_range_strlen_dynamic): New function.
|
||||
(check_and_optimize_call): New function.
|
||||
(handle_integral_assign): New function.
|
||||
(strlen_check_and_optimize_stmt): Factor code out into
|
||||
strlen_check_and_optimize_call and handle_integral_assign.
|
||||
(strlen_dom_walker::evrp): New member.
|
||||
(strlen_dom_walker::before_dom_children): Use evrp member.
|
||||
(strlen_dom_walker::after_dom_children): Use evrp member.
|
||||
(printf_strlen_execute): New function.
|
||||
(pass_strlen::gate): Update to handle printf calls.
|
||||
(dump_strlen_info): New function.
|
||||
(pass_data_warn_printf): New variable.
|
||||
(pass_warn_printf): New class.
|
||||
* tree-ssa-strlen.h (get_range_strlen_dynamic): Declare.
|
||||
(handle_printf_call): Same.
|
||||
* tree-vrp.c (value_range_base::type): Adjust assertion.
|
||||
* vr-values.c (vr_values::update_value_range): Use type of the first
|
||||
argument rather than the second.
|
||||
|
||||
2019-08-26 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* config/i386/i386-features.c (general_remove_non_convertible_regs):
|
||||
|
@ -85,7 +85,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "domwalk.h"
|
||||
#include "alloc-pool.h"
|
||||
#include "vr-values.h"
|
||||
#include "gimple-ssa-evrp-analyze.h"
|
||||
#include "tree-ssa-strlen.h"
|
||||
|
||||
/* The likely worst case value of MB_LEN_MAX for the target, large enough
|
||||
for UTF-8. Ideally, this would be obtained by a target hook if it were
|
||||
@ -100,80 +100,15 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
namespace {
|
||||
|
||||
const pass_data pass_data_sprintf_length = {
|
||||
GIMPLE_PASS, // pass type
|
||||
"printf-return-value", // pass name
|
||||
OPTGROUP_NONE, // optinfo_flags
|
||||
TV_NONE, // tv_id
|
||||
PROP_cfg, // properties_required
|
||||
0, // properties_provided
|
||||
0, // properties_destroyed
|
||||
0, // properties_start
|
||||
0, // properties_finish
|
||||
};
|
||||
|
||||
/* Set to the warning level for the current function which is equal
|
||||
either to warn_format_trunc for bounded functions or to
|
||||
warn_format_overflow otherwise. */
|
||||
|
||||
static int warn_level;
|
||||
|
||||
struct call_info;
|
||||
struct format_result;
|
||||
|
||||
class sprintf_dom_walker : public dom_walker
|
||||
{
|
||||
public:
|
||||
sprintf_dom_walker ()
|
||||
: dom_walker (CDI_DOMINATORS),
|
||||
evrp_range_analyzer (false) {}
|
||||
~sprintf_dom_walker () {}
|
||||
|
||||
edge before_dom_children (basic_block) FINAL OVERRIDE;
|
||||
void after_dom_children (basic_block) FINAL OVERRIDE;
|
||||
bool handle_gimple_call (gimple_stmt_iterator *);
|
||||
|
||||
struct call_info;
|
||||
bool compute_format_length (call_info &, format_result *);
|
||||
class evrp_range_analyzer evrp_range_analyzer;
|
||||
};
|
||||
|
||||
class pass_sprintf_length : public gimple_opt_pass
|
||||
{
|
||||
bool fold_return_value;
|
||||
|
||||
public:
|
||||
pass_sprintf_length (gcc::context *ctxt)
|
||||
: gimple_opt_pass (pass_data_sprintf_length, ctxt),
|
||||
fold_return_value (false)
|
||||
{ }
|
||||
|
||||
opt_pass * clone () { return new pass_sprintf_length (m_ctxt); }
|
||||
|
||||
virtual bool gate (function *);
|
||||
|
||||
virtual unsigned int execute (function *);
|
||||
|
||||
void set_pass_param (unsigned int n, bool param)
|
||||
{
|
||||
gcc_assert (n == 0);
|
||||
fold_return_value = param;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
bool
|
||||
pass_sprintf_length::gate (function *)
|
||||
{
|
||||
/* Run the pass iff -Warn-format-overflow or -Warn-format-truncation
|
||||
is specified and either not optimizing and the pass is being invoked
|
||||
early, or when optimizing and the pass is being invoked during
|
||||
optimization (i.e., "late"). */
|
||||
return ((warn_format_overflow > 0
|
||||
|| warn_format_trunc > 0
|
||||
|| flag_printf_return_value)
|
||||
&& (optimize > 0) == fold_return_value);
|
||||
}
|
||||
|
||||
/* The minimum, maximum, likely, and unlikely maximum number of bytes
|
||||
of output either a formatting function or an individual directive
|
||||
can result in. */
|
||||
@ -684,7 +619,7 @@ fmtresult::type_max_digits (tree type, int base)
|
||||
|
||||
static bool
|
||||
get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT,
|
||||
class vr_values *vr_values);
|
||||
const vr_values *);
|
||||
|
||||
/* Description of a format directive. A directive is either a plain
|
||||
string or a conversion specification that starts with '%'. */
|
||||
@ -719,7 +654,7 @@ struct directive
|
||||
|
||||
/* Format conversion function that given a directive and an argument
|
||||
returns the formatting result. */
|
||||
fmtresult (*fmtfunc) (const directive &, tree, vr_values *);
|
||||
fmtresult (*fmtfunc) (const directive &, tree, const vr_values *);
|
||||
|
||||
/* Return True when a the format flag CHR has been used. */
|
||||
bool get_flag (char chr) const
|
||||
@ -756,9 +691,9 @@ struct directive
|
||||
or 0, whichever is greater. For a non-constant ARG in some range
|
||||
set width to its range adjusting each bound to -1 if it's less.
|
||||
For an indeterminate ARG set width to [0, INT_MAX]. */
|
||||
void set_width (tree arg, vr_values *vr_values)
|
||||
void set_width (tree arg, const vr_values *vr)
|
||||
{
|
||||
get_int_range (arg, width, width + 1, true, 0, vr_values);
|
||||
get_int_range (arg, width, width + 1, true, 0, vr);
|
||||
}
|
||||
|
||||
/* Set both bounds of the precision range to VAL. */
|
||||
@ -772,9 +707,9 @@ struct directive
|
||||
or -1 whichever is greater. For a non-constant ARG in some range
|
||||
set precision to its range adjusting each bound to -1 if it's less.
|
||||
For an indeterminate ARG set precision to [-1, INT_MAX]. */
|
||||
void set_precision (tree arg, vr_values *vr_values)
|
||||
void set_precision (tree arg, const vr_values *vr)
|
||||
{
|
||||
get_int_range (arg, prec, prec + 1, false, -1, vr_values);
|
||||
get_int_range (arg, prec, prec + 1, false, -1, vr);
|
||||
}
|
||||
|
||||
/* Return true if both width and precision are known to be
|
||||
@ -904,7 +839,7 @@ bytes_remaining (unsigned HOST_WIDE_INT navail, const format_result &res)
|
||||
|
||||
/* Description of a call to a formatted function. */
|
||||
|
||||
struct sprintf_dom_walker::call_info
|
||||
struct call_info
|
||||
{
|
||||
/* Function call statement. */
|
||||
gimple *callstmt;
|
||||
@ -978,7 +913,7 @@ struct sprintf_dom_walker::call_info
|
||||
/* Return the result of formatting a no-op directive (such as '%n'). */
|
||||
|
||||
static fmtresult
|
||||
format_none (const directive &, tree, vr_values *)
|
||||
format_none (const directive &, tree, const vr_values *)
|
||||
{
|
||||
fmtresult res (0);
|
||||
return res;
|
||||
@ -987,7 +922,7 @@ format_none (const directive &, tree, vr_values *)
|
||||
/* Return the result of formatting the '%%' directive. */
|
||||
|
||||
static fmtresult
|
||||
format_percent (const directive &, tree, vr_values *)
|
||||
format_percent (const directive &, tree, const vr_values *)
|
||||
{
|
||||
fmtresult res (1);
|
||||
return res;
|
||||
@ -1047,7 +982,7 @@ build_intmax_type_nodes (tree *pintmax, tree *puintmax)
|
||||
static bool
|
||||
get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
|
||||
bool absolute, HOST_WIDE_INT negbound,
|
||||
class vr_values *vr_values)
|
||||
const class vr_values *vr_values)
|
||||
{
|
||||
/* The type of the result. */
|
||||
const_tree type = integer_type_node;
|
||||
@ -1086,7 +1021,9 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
|
||||
&& TYPE_PRECISION (argtype) <= TYPE_PRECISION (type))
|
||||
{
|
||||
/* Try to determine the range of values of the integer argument. */
|
||||
const value_range *vr = vr_values->get_value_range (arg);
|
||||
const value_range *vr
|
||||
= CONST_CAST (class vr_values *, vr_values)->get_value_range (arg);
|
||||
|
||||
if (range_int_cst_p (vr))
|
||||
{
|
||||
HOST_WIDE_INT type_min
|
||||
@ -1203,7 +1140,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, vr_values *vr_values)
|
||||
format_integer (const directive &dir, tree arg, const vr_values *vr_values)
|
||||
{
|
||||
tree intmax_type_node;
|
||||
tree uintmax_type_node;
|
||||
@ -1386,7 +1323,9 @@ format_integer (const directive &dir, tree arg, vr_values *vr_values)
|
||||
{
|
||||
/* Try to determine the range of values of the integer argument
|
||||
(range information is not available for pointers). */
|
||||
const value_range *vr = vr_values->get_value_range (arg);
|
||||
const value_range *vr
|
||||
= CONST_CAST (class vr_values *, vr_values)->get_value_range (arg);
|
||||
|
||||
if (range_int_cst_p (vr))
|
||||
{
|
||||
argmin = vr->min ();
|
||||
@ -1836,7 +1775,7 @@ format_floating (const directive &dir, const HOST_WIDE_INT prec[2])
|
||||
ARG. */
|
||||
|
||||
static fmtresult
|
||||
format_floating (const directive &dir, tree arg, vr_values *)
|
||||
format_floating (const directive &dir, tree arg, const vr_values *)
|
||||
{
|
||||
HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] };
|
||||
tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
|
||||
@ -2030,21 +1969,33 @@ format_floating (const directive &dir, tree arg, vr_values *)
|
||||
Used by the format_string function below. */
|
||||
|
||||
static fmtresult
|
||||
get_string_length (tree str, unsigned eltsize)
|
||||
get_string_length (tree str, unsigned eltsize, const vr_values *vr)
|
||||
{
|
||||
if (!str)
|
||||
return fmtresult ();
|
||||
|
||||
/* Determine the length of the shortest and longest string referenced
|
||||
by STR. Strings of unknown lengths are bounded by the sizes of
|
||||
arrays that subexpressions of STR may refer to. Pointers that
|
||||
aren't known to point any such arrays result in LENDATA.MAXLEN
|
||||
set to SIZE_MAX. */
|
||||
/* Try to determine the dynamic string length first. */
|
||||
c_strlen_data lendata = { };
|
||||
get_range_strlen (str, &lendata, eltsize);
|
||||
if (eltsize == 1)
|
||||
get_range_strlen_dynamic (str, &lendata, vr);
|
||||
else
|
||||
{
|
||||
/* Determine the length of the shortest and longest string referenced
|
||||
by STR. Strings of unknown lengths are bounded by the sizes of
|
||||
arrays that subexpressions of STR may refer to. Pointers that
|
||||
aren't known to point any such arrays result in LENDATA.MAXLEN
|
||||
set to SIZE_MAX. */
|
||||
get_range_strlen (str, &lendata, eltsize);
|
||||
}
|
||||
|
||||
/* Return the default result when nothing is known about the string. */
|
||||
if (integer_all_onesp (lendata.maxbound)
|
||||
/* LENDATA.MAXBOUND is null when LENDATA.MIN corresponds to the shortest
|
||||
string referenced by STR. Otherwise, if it's not equal to .MINLEN it
|
||||
corresponds to the bound of the largest array STR refers to, if known,
|
||||
or it's SIZE_MAX otherwise. */
|
||||
|
||||
/* Return the default result when nothing is known about the string. */
|
||||
if (lendata.maxbound
|
||||
&& integer_all_onesp (lendata.maxbound)
|
||||
&& integer_all_onesp (lendata.maxlen))
|
||||
return fmtresult ();
|
||||
|
||||
@ -2054,7 +2005,7 @@ get_string_length (tree str, unsigned eltsize)
|
||||
: 0);
|
||||
|
||||
HOST_WIDE_INT max
|
||||
= (tree_fits_uhwi_p (lendata.maxbound)
|
||||
= (lendata.maxbound && tree_fits_uhwi_p (lendata.maxbound)
|
||||
? tree_to_uhwi (lendata.maxbound)
|
||||
: HOST_WIDE_INT_M1U);
|
||||
|
||||
@ -2093,10 +2044,11 @@ get_string_length (tree str, unsigned eltsize)
|
||||
else
|
||||
{
|
||||
/* When the upper bound is unknown (it can be zero or excessive)
|
||||
set the likely length to the greater of 1 and the length of
|
||||
the shortest string and reset the lower bound to zero. */
|
||||
set the likely length to the greater of 1. If MAXBOUND is
|
||||
set, also reset the length of the lower bound to zero. */
|
||||
res.range.likely = res.range.min ? res.range.min : warn_level > 1;
|
||||
res.range.min = 0;
|
||||
if (lendata.maxbound)
|
||||
res.range.min = 0;
|
||||
}
|
||||
|
||||
res.range.unlikely = unbounded ? HOST_WIDE_INT_MAX : res.range.max;
|
||||
@ -2110,7 +2062,7 @@ get_string_length (tree str, unsigned eltsize)
|
||||
vsprinf). */
|
||||
|
||||
static fmtresult
|
||||
format_character (const directive &dir, tree arg, vr_values *vr_values)
|
||||
format_character (const directive &dir, tree arg, const vr_values *vr_values)
|
||||
{
|
||||
fmtresult res;
|
||||
|
||||
@ -2186,7 +2138,7 @@ format_character (const directive &dir, tree arg, vr_values *vr_values)
|
||||
vsprinf). */
|
||||
|
||||
static fmtresult
|
||||
format_string (const directive &dir, tree arg, vr_values *)
|
||||
format_string (const directive &dir, tree arg, const vr_values *vr_values)
|
||||
{
|
||||
fmtresult res;
|
||||
|
||||
@ -2204,7 +2156,7 @@ format_string (const directive &dir, tree arg, vr_values *)
|
||||
gcc_checking_assert (count_by == 2 || count_by == 4);
|
||||
}
|
||||
|
||||
fmtresult slen = get_string_length (arg, count_by);
|
||||
fmtresult slen = get_string_length (arg, count_by, vr_values);
|
||||
if (slen.range.min == slen.range.max
|
||||
&& slen.range.min < HOST_WIDE_INT_MAX)
|
||||
{
|
||||
@ -2376,7 +2328,7 @@ format_string (const directive &dir, tree arg, vr_values *)
|
||||
/* Format plain string (part of the format string itself). */
|
||||
|
||||
static fmtresult
|
||||
format_plain (const directive &dir, tree, vr_values *)
|
||||
format_plain (const directive &dir, tree, const vr_values *)
|
||||
{
|
||||
fmtresult res (dir.len);
|
||||
return res;
|
||||
@ -2386,7 +2338,7 @@ format_plain (const directive &dir, tree, vr_values *)
|
||||
should be diagnosed given the AVAILable space in the destination. */
|
||||
|
||||
static bool
|
||||
should_warn_p (const sprintf_dom_walker::call_info &info,
|
||||
should_warn_p (const call_info &info,
|
||||
const result_range &avail, const result_range &result)
|
||||
{
|
||||
if (result.max <= avail.min)
|
||||
@ -2457,7 +2409,7 @@ should_warn_p (const sprintf_dom_walker::call_info &info,
|
||||
|
||||
static bool
|
||||
maybe_warn (substring_loc &dirloc, location_t argloc,
|
||||
const sprintf_dom_walker::call_info &info,
|
||||
const call_info &info,
|
||||
const result_range &avail_range, const result_range &res,
|
||||
const directive &dir)
|
||||
{
|
||||
@ -2737,9 +2689,9 @@ maybe_warn (substring_loc &dirloc, location_t argloc,
|
||||
in *RES. Return true if the directive has been handled. */
|
||||
|
||||
static bool
|
||||
format_directive (const sprintf_dom_walker::call_info &info,
|
||||
format_directive (const call_info &info,
|
||||
format_result *res, const directive &dir,
|
||||
class vr_values *vr_values)
|
||||
const class vr_values *vr_values)
|
||||
{
|
||||
/* Offset of the beginning of the directive from the beginning
|
||||
of the format string. */
|
||||
@ -3086,10 +3038,10 @@ format_directive (const sprintf_dom_walker::call_info &info,
|
||||
the directive. */
|
||||
|
||||
static size_t
|
||||
parse_directive (sprintf_dom_walker::call_info &info,
|
||||
parse_directive (call_info &info,
|
||||
directive &dir, format_result *res,
|
||||
const char *str, unsigned *argno,
|
||||
vr_values *vr_values)
|
||||
const vr_values *vr_values)
|
||||
{
|
||||
const char *pcnt = strchr (str, target_percent);
|
||||
dir.beg = str;
|
||||
@ -3526,9 +3478,8 @@ parse_directive (sprintf_dom_walker::call_info &info,
|
||||
on, false otherwise (e.g., when a unknown or unhandled directive was seen
|
||||
that caused the processing to be terminated early). */
|
||||
|
||||
bool
|
||||
sprintf_dom_walker::compute_format_length (call_info &info,
|
||||
format_result *res)
|
||||
static bool
|
||||
compute_format_length (call_info &info, format_result *res, const vr_values *vr)
|
||||
{
|
||||
if (dump_file)
|
||||
{
|
||||
@ -3564,12 +3515,10 @@ sprintf_dom_walker::compute_format_length (call_info &info,
|
||||
directive dir = directive ();
|
||||
dir.dirno = dirno;
|
||||
|
||||
size_t n = parse_directive (info, dir, res, pf, &argno,
|
||||
evrp_range_analyzer.get_vr_values ());
|
||||
size_t n = parse_directive (info, dir, res, pf, &argno, vr);
|
||||
|
||||
/* Return failure if the format function fails. */
|
||||
if (!format_directive (info, res, dir,
|
||||
evrp_range_analyzer.get_vr_values ()))
|
||||
if (!format_directive (info, res, dir, vr))
|
||||
return false;
|
||||
|
||||
/* Return success the directive is zero bytes long and it's
|
||||
@ -3617,7 +3566,7 @@ get_destination_size (tree dest)
|
||||
of its return values. */
|
||||
|
||||
static bool
|
||||
is_call_safe (const sprintf_dom_walker::call_info &info,
|
||||
is_call_safe (const call_info &info,
|
||||
const format_result &res, bool under4k,
|
||||
unsigned HOST_WIDE_INT retval[2])
|
||||
{
|
||||
@ -3676,7 +3625,7 @@ is_call_safe (const sprintf_dom_walker::call_info &info,
|
||||
|
||||
static bool
|
||||
try_substitute_return_value (gimple_stmt_iterator *gsi,
|
||||
const sprintf_dom_walker::call_info &info,
|
||||
const call_info &info,
|
||||
const format_result &res)
|
||||
{
|
||||
tree lhs = gimple_get_lhs (info.callstmt);
|
||||
@ -3794,7 +3743,7 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
|
||||
|
||||
static bool
|
||||
try_simplify_call (gimple_stmt_iterator *gsi,
|
||||
const sprintf_dom_walker::call_info &info,
|
||||
const call_info &info,
|
||||
const format_result &res)
|
||||
{
|
||||
unsigned HOST_WIDE_INT dummy[2];
|
||||
@ -3847,13 +3796,17 @@ get_user_idx_format (tree fndecl, unsigned *idx_args)
|
||||
return tree_to_uhwi (fmtarg) - 1;
|
||||
}
|
||||
|
||||
/* Determine if a GIMPLE CALL is to one of the sprintf-like built-in
|
||||
functions and if so, handle it. Return true if the call is removed
|
||||
and gsi_next should not be performed in the caller. */
|
||||
} /* Unnamed namespace. */
|
||||
|
||||
/* Determine if a GIMPLE call at *GSI is to one of the sprintf-like built-in
|
||||
functions and if so, handle it. Return true if the call is removed and
|
||||
gsi_next should not be performed in the caller. */
|
||||
|
||||
bool
|
||||
sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
handle_printf_call (gimple_stmt_iterator *gsi, const vr_values *vr_values)
|
||||
{
|
||||
init_target_to_host_charmap ();
|
||||
|
||||
call_info info = call_info ();
|
||||
|
||||
info.callstmt = gsi_stmt (*gsi);
|
||||
@ -4119,7 +4072,9 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
/* Try to determine the range of values of the argument
|
||||
and use the greater of the two at level 1 and the smaller
|
||||
of them at level 2. */
|
||||
const value_range *vr = evrp_range_analyzer.get_value_range (size);
|
||||
const value_range *vr
|
||||
= CONST_CAST (class vr_values *, vr_values)->get_value_range (size);
|
||||
|
||||
if (range_int_cst_p (vr))
|
||||
{
|
||||
unsigned HOST_WIDE_INT minsize = TREE_INT_CST_LOW (vr->min ());
|
||||
@ -4230,7 +4185,7 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
never set to true again). */
|
||||
res.posunder4k = posunder4k && dstptr;
|
||||
|
||||
bool success = compute_format_length (info, &res);
|
||||
bool success = compute_format_length (info, &res, vr_values);
|
||||
if (res.warned)
|
||||
gimple_set_no_warning (info.callstmt, true);
|
||||
|
||||
@ -4256,71 +4211,3 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
|
||||
return call_removed;
|
||||
}
|
||||
|
||||
edge
|
||||
sprintf_dom_walker::before_dom_children (basic_block bb)
|
||||
{
|
||||
evrp_range_analyzer.enter (bb);
|
||||
for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); )
|
||||
{
|
||||
/* Iterate over statements, looking for function calls. */
|
||||
gimple *stmt = gsi_stmt (si);
|
||||
|
||||
/* First record ranges generated by this statement. */
|
||||
evrp_range_analyzer.record_ranges_from_stmt (stmt, false);
|
||||
|
||||
if (is_gimple_call (stmt) && handle_gimple_call (&si))
|
||||
/* If handle_gimple_call returns true, the iterator is
|
||||
already pointing to the next statement. */
|
||||
continue;
|
||||
|
||||
gsi_next (&si);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
sprintf_dom_walker::after_dom_children (basic_block bb)
|
||||
{
|
||||
evrp_range_analyzer.leave (bb);
|
||||
}
|
||||
|
||||
/* Execute the pass for function FUN. */
|
||||
|
||||
unsigned int
|
||||
pass_sprintf_length::execute (function *fun)
|
||||
{
|
||||
init_target_to_host_charmap ();
|
||||
|
||||
calculate_dominance_info (CDI_DOMINATORS);
|
||||
bool use_scev = optimize > 0 && flag_printf_return_value;
|
||||
if (use_scev)
|
||||
{
|
||||
loop_optimizer_init (LOOPS_NORMAL);
|
||||
scev_initialize ();
|
||||
}
|
||||
|
||||
sprintf_dom_walker sprintf_dom_walker;
|
||||
sprintf_dom_walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
|
||||
|
||||
if (use_scev)
|
||||
{
|
||||
scev_finalize ();
|
||||
loop_optimizer_finalize ();
|
||||
}
|
||||
|
||||
/* Clean up object size info. */
|
||||
fini_object_sizes ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* Unnamed namespace. */
|
||||
|
||||
/* Return a pointer to a pass object newly constructed from the context
|
||||
CTXT. */
|
||||
|
||||
gimple_opt_pass *
|
||||
make_pass_sprintf_length (gcc::context *ctxt)
|
||||
{
|
||||
return new pass_sprintf_length (ctxt);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
NEXT_PASS (pass_build_cfg);
|
||||
NEXT_PASS (pass_warn_function_return);
|
||||
NEXT_PASS (pass_expand_omp);
|
||||
NEXT_PASS (pass_sprintf_length, false);
|
||||
NEXT_PASS (pass_warn_printf);
|
||||
NEXT_PASS (pass_walloca, /*strict_mode_p=*/true);
|
||||
NEXT_PASS (pass_build_cgraph_edges);
|
||||
TERMINATE_PASS_LIST (all_lowering_passes)
|
||||
@ -307,7 +307,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
NEXT_PASS (pass_lower_vector_ssa);
|
||||
NEXT_PASS (pass_lower_switch);
|
||||
NEXT_PASS (pass_cse_reciprocals);
|
||||
NEXT_PASS (pass_sprintf_length, true);
|
||||
NEXT_PASS (pass_reassoc, false /* insert_powi_p */);
|
||||
NEXT_PASS (pass_strength_reduction);
|
||||
NEXT_PASS (pass_split_paths);
|
||||
@ -358,7 +357,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
NEXT_PASS (pass_object_sizes);
|
||||
/* Fold remaining builtins. */
|
||||
NEXT_PASS (pass_fold_builtins);
|
||||
NEXT_PASS (pass_sprintf_length, true);
|
||||
NEXT_PASS (pass_strlen);
|
||||
/* Copy propagation also copy-propagates constants, this is necessary
|
||||
to forward object-size and builtin folding results properly. */
|
||||
NEXT_PASS (pass_copy_prop);
|
||||
|
@ -1815,7 +1815,7 @@ print_pattern (pretty_printer *pp, const_rtx x, int verbose)
|
||||
gcc_assert (strlen (print_rtx_head) < sizeof (indented_print_rtx_head) - 4);
|
||||
snprintf (indented_print_rtx_head,
|
||||
sizeof (indented_print_rtx_head),
|
||||
"%s ", print_rtx_head);
|
||||
"%s ", print_rtx_head);
|
||||
print_rtx_head = indented_print_rtx_head;
|
||||
for (int i = 0; i < seq->len (); i++)
|
||||
print_insn_with_notes (pp, seq->insn (i));
|
||||
|
@ -77,6 +77,76 @@
|
||||
|
||||
* gcc.target/mips/get-fcsr-3.c: New test.
|
||||
|
||||
2019-08-23 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/83431
|
||||
* gcc.dg/strlenopt-63.c: New test.
|
||||
* gcc.dg/pr79538.c: Adjust text of expected warning.
|
||||
* gcc.dg/pr81292-1.c: Adjust pass name.
|
||||
* gcc.dg/pr81292-2.c: Same.
|
||||
* gcc.dg/pr81703.c: Same.
|
||||
* gcc.dg/strcmpopt_2.c: Same.
|
||||
* gcc.dg/strcmpopt_3.c: Same.
|
||||
* gcc.dg/strcmpopt_4.c: Same.
|
||||
* gcc.dg/strlenopt-1.c: Same.
|
||||
* gcc.dg/strlenopt-10.c: Same.
|
||||
* gcc.dg/strlenopt-11.c: Same.
|
||||
* gcc.dg/strlenopt-13.c: Same.
|
||||
* gcc.dg/strlenopt-14g.c: Same.
|
||||
* gcc.dg/strlenopt-14gf.c: Same.
|
||||
* gcc.dg/strlenopt-15.c: Same.
|
||||
* gcc.dg/strlenopt-16g.c: Same.
|
||||
* gcc.dg/strlenopt-17g.c: Same.
|
||||
* gcc.dg/strlenopt-18g.c: Same.
|
||||
* gcc.dg/strlenopt-19.c: Same.
|
||||
* gcc.dg/strlenopt-1f.c: Same.
|
||||
* gcc.dg/strlenopt-2.c: Same.
|
||||
* gcc.dg/strlenopt-20.c: Same.
|
||||
* gcc.dg/strlenopt-21.c: Same.
|
||||
* gcc.dg/strlenopt-22.c: Same.
|
||||
* gcc.dg/strlenopt-22g.c: Same.
|
||||
* gcc.dg/strlenopt-24.c: Same.
|
||||
* gcc.dg/strlenopt-25.c: Same.
|
||||
* gcc.dg/strlenopt-26.c: Same.
|
||||
* gcc.dg/strlenopt-27.c: Same.
|
||||
* gcc.dg/strlenopt-28.c: Same.
|
||||
* gcc.dg/strlenopt-29.c: Same.
|
||||
* gcc.dg/strlenopt-2f.c: Same.
|
||||
* gcc.dg/strlenopt-3.c: Same.
|
||||
* gcc.dg/strlenopt-30.c: Same.
|
||||
* gcc.dg/strlenopt-31g.c: Same.
|
||||
* gcc.dg/strlenopt-32.c: Same.
|
||||
* gcc.dg/strlenopt-33.c: Same.
|
||||
* gcc.dg/strlenopt-33g.c: Same.
|
||||
* gcc.dg/strlenopt-34.c: Same.
|
||||
* gcc.dg/strlenopt-35.c: Same.
|
||||
* gcc.dg/strlenopt-4.c: Same.
|
||||
* gcc.dg/strlenopt-48.c: Same.
|
||||
* gcc.dg/strlenopt-49.c: Same.
|
||||
* gcc.dg/strlenopt-4g.c: Same.
|
||||
* gcc.dg/strlenopt-4gf.c: Same.
|
||||
* gcc.dg/strlenopt-5.c: Same.
|
||||
* gcc.dg/strlenopt-50.c: Same.
|
||||
* gcc.dg/strlenopt-51.c: Same.
|
||||
* gcc.dg/strlenopt-52.c: Same.
|
||||
* gcc.dg/strlenopt-53.c: Same.
|
||||
* gcc.dg/strlenopt-54.c: Same.
|
||||
* gcc.dg/strlenopt-55.c: Same.
|
||||
* gcc.dg/strlenopt-56.c: Same.
|
||||
* gcc.dg/strlenopt-6.c: Same.
|
||||
* gcc.dg/strlenopt-61.c: Same.
|
||||
* gcc.dg/strlenopt-7.c: Same.
|
||||
* gcc.dg/strlenopt-8.c: Same.
|
||||
* gcc.dg/strlenopt-9.c: Same.
|
||||
* gcc.dg/strlenopt.h (snprintf, snprintf): Declare.
|
||||
* gcc.dg/tree-ssa/builtin-snprintf-6.c: New test.
|
||||
* gcc.dg/tree-ssa/builtin-snprintf-7.c: New test.
|
||||
* gcc.dg/tree-ssa/builtin-snprintf-8.c: New test.
|
||||
* gcc.dg/tree-ssa/builtin-snprintf-9.c: New test.
|
||||
* gcc.dg/tree-ssa/builtin-sprintf-warn-21.c: New test.
|
||||
* gcc.dg/tree-ssa/dump-4.c: New test.
|
||||
* gcc.dg/tree-ssa/pr83501.c: Adjust pass name.
|
||||
|
||||
2019-08-23 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
* gcc.dg/Warray-bounds-36.c: Make functions static to avoid failures
|
||||
|
@ -17,6 +17,6 @@ void f ()
|
||||
{
|
||||
char des[3];
|
||||
char src[] = "abcd";
|
||||
__builtin_sprintf (des, "%s", src); /* { dg-warning "directive writing up to 4 bytes into a region of size 3" } */
|
||||
__builtin_sprintf (des, "%s", src); /* { dg-warning "directive writing 4 bytes into a region of size 3" } */
|
||||
return;
|
||||
}
|
||||
|
@ -32,4 +32,4 @@ main (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
|
@ -32,4 +32,4 @@ main (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 6 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 6 "strlen1" } } */
|
||||
|
@ -9,4 +9,4 @@ unsigned g (void)
|
||||
return __builtin_strlen (d);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "__builtin_strlen" "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-not "__builtin_strlen" "strlen1" } } */
|
||||
|
@ -64,4 +64,4 @@ int main (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "cmp_eq \\(" 8 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "cmp_eq \\(" 8 "strlen1" } } */
|
||||
|
@ -28,4 +28,4 @@ int main (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strcmp" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcmp" 0 "strlen1" } } */
|
||||
|
@ -13,4 +13,4 @@ f1 (S * s)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "cmp_eq \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "cmp_eq \\(" 1 "strlen1" } } */
|
||||
|
@ -36,9 +36,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -69,14 +69,14 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* avr has BIGGEST_ALIGNMENT 8, allowing fold_builtin_memory_op
|
||||
to expand the memcpy call at the end of fn2. */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 8 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 7 "strlen" { target { avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "\\*q_\[0-9\]* = 32;" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(\[^\n\r\]*, 1\\)" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 8 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 7 "strlen1" { target { avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "\\*q_\[0-9\]* = 32;" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(\[^\n\r\]*, 1\\)" 1 "strlen1" } } */
|
||||
|
@ -58,18 +58,18 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen1" } } */
|
||||
/* avr has BIGGEST_ALIGNMENT 8, allowing fold_builtin_memory_op
|
||||
to expand the memcpy call at the end of fn1. */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 7 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen" { target { avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 7 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen1" { target { avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
/* Where the memcpy is expanded, the assignemts to elements of l are
|
||||
propagated. */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.0. = " 1 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.6. = " 1 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.9. = " 1 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;" 3 "strlen" { target { avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.0. = " 1 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.6. = " 1 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.9. = " 1 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;" 3 "strlen1" { target { avr-*-* } } } } */
|
||||
|
@ -55,19 +55,19 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen1" } } */
|
||||
/* avr has BIGGEST_ALIGNMENT 8, allowing fold_builtin_memory_op
|
||||
to expand the memcpy call at the end of fn1. */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 7 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen" { target { avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 7 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen1" { target { avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
/* Where the memcpy is expanded, the assignemts to elements of l are
|
||||
propagated. */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.0. = " 1 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.1. = " 1 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.5. = " 1 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.6. = " 1 "strlen" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;" 4 "strlen" { target { avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.0. = " 1 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.1. = " 1 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.5. = " 1 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.6. = " 1 "strlen1" { target { ! avr-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;" 4 "strlen1" { target { avr-*-* } } } } */
|
||||
|
@ -107,10 +107,10 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "mempcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "mempcpy \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen1" } } */
|
||||
|
@ -11,15 +11,15 @@
|
||||
/* Compared to strlenopt-14gf.c, strcpy_chk with string literal as
|
||||
second argument isn't being optimized by builtins.c into
|
||||
memcpy. */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__mempcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "mempcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__mempcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "mempcpy \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen1" } } */
|
||||
|
@ -51,9 +51,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -24,10 +24,10 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "mempcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "mempcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen1" } } */
|
||||
|
@ -47,10 +47,10 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "mempcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "mempcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen1" } } */
|
||||
|
@ -73,9 +73,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen1" } } */
|
||||
|
@ -72,9 +72,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -5,13 +5,13 @@
|
||||
#define FORTIFY_SOURCE 2
|
||||
#include "strlenopt-1.c"
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -40,9 +40,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 5 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 5 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -86,9 +86,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -57,9 +57,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -31,9 +31,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -5,9 +5,9 @@
|
||||
#define USE_GNU
|
||||
#include "strlenopt-22.c"
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen1" } } */
|
||||
|
@ -13,4 +13,4 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
|
@ -14,4 +14,4 @@ main ()
|
||||
return len - len2;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
|
@ -20,5 +20,5 @@ main (void)
|
||||
return fn1 (p, q);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
|
@ -19,4 +19,4 @@ main (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
|
@ -56,4 +56,4 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
|
@ -24,4 +24,4 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
|
@ -5,13 +5,13 @@
|
||||
#define FORTIFY_SOURCE 2
|
||||
#include "strlenopt-2.c"
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 5 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 5 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -53,12 +53,12 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "return 0" 3 "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-times "return 4" 1 "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-times "return 3" 1 "optimized" } } */
|
||||
|
@ -60,4 +60,4 @@ _Bool f7(char *s)
|
||||
return (t1 == s);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "__builtin_strncmp" 5 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__builtin_strncmp" 5 "strlen1" } } */
|
||||
|
@ -4,6 +4,6 @@
|
||||
#define USE_GNU
|
||||
#include "strlenopt-31.c"
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-not "strlen \\(" "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-not "strlen \\(" "strlen1" } } */
|
||||
|
@ -190,4 +190,4 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
|
@ -39,4 +39,4 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
|
@ -40,5 +40,5 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 2 "strlen1" } } */
|
||||
|
@ -35,4 +35,4 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
|
@ -28,4 +28,4 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen1" } } */
|
||||
|
@ -66,9 +66,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 3 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 3 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 3 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 3 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -31,5 +31,5 @@ void h (void)
|
||||
abort();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "optimized" } }
|
||||
{ dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */
|
||||
|
@ -45,7 +45,7 @@ int cmp88 (void)
|
||||
return cmp88;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "len0 = 0;" 1 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "len = 18;" 1 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "lenx = 8;" 1 "gimple" } }
|
||||
|
@ -5,9 +5,9 @@
|
||||
#define USE_GNU
|
||||
#include "strlenopt-4.c"
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 5 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 5 "strlen1" } } */
|
||||
|
@ -6,13 +6,13 @@
|
||||
#define FORTIFY_SOURCE 2
|
||||
#include "strlenopt-4.c"
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 5 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__memcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__strcat_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "__stpcpy_chk \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 5 "strlen1" } } */
|
||||
|
@ -48,9 +48,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -112,5 +112,5 @@ void test_array_ref (void)
|
||||
T (&b[16], 0); T (&b[17], 0); T (&b[18], 0); T (&b[19], 0);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "ccp1" } } */
|
||||
|
@ -84,4 +84,4 @@ void test_elim_a9_9 (unsigned i)
|
||||
T (0); T (1); T (2); T (3); T (4); T (5); T (6); T (7); T (8);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "gimple" } } */
|
||||
|
@ -284,5 +284,5 @@ void test_global_struct_struct_array (void)
|
||||
T (ssa[5].sa9[3].a6, 3);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "ccp1" } } */
|
||||
|
@ -112,5 +112,5 @@ void test_array_ref (void)
|
||||
T (&b[16], 0); T (&b[17], 0); T (&b[18], 0); T (&b[19], 0);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "ccp1" } } */
|
||||
|
@ -105,5 +105,5 @@ void elim_after_init_memcpy (void)
|
||||
T ("AB\000CD", 0, "ab\000c", 4, 2);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "optimized" } }
|
||||
{ dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
|
||||
|
@ -224,7 +224,7 @@ const void test_large_string_size (void)
|
||||
}
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "memcmp" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
|
||||
|
@ -45,6 +45,6 @@ void test_contents (void)
|
||||
}
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
|
||||
/* { dg-final { scan-tree-dump-times "strlen1" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
|
||||
{ dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */
|
||||
|
@ -77,9 +77,9 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 7 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 7 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
|
@ -215,4 +215,4 @@ void test_ta2 (void)
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "failure" "optimized" } }
|
||||
{ dg-final { scan-tree-dump-not "strlen" "gimple" } } */
|
||||
{ dg-final { scan-tree-dump-not "strlen1" "gimple" } } */
|
||||
|
382
gcc/testsuite/gcc.dg/strlenopt-68.c
Normal file
382
gcc/testsuite/gcc.dg/strlenopt-68.c
Normal file
@ -0,0 +1,382 @@
|
||||
/* PR tree-optimization/83431 - Verify that snprintf (0, 0, "%s",
|
||||
with an argument that's a conditional expression evaluates to
|
||||
the expected result regardless of the order of the expression
|
||||
operands.
|
||||
{ dg-do run }
|
||||
{ dg-options "-O2 -Wall" } */
|
||||
|
||||
#include "strlenopt.h"
|
||||
|
||||
#define A(expr) \
|
||||
((expr) \
|
||||
? (void)0 \
|
||||
: (__builtin_printf ("assertion failed on line %i: %s\n", \
|
||||
__LINE__, #expr), \
|
||||
__builtin_abort ()))
|
||||
|
||||
const char gs0[] = "";
|
||||
const char gs3[] = "123";
|
||||
|
||||
char gc;
|
||||
char ga5[7];
|
||||
|
||||
struct S { char n, ma7[7], max[]; };
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs0_gs3_ga5_m1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs0 : 0 < i ? gs3 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs0_gs3_ga5_0 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs0 : 0 < i ? gs3 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs0_gs3_ga5_p1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs0 : 0 < i ? gs3 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs0_ga5_gs3_m1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs0 : 0 < i ? ga5 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs0_ga5_gs3_0 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs0 : 0 < i ? ga5 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs0_ga5_gs3_p1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs0 : 0 < i ? ga5 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_ga5_gs0_gs3_m1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs0 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_ga5_gs0_gs3_0 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs0 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_ga5_gs0_gs3_p1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs0 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_ga5_gs3_gs0_m1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs3 : gs0;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_ga5_gs3_gs0_0 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs3 : gs0;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_ga5_gs3_gs0_p1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs3 : gs0;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs3_gs0_ga5_m1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs3 : 0 < i ? gs0 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs3_gs0_ga5_0 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs3 : 0 < i ? gs0 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
equal_4_gs3_gs0_ga5_p1 (int i)
|
||||
{
|
||||
strcpy (ga5, "1234");
|
||||
const char *p = i < 0 ? gs3 : 0 < i ? gs0 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
|
||||
/* Similar to the above but with memcpy creating a string at least
|
||||
four characters long, and the address of the NUL character. */
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gc_gs3_ga5_m1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? &gc : 0 < i ? gs3 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gc_gs3_ga5_0 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? &gc : 0 < i ? gs3 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gc_gs3_ga5_p1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? &gc : 0 < i ? gs3 : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gc_ga5_gs3_m1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? &gc : 0 < i ? ga5 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gc_ga5_gs3_0 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? &gc : 0 < i ? ga5 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gc_ga5_gs3_p1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? &gc : 0 < i ? ga5 : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_ga5_gc_gs3_m1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? &gc : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_ga5_gc_gs3_0 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? &gc : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_ga5_gc_gs3_p1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? &gc : gs3;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_ga5_gs3_gc_m1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs3 : &gc;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_ga5_gs3_gc_0 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs3 : &gc;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_ga5_gs3_gc_p1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? ga5 : 0 < i ? gs3 : &gc;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gs3_gc_ga5_m1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? gs3 : 0 < i ? &gc : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 3);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gs3_gc_ga5_0 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? gs3 : 0 < i ? &gc : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 4);
|
||||
}
|
||||
|
||||
__attribute__ ((noclone, noinline, noipa)) void
|
||||
min_4_gs3_gc_ga5_p1 (int i)
|
||||
{
|
||||
gc = 0;
|
||||
memcpy (ga5, "1234", 4);
|
||||
const char *p = i < 0 ? gs3 : 0 < i ? &gc : ga5;
|
||||
|
||||
A (snprintf (0, 0, "%s", p) == 0);
|
||||
}
|
||||
|
||||
|
||||
int main (void)
|
||||
{
|
||||
equal_4_gs0_gs3_ga5_m1 (-1);
|
||||
equal_4_gs0_gs3_ga5_0 ( 0);
|
||||
equal_4_gs0_gs3_ga5_p1 (+1);
|
||||
|
||||
equal_4_gs0_ga5_gs3_m1 (-1);
|
||||
equal_4_gs0_ga5_gs3_0 ( 0);
|
||||
equal_4_gs0_ga5_gs3_p1 (+1);
|
||||
|
||||
equal_4_ga5_gs0_gs3_m1 (-1);
|
||||
equal_4_ga5_gs0_gs3_0 ( 0);
|
||||
equal_4_ga5_gs0_gs3_p1 (+1);
|
||||
|
||||
equal_4_ga5_gs3_gs0_m1 (-1);
|
||||
equal_4_ga5_gs3_gs0_0 ( 0);
|
||||
equal_4_ga5_gs3_gs0_p1 (+1);
|
||||
|
||||
equal_4_gs3_gs0_ga5_m1 (-1);
|
||||
equal_4_gs3_gs0_ga5_0 ( 0);
|
||||
equal_4_gs3_gs0_ga5_p1 (+1);
|
||||
|
||||
/* Same as aabove but with memcpy creating a string at least four
|
||||
characters long. */
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gc_gs3_ga5_m1 (-1);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gc_gs3_ga5_0 ( 0);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gc_gs3_ga5_p1 (+1);
|
||||
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gc_ga5_gs3_m1 (-1);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gc_ga5_gs3_0 ( 0);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gc_ga5_gs3_p1 (+1);
|
||||
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_ga5_gc_gs3_m1 (-1);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_ga5_gc_gs3_0 ( 0);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_ga5_gc_gs3_p1 (+1);
|
||||
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_ga5_gs3_gc_m1 (-1);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_ga5_gs3_gc_0 ( 0);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_ga5_gs3_gc_p1 (+1);
|
||||
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gs3_gc_ga5_m1 (-1);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gs3_gc_ga5_0 ( 0);
|
||||
memset (ga5, 0, sizeof ga5);
|
||||
min_4_gs3_gc_ga5_p1 (+1);
|
||||
}
|
@ -40,12 +40,12 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "\\*r_\[0-9\]* = 0;" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "\\*r_\[0-9\]* = 0;" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "return 3;" 1 "optimized" } } */
|
||||
/* { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */
|
||||
|
@ -98,10 +98,10 @@ main ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 5 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen \\(" 5 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "return 4;" 1 "optimized" } } */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* This is a replacement of needed parts from stdlib.h and string.h
|
||||
/* This is a replacement of needed parts from <stdlib.h> and <string.h>
|
||||
for -foptimize-strlen testing, to ensure we are testing the builtins
|
||||
rather than whatever the OS has in its headers. */
|
||||
|
||||
@ -25,6 +25,9 @@ void *mempcpy (void *__restrict, const void *__restrict, size_t);
|
||||
char *stpcpy (char *__restrict, const char *__restrict);
|
||||
#endif
|
||||
|
||||
int sprintf (char * __restrict, const char *__restrict, ...);
|
||||
int snprintf (char * __restrict, size_t, const char *__restrict, ...);
|
||||
|
||||
#if defined(FORTIFY_SOURCE) && FORTIFY_SOURCE > 0 && __OPTIMIZE__
|
||||
# define bos(ptr) __builtin_object_size (ptr, FORTIFY_SOURCE > 0)
|
||||
# define bos0(ptr) __builtin_object_size (ptr, 0)
|
||||
|
139
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-6.c
Normal file
139
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-6.c
Normal file
@ -0,0 +1,139 @@
|
||||
/* Test to verify that snprintf can determine the length of a dynamically
|
||||
constructed string argument and fold the result into a constant.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -fdump-tree-optimized" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
char* strcpy (char * restrict, const char * restrict);
|
||||
int sprintf (char * restrict, const char *restrict, ...);
|
||||
int snprintf (char * restrict, size_t, const char *restrict, ...);
|
||||
|
||||
|
||||
#define CONCAT(x, y) x ## y
|
||||
#define CAT(x, y) CONCAT (x, y)
|
||||
#define FAILNAME(name, counter) \
|
||||
CAT (CAT (CAT (call_ ## name ##_on_line_, __LINE__), _), counter)
|
||||
|
||||
#define FAIL(name, counter) do { \
|
||||
extern void FAILNAME (name, counter) (void); \
|
||||
FAILNAME (name, counter)(); \
|
||||
} while (0)
|
||||
|
||||
/* Macro to emit a call to funcation named
|
||||
call_in_true_branch_not_eliminated_on_line_NNN()
|
||||
for each call that's expected to be eliminated. The dg-final
|
||||
scan-tree-dump-time directive at the bottom of the test verifies
|
||||
that no such call appears in output. */
|
||||
#define ELIM(expr) \
|
||||
if (!(expr)) FAIL (in_true_branch_not_eliminated, __COUNTER__); else (void)0
|
||||
|
||||
#define ARGS(...) __VA_ARGS__
|
||||
|
||||
#define T(expect, init, fmt, ...) \
|
||||
do { \
|
||||
char a[] = init; \
|
||||
ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
|
||||
} while (0)
|
||||
|
||||
/* Exercise a non-const local char array initialized by a string literal. */
|
||||
void test_assign_string (void)
|
||||
{
|
||||
T (0, "", "%s", a);
|
||||
T (1, "1", "%s", a);
|
||||
T (4, "1234", "%s", a);
|
||||
T (5, "123", "s=%s", a);
|
||||
T (5, "1234", "s=%s", a + 1);
|
||||
T (2, "1234", "s=%s", a + 4);
|
||||
T (5, "12345", "s=%s", &a[2]);
|
||||
T (5, "123456", "s=%.*s", 3, &a[2]);
|
||||
}
|
||||
|
||||
/* Exercise a non-const local char array initialized by an initializer
|
||||
list. */
|
||||
void test_assign_init_list (void)
|
||||
{
|
||||
T (0, ARGS ({ 0 }), "%s", a);
|
||||
T (1, ARGS ({ 1, 0 }), "%s", a);
|
||||
T (3, ARGS ({ [3] = 0, [1] = 2, [0] = 1, [2] = 3 }), "%s", a);
|
||||
T (3, ARGS ({ [3] = 0, [1] = 2, [0] = 1, [2] = 3, [4] = 0 }), "%s", a);
|
||||
T (4, ARGS ({ 1, 2, 3, 4, 0 }), "%s", a);
|
||||
T (5, ARGS ({ 1, 2, 3, 0 }), "s=%s", a);
|
||||
T (5, ARGS ({ 1, 2, 3, 4, 0 }), "s=%s", a + 1);
|
||||
T (2, ARGS ({ 1, 2, 3, 4, 0 }), "s=%s", a + 4);
|
||||
T (5, ARGS ({ 1, 2, 3, 4, 5, 0 }), "s=%s", &a[2]);
|
||||
T (5, ARGS ({ 1, 2, 3, 4, 5, 6, 0 }), "s=%.*s", 3, &a[2]);
|
||||
}
|
||||
|
||||
#undef T
|
||||
#define T(expect, init, fmt, ...) \
|
||||
do { \
|
||||
struct { int n; char a[sizeof init]; } \
|
||||
s = { sizeof init, init }; \
|
||||
ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
|
||||
} while (0)
|
||||
|
||||
/* Exercise a non-const local struct initialized by an initializer
|
||||
list. */
|
||||
void test_assign_aggregate (void)
|
||||
{
|
||||
T (0, "", "%s", s.a);
|
||||
T (1, "1", "%s", s.a);
|
||||
T (4, "1234", "%s", s.a);
|
||||
T (5, "123", "s=%s", s.a);
|
||||
T (5, "1234", "s=%s", s.a + 1);
|
||||
T (2, "1234", "s=%s", s.a + 4);
|
||||
T (5, "12345", "s=%s", &s.a[2]);
|
||||
T (5, "123456", "s=%.*s", 3, &s.a[2]);
|
||||
}
|
||||
|
||||
|
||||
#undef T
|
||||
#define T(expect, init, fmt, ...) \
|
||||
do { \
|
||||
char a[sizeof init]; \
|
||||
strcpy (a, init); \
|
||||
ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
|
||||
} while (0)
|
||||
|
||||
/* Exercise a local char array initialized by a call to strcpy. */
|
||||
void test_local_strcpy (void)
|
||||
{
|
||||
T (0, "", "%s", a);
|
||||
T (1, "1", "%s", a);
|
||||
T (2, "12", "%s", a);
|
||||
T (3, "123", "%s", a);
|
||||
T (4, "1234", "%s", a);
|
||||
T (5, "123", "s=%s", a);
|
||||
T (5, "1234", "s=%s", a + 1);
|
||||
T (2, "1234", "s=%s", a + 4);
|
||||
T (5, "12345", "s=%s", &a[2]);
|
||||
T (5, "123456", "s=%.*s", 3, &a[2]);
|
||||
}
|
||||
|
||||
#undef T
|
||||
#define T(expect, init, fmt, ...) \
|
||||
do { \
|
||||
char a[n]; \
|
||||
strcpy (a, init); \
|
||||
ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
|
||||
} while (0)
|
||||
|
||||
/* Exercise a VLA initialized by a call to strcpy. */
|
||||
void test_vla_strcpy (unsigned n)
|
||||
{
|
||||
T (0, "", "%s", a);
|
||||
T (1, "1", "%s", a);
|
||||
T (2, "12", "%s", a);
|
||||
T (3, "123", "%s", a);
|
||||
T (4, "1234", "%s", a);
|
||||
T (5, "123", "s=%s", a);
|
||||
T (5, "1234", "s=%s", a + 1);
|
||||
T (2, "1234", "s=%s", a + 4);
|
||||
T (5, "12345", "s=%s", &a[2]);
|
||||
T (5, "123456", "s=%.*s", 3, &a[2]);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "printf" 0 "optimized" } }
|
||||
{ dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
|
||||
{ dg-final { scan-tree-dump-times "not_eliminated" 0 "optimized" } } */
|
152
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-7.c
Normal file
152
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-7.c
Normal file
@ -0,0 +1,152 @@
|
||||
/* Test to verify that snprintf can determine the correct range
|
||||
of lengths of dynamically constructed string arguments.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -fdump-tree-optimized" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
void* memcpy (void*, const void*, size_t);
|
||||
|
||||
char* strcpy (char * restrict, const char * restrict);
|
||||
int snprintf (char * restrict, size_t, const char *restrict, ...);
|
||||
|
||||
void sink (void*, ...);
|
||||
|
||||
#define CONCAT(x, y) x ## y
|
||||
#define CAT(x, y) CONCAT (x, y)
|
||||
#define FAILNAME(name, counter) \
|
||||
CAT (CAT (CAT (call_ ## name ##_on_line_, __LINE__), _), counter)
|
||||
|
||||
#define FAIL(name, counter) do { \
|
||||
extern void FAILNAME (name, counter) (void); \
|
||||
FAILNAME (name, counter)(); \
|
||||
} while (0)
|
||||
|
||||
/* Macro to emit a call to funcation named
|
||||
call_in_true_branch_not_eliminated_on_line_NNN()
|
||||
for each call that's expected to be eliminated. The dg-final
|
||||
scan-tree-dump-time directive at the bottom of the test verifies
|
||||
that no such call appears in output. */
|
||||
#define VERIFY_ELIM(expr) \
|
||||
if (!(expr)) FAIL (in_true_branch_not_eliminated, __COUNTER__); else (void)0
|
||||
|
||||
/* Macro to emit a call to a function named
|
||||
call_made_in_{true,false}_branch_on_line_NNN()
|
||||
for each call that's expected to be retained. The dg-final
|
||||
scan-tree-dump-time directive at the bottom of the test verifies
|
||||
that the expected number of both kinds of calls appears in output
|
||||
(a pair for each line with the invocation of the KEEP() macro. */
|
||||
#define VERIFY_KEEP(expr) \
|
||||
if (expr) \
|
||||
FAIL (made_in_true_branch, __COUNTER__); \
|
||||
else \
|
||||
FAIL (made_in_false_branch, __COUNTER__)
|
||||
|
||||
#define ARGS(...) __VA_ARGS__
|
||||
|
||||
/* Each test macro expands to a new function to get around bug 81776
|
||||
- missing sprintf optimization due to pointer escape analysis. */
|
||||
#define ELIM(expect, dst, init, fmt, ...) \
|
||||
void CAT (test_func_on_line_, __LINE__)(void) \
|
||||
{ \
|
||||
memcpy (dst, init, sizeof (init) - 1); \
|
||||
const int res = snprintf (0, 0, fmt, __VA_ARGS__); \
|
||||
VERIFY_ELIM (expect res); \
|
||||
} typedef void dummy_typedef
|
||||
|
||||
#define KEEP(expect, dst, init, fmt, ...) \
|
||||
void CAT (test_func_on_line_, __LINE__)(void) \
|
||||
{ \
|
||||
memcpy (dst, init, sizeof (init) - 1); \
|
||||
const int ret = snprintf (0, 0, fmt, __VA_ARGS__); \
|
||||
VERIFY_KEEP (expect ret); \
|
||||
} typedef void dummy_typedef
|
||||
|
||||
|
||||
/* Verify that conditions involving snprintf calls with a string
|
||||
of some minimum but otherwise unbounded length stored in an array
|
||||
of unknown bound are not folded unless the format string itself
|
||||
restricts the maximum. The string could be longer than INT_MAX
|
||||
making the snprintf call fail and return a negative value. */
|
||||
|
||||
extern char gax[];
|
||||
|
||||
KEEP (1 <=, gax, "1", "%s", gax);
|
||||
KEEP (2 <=, gax, "12", "%s", gax);
|
||||
KEEP (3 <=, gax, "123", "%s", gax);
|
||||
|
||||
ELIM (3 ==, gax, "123", "%.3s", gax);
|
||||
ELIM (5 ==, gax, "123", "%.3s%.2s", gax, gax);
|
||||
|
||||
|
||||
/* Disabled. The global pointer passed to memcpy as the destination
|
||||
might point at itself, i.e., gptr == &gptr is a valid argument to
|
||||
memcpy.
|
||||
|
||||
extern char *gptr;
|
||||
|
||||
KEEP (1 <=, gptr, "1", "%s", gptr);
|
||||
KEEP (2 <=, gptr, "12", "%s", gptr);
|
||||
KEEP (3 <=, gptr, "123", "%s", gptr);
|
||||
|
||||
ELIM (3 ==, gptr, "123", "%.3s", gptr);
|
||||
ELIM (5 ==, gptr, "123", "%.3s%.2s", gptr, gptr);
|
||||
|
||||
*/
|
||||
|
||||
/* Verify that conditions involving snprintf calls with a string
|
||||
of some minimum but otherwise unbounded length stored in an array
|
||||
of a known bound are folded. The longest string that can be
|
||||
stored in such arrays is bounded by the size of the array. */
|
||||
|
||||
extern char ga4[4];
|
||||
|
||||
ELIM (0 <=, ga4, "\0", "%s", ga4);
|
||||
ELIM (3 >=, ga4, "\0", "%s", ga4);
|
||||
|
||||
ELIM (1 <=, ga4, "1", "%s", ga4);
|
||||
ELIM (0 <=, ga4, "1", "%s", ga4 + 1);
|
||||
ELIM (0 <=, ga4, "1", "%s", &ga4[1]);
|
||||
|
||||
ELIM (3 >=, ga4, "1", "%s", ga4);
|
||||
ELIM (2 >=, ga4, "1", "%s", ga4 + 1);
|
||||
ELIM (2 >=, ga4, "1", "%s", &ga4[1]);
|
||||
|
||||
ELIM (2 <=, ga4, "12", "%s", ga4);
|
||||
ELIM (3 >=, ga4, "12", "%s", ga4);
|
||||
|
||||
ELIM (3 <=, ga4, "123", "%s", ga4);
|
||||
ELIM (3 ==, ga4, "123", "%.3s", ga4);
|
||||
ELIM (5 ==, ga4, "123", "%.3s%.2s", ga4, ga4);
|
||||
|
||||
/* Verify conditionals involving dynamically created strings of known
|
||||
length stored in local arrays. */
|
||||
|
||||
#undef ELIM
|
||||
#define ELIM(expect, N1, N2, init1, init2, fmt, ...) \
|
||||
void CAT (test_func_on_line_, __LINE__)(int i) \
|
||||
{ \
|
||||
char a1[N1], a2[N2]; \
|
||||
memcpy (a1, init1, sizeof (init1) - 1); \
|
||||
memcpy (a2, init2, sizeof (init2) - 1); \
|
||||
const int res = snprintf (0, 0, fmt, __VA_ARGS__); \
|
||||
VERIFY_ELIM (expect res); \
|
||||
} typedef void dummy_typedef
|
||||
|
||||
ELIM (0 ==, 2, 2, "\0", "\0", "%s", i ? a1 : a2);
|
||||
ELIM (2 ==, 2, 2, "\0", "\0", "s=%s", i ? a1 : a2);
|
||||
|
||||
ELIM (1 ==, 2, 2, "a\0", "b\0", "%s", i ? a1 : a2);
|
||||
ELIM (3 ==, 2, 2, "a\0", "b\0", "s=%s", i ? a1 : a2);
|
||||
|
||||
ELIM (2 ==, 3, 5, "ab\0", "cd\0", "%s", i ? a1 : a2);
|
||||
ELIM (3 ==, 3, 5, "ab\0", "cd\0", "%3s", i ? a1 : a2);
|
||||
ELIM (3 ==, 5, 5, "abcd\0", "efgh\0", "%.3s", i ? a1 : a2);
|
||||
|
||||
ELIM (3 ==, 4, 1, "abc\0", "", "%s", i ? a1 : "def");
|
||||
ELIM (4 ==, 1, 5, "", "efgh\0", "%s", i ? "abcd" : a2);
|
||||
|
||||
ELIM (4 ==, 5, 5, "abcd\0", "efgh\0", "%s", i < 0 ? a1 : 0 < i ? a2 : "ijkl");
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "_not_eliminated" 0 "optimized" } }
|
||||
{ dg-final { scan-tree-dump-times "call_made_" 6 "optimized" } } */
|
41
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-8.c
Normal file
41
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-8.c
Normal file
@ -0,0 +1,41 @@
|
||||
/* Test to verify that snprintf can determine the correct range
|
||||
of lengths of string arguments based on the results of prior
|
||||
calls to strlen.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -fdump-tree-optimized" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
void abort (void);
|
||||
size_t strlen (const char *);
|
||||
int snprintf (char * restrict, size_t, const char *restrict, ...);
|
||||
|
||||
void one_str_exact (const char *str)
|
||||
{
|
||||
if (1 == strlen (str))
|
||||
if (1 != snprintf (0, 0, "%s", str))
|
||||
abort ();
|
||||
}
|
||||
|
||||
void two_str_exact (const char *s1, const char *s2)
|
||||
{
|
||||
if (1 == strlen (s1) && 2 == strlen (s2))
|
||||
if (3 != snprintf (0, 0, "%s%s", s1, s2))
|
||||
abort ();
|
||||
}
|
||||
|
||||
void one_str_maxlen (const char *str)
|
||||
{
|
||||
if (2 >= strlen (str))
|
||||
if (2 < snprintf (0, 0, "%s", str))
|
||||
abort ();
|
||||
}
|
||||
|
||||
void two_str_maxlen (const char *s1, const char *s2)
|
||||
{
|
||||
if (2 >= strlen (s1) && 3 >= strlen (s2))
|
||||
if (5 < snprintf (0, 0, "%s%s", s1, s2))
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
|
163
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-9.c
Normal file
163
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-9.c
Normal file
@ -0,0 +1,163 @@
|
||||
/* Test to verify that --param ssa_name_def_chain_limit can be used to
|
||||
limit the maximum number of SSA_NAME assignments the built-in code
|
||||
follows to determine the variable value/string length.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall --param ssa-name-def-chain-limit=4 -fdump-tree-optimized" } */
|
||||
|
||||
void abort (void);
|
||||
int sprintf (char * restrict, const char *restrict, ...);
|
||||
|
||||
void sink (const char*, ...);
|
||||
|
||||
const char a0[] = "";
|
||||
const char a1[] = "1";
|
||||
const char a2[] = "12";
|
||||
const char a3[] = "123";
|
||||
const char a4[] = "1234";
|
||||
const char a5[] = "12345";
|
||||
const char a6[] = "123456";
|
||||
const char a7[] = "1234567";
|
||||
const char a8[] = "12345678";
|
||||
const char a9[] = "123456789";
|
||||
|
||||
int i0, i1, i2, i3, i4, i5, i6, i7, i8;
|
||||
|
||||
void g1 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
|
||||
sink (p0, p1);
|
||||
|
||||
if (sprintf (d, "%s", p1) > 2)
|
||||
abort ();
|
||||
}
|
||||
|
||||
void g2 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
|
||||
sink (p0, p1, p2);
|
||||
|
||||
if (sprintf (d, "%s", p2) > 3)
|
||||
abort ();
|
||||
}
|
||||
|
||||
void g3 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
|
||||
sink (p0, p1, p2, p3);
|
||||
|
||||
if (sprintf (d, "%s", p3) > 4)
|
||||
abort ();
|
||||
}
|
||||
|
||||
void g4 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
|
||||
sink (p0, p1, p2, p3, p4);
|
||||
|
||||
// p4 below is the result of the following five PHI assignments
|
||||
// and with the limit set to 4 the sprintf call result is not
|
||||
// determined:
|
||||
// iftmp.0_7 = PHI <&a0(2), &a1(3)>
|
||||
// iftmp.2_8 = PHI <iftmp.0_7(4), &a2(5)>
|
||||
// iftmp.4_9 = PHI <iftmp.2_8(6), &a3(7)>
|
||||
// iftmp.6_10 = PHI <iftmp.4_9(8), &a4(9)>
|
||||
// iftmp.8_17 = PHI <iftmp.6_10(10), &a5(11)>
|
||||
// p4 = iftmp.8_17
|
||||
extern void keep_g4 (void);
|
||||
if (sprintf (d, "%s", p4) > 5)
|
||||
keep_g4 ();
|
||||
}
|
||||
|
||||
void g5 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
const char *p5 = i5 ? p4 : a6;
|
||||
|
||||
sink (p0, p1, p2, p3, p4, p5);
|
||||
|
||||
extern void keep_g5 (void);
|
||||
if (sprintf (d, "%s", p5) > 6)
|
||||
keep_g5 ();
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "keep_g5" 1 "optimized" } } */
|
||||
}
|
||||
|
||||
void g6 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
const char *p5 = i5 ? p4 : a6;
|
||||
const char *p6 = i6 ? p5 : a7;
|
||||
|
||||
sink (p0, p1, p2, p3, p4, p5, p6);
|
||||
|
||||
extern void keep_g6 (void);
|
||||
if (sprintf (d, "%s", p6) > 7)
|
||||
keep_g6 ();
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "keep_g6" 1 "optimized" } } */
|
||||
}
|
||||
|
||||
void g7 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
const char *p5 = i5 ? p4 : a6;
|
||||
const char *p6 = i6 ? p5 : a7;
|
||||
const char *p7 = i7 ? p6 : a8;
|
||||
|
||||
sink (p0, p1, p2, p3, p4, p5, p6, p7);
|
||||
|
||||
extern void keep_g7 (void);
|
||||
if (sprintf (d, "%s", p7) > 8)
|
||||
keep_g7 ();
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "keep_g7" 1 "optimized" } } */
|
||||
}
|
||||
|
||||
void g8 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
const char *p5 = i5 ? p4 : a6;
|
||||
const char *p6 = i6 ? p5 : a7;
|
||||
const char *p7 = i7 ? p6 : a8;
|
||||
const char *p8 = i8 ? p7 : a9;
|
||||
|
||||
sink (p0, p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
|
||||
extern void keep_g8 (void);
|
||||
if (sprintf (d, "%s", p8) > 9)
|
||||
keep_g8 ();
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "keep_g8" 1 "optimized" } } */
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
|
140
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-5.c
Normal file
140
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-5.c
Normal file
@ -0,0 +1,140 @@
|
||||
/* Test to verify that --param ssa_name_def_chain_limit can be used to
|
||||
limit the maximum number of SSA_NAME assignments the built-in code
|
||||
follows.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -Wformat-truncation=2 --param ssa-name-def-chain-limit=4 -fdump-tree-optimized" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
int snprintf (char * restrict, size_t, const char *restrict, ...);
|
||||
|
||||
void sink (const char*, ...);
|
||||
|
||||
const char a0[] = "";
|
||||
const char a1[] = "1";
|
||||
const char a2[] = "12";
|
||||
const char a3[] = "123";
|
||||
const char a4[] = "1234";
|
||||
const char a5[] = "12345";
|
||||
const char a6[] = "123456";
|
||||
const char a7[] = "1234567";
|
||||
const char a8[] = "12345678";
|
||||
const char a9[] = "123456789";
|
||||
|
||||
int i0, i1, i2, i3, i4, i5, i6, i7, i8;
|
||||
|
||||
void g1 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
|
||||
sink (p0, p1);
|
||||
|
||||
snprintf (d, 1, "%s", p1); // { dg-warning "\\\[-Wformat-truncation" }
|
||||
}
|
||||
|
||||
void g2 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
|
||||
sink (p0, p1, p2);
|
||||
|
||||
snprintf (d, 2, "%s", p2); // { dg-warning "\\\[-Wformat-truncation" }
|
||||
}
|
||||
|
||||
void g3 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
|
||||
sink (p0, p1, p2, p3);
|
||||
|
||||
snprintf (d, 3, "%s", p3); // { dg-warning "\\\[-Wformat-truncation" }
|
||||
}
|
||||
|
||||
void g4 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
|
||||
sink (p0, p1, p2, p3, p4);
|
||||
|
||||
// p4 below is the result of the following five PHI assignments
|
||||
// and with the limit set to 4 the snprintf call is not diagnosed
|
||||
// iftmp.0_7 = PHI <&a0(2), &a1(3)>
|
||||
// iftmp.2_8 = PHI <iftmp.0_7(4), &a2(5)>
|
||||
// iftmp.4_9 = PHI <iftmp.2_8(6), &a3(7)>
|
||||
// iftmp.6_10 = PHI <iftmp.4_9(8), &a4(9)>
|
||||
// iftmp.8_17 = PHI <iftmp.6_10(10), &a5(11)>
|
||||
// p4 = iftmp.8_17
|
||||
snprintf (d, 4, "%s", p4);
|
||||
}
|
||||
|
||||
void g5 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
const char *p5 = i5 ? p4 : a6;
|
||||
|
||||
sink (p0, p1, p2, p3, p4, p5);
|
||||
|
||||
snprintf (d, 5, "%s", p5);
|
||||
}
|
||||
|
||||
void g6 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
const char *p5 = i5 ? p4 : a6;
|
||||
const char *p6 = i6 ? p5 : a7;
|
||||
|
||||
sink (p0, p1, p2, p3, p4, p5, p6);
|
||||
|
||||
snprintf (d, 6, "%s", p6);
|
||||
}
|
||||
|
||||
void g7 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
const char *p5 = i5 ? p4 : a6;
|
||||
const char *p6 = i6 ? p5 : a7;
|
||||
const char *p7 = i7 ? p6 : a8;
|
||||
|
||||
sink (p0, p1, p2, p3, p4, p5, p6, p7);
|
||||
|
||||
snprintf (d, 7, "%s", p7);
|
||||
}
|
||||
|
||||
void g8 (char *d)
|
||||
{
|
||||
const char *p0 = i0 ? a0 : a1;
|
||||
const char *p1 = i1 ? p0 : a2;
|
||||
const char *p2 = i2 ? p1 : a3;
|
||||
const char *p3 = i3 ? p2 : a4;
|
||||
const char *p4 = i4 ? p3 : a5;
|
||||
const char *p5 = i5 ? p4 : a6;
|
||||
const char *p6 = i6 ? p5 : a7;
|
||||
const char *p7 = i7 ? p6 : a8;
|
||||
const char *p8 = i8 ? p7 : a9;
|
||||
|
||||
sink (p0, p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
|
||||
snprintf (d, 8, "%s", p8);
|
||||
}
|
94
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-21.c
Normal file
94
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-21.c
Normal file
@ -0,0 +1,94 @@
|
||||
/* PR tree-optimization/83431 -Wformat-truncation may incorrectly report
|
||||
truncation
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
extern int snprintf (char*, size_t, const char*, ...);
|
||||
extern char* strcpy (char*, const char*);
|
||||
|
||||
struct S
|
||||
{
|
||||
char a9[9];
|
||||
char a5[5];
|
||||
int x;
|
||||
};
|
||||
|
||||
|
||||
void test_assign_nowarn (struct S* s)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
{
|
||||
char a9[9] = "1234";
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s", a9); /* { dg-bogus "\\\[-Wformat-truncation]" } */
|
||||
}
|
||||
|
||||
{
|
||||
++i;
|
||||
char a8[8] = "123";
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s\n", a8); /* { dg-bogus "\\\[-Wformat-truncation]" } */
|
||||
}
|
||||
|
||||
{
|
||||
++i;
|
||||
char a7[7] = "12";
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "[%s]", a7); /* { dg-bogus "\\\[-Wformat-truncation]" } */
|
||||
}
|
||||
|
||||
{
|
||||
++i;
|
||||
char a6[6] = "1";
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "[%s]\n", a6); /* { dg-bogus "\\\[-Wformat-truncation]" } */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_strcpy_nowarn (struct S* s)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
strcpy (s[i].a9, "1234");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s", s[i].a9);
|
||||
|
||||
++i;
|
||||
strcpy (s[i].a9, "123");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s\n", s[i].a9); /* { dg-bogus "\\\[-Wformat-truncation]" } */
|
||||
|
||||
++i;
|
||||
strcpy (s[i].a9, "12");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "[%s]", s[i].a9); /* { dg-bogus "\\\[-Wformat-truncation]" } */
|
||||
|
||||
++i;
|
||||
strcpy (s[i].a9, "1");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "[%s]\n", s[i].a9); /* { dg-bogus "\\\[-Wformat-truncation]" } */
|
||||
}
|
||||
|
||||
|
||||
void test_warn (struct S* s)
|
||||
{
|
||||
int i = 0;
|
||||
strcpy (s[i].a9, "12345678");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s", s[i].a9); /* { dg-warning "'%s' directive output truncated writing 8 bytes into a region of size 5" } */
|
||||
|
||||
++i;
|
||||
strcpy (s[i].a9, "1234567");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s", s[i].a9); /* { dg-warning "'%s' directive output truncated writing 7 bytes into a region of size 5" } */
|
||||
|
||||
++i;
|
||||
strcpy (s[i].a9, "123456");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s", s[i].a9); /* { dg-warning "'%s' directive output truncated writing 6 bytes into a region of size 5" } */
|
||||
|
||||
++i;
|
||||
strcpy (s[i].a9, "12345");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s", s[i].a9); /* { dg-warning "'snprintf' output truncated before the last format character" } */
|
||||
|
||||
++i;
|
||||
strcpy (s[i].a9, "1234");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), "%s\n", s[i].a9); /* { dg-warning "output truncated before the last format character" } */
|
||||
|
||||
++i;
|
||||
strcpy (s[i].a9, "123");
|
||||
snprintf (s[i].a5, sizeof (s[i].a5), ">%s<", s[i].a9); /* { dg-warning "output truncated before the last format character" } */
|
||||
}
|
11
gcc/testsuite/gcc.dg/tree-ssa/dump-4.c
Normal file
11
gcc/testsuite/gcc.dg/tree-ssa/dump-4.c
Normal file
@ -0,0 +1,11 @@
|
||||
/* PR middle-end/87052 - STRING_CST printing incomplete in Gimple dumps
|
||||
{ dg-do compile }
|
||||
{ dg-options "-fdump-tree-original" } */
|
||||
|
||||
void* f (char *d, int c)
|
||||
{
|
||||
return __builtin_memchr ("1\0\0", c, 4);
|
||||
}
|
||||
|
||||
/* Veriy the full string appears in the dump:
|
||||
{ dg-final { scan-tree-dump "\"1\\\\x00\\\\x00\"" "original" } } */
|
@ -11,4 +11,4 @@ void f (void)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "__builtin_strlen" "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-not "__builtin_strlen" "strlen1" } } */
|
||||
|
@ -12,4 +12,4 @@ void f3 (void)
|
||||
f (__builtin_strlen (s));
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "strlen" } } */
|
||||
/* { dg-final { scan-tree-dump-times "strlen" 0 "strlen1" } } */
|
||||
|
@ -419,6 +419,7 @@ extern gimple_opt_pass *make_pass_omp_target_link (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_oacc_device_lower (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_omp_device_lower (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_object_sizes (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_warn_printf (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_strlen (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_fold_builtins (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_post_ipa_warn (gcc::context *ctxt);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,4 +25,11 @@ extern bool is_strlen_related_p (tree, tree);
|
||||
extern bool maybe_diag_stxncpy_trunc (gimple_stmt_iterator, tree, tree);
|
||||
extern tree set_strlen_range (tree, wide_int, wide_int, tree = NULL_TREE);
|
||||
|
||||
struct c_strlen_data;
|
||||
class vr_values;
|
||||
extern void get_range_strlen_dynamic (tree , c_strlen_data *, const vr_values *);
|
||||
|
||||
/* APIs internal to strlen pass. Defined in in gimple-ssa-sprintf.c. */
|
||||
extern bool handle_printf_call (gimple_stmt_iterator *, const vr_values *);
|
||||
|
||||
#endif // GCC_TREE_SSA_STRLEN_H
|
||||
|
@ -369,7 +369,7 @@ value_range_base::singleton_p (tree *result) const
|
||||
tree
|
||||
value_range_base::type () const
|
||||
{
|
||||
gcc_assert (m_min || undefined_p ());
|
||||
gcc_assert (m_min);
|
||||
return TREE_TYPE (min ());
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ vr_values::update_value_range (const_tree var, value_range *new_vr)
|
||||
called, if we are anyway, keep it VARYING. */
|
||||
if (old_vr->varying_p ())
|
||||
{
|
||||
new_vr->set_varying (new_vr->type ());
|
||||
new_vr->set_varying (TREE_TYPE (var));
|
||||
is_new = false;
|
||||
}
|
||||
else if (new_vr->undefined_p ())
|
||||
|
Loading…
x
Reference in New Issue
Block a user