PR tree-optimization/78913 - Probably misleading error reported by -Wformat-length

PR tree-optimization/78913 - Probably misleading error reported by -Wformat-length
PR middle-end/77708 - -Wformat-length %s warns for snprintf

gcc/ChangeLog:

	PR middle-end/77708
	* doc/invoke.texi (Warning Options): Document -Wformat-truncation.
	* gimple-ssa-sprintf.c (call_info::reval_used, call_info::warnopt):
	New member functions.
	(format_directive): Used them.
	(add_bytes): Same.
	(pass_sprintf_length::handle_gimple_call): Same.
	* graphite-sese-to-poly.c (tree_int_to_gmp): Increase buffer size
	to avoid truncation for any argument.
	(extract_affine_mul): Same.
	* tree.c (get_file_function_name): Same.

gcc/c-family/ChangeLog:

	PR middle-end/77708
	* c.opt (-Wformat-truncation): New option.

gcc/fortran/ChangeLog:

	PR tree-optimization/78913
	PR middle-end/77708
	* trans-common.c (build_equiv_decl): Increase buffer size to avoid
	truncation for any argument.
	* trans-types.c (gfc_build_logical_type): Same.

gcc/testsuite/ChangeLog:

	PR middle-end/77708
	* gcc.dg/tree-ssa/builtin-snprintf-warn-1.c: New test.
	* gcc.dg/tree-ssa/builtin-snprintf-warn-2.c: New test.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-6.c: XFAIL test cases failing
	due to bug 78969.
	* gcc.dg/format/pr78569.c: Adjust.

From-SVN: r244210
This commit is contained in:
Martin Sebor 2017-01-08 23:42:09 +00:00 committed by Martin Sebor
parent 1243c42d64
commit efcc8d387f
15 changed files with 304 additions and 73 deletions

View File

@ -1,3 +1,17 @@
2017-01-08 Martin Sebor <msebor@redhat.com>
PR middle-end/77708
* doc/invoke.texi (Warning Options): Document -Wformat-truncation.
* gimple-ssa-sprintf.c (call_info::reval_used, call_info::warnopt):
New member functions.
(format_directive): Used them.
(add_bytes): Same.
(pass_sprintf_length::handle_gimple_call): Same.
* graphite-sese-to-poly.c (tree_int_to_gmp): Increase buffer size
to avoid truncation for any argument.
(extract_affine_mul): Same.
* tree.c (get_file_function_name): Same.
2017-01-01 Jan Hubicka <hubicka@ucw.cz>
PR middle-end/77484

View File

@ -1,3 +1,8 @@
2017-01-08 Martin Sebor <msebor@redhat.com>
PR middle-end/77708
* c.opt (-Wformat-truncation): New option.
2017-01-06 Alexandre Oliva <aoliva@redhat.com>
* c-pretty-print.c (pp_c_tree_decl_identifier): Convert 16-bit

View File

@ -537,6 +537,11 @@ Wformat-signedness
C ObjC C++ ObjC++ Var(warn_format_signedness) Warning
Warn about sign differences with format functions.
Wformat-truncation
C ObjC C++ ObjC++ Warning Alias(Wformat-truncation=, 1, 0)
Warn about calls to snprintf and similar functions that truncate output.
Same as -Wformat-truncation=1.
Wformat-y2k
C ObjC C++ ObjC++ Var(warn_format_y2k) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=,warn_format >= 2, 0)
Warn about strftime formats yielding 2-digit years.
@ -554,6 +559,10 @@ C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_length) Warning
Warn about function calls with format strings that write past the end
of the destination region.
Wformat-truncation=
C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
Warn about calls to snprintf and similar functions that truncate output.
Wignored-qualifiers
C C++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra)
Warn whenever type qualifiers are ignored.

View File

@ -276,7 +276,8 @@ Objective-C and Objective-C++ Dialects}.
-Werror -Werror=* -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol
-Wno-format-contains-nul -Wno-format-extra-args -Wformat-length=@var{n} @gol
-Wformat-nonliteral @gol
-Wformat-security -Wformat-signedness -Wformat-y2k -Wframe-address @gol
-Wformat-security -Wformat-signedness -Wformat-truncation=@var{n} @gol
-Wformat-y2k -Wframe-address @gol
-Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol
-Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol
-Wimplicit -Wimplicit-fallthrough -Wimplicit-fallthrough=@var{n} @gol
@ -3959,10 +3960,9 @@ Unix Specification says that such unused arguments are allowed.
@opindex Wformat-length
@opindex Wno-format-length
Warn about calls to formatted input/output functions such as @code{sprintf}
that might overflow the destination buffer, or about bounded functions such
as @code{snprintf} that might result in output truncation. When the exact
number of bytes written by a format directive cannot be determined at
compile-time it is estimated based on heuristics that depend on the
and @code{vsprintf} that might overflow the destination buffer. When the
exact number of bytes written by a format directive cannot be determined
at compile-time it is estimated based on heuristics that depend on the
@var{level} argument and on optimization. While enabling optimization
will in most cases improve the accuracy of the warning, it may also
result in false positives.
@ -3974,15 +3974,14 @@ result in false positives.
@opindex Wno-format-length
Level @var{1} of @option{-Wformat-length} enabled by @option{-Wformat}
employs a conservative approach that warns only about calls that most
likely overflow the buffer or result in output truncation. At this
level, numeric arguments to format directives with unknown values are
assumed to have the value of one, and strings of unknown length to be
empty. Numeric arguments that are known to be bounded to a subrange
of their type, or string arguments whose output is bounded either by
their directive's precision or by a finite set of string literals, are
assumed to take on the value within the range that results in the most
bytes on output. For example, the call to @code{sprintf} below is
diagnosed because even with both @var{a} and @var{b} equal to zero,
likely overflow the buffer. At this level, numeric arguments to format
directives with unknown values are assumed to have the value of one, and
strings of unknown length to be empty. Numeric arguments that are known
to be bounded to a subrange of their type, or string arguments whose output
is bounded either by their directive's precision or by a finite set of
string literals, are assumed to take on the value within the range that
results in the most bytes on output. For example, the call to @code{sprintf}
below is diagnosed because even with both @var{a} and @var{b} equal to zero,
the terminating NUL character (@code{'\0'}) appended by the function
to the destination buffer will be written past its end. Increasing
the size of the buffer by a single byte is sufficient to avoid the
@ -3998,14 +3997,13 @@ void f (int a, int b)
@item -Wformat-length=2
Level @var{2} warns also about calls that might overflow the destination
buffer or result in truncation given an argument of sufficient length
or magnitude. At level @var{2}, unknown numeric arguments are assumed
to have the minimum representable value for signed types with a precision
greater than 1, and the maximum representable value otherwise. Unknown
string arguments whose length cannot be assumed to be bounded either by
the directive's precision, or by a finite set of string literals they
may evaluate to, or the character array they may point to, are assumed
to be 1 character long.
buffer given an argument of sufficient length or magnitude. At level
@var{2}, unknown numeric arguments are assumed to have the minimum
representable value for signed types with a precision greater than 1, and
the maximum representable value otherwise. Unknown string arguments whose
length cannot be assumed to be bounded either by the directive's precision,
or by a finite set of string literals they may evaluate to, or the character
array they may point to, are assumed to be 1 character long.
At level @var{2}, the call in the example above is again diagnosed, but
this time because with @var{a} equal to a 32-bit @code{INT_MIN} the first
@ -4075,6 +4073,35 @@ included in @option{-Wformat-nonliteral}.)
If @option{-Wformat} is specified, also warn if the format string
requires an unsigned argument and the argument is signed and vice versa.
@item -Wformat-truncation
@itemx -Wformat-truncation=@var{level}
@opindex Wformat-truncation
@opindex Wno-format-truncation
Warn about calls to formatted input/output functions such as @code{snprintf}
and @code{vsnprintf} that might result in output truncation. When the exact
number of bytes written by a format directive cannot be determined at
compile-time it is estimated based on heuristics that depend on
the @var{level} argument and on optimization. While enabling optimization
will in most cases improve the accuracy of the warning, it may also result
in false positives. Except as noted otherwise, the option uses the same
logic @option{-Wformat-length}.
@table @gcctabopt
@item -Wformat-truncation
@item -Wformat-truncation=1
@opindex Wformat-truncation
@opindex Wno-format-length
Level @var{1} of @option{-Wformat-truncation} enabled by @option{-Wformat}
employs a conservative approach that warns only about calls to bounded
functions whose return value is unused and that will most likely result
in output truncatation.
@item -Wformat-truncation=2
Level @var{2} warns also about calls to bounded functions whose return
value is used and that might result in truncation given an argument of
sufficient length or magnitude.
@end table
@item -Wformat-y2k
@opindex Wformat-y2k
@opindex Wno-format-y2k
@ -8429,8 +8456,8 @@ if (snprintf (buf, "%08x", i) >= sizeof buf)
The @option{-fprintf-return-value} option relies on other optimizations
and yields best results with @option{-O2}. It works in tandem with the
@option{-Wformat-length} option. The @option{-fprintf-return-value}
option is enabled by default.
@option{-Wformat-length} and @option{-Wformat-truncation} options.
The @option{-fprintf-return-value} option is enabled by default.
@item -fno-peephole
@itemx -fno-peephole2

View File

@ -1,3 +1,11 @@
2017-01-08 Martin Sebor <msebor@redhat.com>
PR tree-optimization/78913
PR middle-end/77708
* trans-common.c (build_equiv_decl): Increase buffer size to avoid
truncation for any argument.
* trans-types.c (gfc_build_logical_type): Same.
2017-01-07 Andre Vehreschild <vehre@gcc.gnu.org>
PR fortran/78781

View File

@ -342,7 +342,7 @@ static tree
build_equiv_decl (tree union_type, bool is_init, bool is_saved)
{
tree decl;
char name[15];
char name[18];
static int serial = 0;
if (is_init)

View File

@ -861,7 +861,7 @@ gfc_build_logical_type (gfc_logical_info *info)
void
gfc_init_types (void)
{
char name_buf[18];
char name_buf[26];
int index;
tree type;
unsigned n;

View File

@ -718,6 +718,18 @@ struct pass_sprintf_length::call_info
writing any. NOWRITE is cleared in response to the %n directive
which has side-effects similar to writing output. */
bool nowrite;
/* Return true if the called function's return value is used. */
bool retval_used () const
{
return gimple_get_lhs (callstmt);
}
/* Return the warning option corresponding to the called function. */
int warnopt () const
{
return bounded ? OPT_Wformat_truncation_ : OPT_Wformat_length_;
}
};
/* Return the result of formatting the '%%' directive. */
@ -1950,8 +1962,7 @@ format_directive (const pass_sprintf_length::call_info &info,
if (fmtres.nullp)
{
fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_,
fmtwarn (dirloc, pargrange, NULL, info.warnopt (),
"%<%.*s%> directive argument is null",
(int)cvtlen, cvtbeg);
@ -1986,8 +1997,8 @@ format_directive (const pass_sprintf_length::call_info &info,
"%wu bytes into a region of size %wu")
: G_("%<%.*s%> directive writing %wu bytes "
"into a region of size %wu"));
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_, fmtstr,
warned = fmtwarn (dirloc, pargrange, NULL, info.warnopt (),
fmtstr,
(int)cvtlen, cvtbeg, fmtres.range.min,
navail);
}
@ -2001,7 +2012,7 @@ format_directive (const pass_sprintf_length::call_info &info,
: G_("%<%.*s%> directive writing between %wu and "
"%wu bytes into a region of size %wu"));
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_, fmtstr,
info.warnopt (), fmtstr,
(int)cvtlen, cvtbeg,
fmtres.range.min, fmtres.range.max, navail);
}
@ -2014,16 +2025,20 @@ format_directive (const pass_sprintf_length::call_info &info,
: G_("%<%.*s%> directive writing %wu or more bytes "
"into a region of size %wu"));
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_, fmtstr,
info.warnopt (), fmtstr,
(int)cvtlen, cvtbeg,
fmtres.range.min, navail);
}
}
else if (navail < fmtres.range.max
&& (((spec.specifier == 's'
&& fmtres.range.max < HOST_WIDE_INT_MAX)
/* && (spec.precision || spec.star_precision) */)
|| 1 < warn_format_length))
&& (spec.specifier != 's'
|| fmtres.range.max < HOST_WIDE_INT_MAX)
&& ((info.bounded
&& (!info.retval_used ()
|| warn_format_trunc > 1))
|| (!info.bounded
&& (spec.specifier == 's'
|| 1 < warn_format_length))))
{
/* The maximum directive output is longer than there is
room in the destination and the output length is either
@ -2038,7 +2053,7 @@ format_directive (const pass_sprintf_length::call_info &info,
: G_("%<%.*s%> directive writing %wu or more bytes "
"into a region of size %wu"));
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_, fmtstr,
info.warnopt (), fmtstr,
(int)cvtlen, cvtbeg,
fmtres.range.min, navail);
}
@ -2052,7 +2067,7 @@ format_directive (const pass_sprintf_length::call_info &info,
: G_("%<%.*s%> directive writing between %wu and %wu "
"bytes into a region of size %wu"));
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_, fmtstr,
info.warnopt (), fmtstr,
(int)cvtlen, cvtbeg,
fmtres.range.min, fmtres.range.max,
navail);
@ -2086,7 +2101,7 @@ format_directive (const pass_sprintf_length::call_info &info,
"into a region of size %wu")));
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_, fmtstr,
info.warnopt (), fmtstr,
(int)cvtlen, cvtbeg, fmtres.range.min,
navail);
}
@ -2111,7 +2126,7 @@ format_directive (const pass_sprintf_length::call_info &info,
if (fmtres.range.min == fmtres.range.max)
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_,
info.warnopt (),
"%<%.*s%> directive output of %wu bytes exceeds "
"minimum required size of 4095",
(int)cvtlen, cvtbeg, fmtres.range.min);
@ -2125,7 +2140,7 @@ format_directive (const pass_sprintf_length::call_info &info,
"bytes exceeds minimum required size of 4095"));
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_, fmtstr,
info.warnopt (), fmtstr,
(int)cvtlen, cvtbeg,
fmtres.range.min, fmtres.range.max);
}
@ -2143,8 +2158,7 @@ format_directive (const pass_sprintf_length::call_info &info,
to exceed INT_MAX bytes. */
if (fmtres.range.min == fmtres.range.max)
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_,
warned = fmtwarn (dirloc, pargrange, NULL, info.warnopt (),
"%<%.*s%> directive output of %wu bytes causes "
"result to exceed %<INT_MAX%>",
(int)cvtlen, cvtbeg, fmtres.range.min);
@ -2157,7 +2171,7 @@ format_directive (const pass_sprintf_length::call_info &info,
: G_ ("%<%.*s%> directive output between %wu and %wu "
"bytes may cause result to exceed %<INT_MAX%>"));
warned = fmtwarn (dirloc, pargrange, NULL,
OPT_Wformat_length_, fmtstr,
info.warnopt (), fmtstr,
(int)cvtlen, cvtbeg,
fmtres.range.min, fmtres.range.max);
}
@ -2265,7 +2279,11 @@ add_bytes (const pass_sprintf_length::call_info &info,
: G_("writing a terminating nul past the end "
"of the destination")));
res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_, text);
if (!info.bounded
|| !boundrange
|| !info.retval_used ()
|| warn_format_trunc > 1)
res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (), text);
}
else
{
@ -2283,8 +2301,12 @@ add_bytes (const pass_sprintf_length::call_info &info,
: G_("writing format character %#qc at offset %wu past "
"the end of the destination")));
res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_,
text, info.fmtstr[off], off);
if (!info.bounded
|| !boundrange
|| !info.retval_used ()
|| warn_format_trunc > 1)
res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (),
text, info.fmtstr[off], off);
}
}
@ -2351,8 +2373,7 @@ add_bytes (const pass_sprintf_length::call_info &info,
off + len - !!len);
if (res->number_chars_min == res->number_chars_max)
res->warned = fmtwarn (loc, NULL, NULL,
OPT_Wformat_length_,
res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (),
"output of %wu bytes causes "
"result to exceed %<INT_MAX%>",
res->number_chars_min - !end);
@ -2364,8 +2385,7 @@ add_bytes (const pass_sprintf_length::call_info &info,
"result to exceed %<INT_MAX%>")
: G_ ("output between %wu and %wu bytes may cause "
"result to exceed %<INT_MAX%>"));
res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_,
text,
res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (), text,
res->number_chars_min - !end,
res->number_chars_max - !end);
}
@ -2970,14 +2990,13 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
checking built-ins. */
if ((idx_objsize == HOST_WIDE_INT_M1U
|| !warn_stringop_overflow))
warning_at (gimple_location (info.callstmt),
OPT_Wformat_length_,
warning_at (gimple_location (info.callstmt), info.warnopt (),
"specified bound %wu exceeds maximum object size "
"%wu",
dstsize, target_size_max () / 2);
}
else if (dstsize > target_int_max ())
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
warning_at (gimple_location (info.callstmt), info.warnopt (),
"specified bound %wu exceeds %<INT_MAX %>",
dstsize);
}
@ -3028,7 +3047,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
is not constant. */
location_t loc = gimple_location (info.callstmt);
warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
OPT_Wformat_length_, "null destination pointer");
info.warnopt (), "null destination pointer");
return;
}
@ -3044,7 +3063,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
&& (idx_objsize == HOST_WIDE_INT_M1U
|| !warn_stringop_overflow))
{
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
warning_at (gimple_location (info.callstmt), info.warnopt (),
"specified bound %wu exceeds the size %wu "
"of the destination object", dstsize, objsize);
}
@ -3057,7 +3076,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
is not constant. */
location_t loc = gimple_location (info.callstmt);
warning_at (EXPR_LOC_OR_LOC (info.format, loc),
OPT_Wformat_length_, "null format string");
info.warnopt (), "null format string");
return;
}

View File

@ -72,7 +72,7 @@ tree_int_to_gmp (tree t, mpz_t res)
static isl_id *
isl_id_for_pbb (scop_p s, poly_bb_p pbb)
{
char name[10];
char name[14];
snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
return isl_id_alloc (s->isl_context, name, pbb);
}
@ -271,7 +271,7 @@ extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
static isl_id *
isl_id_for_ssa_name (scop_p s, tree e)
{
char name1[10];
char name1[14];
snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
return isl_id_alloc (s->isl_context, name1, e);
}

View File

@ -1,3 +1,12 @@
2017-01-08 Martin Sebor <msebor@redhat.com>
PR middle-end/77708
* gcc.dg/tree-ssa/builtin-snprintf-warn-1.c: New test.
* gcc.dg/tree-ssa/builtin-snprintf-warn-2.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-warn-6.c: XFAIL test cases failing
due to bug 78969.
* gcc.dg/format/pr78569.c: Adjust.
2017-01-07 David Malcolm <dmalcolm@redhat.com>
PR c++/72803

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-Wformat-length" } */
/* { dg-options "-Wformat-truncation" } */
/* A run of blank lines, so that we would fail the assertion in input.c:1388:
gcc_assert (line_width >= (start.column - 1 + literal_length)); */

