Commit 5d93da1d by Martin Sebor Committed by Martin Sebor

PR middle-end/78703 -fprintf-return-value floating point handling incorrect in…

PR middle-end/78703 -fprintf-return-value floating point handling incorrect in locales with a mulltibyte decimal point

gcc/ChangeLog:
	PR middle-end/78703
	* gimple-ssa-sprintf.c (struct result_range): Add likely and
	unlikely counters.
	(struct format_result): Replace number_chars, number_chars_min,
	and number_chars_max with a single member of struct result_range.
	Remove bounded.
	(format_result::operator+=): Adjust.
	(struct fmtresult): Remove bounded.  Handle likely and unlikely
	counters.
	(fmtresult::adjust_for_width_or_precision): New function.
	(fmtresult:type_max_digits): New function.
	(bytes_remaining): Handle likely and unlikely counters.
	(min_bytes_remaining): Remove.
	(format_percent): Simplify.
	(format_integer, format_floating): Set likely and unlikely counters.
	(get_string_length, format_character, format_string): Same.
	(format_plain, should_warn_p): New function.
	(maybe_warn): Call should_warn_p.  Update diagnostic messages
	and handle those for all directives, including plain strings.
	(format_directive): Handle likely and unlikely counters.
	Remove unnecessary quoting from diagnostics.  Add an informational
	note.
	(add_bytes): Remove.
	(pass_sprintf_length::compute_format_length): Simplify.
	(try_substitute_return_value): Handle likely and unlikely counters.

gcc/testsuite/ChangeLog:

	PR middle-end/78703
	* gcc.dg/format/pr78569.c: Adjust.
	* gcc.dg/tree-ssa/builtin-snprintf-warn-2.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-2.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-5.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-2.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-3.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-4.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-6.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-7.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-9.c: Same.
	* gcc.dg/tree-ssa/builtin-sprintf.c: Same.

