This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] handle enumerated types in -Wformat-overflow (PR 80397)
- From: Martin Sebor <msebor at gmail dot com>
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 11 Apr 2017 12:57:02 -0600
- Subject: [PATCH] handle enumerated types in -Wformat-overflow (PR 80397)
- Authentication-results: sourceware.org; auth=none
In a review of my fix for bug 80364 Jakub pointed out that to
determine whether an argument to an integer directive is of
an integer type the gimple-ssa-sprintf pass tests the type code
for equality to INTEGER_TYPE when it should instead be using
INTEGRAL_TYPE_P(). This has the effect of the pass being unable
to use the available range of arguments of enumerated types,
resulting in both false positives and false negatives, and in
some cases, in emitting suboptimal code.
The attached patch replaces those tests with INTEGRAL_TYPE_P().
Since this is not a regression I submit it for GCC 8.
Martin
PR tree-optimization/80397 - missing -Wformat-overflow with arguments of enum types
gcc/ChangeLog:
PR tree-optimization/80397
* gimple-ssa-sprintf.c (format_integer): Use INTEGRAL_TYPE_P()
instead of testing for equality to INTEGER_TYPE.
gcc/testsuite/ChangeLog:
PR tree-optimization/80397
* gcc.dg/tree-ssa/builtin-sprintf-warn-17.c: New test.
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 2e62086..d63d5be 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -1249,7 +1249,7 @@ format_integer (const directive &dir, tree arg)
return res;
}
- else if (TREE_CODE (TREE_TYPE (arg)) == INTEGER_TYPE
+ else if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
|| TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE)
/* Determine the type of the provided non-constant argument. */
argtype = TREE_TYPE (arg);
@@ -1269,7 +1269,7 @@ format_integer (const directive &dir, tree arg)
if (arg
&& TREE_CODE (arg) == SSA_NAME
- && TREE_CODE (argtype) == INTEGER_TYPE)
+ && INTEGRAL_TYPE_P (argtype))
{
/* Try to determine the range of values of the integer argument
(range information is not available for pointers). */
@@ -1314,7 +1314,7 @@ format_integer (const directive &dir, tree arg)
if (code == NOP_EXPR)
{
tree type = TREE_TYPE (gimple_assign_rhs1 (def));
- if (TREE_CODE (type) == INTEGER_TYPE
+ if (INTEGRAL_TYPE_P (type)
|| TREE_CODE (type) == POINTER_TYPE)
argtype = type;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-17.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-17.c
new file mode 100644
index 0000000..e043938
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-17.c
@@ -0,0 +1,62 @@
+/* PR tree-optimization/80397 - missing -Wformat-overflow with arguments
+ of enum types
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" }
+ { dg-require-effective-target int32plus } */
+
+void sink (char*);
+
+long long integer_range (long long min, long long max)
+{
+ extern long long integer_value (void);
+ long long n = integer_value ();
+ return n < min || max < n ? min : n;
+}
+
+typedef enum { i0, imax = __INT_MAX__ } Int;
+typedef enum { ll0, llmax = __LONG_LONG_MAX__ } LLong;
+
+#define R(T, min, max) (T)integer_range (min, max)
+
+char buffer[1];
+#define T(fmt, ...) \
+ __builtin_sprintf (buffer + 1, fmt, __VA_ARGS__), sink (buffer)
+
+void test_bool (_Bool b)
+{
+ T ("%hhi", b); // { dg-warning "writing 1 byte" }
+ T ( "%hi", b); // { dg-warning "writing 1 byte" }
+ T ( "%i", b); // { dg-warning "writing 1 byte" }
+}
+
+void test_enum (void)
+{
+ T ("%hhi", R (Int, 1, 1)); // { dg-warning "writing 1 byte" }
+ T ("%hhi", R (Int, 1, 22)); // { dg-warning "between 1 and 2 bytes" }
+
+ T ( "%hi", R (Int, 1, 2)); // { dg-warning "writing 1 " }
+ T ( "%hi", R (Int, 1, 22)); // { dg-warning "between 1 and 2 " }
+ T ( "%hi", R (Int, 22, 333)); // { dg-warning "between 2 and 3 " }
+ T ( "%hi", R (Int, 333, 4444)); // { dg-warning "between 3 and 4 " }
+
+ T ( "%i", R (Int, 1, 1)); // { dg-warning "writing 1 " }
+ T ( "%i", R (Int, 1, 22)); // { dg-warning "between 1 and 2 " }
+ T ( "%i", R (Int, 22, 333)); // { dg-warning "between 2 and 3 " }
+ T ( "%i", R (Int, 333, 4444)); // { dg-warning "between 3 and 4 " }
+ T ( "%i", R (Int, 4444, 55555)); // { dg-warning "between 4 and 5 " }
+
+#if __LONG_MAX__ == __LONG_LONG_MAX__
+# define LLI "%li"
+#else
+# define LLI "%lli"
+#endif
+
+ T (LLI, R (LLong, 1, 1)); // { dg-warning "writing 1 " }
+ T (LLI, R (LLong, 1, 22)); // { dg-warning "between 1 and 2 " }
+ T (LLI, R (LLong, 22, 333)); // { dg-warning "between 2 and 3 " }
+ T (LLI, R (LLong, 333, 4444)); // { dg-warning "between 3 and 4 " }
+ T (LLI, R (LLong, 4444, 55555)); // { dg-warning "between 4 and 5 " }
+
+ T (LLI, R (LLong, 4444, 1234567890)); // { dg-warning "between 4 and 10 " }
+ T (LLI, R (LLong, 4444, 12345678901)); // { dg-warning "between 4 and 11 " }
+}