View File

@ -0,0 +1,73 @@
/* { dg-do compile } */
/* { dg-options "-O2 -Wformat -Wformat-truncation=1 -ftrack-macro-expansion=0" } */
typedef struct
{
char a0[0];
char a1[1];
char a2[2];
char a3[3];
char a4[4];
char ax[];
} Arrays;
char buffer[1024];
#define buffer(size) (buffer + sizeof buffer - size)
int value_range (int min, int max)
{
extern int value (void);
int val = value ();
return val < min || max < val ? min : val;
}
#define R(min, max) value_range (min, max)
/* Verify that calls to snprintf whose return value is unused are
diagnosed if certain or possible truncation is detected. */
#define T(size, ...) \
__builtin_snprintf (buffer (size), size, __VA_ARGS__)
void test_int_retval_unused (void)
{
T (2, "%i", 123); /* { dg-warning "output truncated" } */
T (2, "%i", R (1, 99)); /* { dg-warning "output may be truncated" } */
T (2, "%i", R (10, 99)); /* { dg-warning "output truncated" } */
T (3, "%i%i", R (1, 99), R (1, 99)); /* { dg-warning "output may be truncated" } */
}
void test_string_retval_unused (const Arrays *ar)
{
T (1, "%-s", ar->a0);
T (1, "%-s", ar->a1);
T (1, "%-s", ar->a2); /* { dg-warning "output may be truncated" } */
}
/* Verify that calls to snprintf whose return value is used are
diagnosed only if certain truncation is detected but not when
truncation is only possible but not certain. */
volatile int retval;
#undef T
#define T(size, ...) \
retval = __builtin_snprintf (buffer (size), size, __VA_ARGS__)
void test_int_retval_used (void)
{
T (2, "%i", 123); /* { dg-warning "output truncated" } */
T (2, "%i", R (1, 99));
T (2, "%i", R (10, 99)); /* { dg-warning "output truncated" } */
T (3, "%i%i", R (1, 99), R (1, 99));
}
void test_string_retval_used (const Arrays *ar)
{
T (1, "%-s", ar->a0);
T (1, "%-s", ar->a1);
T (1, "%-s", ar->a2);
T (1, "%-s", ar->a4);
T (1, "%-s", "123"); /* { dg-warning "output truncated" } */
}

View File

@ -0,0 +1,70 @@
/* { dg-do compile } */
/* { dg-options "-O2 -Wformat -Wformat-truncation=2 -ftrack-macro-expansion=0" } */
typedef struct
{
char a0[0];
char a1[1];
char a2[2];
char a3[3];
char a4[4];
char ax[];
} Arrays;
char buffer[1024];
#define buffer(size) (buffer + sizeof buffer - size)
int value_range (int min, int max)
{
extern int value (void);
int val = value ();
return val < min || max < val ? min : val;
}
#define R(min, max) value_range (min, max)
/* Verify that calls to snprintf whose return value is unused are
diagnosed if certain or possible truncation is detected. */
#define T(size, ...) \
__builtin_snprintf (buffer (size), size, __VA_ARGS__)
void test_int_retval_unused (void)
{
T (2, "%i", 123); /* { dg-warning "output truncated" } */
T (2, "%i", R (1, 99)); /* { dg-warning "output may be truncated" } */
T (2, "%i", R (10, 99)); /* { dg-warning "output truncated" } */
T (3, "%i%i", R (1, 99), R (1, 99)); /* { dg-warning "output may be truncated" } */
}
void test_string_retval_unused (const Arrays *ar)
{
T (1, "%-s", ar->a0);
T (1, "%-s", ar->a1);
T (1, "%-s", ar->a2); /* { dg-warning "output may be truncated" } */
}
/* Verify that (at -Wformat-trunc=2) calls to snprintf whose return value
is used are diagnosed the same way as those whose value is unused. */
volatile int retval;
#undef T
#define T(size, ...) \
retval = __builtin_snprintf (buffer (size), size, __VA_ARGS__)
void test_int_retval_used (void)
{
T (2, "%i", 123); /* { dg-warning "output truncated" } */
T (2, "%i", R (1, 99)); /* { dg-warning "output may be truncated" } */
T (2, "%i", R (10, 99)); /* { dg-warning "output truncated" } */
T (3, "%i%i", R (1, 99), R (1, 99)); /* { dg-warning "output may be truncated" } */
}
void test_string_retval_used (const Arrays *ar)
{
T (1, "%-s", ar->a0);
T (1, "%-s", ar->a1);
T (1, "%-s", ar->a2); /* { dg-warning "output may be truncated" } */
}

View File

@ -51,7 +51,8 @@ void fuint (unsigned j, char *p)
{
if (j > 999)
return;
snprintf (p, 4, "%3u", j);
snprintf (p, 4, "%3u", j); /* { dg-bogus "may be truncated" "unsigned int" { xfail *-*-* } } */
}
void fint (int j, char *p)
@ -61,8 +62,7 @@ void fint (int j, char *p)
if (k > 999)
return;
/* Range info isn't available here. */
snprintf (p, 4, "%3u", k);
snprintf (p, 4, "%3u", k); /* { dg-bogus "may be truncated" "signed int" { xfail *-*-* } } */
}
void fulong (unsigned long j, char *p)
@ -70,8 +70,7 @@ void fulong (unsigned long j, char *p)
if (j > 999)
return;
/* Range info isn't available here. */
snprintf (p, 4, "%3lu", j);
snprintf (p, 4, "%3lu", j); /* { dg-bogus "may be truncated" "unsigned long" { xfail *-*-* } } */
}
void flong (long j, char *p)
@ -81,8 +80,7 @@ void flong (long j, char *p)
if (k > 999)
return;
/* Range info isn't available here. */
snprintf (p, 4, "%3lu", k);
snprintf (p, 4, "%3lu", k); /* { dg-bogus "may be truncated" "signed long" { xfail *-*-* } } */
}
void fullong (unsigned long long j, char *p)
@ -90,18 +88,17 @@ void fullong (unsigned long long j, char *p)
if (j > 999)
return;
/* Range info isn't available here. */
snprintf (p, 4, "%3llu", j);
snprintf (p, 4, "%3llu", j); /* { dg-bogus "may be truncated" "signed long" { xfail *-*-* } } */
}
void fllong (long j, char *p)
void fllong (long long j, char *p)
{
const unsigned long long k = (unsigned long long) j;
if (k > 999)
return;
snprintf (p, 4, "%3llu", k);
snprintf (p, 4, "%3llu", k); /* { dg-bogus "may be truncated" "unsigned long long" { xfail *-*-* } } */
}
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */

View File

@ -9746,10 +9746,10 @@ get_file_function_name (const char *type)
file = LOCATION_FILE (input_location);
len = strlen (file);
q = (char *) alloca (9 + 17 + len + 1);
q = (char *) alloca (9 + 19 + len + 1);
memcpy (q, file, len + 1);
snprintf (q + len, 9 + 17 + 1, "_%08X_" HOST_WIDE_INT_PRINT_HEX,
snprintf (q + len, 9 + 19 + 1, "_%08X_" HOST_WIDE_INT_PRINT_HEX,
crc32_string (0, name), get_random_seed (false));
p = q;