re PR tree-optimization/79327 (wrong code at -O2 and -fprintf-return-value)
PR tree-optimization/79327 * gimple-ssa-sprintf.c (adjust_range_for_overflow): If returning true, always set *argmin and *argmax to TYPE_{MIN,MAX}_VALUE of dirtype. (format_integer): Use wide_int_to_tree instead of build_int_cst + to_?hwi. If argmin is NULL, just set argmin and argmax to TYPE_{MIN,MAX}_VALUE of argtype. Simplify and fix computation of shortest and longest sequence. * gcc.dg/tree-ssa/pr79327.c: New test. * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c (test_sprintf_chk_hh_nonconst): Don't expect 2 bogus warnings. * gcc.dg/tree-ssa/builtin-sprintf-warn-3.c (test_sprintf_chk_range_schar): Adjust dg-message. * gcc.dg/tree-ssa/builtin-sprintf-warn-12.c: New test. * gcc.c-torture/execute/pr79327.c: New test. Co-Authored-By: Martin Sebor <msebor@redhat.com> From-SVN: r245166
This commit is contained in:
parent
b333e8ebb0
commit
5b00f9d236
|
@ -1,3 +1,14 @@
|
||||||
|
2017-02-03 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/79327
|
||||||
|
* gimple-ssa-sprintf.c (adjust_range_for_overflow): If returning
|
||||||
|
true, always set *argmin and *argmax to TYPE_{MIN,MAX}_VALUE of
|
||||||
|
dirtype.
|
||||||
|
(format_integer): Use wide_int_to_tree instead of build_int_cst
|
||||||
|
+ to_?hwi. If argmin is NULL, just set argmin and argmax to
|
||||||
|
TYPE_{MIN,MAX}_VALUE of argtype. Simplify and fix computation
|
||||||
|
of shortest and longest sequence.
|
||||||
|
|
||||||
2017-02-03 Uros Bizjak <ubizjak@gmail.com>
|
2017-02-03 Uros Bizjak <ubizjak@gmail.com>
|
||||||
|
|
||||||
* config/i386/i386.c (dimode_scalar_chain::convert_reg):
|
* config/i386/i386.c (dimode_scalar_chain::convert_reg):
|
||||||
|
|
|
@ -1014,8 +1014,8 @@ get_int_range (tree arg, tree type, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
|
||||||
determined by checking for the actual argument being in the range
|
determined by checking for the actual argument being in the range
|
||||||
of the type of the directive. If it isn't it must be assumed to
|
of the type of the directive. If it isn't it must be assumed to
|
||||||
take on the full range of the directive's type.
|
take on the full range of the directive's type.
|
||||||
Return true when the range has been adjusted to the full unsigned
|
Return true when the range has been adjusted to the full range
|
||||||
range of DIRTYPE, or [0, DIRTYPE_MAX], and false otherwise. */
|
of DIRTYPE, and false otherwise. */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
|
adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
|
||||||
|
@ -1051,20 +1051,8 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree dirmin = TYPE_MIN_VALUE (dirtype);
|
*argmin = TYPE_MIN_VALUE (dirtype);
|
||||||
tree dirmax = TYPE_MAX_VALUE (dirtype);
|
*argmax = TYPE_MAX_VALUE (dirtype);
|
||||||
|
|
||||||
if (TYPE_UNSIGNED (dirtype))
|
|
||||||
{
|
|
||||||
*argmin = dirmin;
|
|
||||||
*argmax = dirmax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*argmin = integer_zero_node;
|
|
||||||
*argmax = dirmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1260,10 +1248,8 @@ format_integer (const directive &dir, tree arg)
|
||||||
enum value_range_type range_type = get_range_info (arg, &min, &max);
|
enum value_range_type range_type = get_range_info (arg, &min, &max);
|
||||||
if (range_type == VR_RANGE)
|
if (range_type == VR_RANGE)
|
||||||
{
|
{
|
||||||
argmin = build_int_cst (argtype, wi::fits_uhwi_p (min)
|
argmin = wide_int_to_tree (argtype, min);
|
||||||
? min.to_uhwi () : min.to_shwi ());
|
argmax = wide_int_to_tree (argtype, max);
|
||||||
argmax = build_int_cst (argtype, wi::fits_uhwi_p (max)
|
|
||||||
? max.to_uhwi () : max.to_shwi ());
|
|
||||||
|
|
||||||
/* Set KNOWNRANGE if the argument is in a known subrange
|
/* Set KNOWNRANGE if the argument is in a known subrange
|
||||||
of the directive's type (KNOWNRANGE may be reset below). */
|
of the directive's type (KNOWNRANGE may be reset below). */
|
||||||
|
@ -1307,47 +1293,16 @@ format_integer (const directive &dir, tree arg)
|
||||||
|
|
||||||
if (!argmin)
|
if (!argmin)
|
||||||
{
|
{
|
||||||
/* For an unknown argument (e.g., one passed to a vararg function)
|
if (TREE_CODE (argtype) == POINTER_TYPE)
|
||||||
or one whose value range cannot be determined, create a T_MIN
|
|
||||||
constant if the argument's type is signed and T_MAX otherwise,
|
|
||||||
and use those to compute the range of bytes that the directive
|
|
||||||
can output. When precision may be zero, use zero as the minimum
|
|
||||||
since it results in no bytes on output (unless width is specified
|
|
||||||
to be greater than 0). */
|
|
||||||
bool zero = dir.prec[0] <= 0 && dir.prec[1] >= 0;
|
|
||||||
argmin = build_int_cst (argtype, !zero);
|
|
||||||
|
|
||||||
int typeprec = TYPE_PRECISION (dirtype);
|
|
||||||
int argprec = TYPE_PRECISION (argtype);
|
|
||||||
|
|
||||||
if (argprec < typeprec)
|
|
||||||
{
|
{
|
||||||
if (POINTER_TYPE_P (argtype))
|
argmin = build_int_cst (pointer_sized_int_node, 0);
|
||||||
argmax = build_all_ones_cst (argtype);
|
argmax = build_all_ones_cst (pointer_sized_int_node);
|
||||||
else if (TYPE_UNSIGNED (argtype))
|
|
||||||
argmax = TYPE_MAX_VALUE (argtype);
|
|
||||||
else
|
|
||||||
argmax = TYPE_MIN_VALUE (argtype);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (POINTER_TYPE_P (dirtype))
|
argmin = TYPE_MIN_VALUE (argtype);
|
||||||
argmax = build_all_ones_cst (dirtype);
|
argmax = TYPE_MAX_VALUE (argtype);
|
||||||
else if (TYPE_UNSIGNED (dirtype))
|
|
||||||
argmax = TYPE_MAX_VALUE (dirtype);
|
|
||||||
else
|
|
||||||
argmax = TYPE_MIN_VALUE (dirtype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res.argmin = argmin;
|
|
||||||
res.argmax = argmax;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tree_int_cst_lt (argmax, argmin))
|
|
||||||
{
|
|
||||||
tree tmp = argmax;
|
|
||||||
argmax = argmin;
|
|
||||||
argmin = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear KNOWNRANGE if the range has been adjusted to the maximum
|
/* Clear KNOWNRANGE if the range has been adjusted to the maximum
|
||||||
|
@ -1361,34 +1316,33 @@ format_integer (const directive &dir, tree arg)
|
||||||
res.argmax = argmax;
|
res.argmax = argmax;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Recursively compute the minimum and maximum from the known range,
|
/* Recursively compute the minimum and maximum from the known range. */
|
||||||
taking care to swap them if the lower bound results in longer
|
if (TYPE_UNSIGNED (dirtype) || tree_int_cst_sgn (argmin) >= 0)
|
||||||
output than the upper bound (e.g., in the range [-1, 0]. */
|
|
||||||
|
|
||||||
if (TYPE_UNSIGNED (dirtype))
|
|
||||||
{
|
{
|
||||||
/* For unsigned conversions/directives, use the minimum (i.e., 0
|
/* For unsigned conversions/directives or signed when
|
||||||
or 1) and maximum to compute the shortest and longest output,
|
the minimum is positive, use the minimum and maximum to compute
|
||||||
respectively. */
|
the shortest and longest output, respectively. */
|
||||||
res.range.min = format_integer (dir, argmin).range.min;
|
res.range.min = format_integer (dir, argmin).range.min;
|
||||||
res.range.max = format_integer (dir, argmax).range.max;
|
res.range.max = format_integer (dir, argmax).range.max;
|
||||||
}
|
}
|
||||||
else
|
else if (tree_int_cst_sgn (argmax) < 0)
|
||||||
{
|
{
|
||||||
/* For signed conversions/directives, use the maximum (i.e., 0)
|
/* For signed conversions/directives if maximum is negative,
|
||||||
to compute the shortest output and the minimum (i.e., TYPE_MIN)
|
use the minimum as the longest output and maximum as the
|
||||||
to compute the longest output. This is important when precision
|
shortest output. */
|
||||||
is specified but unknown because otherwise both output lengths
|
|
||||||
would reflect the largest possible precision (i.e., INT_MAX). */
|
|
||||||
res.range.min = format_integer (dir, argmax).range.min;
|
res.range.min = format_integer (dir, argmax).range.min;
|
||||||
res.range.max = format_integer (dir, argmin).range.max;
|
res.range.max = format_integer (dir, argmin).range.max;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (res.range.max < res.range.min)
|
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT tmp = res.range.max;
|
/* Otherwise, 0 is inside of the range and minimum negative. Use 0
|
||||||
res.range.max = res.range.min;
|
as the shortest output and for the longest output compute the
|
||||||
res.range.min = tmp;
|
length of the output of both minimum and maximum and pick the
|
||||||
|
longer. */
|
||||||
|
unsigned HOST_WIDE_INT max1 = format_integer (dir, argmin).range.max;
|
||||||
|
unsigned HOST_WIDE_INT max2 = format_integer (dir, argmax).range.max;
|
||||||
|
res.range.min = format_integer (dir, integer_zero_node).range.min;
|
||||||
|
res.range.max = MAX (max1, max2);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.range.likely = res.knownrange ? res.range.max : res.range.min;
|
res.range.likely = res.knownrange ? res.range.max : res.range.min;
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
2017-02-03 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/79327
|
||||||
|
* gcc.dg/tree-ssa/pr79327.c: New test.
|
||||||
|
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
|
||||||
|
(test_sprintf_chk_hh_nonconst): Don't expect 2 bogus warnings.
|
||||||
|
* gcc.dg/tree-ssa/builtin-sprintf-warn-3.c
|
||||||
|
(test_sprintf_chk_range_schar): Adjust dg-message.
|
||||||
|
* gcc.dg/tree-ssa/builtin-sprintf-warn-12.c: New test.
|
||||||
|
* gcc.c-torture/execute/pr79327.c: New test.
|
||||||
|
|
||||||
2017-02-03 Jakub Jelinek <jakub@redhat.com>
|
2017-02-03 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR target/79354
|
PR target/79354
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* PR tree-optimization/79327 */
|
||||||
|
/* { dg-require-effective-target c99_runtime } */
|
||||||
|
|
||||||
|
volatile int a;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char buf[64];
|
||||||
|
if (__builtin_sprintf (buf, "%#hho", a) != 1)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (__builtin_sprintf (buf, "%#hhx", a) != 1)
|
||||||
|
__builtin_abort ();
|
||||||
|
a = 1;
|
||||||
|
if (__builtin_sprintf (buf, "%#hho", a) != 2)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (__builtin_sprintf (buf, "%#hhx", a) != 3)
|
||||||
|
__builtin_abort ();
|
||||||
|
a = 127;
|
||||||
|
if (__builtin_sprintf (buf, "%#hho", a) != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
if (__builtin_sprintf (buf, "%#hhx", a) != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1151,8 +1151,8 @@ void test_sprintf_chk_hh_nonconst (int w, int p, int a)
|
||||||
T (2, "% hhu", a); /* { dg-warning ". . flag used with .%u." } */
|
T (2, "% hhu", a); /* { dg-warning ". . flag used with .%u." } */
|
||||||
T (2, "% hhx", a); /* { dg-warning ". . flag used with .%x." } */
|
T (2, "% hhx", a); /* { dg-warning ". . flag used with .%x." } */
|
||||||
|
|
||||||
T (2, "%#hho", a); /* { dg-warning "nul past the end" } */
|
T (2, "%#hho", a);
|
||||||
T (2, "%#hhx", a); /* { dg-warning ".%#hhx. directive writing between 3 and . bytes into a region of size 2" } */
|
T (2, "%#hhx", a);
|
||||||
|
|
||||||
T (3, "%0hhd", a);
|
T (3, "%0hhd", a);
|
||||||
T (3, "%1hhd", a);
|
T (3, "%1hhd", a);
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
/* PR tree-optimization/79327 - wrong code at -O2 and -fprintf-return-value
|
||||||
|
{ 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)
|
||||||
|
|
||||||
|
/* Return a unsigned integer in the range [MIN, MAX]. */
|
||||||
|
#define U(min, max) uint_range (min, max)
|
||||||
|
|
||||||
|
/* Exercise the hh length modifier with ranges. */
|
||||||
|
void test_hh (void)
|
||||||
|
{
|
||||||
|
T (0, "%hhi", R ( -1, 0)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -1, 1)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -1, 12)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -1, 123)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -1, 128)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -1, 257)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -1, 1234)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, -11)); /* { dg-warning "writing 3 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, -1)); /* { dg-warning "between 2 and 3 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, 0)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, 12)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, 123)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, 128)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, 257)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -12, 1234)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R ( -99, -10)); /* { dg-warning "writing 3 bytes" } */
|
||||||
|
T (0, "%hhi", R (-123, -1)); /* { dg-warning "between 2 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R (-123, 0)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R (-123, 1)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R (-123, 12)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R (-123, 123)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R (-123, 257)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R (-123, 1234)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R (-129, 1)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hhi", R (-130, -129)); /* { dg-warning "writing 3 bytes" } */
|
||||||
|
|
||||||
|
T (0, "%hhi", U ( 0, 127)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
|
||||||
|
/* The following results in either "127" and "-128" so the ideal result
|
||||||
|
should be "between 3 and 4 bytes" but because of the overflow from
|
||||||
|
128 to -128 in the %hhi directive the input range is reset to that
|
||||||
|
of char, or [CHAR_MIN, CHAR_MAX], and the warning reflects that. */
|
||||||
|
T (0, "%hhi", U ( 127, 128)); /* { dg-warning "between \[13\] and 4 bytes" } */
|
||||||
|
/* The following results in either "-128" or "-127". */
|
||||||
|
T (0, "%hhi", U ( 128, 129)); /* { dg-warning "writing 4 bytes" } */
|
||||||
|
/* The following results in between "-128" and "-99". */
|
||||||
|
T (0, "%hhi", U ( 128, 157)); /* { dg-warning "writing between 3 and 4 bytes" } */
|
||||||
|
/* Between "-128" and "-1". */
|
||||||
|
T (0, "%hhi", U ( 128, 255)); /* { dg-warning "writing between 2 and 4 bytes" } */
|
||||||
|
/* Between "-128" and "0". */
|
||||||
|
T (0, "%hhi", U ( 128, 256)); /* { dg-warning "writing between 1 and 4 bytes" } */
|
||||||
|
/* Between "-128" and "" (zero formats as nothing with zero precision). */
|
||||||
|
T (0, "%.0hhi", U ( 128, 256)); /* { dg-warning "writing up to 4 bytes" } */
|
||||||
|
/* Same as above but with a range of precisions including zero. */
|
||||||
|
T (0, "%.*hhi", /* { dg-warning "writing up to 4 bytes" } */
|
||||||
|
R (0, 1), U ( 128, 256));
|
||||||
|
/* Same as above but with a positive range of precisions. */
|
||||||
|
T (0, "%.*hhi", /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
R (1, 2), U ( 128, 256));
|
||||||
|
/* Precision range includes zero but width is non-zero so output cannot
|
||||||
|
be empty. */
|
||||||
|
T (0, "%1.*hhi", /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
R (0, 2), U ( 128, 256));
|
||||||
|
/* Same as above but with a width range. */
|
||||||
|
T (0, "%*.*hhi", /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
R (1, 2), R (0, 2), U ( 128, 256));
|
||||||
|
/* Same as above but this time width range does include zero. */
|
||||||
|
T (0, "%*.*hhi", /* { dg-warning "up to 4 bytes" } */
|
||||||
|
R (0, 2), R (0, 2), U ( 128, 256));
|
||||||
|
|
||||||
|
/* Range of precisions in excess of the number of digits and sign. */
|
||||||
|
T (0, "%.*hhi", /* { dg-warning "between 5 and 8 bytes" } */
|
||||||
|
R (5, 7), U ( 128, 256));
|
||||||
|
|
||||||
|
/* Between "-128" and "+0". */
|
||||||
|
T (0, "%+hhi", U ( 128, 256)); /* { dg-warning "between 2 and 4 bytes" } */
|
||||||
|
/* Between "-128" and " 0". */
|
||||||
|
T (0, "% hhi", U ( 128, 256)); /* { dg-warning "between 2 and 4 bytes" } */
|
||||||
|
|
||||||
|
T (0, "%hhu", R ( -1, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -1, 12)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -1, 123)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -1, 128)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -1, 257)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -1, 1234)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -12, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -12, 12)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -12, 123)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -12, 128)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -12, 257)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R ( -12, 1234)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R (-123, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R (-123, 12)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R (-123, 123)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R (-123, 257)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R (-123, 1234)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R (-129, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hhu", R (-199, -159)); /* { dg-warning "writing 2 bytes" } */
|
||||||
|
T (0, "%hhu", R (-255, -250)); /* { dg-warning "writing 1 byte" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exercise the h length modifier. */
|
||||||
|
void test_h (void)
|
||||||
|
{
|
||||||
|
T (0, "%hi", R ( -1, 0)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%hi", R ( 0, 1)); /* { dg-warning "writing 1 byte" } */
|
||||||
|
T (0, "%hi", R ( -1, 1)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%hi", R ( -1, 12)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%hi", R ( -12, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%hi", R ( -99, -10)); /* { dg-warning "writing 3 bytes" } */
|
||||||
|
T (0, "%hi", R ( -123, 4)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%hi", R ( -1234, 56)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hi", R ( -1234, 567)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hi", R ( -1234, 5678)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%ho", R (-32768,-32767)); /* { dg-warning "writing 6 bytes" } */
|
||||||
|
|
||||||
|
T (0, "%ho", R ( -1, 0)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||||
|
T (0, "%ho", R ( 0, 1)); /* { dg-warning "writing 1 byte" } */
|
||||||
|
T (0, "%ho", R ( -1, 1)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||||
|
T (0, "%ho", R ( -1, 12)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||||
|
T (0, "%ho", R ( -12, 1)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||||
|
T (0, "%ho", R ( -123, 4)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||||
|
T (0, "%ho", R ( -1234, 56)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||||
|
T (0, "%ho", R ( -1234, 567)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||||
|
T (0, "%ho", R ( -1234, 5678)); /* { dg-warning "between 1 and 6 bytes" } */
|
||||||
|
T (0, "%ho", R (-32768,-32767)); /* { dg-warning "writing 6 bytes" } */
|
||||||
|
|
||||||
|
T (0, "%hu", R ( -1, 0)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hu", R ( 0, 1)); /* { dg-warning "writing 1 byte" } */
|
||||||
|
T (0, "%hu", R ( -1, 1)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hu", R ( -1, 12)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hu", R ( -12, 1)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hu", R ( -123, 4)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hu", R ( -1234, 56)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hu", R ( -1234, 567)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hu", R ( -1234, 5678)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%hu", R (-32768,-32767)); /* { dg-warning "writing 5 bytes" } */
|
||||||
|
|
||||||
|
T (0, "%hx", R (-32768,-32767)); /* { dg-warning "writing 4 bytes" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exercise integer directives with no length modifier. */
|
||||||
|
void test_diou (void)
|
||||||
|
{
|
||||||
|
T (0, "%d", R ( -1, 0)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%i", R ( 0, 1)); /* { dg-warning "writing 1 byte" } */
|
||||||
|
T (0, "%d", R ( -1, 1)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%i", R ( -1, 12)); /* { dg-warning "between 1 and 2 bytes" } */
|
||||||
|
T (0, "%d", R ( -12, 1)); /* { dg-warning "between 1 and 3 bytes" } */
|
||||||
|
T (0, "%i", R ( -123, 4)); /* { dg-warning "between 1 and 4 bytes" } */
|
||||||
|
T (0, "%d", R ( -1234, 56)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%i", R ( -1234, 567)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
T (0, "%d", R ( -1234, 5678)); /* { dg-warning "between 1 and 5 bytes" } */
|
||||||
|
|
||||||
|
T (0, "%u", R ( -1, 0)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||||
|
T (0, "%u", R ( 0, 1)); /* { dg-warning "writing 1 byte" } */
|
||||||
|
T (0, "%u", R ( -1, 1)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||||
|
T (0, "%u", R ( -1, 12)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||||
|
T (0, "%u", R ( -12, 1)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||||
|
T (0, "%u", R ( -123, 4)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||||
|
T (0, "%u", R ( -1234, 56)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||||
|
T (0, "%u", R ( -1234, 567)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||||
|
T (0, "%u", R ( -1234, 5678)); /* { dg-warning "between 1 and 10 bytes" } */
|
||||||
|
|
||||||
|
T (0, "%o", R ( -1, 0)); /* { dg-warning "between 1 and 11 bytes" } */
|
||||||
|
T (0, "%o", R ( -2, 1)); /* { dg-warning "between 1 and 11 bytes" } */
|
||||||
|
T (0, "%o", R ( 0, 1)); /* { dg-warning "writing 1 byte" } */
|
||||||
|
|
||||||
|
T (0, "%x", R ( -1, 0)); /* { dg-warning "between 1 and 8 bytes" } */
|
||||||
|
T (0, "%x", R ( -2, 1)); /* { dg-warning "between 1 and 8 bytes" } */
|
||||||
|
T (0, "%x", R ( 0, 1)); /* { dg-warning "writing 1 byte" } */
|
||||||
|
}
|
|
@ -198,7 +198,7 @@ void test_sprintf_chk_range_schar (void)
|
||||||
/* { dg-message "directive argument in the range \\\[1024, 1034\\\]" "note" { target *-*-* } .-1 } */
|
/* { dg-message "directive argument in the range \\\[1024, 1034\\\]" "note" { target *-*-* } .-1 } */
|
||||||
|
|
||||||
T ( 0, "%hhi", R (1024, 2035)); /* { dg-warning ".%hhi. directive writing between 1 and 4 bytes into a region of size 0" } */
|
T ( 0, "%hhi", R (1024, 2035)); /* { dg-warning ".%hhi. directive writing between 1 and 4 bytes into a region of size 0" } */
|
||||||
/* { dg-message "using the range \\\[0, -128\\\] for directive argument" "note" { target *-*-* } .-1 } */
|
/* { dg-message "using the range \\\[-128, 127\\\] for directive argument" "note" { target *-*-* } .-1 } */
|
||||||
|
|
||||||
#undef R
|
#undef R
|
||||||
#define R(min, max) range_schar (min, max)
|
#define R(min, max) range_schar (min, max)
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* PR tree-optimization/79327 - wrong code at -O2 and -fprintf-return-value
|
||||||
|
{ dg-do run }
|
||||||
|
{ dg-options "-O2 -Wall" } */
|
||||||
|
|
||||||
|
volatile int a, b = -1;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
#define FMT "%+03d%02d"
|
||||||
|
const char *volatile fmt = FMT;
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
int c = a;
|
||||||
|
int d = b;
|
||||||
|
if (c >= -35791395 && c < 35791394 && d >= -1 && d < __INT_MAX__)
|
||||||
|
{
|
||||||
|
/* In the following the range of return values can be computed
|
||||||
|
by GCC. */
|
||||||
|
int n1 = __builtin_sprintf (buf, FMT, c + 1, d + 1);
|
||||||
|
if (n1 > 7)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
/* Here GCC can't see the format string so the return value
|
||||||
|
must be computed by a libc call. */
|
||||||
|
int n2 = __builtin_sprintf (buf, fmt, c + 1, d + 1);
|
||||||
|
|
||||||
|
if (n1 != n2)
|
||||||
|
__builtin_abort ();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue