PR tree-optimization/79327 - wrong code at -O2 and -fprintf-return-value
PR tree-optimization/79327 - wrong code at -O2 and -fprintf-return-value gcc/ChangeLog: * gimple-ssa-sprintf.c (tree_digits): Avoid adding the base prefix when precision has resulted in leading zeros. (format_integer): Adjust the likely counter to assume an unknown argument that may be zero is non-zero. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust. * gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-13.c: New test. * gcc/testsuite/gcc.dg/tree-ssa/pr79327-2.c: Ditto. From-SVN: r245173
This commit is contained in:
parent
77095a6ab1
commit
f589a1ce25
|
@ -1,3 +1,11 @@
|
|||
2017-02-03 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/79327
|
||||
* gimple-ssa-sprintf.c (tree_digits): Avoid adding the base prefix
|
||||
when precision has resulted in leading zeros.
|
||||
(format_integer): Adjust the likely counter to assume an unknown
|
||||
argument that may be zero is non-zero.
|
||||
|
||||
2017-02-03 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/78689
|
||||
|
|
|
@ -762,7 +762,9 @@ tree_digits (tree x, int base, HOST_WIDE_INT prec, bool plus, bool prefix)
|
|||
|
||||
res += prec < ndigs ? ndigs : prec;
|
||||
|
||||
if (prefix && absval)
|
||||
/* Adjust a non-zero value for the base prefix, either hexadecimal,
|
||||
or, unless precision has resulted in a leading zero, also octal. */
|
||||
if (prefix && absval && (base == 16 || prec <= ndigs))
|
||||
{
|
||||
if (base == 8)
|
||||
res += 1;
|
||||
|
@ -1230,6 +1232,10 @@ format_integer (const directive &dir, tree arg)
|
|||
of the format string by returning [-1, -1]. */
|
||||
return fmtresult ();
|
||||
|
||||
/* True if the LIKELY counter should be adjusted upward from the MIN
|
||||
counter to account for arguments with unknown values. */
|
||||
bool likely_adjust = false;
|
||||
|
||||
fmtresult res;
|
||||
|
||||
/* Using either the range the non-constant argument is in, or its
|
||||
|
@ -1259,6 +1265,14 @@ format_integer (const directive &dir, tree arg)
|
|||
|
||||
res.argmin = argmin;
|
||||
res.argmax = argmax;
|
||||
|
||||
/* Set the adjustment for an argument whose range includes
|
||||
zero since that doesn't include the octal or hexadecimal
|
||||
base prefix. */
|
||||
wide_int wzero = wi::zero (wi::get_precision (min));
|
||||
if (wi::le_p (min, wzero, SIGNED)
|
||||
&& !wi::neg_p (max))
|
||||
likely_adjust = true;
|
||||
}
|
||||
else if (range_type == VR_ANTI_RANGE)
|
||||
{
|
||||
|
@ -1293,6 +1307,11 @@ format_integer (const directive &dir, tree arg)
|
|||
|
||||
if (!argmin)
|
||||
{
|
||||
/* Set the adjustment for an argument whose range includes
|
||||
zero since that doesn't include the octal or hexadecimal
|
||||
base prefix. */
|
||||
likely_adjust = true;
|
||||
|
||||
if (TREE_CODE (argtype) == POINTER_TYPE)
|
||||
{
|
||||
argmin = build_int_cst (pointer_sized_int_node, 0);
|
||||
|
@ -1345,7 +1364,24 @@ format_integer (const directive &dir, tree arg)
|
|||
res.range.max = MAX (max1, max2);
|
||||
}
|
||||
|
||||
res.range.likely = res.knownrange ? res.range.max : res.range.min;
|
||||
/* Add the adjustment for an argument whose range includes zero
|
||||
since it doesn't include the octal or hexadecimal base prefix. */
|
||||
if (res.knownrange)
|
||||
res.range.likely = res.range.max;
|
||||
else
|
||||
{
|
||||
res.range.likely = res.range.min;
|
||||
if (likely_adjust && maybebase && base != 10)
|
||||
{
|
||||
if (res.range.min == 1)
|
||||
res.range.likely += base == 8 ? 1 : 2;
|
||||
else if (res.range.min == 2
|
||||
&& base == 16
|
||||
&& (dir.width[0] == 2 || dir.prec[0] == 2))
|
||||
++res.range.likely;
|
||||
}
|
||||
}
|
||||
|
||||
res.range.unlikely = res.range.max;
|
||||
res.adjust_for_width_or_precision (dir.width, dirtype, base,
|
||||
(sign | maybebase) + (base == 16));
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2017-02-03 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/79327
|
||||
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust.
|
||||
* gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-13.c: New test.
|
||||
* gcc/testsuite/gcc.dg/tree-ssa/pr79327-2.c: Ditto.
|
||||
|
||||
2017-02-03 Jakub Jelinek <jakub@redhat.com>
|
||||
Martin Sebor <msebor@redhat.com>
|
||||
|
||||
|
|
|
@ -1151,8 +1151,16 @@ void test_sprintf_chk_hh_nonconst (int w, int p, int a)
|
|||
T (2, "% hhu", a); /* { dg-warning ". . flag used with .%u." } */
|
||||
T (2, "% hhx", a); /* { dg-warning ". . flag used with .%x." } */
|
||||
|
||||
T (2, "%#hho", a);
|
||||
T (2, "%#hhx", a);
|
||||
/* The following results in between "0" and "0377" for -1. Although
|
||||
the minimum output would fit, given the '#' flag the likely output
|
||||
(i.e., for any non-zero argument) includes a leading zero followed
|
||||
by one or more octal digits, which results in the terminating nul
|
||||
being written past the end. Thus the "may write" warning. */
|
||||
T (2, "%#hho", a); /* { dg-warning "may write a terminating nul" } */
|
||||
/* Similar to the above, but the likely output of the directive for
|
||||
a non-zero argument overflows. Thus the "writing X bytes" (as
|
||||
opposed to "may write") warning. */
|
||||
T (2, "%#hhx", a); /* { dg-warning "writing between 1 and 4 bytes" } */
|
||||
|
||||
T (3, "%0hhd", a);
|
||||
T (3, "%1hhd", a);
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
/* { dg-do compile }
|
||||
{ dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" }
|
||||
{ dg-require-effective-target int32plus } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
|
||||
#define INT_MAX __INT_MAX__
|
||||
#define INT_MIN (-INT_MAX - 1)
|
||||
|
||||
/* 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
|
||||
below make use of LINE to avoid warnings for other lines. */
|
||||
#ifndef LINE
|
||||
# define LINE 0
|
||||
#endif
|
||||
|
||||
void sink (char*, char*);
|
||||
|
||||
int dummy_sprintf (char*, const char*, ...);
|
||||
|
||||
char buffer [256];
|
||||
extern char *ptr;
|
||||
|
||||
int int_range (int min, int max)
|
||||
{
|
||||
extern int int_value (void);
|
||||
int n = int_value ();
|
||||
return n < min || max < n ? min : n;
|
||||
}
|
||||
|
||||
unsigned uint_range (unsigned min, unsigned max)
|
||||
{
|
||||
extern unsigned uint_value (void);
|
||||
unsigned n = uint_value ();
|
||||
return n < min || max < n ? min : n;
|
||||
}
|
||||
|
||||
/* Evaluate to an array of SIZE characters when non-negative, or to
|
||||
a pointer to an unknown object otherwise. */
|
||||
#define buffer(size) \
|
||||
((0 <= size) ? buffer + sizeof buffer - (size) : ptr)
|
||||
|
||||
/* Helper to expand function to either __builtin_f or dummy_f to
|
||||
make debugging GCC easy. */
|
||||
#define FUNC(f) \
|
||||
((!LINE || LINE == __LINE__) ? __builtin_ ## f : dummy_ ## f)
|
||||
|
||||
/* Macro to verify that calls to __builtin_sprintf (i.e., with no size
|
||||
argument) issue diagnostics by correctly determining the size of
|
||||
the destination buffer. */
|
||||
#define T(size, ...) \
|
||||
(FUNC (sprintf) (buffer (size), __VA_ARGS__), \
|
||||
sink (buffer, ptr))
|
||||
|
||||
/* Return a signed integer in the range [MIN, MAX]. */
|
||||
#define R(min, max) int_range (min, max)
|
||||
|
||||
/* Verify warnings and ranges for certain overflow. */
|
||||
void test_min_overflow (int i)
|
||||
{
|
||||
T (0, "%#hho", i); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#1hho", i); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#2hho", i); /* { dg-warning "between 2 and 4 bytes" } */
|
||||
T (0, "%#3hho", i); /* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (0, "%#4hho", i); /* { dg-warning "writing 4 bytes" } */
|
||||
T (0, "%#hho", R (-1, 0)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#1hho", R (-1, 0)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#2hho", R (-1, 0)); /* { dg-warning "between 2 and 4 bytes" } */
|
||||
T (0, "%#3hho", R (-1, 0)); /* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (0, "%#4hho", R (-1, 0)); /* { dg-warning "writing 4 bytes" } */
|
||||
T (0, "%#hho", R (-1, 1)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#1hho", R (-1, 1)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#2hho", R (-1, 1)); /* { dg-warning "between 2 and 4 bytes" } */
|
||||
T (0, "%#3hho", R (-1, 1)); /* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (0, "%#4hho", R (-1, 1)); /* { dg-warning "writing 4 bytes" } */
|
||||
T (0, "%#hho", R ( 0, 1)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||
T (0, "%#1hho", R ( 0, 1)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||
T (0, "%#2hho", R ( 0, 1)); /* { dg-warning "writing 2 bytes" } */
|
||||
T (0, "%#3hho", R ( 0, 1)); /* { dg-warning "writing 3 bytes" } */
|
||||
T (0, "%#4hho", R ( 0, 1)); /* { dg-warning "writing 4 bytes" } */
|
||||
T (0, "%#hho", R ( 1, 2)); /* { dg-warning "writing 2 bytes" } */
|
||||
T (0, "%#1hho", R ( 1, 2)); /* { dg-warning "writing 2 bytes" } */
|
||||
T (0, "%#2hho", R ( 1, 2)); /* { dg-warning "writing 2 bytes" } */
|
||||
T (0, "%#3hho", R ( 1, 2)); /* { dg-warning "writing 3 bytes" } */
|
||||
T (0, "%#4hho", R ( 1, 2)); /* { dg-warning "writing 4 bytes" } */
|
||||
|
||||
T (0, "%#ho", i); /* { dg-warning "between 1 and 7 bytes" } */
|
||||
T (0, "%#.*ho", /* { dg-warning "between 1 and 7 bytes" } */
|
||||
R (0, 2), i);
|
||||
T (0, "%#.*ho", /* { dg-warning "between 1 and 7 bytes" } */
|
||||
R (1, 2), i);
|
||||
T (0, "%#.*ho", /* { dg-warning "between 2 and 7 bytes" } */
|
||||
R (2, 3), i);
|
||||
T (0, "%#.*ho", /* { dg-warning "between 3 and 7 bytes" } */
|
||||
R (3, 4), i);
|
||||
T (0, "%#.*ho", /* { dg-warning "between 7 and 8 bytes" } */
|
||||
R (7, 8), i);
|
||||
|
||||
T (0, "%#ho", R (-1, 0)); /* { dg-warning "between 1 and 7 bytes" } */
|
||||
T (0, "%#ho", R (-1, 1)); /* { dg-warning "between 1 and 7 bytes" } */
|
||||
T (0, "%#ho", R ( 0, 1)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||
T (0, "%#ho", R ( 1, 2)); /* { dg-warning "writing 2 bytes" } */
|
||||
|
||||
T (0, "%#o", i); /* { dg-warning "between 1 and 12 bytes" } */
|
||||
T (0, "%#o", R (-1, 0)); /* { dg-warning "between 1 and 12 bytes" } */
|
||||
T (0, "%#o", R (-1, 1)); /* { dg-warning "between 1 and 12 bytes" } */
|
||||
T (0, "%#o", R ( 0, 1)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||
T (0, "%#o", R ( 1, 2)); /* { dg-warning "writing 2 bytes" } */
|
||||
|
||||
T (0, "%#hhx", i); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#.*hhx", /* { dg-warning "writing up to 4 bytes" } */
|
||||
R (0, 2), i);
|
||||
T (0, "%#.*hhx", /* { dg-warning "between 1 and 4 bytes" } */
|
||||
R (1, 2), i);
|
||||
T (0, "%#.*hhx", /* { dg-warning "between 2 and 5 bytes" } */
|
||||
R (2, 3), i);
|
||||
T (0, "%#.*hhx", /* { dg-warning "between 3 and 6 bytes" } */
|
||||
R (3, 4), i);
|
||||
|
||||
T (0, "%#hhx", R (-1, 0)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#hhx", R (-1, 1)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (0, "%#hhx", R ( 0, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||
T (0, "%#hhx", R ( 1, 2)); /* { dg-warning "writing 3 bytes" } */
|
||||
|
||||
T (0, "%#hx", i); /* { dg-warning "between 1 and 6 bytes" } */
|
||||
T (0, "%#hx", R (-1, 0)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||
T (0, "%#hx", R (-1, 1)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||
T (0, "%#hx", R ( 0, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||
T (0, "%#hx", R ( 1, 2)); /* { dg-warning "writing 3 bytes" } */
|
||||
|
||||
T (0, "%#x", i); /* { dg-warning "between 1 and 10 bytes" } */
|
||||
T (0, "%#x", R (-1, 0)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||
T (0, "%#x", R (-1, 1)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||
T (0, "%#x", R ( 0, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||
T (0, "%#x", R ( 1, 2)); /* { dg-warning "writing 3 bytes" } */
|
||||
}
|
||||
|
||||
/* Verify warnings and ranges for likely overflow. */
|
||||
void test_likely_overflow (int i)
|
||||
{
|
||||
T (2, "%#hho", i); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#1hho", i); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#2hho", i); /* { dg-warning "writing a terminating nul" } */
|
||||
T (2, "%#3hho", i); /* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (2, "%#4hho", i); /* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#hho", R (-1, 0)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#1hho", R (-1, 0));/* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#2hho", R (-1, 0));/* { dg-warning "writing a terminating nul" } */
|
||||
T (2, "%#3hho", R (-1, 0));/* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (2, "%#4hho", R (-1, 0));/* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#hho", R (-1, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#1hho", R (-1, 1));/* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#2hho", R (-1, 1));/* { dg-warning "writing a terminating nul" } */
|
||||
T (2, "%#3hho", R (-1, 1));/* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (2, "%#4hho", R (-1, 1));/* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#hho", R ( 0, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#1hho", R ( 0, 1));/* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#2hho", R ( 0, 1));/* { dg-warning "writing a terminating nul" } */
|
||||
T (2, "%#3hho", R ( 0, 1));/* { dg-warning "writing 3 bytes" } */
|
||||
T (2, "%#4hho", R ( 0, 1));/* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#hho", R ( 1, 2)); /* { dg-warning "writing a terminating nul" } */
|
||||
T (2, "%#1hho", R ( 1, 2));/* { dg-warning "writing a terminating nul" } */
|
||||
T (2, "%#2hho", R ( 1, 2));/* { dg-warning "writing a terminating nul" } */
|
||||
T (2, "%#3hho", R ( 1, 2));/* { dg-warning "writing 3 bytes" } */
|
||||
T (2, "%#4hho", R ( 1, 2));/* { dg-warning "writing 4 bytes" } */
|
||||
|
||||
T (2, "%#ho", i); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#ho", R (-1, 0)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#ho", R (-1, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#ho", R ( 0, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#ho", R ( 1, 2)); /* { dg-warning "writing a terminating nul" } */
|
||||
|
||||
T (2, "%#o", i); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#o", R (-1, 0)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#o", R (-1, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#o", R ( 0, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (2, "%#o", R ( 1, 2)); /* { dg-warning "writing a terminating nul" } */
|
||||
|
||||
T (2, "%#hhx", i); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (2, "%#1hhx", i); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (2, "%#2hhx", i); /* { dg-warning "between 2 and 4 bytes" } */
|
||||
T (2, "%#3hhx", i); /* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (2, "%#4hhx", i); /* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#1hhx", R (-1, 0));/* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (2, "%#2hhx", R (-1, 0));/* { dg-warning "between 2 and 4 bytes" } */
|
||||
T (2, "%#3hhx", R (-1, 0));/* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (2, "%#4hhx", R (-1, 0));/* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#hhx", R (-1, 0)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (2, "%#1hhx", R (-1, 0));/* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (2, "%#2hhx", R (-1, 0));/* { dg-warning "between 2 and 4 bytes" } */
|
||||
T (2, "%#3hhx", R (-1, 0));/* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (2, "%#4hhx", R (-1, 0));/* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#hhx", R (-1, 1)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (2, "%#1hhx", R (-1, 1));/* { dg-warning "between 1 and 4 bytes" } */
|
||||
T (2, "%#2hhx", R (-1, 1));/* { dg-warning "between 2 and 4 bytes" } */
|
||||
T (2, "%#3hhx", R (-1, 1));/* { dg-warning "between 3 and 4 bytes" } */
|
||||
T (2, "%#4hhx", R (-1, 1));/* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#hhx", R ( 0, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||
T (2, "%#1hhx", R ( 0, 1));/* { dg-warning "between 1 and 3 bytes" } */
|
||||
T (2, "%#2hhx", R ( 0, 1));/* { dg-warning "between 2 and 3 bytes" } */
|
||||
T (2, "%#3hhx", R ( 0, 1));/* { dg-warning "writing 3 bytes" } */
|
||||
T (2, "%#4hhx", R ( 0, 1));/* { dg-warning "writing 4 bytes" } */
|
||||
T (2, "%#hhx", R ( 1, 2)); /* { dg-warning "writing 3 bytes" } */
|
||||
T (2, "%#1hhx", R ( 1, 2));/* { dg-warning "writing 3 bytes" } */
|
||||
T (2, "%#2hhx", R ( 1, 2));/* { dg-warning "writing 3 bytes" } */
|
||||
T (2, "%#3hhx", R ( 1, 2));/* { dg-warning "writing 3 bytes" } */
|
||||
T (2, "%#4hhx", R ( 1, 2));/* { dg-warning "writing 4 bytes" } */
|
||||
|
||||
T (2, "%#hx", i); /* { dg-warning "between 1 and 6 bytes" } */
|
||||
T (2, "%#hx", R (-1, 0)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||
T (2, "%#hx", R (-1, 1)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||
T (2, "%#hx", R ( 0, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||
T (2, "%#hx", R ( 1, 2)); /* { dg-warning "writing 3 bytes" } */
|
||||
|
||||
T (2, "%#x", i); /* { dg-warning "between 1 and 10 bytes" } */
|
||||
T (2, "%#x", R (-1, 0)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||
T (2, "%#x", R (-1, 1)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||
T (2, "%#x", R ( 0, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||
T (2, "%#x", R ( 1, 2)); /* { dg-warning "writing 3 bytes" } */
|
||||
}
|
||||
|
||||
/* Verify warnings likely overflow due to the terminating nul. */
|
||||
void test_likely_nul_overflow (int i)
|
||||
{
|
||||
T (3, "%#hho", i);
|
||||
T (3, "%#hho", R (-1, 0));
|
||||
T (3, "%#hho", R (-1, 1));
|
||||
T (3, "%#hho", R ( 0, 1));
|
||||
T (3, "%#hho", R ( 1, 2));
|
||||
|
||||
T (3, "%#ho", i);
|
||||
T (3, "%#ho", R (-1, 0));
|
||||
T (3, "%#ho", R (-1, 1));
|
||||
T (3, "%#ho", R ( 0, 1));
|
||||
T (3, "%#ho", R ( 1, 2));
|
||||
|
||||
T (3, "%#o", i);
|
||||
T (3, "%#o", R (-1, 0));
|
||||
T (3, "%#o", R (-1, 1));
|
||||
T (3, "%#o", R ( 0, 1));
|
||||
T (3, "%#o", R ( 1, 2));
|
||||
|
||||
T (3, "%#hhx", i); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#hhx", R (-1, 0)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#hhx", R (-1, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#hhx", R ( 0, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#hhx", R ( 1, 2)); /* { dg-warning "writing a terminating nul" } */
|
||||
|
||||
T (3, "%#hx", i); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#hx", R (-1, 0)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#hx", R (-1, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#hx", R ( 0, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#hx", R ( 1, 2)); /* { dg-warning "writing a terminating nul" } */
|
||||
|
||||
T (3, "%#x", i); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#x", R (-1, 0)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#x", R (-1, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#x", R ( 0, 1)); /* { dg-warning "may write a terminating nul" } */
|
||||
T (3, "%#x", R ( 1, 2)); /* { dg-warning "writing a terminating nul" } */
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/* PR tree-optimization/79327 - wrong code at -O2 and -fprintf-return-value
|
||||
{ dg-compile }
|
||||
{ dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
#define CAT(s, n) s ## n
|
||||
#define FAIL(line) CAT (failure_on_line_, line)
|
||||
|
||||
/* Emit a call to a function named failure_on_line_NNN when EXPR is false. */
|
||||
#define ASSERT(expr) \
|
||||
do { \
|
||||
extern void FAIL (__LINE__)(void); \
|
||||
if (!(expr)) FAIL (__LINE__)(); \
|
||||
} while (0)
|
||||
|
||||
#define KEEP(line) CAT (keep_call_on_line_, line)
|
||||
|
||||
/* Emit a call to a function named keep_call_on_line_NNN when EXPR is true.
|
||||
Used to verify that the expression need not be the only one that holds. */
|
||||
#define ASSERT_MAYBE(expr) \
|
||||
do { \
|
||||
extern void KEEP (__LINE__)(void); \
|
||||
if (expr) KEEP (__LINE__)(); \
|
||||
} while (0)
|
||||
|
||||
void test_hho_cst (void)
|
||||
{
|
||||
ASSERT (1 == __builtin_snprintf (0, 0, "%#.1hho", 0));
|
||||
ASSERT (2 == __builtin_snprintf (0, 0, "%#.2hho", 0));
|
||||
|
||||
ASSERT (2 == __builtin_snprintf (0, 0, "%#.1hho", 1));
|
||||
ASSERT (2 == __builtin_snprintf (0, 0, "%#.2hho", 1));
|
||||
ASSERT (3 == __builtin_snprintf (0, 0, "%#.3hho", 1));
|
||||
}
|
||||
|
||||
int test_hho_var (int i)
|
||||
{
|
||||
int n = __builtin_snprintf (0, 0, "%#hho", i);
|
||||
|
||||
ASSERT (0 < n && n < 5);
|
||||
|
||||
ASSERT_MAYBE (1 == n);
|
||||
ASSERT_MAYBE (2 == n);
|
||||
ASSERT_MAYBE (3 == n);
|
||||
ASSERT_MAYBE (4 == n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int test_ho_var (int i)
|
||||
{
|
||||
int n = __builtin_snprintf (0, 0, "%#ho", i);
|
||||
|
||||
ASSERT (0 < n && n < 8);
|
||||
|
||||
ASSERT_MAYBE (1 == n);
|
||||
ASSERT_MAYBE (2 == n);
|
||||
ASSERT_MAYBE (3 == n);
|
||||
ASSERT_MAYBE (4 == n);
|
||||
ASSERT_MAYBE (5 == n);
|
||||
ASSERT_MAYBE (6 == n);
|
||||
ASSERT_MAYBE (7 == n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int test_o_var (int i)
|
||||
{
|
||||
int n = __builtin_snprintf (0, 0, "%#o", i);
|
||||
|
||||
ASSERT (0 < n && n < 13);
|
||||
|
||||
ASSERT_MAYBE (1 == n);
|
||||
ASSERT_MAYBE (2 == n);
|
||||
ASSERT_MAYBE (3 == n);
|
||||
ASSERT_MAYBE (4 == n);
|
||||
ASSERT_MAYBE (5 == n);
|
||||
ASSERT_MAYBE (6 == n);
|
||||
ASSERT_MAYBE (7 == n);
|
||||
ASSERT_MAYBE (8 == n);
|
||||
ASSERT_MAYBE (9 == n);
|
||||
ASSERT_MAYBE (10 == n);
|
||||
ASSERT_MAYBE (11 == n);
|
||||
ASSERT_MAYBE (12 == n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void test_hhx_cst (void)
|
||||
{
|
||||
ASSERT (1 == __builtin_snprintf (0, 0, "%#.1hhx", 0));
|
||||
ASSERT (2 == __builtin_snprintf (0, 0, "%#.2hhx", 0));
|
||||
|
||||
ASSERT (3 == __builtin_snprintf (0, 0, "%#.1hhx", 1));
|
||||
ASSERT (4 == __builtin_snprintf (0, 0, "%#.2hhx", 1));
|
||||
ASSERT (5 == __builtin_snprintf (0, 0, "%#.3hhx", 1));
|
||||
}
|
||||
|
||||
int test_hhx_var (int i)
|
||||
{
|
||||
int n = __builtin_snprintf (0, 0, "%#hhx", i);
|
||||
|
||||
ASSERT (0 < n && n < 5);
|
||||
|
||||
ASSERT_MAYBE (1 == n);
|
||||
ASSERT_MAYBE (2 == n);
|
||||
ASSERT_MAYBE (3 == n);
|
||||
ASSERT_MAYBE (4 == n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void test_hx_cst (void)
|
||||
{
|
||||
ASSERT (1 == __builtin_snprintf (0, 0, "%#.1hx", 0));
|
||||
ASSERT (2 == __builtin_snprintf (0, 0, "%#.2hx", 0));
|
||||
|
||||
ASSERT (3 == __builtin_snprintf (0, 0, "%#.1hx", 1));
|
||||
ASSERT (4 == __builtin_snprintf (0, 0, "%#.2hx", 1));
|
||||
ASSERT (5 == __builtin_snprintf (0, 0, "%#.3hx", 1));
|
||||
}
|
||||
|
||||
int test_hx_var (int i)
|
||||
{
|
||||
int n = __builtin_snprintf (0, 0, "%#hx", i);
|
||||
|
||||
ASSERT (0 < n && n < 7);
|
||||
|
||||
ASSERT_MAYBE (1 == n);
|
||||
ASSERT_MAYBE (2 == n);
|
||||
ASSERT_MAYBE (3 == n);
|
||||
ASSERT_MAYBE (4 == n);
|
||||
ASSERT_MAYBE (5 == n);
|
||||
ASSERT_MAYBE (6 == n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int test_x_var (int i)
|
||||
{
|
||||
int n = __builtin_snprintf (0, 0, "%#x", i);
|
||||
|
||||
ASSERT (0 < n && n < 11);
|
||||
|
||||
ASSERT_MAYBE (1 == n);
|
||||
ASSERT_MAYBE (2 == n);
|
||||
ASSERT_MAYBE (3 == n);
|
||||
ASSERT_MAYBE (4 == n);
|
||||
ASSERT_MAYBE (5 == n);
|
||||
ASSERT_MAYBE (6 == n);
|
||||
ASSERT_MAYBE (7 == n);
|
||||
ASSERT_MAYBE (8 == n);
|
||||
ASSERT_MAYBE (9 == n);
|
||||
ASSERT_MAYBE (10 == n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "failure_on_line" "optimized"} }
|
||||
{ dg-final { scan-tree-dump-times "keep_call_on_line" 43 "optimized"} } */
|
Loading…
Reference in New Issue