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:
Martin Sebor 2017-02-03 22:47:35 +00:00 committed by Martin Sebor
parent 77095a6ab1
commit f589a1ce25
6 changed files with 483 additions and 4 deletions

View File

@ -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

View File

@ -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));

View File

@ -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>

View File

@ -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);

View File

@ -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" } */
}

View File

@ -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"} } */