[PATCH v3] c-format: Add -Wformat-int-precision option [PR80060]

Daniil Stas daniil.stas@posteo.net
Sun Nov 21 14:52:32 GMT 2021


This option is enabled by default when -Wformat option is enabled. A
user can specify -Wno-format-int-precision to disable emitting
warnings when passing an argument of an incompatible integer type to
a 'd', 'i', 'o', 'u', 'x', or 'X' conversion specifier when it has
the same precision as the expected type.

Signed-off-by: Daniil Stas <daniil.stas@posteo.net>

gcc/c-family/ChangeLog:

	* c-format.c (check_format_types): Don't emit warnings when
	passing an argument of an incompatible integer type to
	a 'd', 'i', 'o', 'u', 'x', or 'X' conversion specifier when it has
	the same precision as the expected type if
	-Wno-format-int-precision option is specified.
	* c.opt: Add -Wformat-int-precision option.

gcc/ChangeLog:

	* doc/invoke.texi: Add -Wformat-int-precision option description.

gcc/testsuite/ChangeLog:

	* c-c++-common/Wformat-int-precision-1.c: New test.
	* c-c++-common/Wformat-int-precision-2.c: New test.
---
Changes for v3:
  - Added additional @code{} derictives to the documentation where needed.
  - Changed tests to run on "! long_neq_int" target instead of "lp64".
  - Added a test case to check that gcc still emits warnings for arguments
  with different precision even with -Wno-format-int-precision option enabled.

Changes for v2:
  - Changed the option name to -Wformat-int-precision.
  - Changed the option description as was suggested by Martin.
  - Changed Wformat-int-precision-2.c to use dg-bogus instead of previous
  invalid syntax.

 gcc/c-family/c-format.c                         |  2 +-
 gcc/c-family/c.opt                              |  6 ++++++
 gcc/doc/invoke.texi                             | 17 ++++++++++++++++-
 .../c-c++-common/Wformat-int-precision-1.c      |  7 +++++++
 .../c-c++-common/Wformat-int-precision-2.c      |  8 ++++++++
 5 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wformat-int-precision-1.c
 create mode 100644 gcc/testsuite/c-c++-common/Wformat-int-precision-2.c

diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index e735e092043..c66787f931f 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -4248,7 +4248,7 @@ check_format_types (const substring_loc &fmt_loc,
 	  && (!pedantic || i < 2)
 	  && char_type_flag)
 	continue;
-      if (types->scalar_identity_flag
+      if ((types->scalar_identity_flag || !warn_format_int_precision)
 	  && (TREE_CODE (cur_type) == TREE_CODE (wanted_type)
 	      || (INTEGRAL_TYPE_P (cur_type)
 		  && INTEGRAL_TYPE_P (wanted_type)))
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 3976fc368db..0621585a4f9 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -684,6 +684,12 @@ C ObjC C++ LTO ObjC++ Warning Alias(Wformat-overflow=, 1, 0) IntegerRange(0, 2)
 Warn about function calls with format strings that write past the end
 of the destination region.  Same as -Wformat-overflow=1.
 
+Wformat-int-precision
+C ObjC C++ ObjC++ Var(warn_format_int_precision) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=,warn_format >= 1, 0)
+Warn when passing an argument of an incompatible integer type to a 'd', 'i',
+'o', 'u', 'x', or 'X' conversion specifier even when it has the same precision
+as the expected type.
+
 Wformat-security
 C ObjC C++ ObjC++ Var(warn_format_security) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 2, 0)
 Warn about possible security problems with format functions.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4b1b58318f0..da69d804598 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -351,7 +351,7 @@ Objective-C and Objective-C++ Dialects}.
 -Werror  -Werror=*  -Wexpansion-to-defined  -Wfatal-errors @gol
 -Wfloat-conversion  -Wfloat-equal  -Wformat  -Wformat=2 @gol
 -Wno-format-contains-nul  -Wno-format-extra-args  @gol
--Wformat-nonliteral  -Wformat-overflow=@var{n} @gol
+-Wformat-nonliteral  -Wformat-overflow=@var{n} -Wformat-int-precision @gol
 -Wformat-security  -Wformat-signedness  -Wformat-truncation=@var{n} @gol
 -Wformat-y2k  -Wframe-address @gol
 -Wframe-larger-than=@var{byte-size}  -Wno-free-nonheap-object @gol
@@ -6113,6 +6113,21 @@ If @option{-Wformat} is specified, also warn if the format string is not a
 string literal and so cannot be checked, unless the format function
 takes its format arguments as a @code{va_list}.
 
+@item -Wformat-int-precision
+@opindex Wformat-int-precision
+@opindex Wno-format-int-precision
+Warn when passing an argument of an incompatible integer type to
+a @samp{d}, @samp{i}, @samp{o}, @samp{u}, @samp{x}, or @samp{X} conversion
+specifier even when it has the same precision as the expected type.
+For example, on targets where @code{int64_t} is a typedef for @code{long},
+the warning is issued for the @code{printf} call below even when both
+@code{long} and @code{long long} have the same size and precision.
+
+@smallexample
+  extern int64_t n;
+  printf ("%lli", n);
+@end smallexample
+
 @item -Wformat-security
 @opindex Wformat-security
 @opindex Wno-format-security
diff --git a/gcc/testsuite/c-c++-common/Wformat-int-precision-1.c b/gcc/testsuite/c-c++-common/Wformat-int-precision-1.c
new file mode 100644
index 00000000000..a06e047c933
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wformat-int-precision-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { ! long_neq_int } } } */
+/* { dg-options "-Wformat" } */
+
+void test ()
+{
+  __builtin_printf ("%d\n", (long) 1); /* { dg-warning "expects argument of type" } */
+}
diff --git a/gcc/testsuite/c-c++-common/Wformat-int-precision-2.c b/gcc/testsuite/c-c++-common/Wformat-int-precision-2.c
new file mode 100644
index 00000000000..e9b41b4f42e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wformat-int-precision-2.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { ! long_neq_int } } } */
+/* { dg-options "-Wformat -Wno-format-int-precision" } */
+
+void test ()
+{
+  __builtin_printf ("%d\n", (long) 1); /* { dg-bogus "expects argument of type" } */
+  __builtin_printf ("%d\n", (long long) 1); /* { dg-warning "expects argument of type" "" { target int32 } } */
+}
-- 
2.34.0



More information about the Gcc-patches mailing list