From-SVN: r244953
parent c8699672
2017-01-26 Martin Sebor <msebor@redhat.com>
PR middle-end/78703
* gimple-ssa-sprintf.c (struct result_range): Add likely and
unlikely counters.
(struct format_result): Replace number_chars, number_chars_min,
and number_chars_max with a single member of struct result_range.
Remove bounded.
(format_result::operator+=): Adjust.
(struct fmtresult): Remove bounded. Handle likely and unlikely
counters.
(fmtresult::adjust_for_width_or_precision): New function.
(fmtresult:type_max_digits): New function.
(bytes_remaining): Handle likely and unlikely counters.
(min_bytes_remaining): Remove.
(format_percent): Simplify.
(format_integer, format_floating): Set likely and unlikely counters.
(get_string_length, format_character, format_string): Same.
(format_plain, should_warn_p): New function.
(maybe_warn): Call should_warn_p. Update diagnostic messages
and handle those for all directives, including plain strings.
(format_directive): Handle likely and unlikely counters.
Remove unnecessary quoting from diagnostics. Add an informational
note.
(add_bytes): Remove.
(pass_sprintf_length::compute_format_length): Simplify.
(try_substitute_return_value): Handle likely and unlikely counters.
2017-01-26 Carl Love <cel@us.ibm.com>
* config/rs6000/rs6000-c (altivec_overloaded_builtins): Remove
......
2017-01-26 Martin Sebor <msebor@redhat.com>
PR middle-end/78703
* gcc.dg/format/pr78569.c: Adjust.
* gcc.dg/tree-ssa/builtin-snprintf-warn-2.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-2.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-5.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-2.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-3.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-4.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-6.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-7.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-9.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf.c: Same.
2017-01-26 Jakub Jelinek <jakub@redhat.com>
PR c++/68727
......
......@@ -20,5 +20,5 @@ void test (void)
"channel uplink (see section 7.6.1).");
/* { dg-warning "output truncated" "" { target *-*-* } 7 } */
/* { dg-message "format output" "" { target *-*-* } 6 } */
/* { dg-message "output" "" { target *-*-* } 6 } */
}
......@@ -4,6 +4,9 @@
typedef struct
{
char a0[0];
/* Separate a0 from a1 to prevent the former from being substituted
for the latter and causing false positives. */
int: 8;
char a1[1];
char a2[2];
char a3[3];
......@@ -39,7 +42,9 @@ void test_int_retval_unused (void)
void test_string_retval_unused (const Arrays *ar)
{
T (1, "%-s", ar->a0);
/* At level 2 strings of unknown length are assumed to be 1 character
long, so the following is diagnosed. */
T (1, "%-s", ar->a0); /* { dg-warning "output may be truncated" } */
T (1, "%-s", ar->a1);
T (1, "%-s", ar->a2); /* { dg-warning "output may be truncated" } */
}
......@@ -64,7 +69,7 @@ void test_int_retval_used (void)
void test_string_retval_used (const Arrays *ar)
{
T (1, "%-s", ar->a0);
T (1, "%-s", ar->a0); /* { dg-warning "output may be truncated" } */
T (1, "%-s", ar->a1);
T (1, "%-s", ar->a2); /* { dg-warning "output may be truncated" } */
}
......@@ -59,15 +59,15 @@ void must_not_eliminate (void);
typedef __SIZE_TYPE__ size_t;
extern int i;
extern unsigned u;
extern long li;
extern unsigned long lu;
extern size_t sz;
extern char *str;
volatile int i;
volatile unsigned u;
volatile long li;
volatile unsigned long lu;
volatile size_t sz;
volatile char *str;
extern double d;
extern long double ld;
volatile double d;
volatile long double ld;
/* Verify that overflowing the destination object disables the return
value optimization. */
......@@ -280,7 +280,8 @@ RNG (0, 6, 8, "%s%ls", "1", L"2");
*/
/* Only conditional calls to abort should be made (with any probability):
/* Only conditional calls to must_not_eliminate must be made (with
any probability):
{ dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]:\n *must_not_eliminate" 124 "optimized" { target { ilp32 || lp64 } } } }
{ dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]:\n *must_not_eliminate" 93 "optimized" { target { { ! ilp32 } && { ! lp64 } } } } }
No unconditional calls to abort should be made:
......
......@@ -136,7 +136,6 @@ void test_arg_string (const char *s)
void test_arg_multiarg (int i, double d)
{
EQL (16, "%i %f %s", 123, 3.14, "abc");
EQL (16, "%12i %s", i, "abc");
EQL (16, "%*i %s", 12, i, "abc");
}
......
/* { dg-do compile } */
/* { dg-options "-std=c99 -Wformat -Wformat-overflow=2 -ftrack-macro-expansion=0" } */
/* { dg-options "-Wformat -Wformat-overflow=2 -ftrack-macro-expansion=0" } */
/* When debugging, define LINE to the line number of the test case to exercise
and avoid exercising any of the others. The buffer and objsize macros
......@@ -47,12 +47,16 @@ void test_s_const (void)
T (1, "%*ls", 0, L"\0");
T (1, "%*ls", 1, L""); /* { dg-warning "nul past the end" } */
T (1, "%ls", L"1"); /* { dg-warning "directive writing between 1 and 6 bytes into a region of size 1" } */
/* A wide character converts into between zero and MB_LEN_MAX bytes
(although individual ASCII characters are assumed to convert into
1 bt %lc so this could be made smarter. */
T (1, "%ls", L"1"); /* { dg-warning "directive writing up to 6 bytes into a region of size 1" } */
T (1, "%.0ls", L"1");
T (2, "%.0ls", L"1");
T (2, "%.1ls", L"1");
T (2, "%.2ls", L"1"); /* { dg-warning "nul past the end" } */
T (2, "%.3ls", L"1"); /* { dg-warning "directive writing between 1 and 3 bytes into a region of size 2" } */
T (2, "%.3ls", L"1"); /* { dg-warning "directive writing up to 3 bytes into a region of size 2" } */
T (2, "%.7ls", L"1"); /* { dg-warning "directive writing up to 6 bytes into a region of size 2" } */
T (2, "%.2ls", L"12"); /* { dg-warning "nul past the end" } */
/* The "%.2ls" directive below will write at a minimum 1 byte (because
......@@ -71,8 +75,8 @@ void test_s_const (void)
T (3, "%.3ls", L"12"); /* { dg-warning "nul past the end" } */
T (4, "%.3ls", L"123");
T (4, "%.4ls", L"123"); /* { dg-warning "nul past the end" } */
T (4, "%.5ls", L"123"); /* { dg-warning "directive writing between 3 and 5 bytes into a region of size 4" } */
T (4, "%.6ls", L"123"); /* { dg-warning "directive writing between 3 and 6 bytes into a region of size 4" } */
T (4, "%.5ls", L"123"); /* { dg-warning "directive writing up to 5 bytes into a region of size 4" } */
T (4, "%.6ls", L"123"); /* { dg-warning "directive writing up to 6 bytes into a region of size 4" } */
}
......@@ -87,37 +91,48 @@ struct Arrays {
/* Exercise buffer overflow detection with non-const string arguments. */
void test_s_nonconst (const char *s, const wchar_t *ws, struct Arrays *a)
void test_s_nonconst (int w, int p, const char *s, const wchar_t *ws,
struct Arrays *a)
{
T (0, "%s", s); /* { dg-warning "into a region" "sprintf transformed into strcpy" { xfail *-*-* } } */
T (1, "%s", s); /* { dg-warning "nul past the end" "sprintf transformed into strcpy" { xfail *-*-* } } */
T (1, "%1s", s); /* { dg-warning "nul past the end" } */
T (1, "%1s", s); /* { dg-warning "writing a terminating nul" } */
T (1, "%.0s", s);
T (1, "%.1s", s); /* { dg-warning "may write a terminating nul" } */
T (1, "%*s", 0, s); /* { dg-warning "may write a terminating nul" } */
T (1, "%*s", 1, s); /* { dg-warning "writing a terminating nul" } */
T (1, "%*s", 2, s); /* { dg-warning "directive writing 2 or more bytes" } */
T (1, "%*s", 3, s); /* { dg-warning "directive writing 3 or more bytes" } */
T (1, "%.*s", 1, s); /* { dg-warning "may write a terminating nul" } */
T (1, "%.*s", 2, s); /* { dg-warning "writing up to 2 bytes" } */
T (1, "%.*s", 3, s); /* { dg-warning "writing up to 3 bytes" } */
T (1, "%.0ls", ws);
T (1, "%.1ls", ws); /* { dg-warning "may write a terminating nul" } */
T (1, "%ls", ws); /* { dg-warning "writing a terminating nul" } */
T (1, "%ls", ws); /* { dg-warning "may write a terminating nul" } */
/* Verify that the size of the array is used in lieu of its length.
The minus sign disables GCC's sprintf to strcpy transformation. */
T (1, "%-s", a->a1); /* { dg-warning "nul past the end" } */
The minus sign disables GCC's sprintf to strcpy transformation.
In the case below, the length of s->a1 can be at most zero, so
the call should not be diagnosed. */
T (1, "%-s", a->a1);
/* In the following test, since the length of the strings isn't known,
their type (the array) is used to bound the maximum length to 1,
which means the "%-s" directive would not overflow the buffer,
but it would leave no room for the terminating nul. */
T (1, "%-s", a->a2); /* { dg-warning "writing a terminating nul" } */
T (1, "%-s", a->a2); /* { dg-warning "may write a terminating nul" } */
/* Unlike in the test above, since the length of the string is bounded
by the array type to at most 2, the "^-s" directive is diagnosed firts,
preventing the diagnostic about the terminatinb nul. */
T (1, "%-s", a->a3); /* { dg-warning "directive writing between 1 and 2 bytes" } */
T (1, "%-s", a->a3); /* { dg-warning "directive writing up to 2 bytes" } */
/* The length of a zero length array and flexible array member is
unknown and at leve 2 assumed to be at least 1. */
T (1, "%-s", a->a0); /* { dg-warning "nul past the end" } */
T (1, "%-s", a->ax); /* { dg-warning "nul past the end" } */
T (1, "%-s", a->a0); /* { dg-warning "may write a terminating nul" } */
T (1, "%-s", a->ax); /* { dg-warning "may write a terminating nul" } */
T (2, "%-s", a->a0);
T (2, "%-s", a->ax);
......@@ -145,20 +160,20 @@ void test_hh_nonconst (int w, int p, int x, unsigned y)
/* Zero precision means that zero argument formats as no bytes unless
length or flags make it otherwise. */
T (1, "%.*hhi", 0, x); /* { dg-warning "between 0 and 4 bytes" } */
T (2, "%.*hhi", 0, x); /* { dg-warning "between 0 and 4 bytes" } */
T (3, "%.*hhi", 0, x); /* { dg-warning "between 0 and 4 bytes" } */
T (1, "%.*hhi", 0, x); /* { dg-warning "writing up to 4 bytes" } */
T (2, "%.*hhi", 0, x); /* { dg-warning "writing up to 4 bytes" } */
T (3, "%.*hhi", 0, x); /* { dg-warning "writing up to 4 bytes" } */
T (4, "%.*hhi", 0, x); /* { dg-warning "may write a terminating nul past the end of the destination" } */
T (1, "%.*hhi", 0, y); /* { dg-warning "between 0 and 4 bytes" } */
T (2, "%.*hhi", 0, y); /* { dg-warning "between 0 and 4 bytes" } */
T (3, "%.*hhi", 0, y); /* { dg-warning "between 0 and 4 bytes" } */
T (1, "%.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
T (2, "%.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
T (3, "%.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
T (4, "%.*hhi", 0, y); /* { dg-warning "may write a terminating nul past the end of the destination" } */
T (1, "%#.*hhi", 0, y); /* { dg-warning "between 0 and 4 bytes" } */
T (1, "%#.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
/* { dg-warning ".#. flag used" "-Wformat" { target *-*-* } .-1 } */
T (1, "%+.*hhi", 0, y); /* { dg-warning "between 1 and 4 bytes" } */
T (1, "%-.*hhi", 0, y); /* { dg-warning "between 0 and 4 bytes" } */
T (1, "%-.*hhi", 0, y); /* { dg-warning "writing up to 4 bytes" } */
T (1, "% .*hhi", 0, y); /* { dg-warning "between 1 and 4 bytes" } */
T (1, "%#.*hhi", 1, y); /* { dg-warning "between 1 and 4 bytes" } */
......@@ -167,18 +182,18 @@ void test_hh_nonconst (int w, int p, int x, unsigned y)
T (1, "%-.*hhi", 1, y); /* { dg-warning "between 1 and 4 bytes" } */
T (1, "% .*hhi", 1, y); /* { dg-warning "between 2 and 4 bytes" } */
T (1, "%#.*hhi", p, y); /* { dg-warning "writing 0 or more bytes" } */
T (1, "%#.*hhi", p, y); /* { dg-warning "writing up to \[0-9\]+ bytes" } */
/* { dg-warning ".#. flag used" "-Wformat" { target *-*-* } .-1 } */
T (1, "%+.*hhi", p, y); /* { dg-warning "writing 1 or more bytes" } */
T (1, "%-.*hhi", p, y); /* { dg-warning "writing 0 or more bytes" } */
T (1, "% .*hhi", p, y); /* { dg-warning "writing 1 or more bytes" } */
T (1, "%+.*hhi", p, y); /* { dg-warning "writing 1 or more bytes|writing between 1 and \[0-9\]+ bytes" } */
T (1, "%-.*hhi", p, y); /* { dg-warning "writing up to \[0-9\]+ bytes" } */
T (1, "% .*hhi", p, y); /* { dg-warning "writing between 1 and \[0-9\]+ bytes|writing 1 or more bytes" } */
T (1, "%#.*hhu", 0, y); /* { dg-warning "between 0 and 3 bytes" } */
T (1, "%#.*hhu", 0, y); /* { dg-warning "writing up to 3 bytes" } */
/* { dg-warning ".#. flag used" "-Wformat" { target *-*-* } .-1 } */
T (1, "%+.*hhu", 0, y); /* { dg-warning "between 0 and 3 bytes" } */
T (1, "%+.*hhu", 0, y); /* { dg-warning "writing up to 3 bytes" } */
/* { dg-warning ".\\+. flag used" "-Wformat" { target *-*-* } .-1 } */
T (1, "%-.*hhu", 0, y); /* { dg-warning "between 0 and 3 bytes" } */
T (1, "% .*hhu", 0, y); /* { dg-warning "between 0 and 3 bytes" } */
T (1, "%-.*hhu", 0, y); /* { dg-warning "writing up to 3 bytes" } */
T (1, "% .*hhu", 0, y); /* { dg-warning "writing up to 3 bytes" } */
/* { dg-warning ". . flag used" "-Wformat" { target *-*-* } .-1 } */
}
......
......@@ -60,6 +60,9 @@ void test_sprintf_chk_string (const char *s, const char *t)
T (1, "%s", x ? "1" : ""); /* { dg-warning "nul past the end" } */
T (1, "%s", x ? s : "1"); /* { dg-warning "nul past the end" } */
T (1, "%s", x ? "1" : s); /* { dg-warning "nul past the end" } */
/* When neither string is known no warning should be issued at level 1
since their lenghts are assumed to be zero. */
T (1, "%s", x ? s : t);
T (2, "%s", x ? "" : "1");
......@@ -85,7 +88,7 @@ void test_sprintf_chk_integer_value (void)
T ( 1, "%i", i ( 0)); /* { dg-warning "nul past the end" } */
T ( 1, "%i", i ( 1)); /* { dg-warning "nul past the end" } */
T ( 1, "%i", i ( -1)); /* { dg-warning "into a region" } */
T ( 1, "%i_", i ( 1)); /* { dg-warning "character ._. at offset 2 past the end" } */
T ( 1, "%i_", i ( 1)); /* { dg-warning " 1 byte into a region of size 0" } */
T ( 1, "_%i", i ( 1)); /* { dg-warning "into a region" } */
T ( 1, "_%i_",i ( 1)); /* { dg-warning "into a region" } */
T ( 1, "%o", i ( 0)); /* { dg-warning "nul past the end" } */
......@@ -102,7 +105,7 @@ void test_sprintf_chk_integer_value (void)
T ( 2, "%i", i ( 10)); /* { dg-warning "nul past the end" } */
T ( 2, "%i_", i ( 0)); /* { dg-warning "nul past the end" } */
T ( 2, "_%i", i ( 0)); /* { dg-warning "nul past the end" } */
T ( 2, "_%i_",i ( 0)); /* { dg-warning "character ._. at offset 3 past the end" } */
T ( 2, "_%i_",i ( 0)); /* { dg-warning " 1 byte into a region of size 0" } */
T ( 2, "%o", i ( 1));
T ( 2, "%o", i ( 7));
T ( 2, "%o", i ( 010)); /* { dg-warning "nul past the end" } */
......@@ -211,10 +214,10 @@ void test_sprintf_chk_range_schar (void)
T ( 3, "%i", R ( 0, 99));
T ( 3, "%i", R ( 0, 100)); /* { dg-warning "may write a terminating nul past the end of the destination" } */
/* The following call may write as few as 3 bytes and as many as 5.
/* The following call may write as few as 2 bytes and as many as 4.
It's a judgment call how best to diagnose it to make the potential
problem clear. */
T ( 3, "%i%i", R (1, 10), R (9, 10)); /* { dg-warning "may write a terminating nul past the end|.%i. directive writing between 1 and 2 bytes into a region of size 1" } */
T ( 3, "%i%i", R (1, 10), R (9, 10)); /* { dg-warning "directive writing between 1 and 2 bytes into a region of size between 1 and 2" } */
T ( 4, "%i%i", R (10, 11), R (12, 13)); /* { dg-warning "nul past the end" } */
......@@ -224,7 +227,11 @@ void test_sprintf_chk_range_schar (void)
T ( 6, "%i_%i_%i", R (0, 9), R (0, 9), R (0, 10)); /* { dg-warning "may write a terminating nul past the end" } */
T ( 6, "%i_%i_%i", R (0, 9), R (0, 10), R (0, 9)); /* { dg-warning "may write a terminating nul past the end" } */
T ( 6, "%i_%i_%i", R (0, 10), R (0, 9), R (0, 9)); /* { dg-warning "may write a terminating nul past the end" } */
T ( 6, "%i_%i_%i", R (0, 9), R (0, 10), R (0, 10)); /* { dg-warning "may write a terminating nul past the end|.%i. directive writing between 1 and 2 bytes into a region of size 1" } */
T ( 6, "%hhi_%hi_%i", R (0, 9), R (0, 10), R (0, 10)); /* { dg-warning ".i. directive writing between 1 and 2 bytes into a region of size between 1 and 2" } */
T ( 6, "%3i|%2i/%1i", R (0, 99), R (0, 99), R (0, 99)); /* { dg-warning "./. directive writing 1 byte into a region of size 0" } */
T ( 6, "%.3i|%.2i/%i", R (0, 99), R (0, 99), R (0, 99)); /* { dg-warning "./. directive writing 1 byte into a region of size 0" } */
T ( 6, "%.3i|%.2i/%i", R (0, 119), R (0, 99), R (0, 99)); /* { dg-warning "./. directive writing 1 byte into a region of size 0" } */
T ( 6, "%.3i|%.2i/%i", R (0, 1), R (0, 2), R (0, 3)); /* { dg-warning "./. directive writing 1 byte into a region of size 0" } */
}
void test_sprintf_chk_range_uchar (void)
......
......@@ -12,14 +12,14 @@ void test (void)
The redundant argument is there to get around GCC bug 77799. */
sprintf (dst + 2, "1", 0);
/* { dg-warning "writing a terminating nul past the end of the destination" "nul warning" { target *-*-* } .-1 }
{ dg-message "format output 2 bytes into a destination of size 1" "note" { target *-*-* } .-2 }
{ dg-message ".sprintf. output 2 bytes into a destination of size 1" "note" { target *-*-* } .-2 }
{ dg-begin-multiline-output "-Wformat output: redundant argument" }
sprintf (dst + 2, "1", 0);
^~~
{ dg-end-multiline-output "" }
{ dg-begin-multiline-output "-Wformat-overflow output" }
sprintf (dst + 2, "1", 0);
~^
^
{ dg-end-multiline-output "" }
{ dg-begin-multiline-output "note" }
sprintf (dst + 2, "1", 0);
......@@ -29,15 +29,15 @@ void test (void)
/* Verify thet the caret points at the first format character written
past the end of the destination. */
sprintf (dst, "1234", 0);
/* { dg-warning "writing format character .4. at offset 3 past the end of the destination" "nul warning" { target *-*-* } .-1 }
{ dg-message "format output 5 bytes into a destination of size 3" "note" { target *-*-* } .-2 }
/* { dg-warning "writing 4 bytes into a region of size 3" "overlong format string" { target *-*-* } .-1 }
{ dg-message ".sprintf. output 5 bytes into a destination of size 3" "note" { target *-*-* } .-2 }
{ dg-begin-multiline-output "-Wformat output: redundant argument" }
sprintf (dst, "1234", 0);
^~~~~~
{ dg-end-multiline-output "" }
{ dg-begin-multiline-output "-Wformat-overflow output" }
sprintf (dst, "1234", 0);
^
~~~^
{ dg-end-multiline-output "" }
{ dg-begin-multiline-output "note" }
sprintf (dst, "1234", 0);
......@@ -48,15 +48,15 @@ void test (void)
past the end of the destination and the rest of the format string
is underlined. */
sprintf (dst, "12345", 0);
/* { dg-warning "writing format character .4. at offset 3 past the end of the destination" "nul warning" { target *-*-* } .-1 }
{ dg-message "format output 6 bytes into a destination of size 3" "note" { target *-*-* } .-2 }
/* { dg-warning "writing 5 bytes into a region of size 3" "nul warning" { target *-*-* } .-1 }
{ dg-message ".sprintf. output 6 bytes into a destination of size 3" "note" { target *-*-* } .-2 }
{ dg-begin-multiline-output "-Wformat output: redundant argument" }
sprintf (dst, "12345", 0);
^~~~~~~
{ dg-end-multiline-output "" }
{ dg-begin-multiline-output "-Wformat-overflow output" }
sprintf (dst, "12345", 0);
^~
~~~^~
{ dg-end-multiline-output "" }
{ dg-begin-multiline-output "note" }
sprintf (dst, "12345", 0);
......@@ -67,10 +67,10 @@ void test (void)
get around GCC bug 77671. */
sprintf (dst + 2, "%-s", "1");
/* { dg-warning "writing a terminating nul past the end of the destination" "warning" { target *-*-* } .-1 }
{ dg-message "format output 2 bytes into a destination of size 1" "note" { target *-*-* } .-2 }
{ dg-message ".sprintf. output 2 bytes into a destination of size 1" "note" { target *-*-* } .-2 }
{ dg-begin-multiline-output "-Wformat-overflow output" }
sprintf (dst + 2, "%-s", "1");
~~~^
^
{ dg-end-multiline-output "" }
{ dg-begin-multiline-output "note" }
sprintf (dst + 2, "%-s", "1");
......@@ -79,7 +79,7 @@ void test (void)
sprintf (dst + 2, "%-s", "abcd");
/* { dg-warning ".%-s. directive writing 4 bytes into a region of size 1" "warning" { target *-*-* } .-1 }
{ dg-message "format output 5 bytes into a destination of size 1" "note" { target *-*-* } .-2 }
{ dg-message ".sprintf. output 5 bytes into a destination of size 1" "note" { target *-*-* } .-2 }
{ dg-begin-multiline-output "-Wformat-overflow output" }
sprintf (dst + 2, "%-s", "abcd");
^~~ ~~~~~~
......@@ -105,8 +105,8 @@ extern char *ptr;
/* Evaluate to an array of SIZE characters when non-negative and LINE
is not set or set to the line the macro is on, or to a pointer to
an unknown object otherwise. */
#define buffer(size) \
(0 <= size && (!LINE || __LINE__ == LINE) \
#define buffer(size) \
(0 <= size && (!LINE || __LINE__ == LINE) \
? buffer + sizeof buffer - size : ptr)
/* Verify that the note printed along with the diagnostic mentions
......@@ -124,7 +124,7 @@ void test_sprintf_note (void)
^~
{ dg-end-multiline-output "" }
{ dg-message "format output 4 bytes into a destination of size 0" "" { target *-*-* } .-7 }
{ dg-message ".__builtin_sprintf. output 4 bytes into a destination of size 0" "" { target *-*-* } .-7 }
{ dg-begin-multiline-output "" }
__builtin_sprintf (buffer (0), "%c%s%i", '1', "2", 3);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -137,7 +137,7 @@ void test_sprintf_note (void)
^~ ~~~~
{ dg-end-multiline-output "" }
{ dg-message "format output 6 bytes into a destination of size 1" "" { target *-*-* } .-7 }
{ dg-message ".__builtin_sprintf. output 6 bytes into a destination of size 1" "" { target *-*-* } .-7 }
{ dg-begin-multiline-output "" }
__builtin_sprintf (buffer (1), "%c%s%i", '1', "23", 45);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -150,7 +150,7 @@ void test_sprintf_note (void)
^~
{ dg-end-multiline-output "" }
{ dg-message "format output 6 bytes into a destination of size 2" "" { target *-*-* } .-7 }
{ dg-message ".__builtin_sprintf. output 6 bytes into a destination of size 2" "" { target *-*-* } .-7 }
{ dg-begin-multiline-output "" }
__builtin_sprintf (buffer (2), "%c%s%i", '1', "2", 345);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -160,10 +160,10 @@ void test_sprintf_note (void)
/* { dg-warning "41: writing a terminating nul past the end of the destination" "" { target *-*-* } .-1 }
{ dg-begin-multiline-output "" }
__builtin_sprintf (buffer (6), "%c%s%i", '1', "2", 3456);
~~~~~~^
^
{ dg-end-multiline-output "" }
{ dg-message "format output 7 bytes into a destination of size 6" "" { target *-*-* } .-7 }
{ dg-message ".__builtin_sprintf. output 7 bytes into a destination of size 6" "" { target *-*-* } .-7 }
{ dg-begin-multiline-output "" }
__builtin_sprintf (buffer (6), "%c%s%i", '1', "2", 3456);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -52,7 +52,7 @@ void fuint (unsigned j, char *p)
if (j > 999)
return;
snprintf (p, 4, "%3u", j); /* { dg-bogus "may be truncated" "unsigned int" { xfail *-*-* } } */
snprintf (p, 4, "%3u", j);
}
void fint (int j, char *p)
......@@ -62,7 +62,7 @@ void fint (int j, char *p)
if (k > 999)
return;
snprintf (p, 4, "%3u", k); /* { dg-bogus "may be truncated" "signed int" { xfail *-*-* } } */
snprintf (p, 4, "%3u", k);
}
void fulong (unsigned long j, char *p)
......@@ -70,7 +70,7 @@ void fulong (unsigned long j, char *p)
if (j > 999)
return;
snprintf (p, 4, "%3lu", j); /* { dg-bogus "may be truncated" "unsigned long" { xfail *-*-* } } */
snprintf (p, 4, "%3lu", j);
}
void flong (long j, char *p)
......@@ -80,7 +80,7 @@ void flong (long j, char *p)
if (k > 999)
return;
snprintf (p, 4, "%3lu", k); /* { dg-bogus "may be truncated" "signed long" { xfail *-*-* } } */
snprintf (p, 4, "%3lu", k);
}
void fullong (unsigned long long j, char *p)
......@@ -88,7 +88,7 @@ void fullong (unsigned long long j, char *p)
if (j > 999)
return;
snprintf (p, 4, "%3llu", j); /* { dg-bogus "may be truncated" "signed long" { xfail *-*-* } } */
snprintf (p, 4, "%3llu", j);
}
void fllong (long long j, char *p)
......@@ -98,7 +98,7 @@ void fllong (long long j, char *p)
if (k > 999)
return;
snprintf (p, 4, "%3llu", k); /* { dg-bogus "may be truncated" "unsigned long long" { xfail *-*-* } } */
snprintf (p, 4, "%3llu", k);
}
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
......@@ -32,14 +32,16 @@ void test_integer_cst (void)
void test_integer_var (int i)
{
T (0, "%*d", INT_MIN, i); /* { dg-warning "writing 2147483648 bytes" } */
T (0, "%*d", INT_MAX, i); /* { dg-warning "writing 2147483647 bytes" } */
T (0, "%.*d", INT_MIN, i); /* { dg-warning "writing between 1 and 11 bytes" } */
/* The following writes INT_MAX digits and, when i is negative, a minus
sign. */
T (0, "%.*d", INT_MAX, i); /* { dg-warning "writing between 2147483647 and 2147483648 bytes" } */
T (0, "%.*d", INT_MIN, i); /* { dg-warning "writing between 1 and 11 bytes" } */
/* The following writes a range because of the possible minus sign. */
T (0, "%.*d", INT_MAX, i); /* { dg-warning "writing between 2147483647 and 2147483648 bytes" } */
T (0, "%*.*d", INT_MIN, INT_MIN, i); /* { dg-warning "writing 2147483648 bytes" } */
/* The following writes INT_MAX digits and, when i is negative, a minus
......@@ -52,7 +54,10 @@ void test_floating_a_cst (void)
T (0, "%*a", INT_MIN, 0.); /* { dg-warning "writing 2147483648 bytes" } */
T (0, "%*a", INT_MAX, 0.); /* { dg-warning "writing 2147483647 bytes" } */
T (0, "%.*a", INT_MIN, 0.); /* { dg-warning "writing 6 bytes" } */
/* %a is poorly specified and as a result some implementations trim
redundant trailing zeros (e.g., Glibc) and others don't (e.g.,
Solaris). */
T (0, "%.*a", INT_MIN, 0.); /* { dg-warning "writing between 6 and 20 bytes" } */
T (0, "%.*a", INT_MAX, 0.); /* { dg-warning "writing 2147483654 bytes" } */
......@@ -111,7 +116,7 @@ void test_floating_f_cst (void)
T (0, "%*f", INT_MIN, 0.); /* { dg-warning "writing 2147483648 bytes" } */
T (0, "%*f", INT_MAX, 0.); /* { dg-warning "writing 2147483647 bytes" } */
T (0, "%.*f", INT_MIN, 0.); /* { dg-warning "writing 8 byte" } */
T (0, "%.*f", INT_MIN, 0.); /* { dg-warning "writing 8 bytes" } */
T (0, "%.*f", INT_MAX, 0.); /* { dg-warning "writing 2147483649 bytes" } */
......@@ -178,14 +183,14 @@ void test_string_cst (void)
void test_string_var (const char *s)
{
T (0, "%*s", INT_MIN, s); /* { dg-warning "writing 2147483648 bytes" } */
T (0, "%*s", INT_MAX, s); /* { dg-warning "writing 2147483647 bytes" } */
T (0, "%*s", INT_MIN, s); /* { dg-warning "writing 2147483648 or more bytes" } */
T (0, "%*s", INT_MAX, s); /* { dg-warning "writing 2147483647 or more bytes" } */
T (0, "%.*s", INT_MIN, s); /* { dg-warning "writing a terminating nul" } */
T (0, "%.*s", INT_MAX, s); /* { dg-warning "writing between 0 and 2147483647 bytes" } */
T (0, "%.*s", INT_MAX, s); /* { dg-warning "writing up to 2147483647 bytes" } */
T (0, "%*.*s", INT_MIN, INT_MIN, s); /* { dg-warning "writing 2147483648 bytes" } */
T (0, "%*.*s", INT_MIN, INT_MIN, s); /* { dg-warning "writing 2147483648 or more bytes" } */
T (0, "%*.*s", INT_MAX, INT_MAX, s); /* { dg-warning "writing 2147483647 bytes" } */
}
......@@ -37,19 +37,17 @@ void test_a (int w, int p, double x)
T1 ("%*.a", 6); /* { dg-warning "between 6 and 10 bytes" } */
T1 ("%*.a", 7); /* { dg-warning "between 7 and 10 bytes" } */
T1 ("%*.a", w); /* { dg-warning "writing 6 or more bytes" } */
T1 ("%*.0a", w); /* { dg-warning "writing 6 or more bytes" } */
T1 ("%*.1a", w); /* { dg-warning "writing 8 or more bytes" } */
T1 ("%*.2a", w); /* { dg-warning "writing 9 or more bytes" } */
T1 ("%.*a", p); /* { dg-warning "writing 6 or more bytes" } */
T1 ("%1.*a", p); /* { dg-warning "writing 6 or more bytes" } */
T1 ("%2.*a", p); /* { dg-warning "writing 6 or more bytes" } */
T1 ("%3.*a", p); /* { dg-warning "writing 6 or more bytes" } */
T2 ("%*.*a", w, p); /* { dg-warning "writing 6 or more bytes" } */
T2 ("%*.*a", w, p); /* { dg-warning "writing 6 or more bytes" } */
T2 ("%*.*a", w, p); /* { dg-warning "writing 6 or more bytes" } */
T1 ("%*.a", w); /* { dg-warning "writing between 6 and 2147483648 bytes" } */
T1 ("%*.0a", w); /* { dg-warning "writing between 6 and 2147483648 bytes" } */
T1 ("%*.1a", w); /* { dg-warning "writing between 8 and 2147483648 bytes" } */
T1 ("%*.2a", w); /* { dg-warning "writing between 9 and 2147483648 bytes" } */
T1 ("%.*a", p); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
T1 ("%1.*a", p); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
T1 ("%2.*a", p); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
T1 ("%3.*a", p); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
T2 ("%*.*a", w, p); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
}
/* Exercise %e. */
......@@ -69,19 +67,17 @@ void test_e (int w, int p, double x)
T1 ("%*.e", 6); /* { dg-warning "between 6 and 7 bytes" } */
T1 ("%*.e", 7); /* { dg-warning "writing 7 bytes" } */
T1 ("%*.e", w); /* { dg-warning "writing 5 or more bytes" } */
T1 ("%*.0e", w); /* { dg-warning "writing 5 or more bytes" } */
T1 ("%*.1e", w); /* { dg-warning "writing 7 or more bytes" } */
T1 ("%*.2e", w); /* { dg-warning "writing 8 or more bytes" } */
T1 ("%*.e", w); /* { dg-warning "writing between 5 and 2147483648 bytes" } */
T1 ("%*.0e", w); /* { dg-warning "writing between 5 and 2147483648 bytes" } */
T1 ("%*.1e", w); /* { dg-warning "writing between 7 and 2147483648 bytes" } */
T1 ("%*.2e", w); /* { dg-warning "writing between 8 and 2147483648 bytes" } */
T1 ("%.*e", p); /* { dg-warning "writing 5 or more bytes" } */
T1 ("%1.*e", p); /* { dg-warning "writing 5 or more bytes" } */
T1 ("%2.*e", p); /* { dg-warning "writing 5 or more bytes" } */
T1 ("%3.*e", p); /* { dg-warning "writing 5 or more bytes" } */
T1 ("%.*e", p); /* { dg-warning "writing between 5 and 2147483655 bytes" } */
T1 ("%1.*e", p); /* { dg-warning "writing between 5 and 2147483655 bytes" } */
T1 ("%2.*e", p); /* { dg-warning "writing between 5 and 2147483655 bytes" } */
T1 ("%3.*e", p); /* { dg-warning "writing between 5 and 2147483655 bytes" } */
T2 ("%*.*e", w, p); /* { dg-warning "writing 5 or more bytes" } */
T2 ("%*.*e", w, p); /* { dg-warning "writing 5 or more bytes" } */
T2 ("%*.*e", w, p); /* { dg-warning "writing 5 or more bytes" } */
T2 ("%*.*e", w, p); /* { dg-warning "writing between 5 and 2147483655 bytes" } */
}
/* Exercise %f. */
......@@ -103,19 +99,17 @@ void test_f (int w, int p, double x)
T2 ("%*.*f", 312, 312); /* { dg-warning "between 314 and 623 bytes" } */
T2 ("%*.*f", 312, 313); /* { dg-warning "between 315 and 624 bytes" } */
T1 ("%*.f", w); /* { dg-warning "writing 1 or more bytes" } */
T1 ("%*.0f", w); /* { dg-warning "writing 1 or more bytes" } */
T1 ("%*.1f", w); /* { dg-warning "writing 3 or more bytes" } */
T1 ("%*.2f", w); /* { dg-warning "writing 4 or more bytes" } */
T1 ("%*.f", w); /* { dg-warning "writing between 1 and 2147483648 bytes" } */
T1 ("%*.0f", w); /* { dg-warning "writing between 1 and 2147483648 bytes" } */
T1 ("%*.1f", w); /* { dg-warning "writing between 3 and 2147483648 bytes" } */
T1 ("%*.2f", w); /* { dg-warning "writing between 4 and 2147483648 bytes" } */
T1 ("%.*f", p); /* { dg-warning "writing 1 or more bytes" } */
T1 ("%1.*f", p); /* { dg-warning "writing 1 or more bytes" } */
T1 ("%2.*f", p); /* { dg-warning "writing 2 or more bytes" } */
T1 ("%3.*f", p); /* { dg-warning "writing 3 or more bytes" } */
T1 ("%.*f", p); /* { dg-warning "writing between 1 and 2147483958 bytes" } */
T1 ("%1.*f", p); /* { dg-warning "writing between 1 and 2147483958 bytes" } */
T1 ("%2.*f", p); /* { dg-warning "writing between 2 and 2147483958 bytes" } */
T1 ("%3.*f", p); /* { dg-warning "writing between 3 and 2147483958 bytes" } */
T2 ("%*.*f", w, p); /* { dg-warning "writing 1 or more bytes" } */
T2 ("%*.*f", w, p); /* { dg-warning "writing 1 or more bytes" } */
T2 ("%*.*f", w, p); /* { dg-warning "writing 1 or more bytes" } */
T2 ("%*.*f", w, p); /* { dg-warning "writing between 1 and 2147483958 bytes" } */
}
/* Exercise %g. The expected output is the lesser of %e and %f. */
......@@ -156,18 +150,18 @@ void test_a_va (va_list va)
T ("%6.a"); /* { dg-warning "between 6 and 10 bytes" } */
T ("%7.a"); /* { dg-warning "between 7 and 10 bytes" } */
T ("%*.a"); /* { dg-warning "writing 6 or more bytes" } */
T ("%*.0a"); /* { dg-warning "writing 6 or more bytes" } */
T ("%*.1a"); /* { dg-warning "writing 8 or more bytes" } */
T ("%*.2a"); /* { dg-warning "writing 9 or more bytes" } */
T ("%*.a"); /* { dg-warning "writing between 6 and 2147483648 bytes" } */
T ("%*.0a"); /* { dg-warning "writing between 6 and 2147483648 bytes" } */
T ("%*.1a"); /* { dg-warning "writing between 8 and 2147483648 bytes" } */
T ("%*.2a"); /* { dg-warning "writing between 9 and 2147483648 bytes" } */
T ("%.*a"); /* { dg-warning "writing 6 or more bytes" } */
T ("%1.*a"); /* { dg-warning "writing 6 or more bytes" } */
T ("%2.*a"); /* { dg-warning "writing 6 or more bytes" } */
T ("%6.*a"); /* { dg-warning "writing 6 or more bytes" } */
T ("%9.*a"); /* { dg-warning "writing 9 or more bytes" } */
T ("%.*a"); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
T ("%1.*a"); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
T ("%2.*a"); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
T ("%6.*a"); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
T ("%9.*a"); /* { dg-warning "writing between 9 and 2147483658 bytes" } */
T ("%*.*a"); /* { dg-warning "writing 6 or more bytes" } */
T ("%*.*a"); /* { dg-warning "writing between 6 and 2147483658 bytes" } */
}
/* Exercise %e. */
......@@ -195,12 +189,12 @@ void test_e_va (va_list va)
T ("%6.e"); /* { dg-warning "between 6 and 7 bytes" } */
T ("%7.e"); /* { dg-warning "writing 7 bytes" } */
T ("%.*e"); /* { dg-warning "writing 5 or more bytes" } */
T ("%1.*e"); /* { dg-warning "writing 5 or more bytes" } */
T ("%6.*e"); /* { dg-warning "writing 6 or more bytes" } */
T ("%9.*e"); /* { dg-warning "writing 9 or more bytes" } */
T ("%.*e"); /* { dg-warning "writing between 5 and 2147483655 bytes" } */
T ("%1.*e"); /* { dg-warning "writing between 5 and 2147483655 bytes" } */
T ("%6.*e"); /* { dg-warning "writing between 6 and 2147483655 bytes" } */
T ("%9.*e"); /* { dg-warning "writing between 9 and 2147483655 bytes" } */
T ("%*.*e"); /* { dg-warning "writing 5 or more bytes" } */
T ("%*.*e"); /* { dg-warning "writing between 5 and 2147483655 bytes" } */
}
/* Exercise %f. */
......@@ -232,11 +226,11 @@ void test_f_va (va_list va)
T ("%312.312f"); /* { dg-warning "between 314 and 623 bytes" } */
T ("%312.313f"); /* { dg-warning "between 315 and 624 bytes" } */
T ("%.*f"); /* { dg-warning "writing 1 or more bytes" } */
T ("%1.*f"); /* { dg-warning "writing 1 or more bytes" } */
T ("%3.*f"); /* { dg-warning "writing 3 or more bytes" } */
T ("%.*f"); /* { dg-warning "writing between 1 and 2147483958 bytes" } */
T ("%1.*f"); /* { dg-warning "writing between 1 and 2147483958 bytes" } */
T ("%3.*f"); /* { dg-warning "writing between 3 and 2147483958 bytes" } */
T ("%*.*f"); /* { dg-warning "writing 1 or more bytes" } */
T ("%*.*f"); /* { dg-warning "writing between 1 and 2147483958 bytes" } */
}
/* Exercise %g. The expected output is the lesser of %e and %f. */
......@@ -268,9 +262,9 @@ void test_g_va (va_list va)
T ("%312.313g"); /* { dg-warning "writing 312 bytes" } */
T ("%333.999g"); /* { dg-warning "writing 333 bytes" } */
T ("%.*g"); /* { dg-warning "writing 1 or more bytes" } */
T ("%1.*g"); /* { dg-warning "writing 1 or more bytes" } */
T ("%4.*g"); /* { dg-warning "writing 4 or more bytes" } */
T ("%.*g"); /* { dg-warning "writing between 1 and 310 bytes" } */
T ("%1.*g"); /* { dg-warning "writing between 1 and 310 bytes" } */
T ("%4.*g"); /* { dg-warning "writing between 4 and 310 bytes" } */
T ("%*.*g"); /* { dg-warning "writing 1 or more bytes" } */
T ("%*.*g"); /* { dg-warning "writing between 1 and 2147483648 bytes" } */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment