From: Martin Sebor <msebor@gmail.com>
To: Jeff Law <law@redhat.com>
Cc: Jakub Jelinek <jakub@redhat.com>,
Gcc Patch List <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] use zero as the lower bound for a signed-unsigned range (PR 79327)
Date: Fri, 03 Feb 2017 05:37:00 -0000 [thread overview]
Message-ID: <4e3f1cef-925e-af3a-8be5-4257d07925a9@gmail.com> (raw)
In-Reply-To: <b9bf475d-f46c-62c0-80f9-de63a77e2e75@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1214 bytes --]
On 02/02/2017 05:31 PM, Martin Sebor wrote:
>>>> - T (2, "%#hho", a); /* { dg-warning "nul past the end"
>>>> } */
>>>> - T (2, "%#hhx", a); /* { dg-warning ".%#hhx. directive
>>>> writing between 3 and . bytes into a region of size 2" } */
>>>> + T (2, "%#hho", a);
>>>> + T (2, "%#hhx", a);
>>
>> On reflection, this isn't quite the right fix. We want to both set
>> the correct range and warn because the call will likely overflow.
>> This is an example of why the likely/unlikely counters have been
>> introduced. By setting min = 1 and likely = 2 for the %#hho and
>> 3 for the %#hhx we get the desired result.
>
> Attached is a simple patch that removes the vestigial setting of
> the minimum counter while preserving the warnings above by using
> the likely counter.
>
> I had overlooked this when I introduced the likely counter and so
> in the corner cases of "%#o" and "%#x" with a non-constant argument
> that could be zero, the minimum counter would be set to 2 and 3
> respectively rather than 1 (because zero is formatted without
> the '0' or '0x' base prefix).
The attached is an updated version that addresses Jakub's comments
in a separate post.
Martin
[-- Attachment #2: gcc-79327-2.diff --]
[-- Type: text/x-patch, Size: 22719 bytes --]
gcc/ChangeLog:
* gimple-ssa-sprintf.c (tree_digits): Avoid adding octal 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-13.c: New test.
Index: gcc/gimple-ssa-sprintf.c
===================================================================
--- gcc/gimple-ssa-sprintf.c (revision 245142)
+++ gcc/gimple-ssa-sprintf.c (working copy)
@@ -762,7 +762,9 @@ tree_digits (tree x, int base, HOST_WIDE_INT prec,
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;
@@ -1242,6 +1244,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
@@ -1273,6 +1279,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)
{
@@ -1311,12 +1325,14 @@ format_integer (const directive &dir, tree arg)
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);
+ can output. */
+ argmin = integer_zero_node;
+ /* Set the adjustment for an argument whose range includes
+ zero since that doesn't include the octal or hexadecimal
+ base prefix. */
+ likely_adjust = true;
+
int typeprec = TYPE_PRECISION (dirtype);
int argprec = TYPE_PRECISION (argtype);
@@ -1391,7 +1407,24 @@ format_integer (const directive &dir, tree arg)
res.range.min = tmp;
}
- 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));
Index: gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c (revision 245142)
+++ gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c (working copy)
@@ -1152,7 +1152,7 @@ void test_sprintf_chk_hh_nonconst (int w, int p, i
T (2, "% hhx", a); /* { dg-warning ". . flag used with .%x." } */
T (2, "%#hho", a); /* { dg-warning "nul past the end" } */
- T (2, "%#hhx", a); /* { dg-warning ".%#hhx. directive writing between 3 and . bytes into a region of size 2" } */
+ T (2, "%#hhx", a); /* { dg-warning ".%#hhx. directive writing between 1 and . bytes into a region of size 2" } */
T (3, "%0hhd", a);
T (3, "%1hhd", a);
Index: gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-13.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-13.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-13.c (working copy)
@@ -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" } */
+}
Index: gcc/testsuite/gcc.dg/tree-ssa/pr79327-2.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/pr79327-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr79327-2.c (working copy)
@@ -0,0 +1,158 @@
+/* { 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"} } */
next prev parent reply other threads:[~2017-02-03 5:37 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-01 23:52 Martin Sebor
2017-02-02 7:37 ` Jakub Jelinek
2017-02-02 9:52 ` Jakub Jelinek
2017-02-02 14:12 ` Jakub Jelinek
2017-02-03 18:44 ` Jeff Law
2017-02-03 19:02 ` Jakub Jelinek
2017-02-02 16:58 ` Martin Sebor
2017-02-02 19:59 ` Martin Sebor
2017-02-02 23:23 ` Jakub Jelinek
2017-02-03 0:50 ` Martin Sebor
2017-02-03 19:07 ` Jeff Law
2017-02-03 0:31 ` Martin Sebor
2017-02-03 0:48 ` Jakub Jelinek
2017-02-03 5:37 ` Martin Sebor [this message]
2017-02-03 19:02 ` Jeff Law
2017-02-03 19:08 ` Martin Sebor
2017-02-02 22:15 ` Jakub Jelinek
2017-02-03 18:53 ` Jeff Law
2017-02-03 7:35 ` Jeff Law
2017-02-03 16:13 ` Martin Sebor
2017-02-03 16:39 ` Jakub Jelinek
2017-02-03 17:02 ` Martin Sebor
2017-02-03 17:17 ` Jakub Jelinek
2017-02-03 17:49 ` Jeff Law
2017-02-04 8:07 ` Jakub Jelinek
2017-02-06 19:45 ` Jakub Jelinek
2017-02-14 0:15 ` Jeff Law
2017-02-14 7:48 ` Jakub Jelinek
2017-02-14 13:57 ` Jakub Jelinek
2017-02-16 23:22 ` Jeff Law
2017-02-14 16:37 ` Martin Sebor
2017-02-14 16:40 ` Jakub Jelinek
2017-02-14 19:24 ` Martin Sebor
2017-02-14 20:59 ` Jakub Jelinek
2017-02-14 22:17 ` Martin Sebor
2017-02-16 23:34 ` Jeff Law
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4e3f1cef-925e-af3a-8be5-4257d07925a9@gmail.com \
--to=msebor@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--cc=law@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).