[v3] c-format: Add -Wformat-int-precision option [PR80060]
Commit Message
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
Comments
On Sun, 21 Nov 2021, Daniil Stas via Gcc-patches wrote:
> 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.
I'd expect this to apply to 'b' and 'B' as well (affects commit message,
ChangeLog entry, option help string, documentation).
On Mon, 22 Nov 2021 20:35:03 +0000
Joseph Myers <joseph@codesourcery.com> wrote:
> On Sun, 21 Nov 2021, Daniil Stas via Gcc-patches wrote:
>
> > 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.
>
> I'd expect this to apply to 'b' and 'B' as well (affects commit
> message, ChangeLog entry, option help string, documentation).
>
Hi Joseph,
I can't find any description of these specifiers anywhere. And looks
like gcc doesn't recognize them when I try to compile a sample program
with them (I just get %B printed when I run the program).
Do these specifiers actually exist? Can you point me to the
documentation?
Thanks
On Tue, 23 Nov 2021, Daniil Stas via Gcc-patches wrote:
> On Mon, 22 Nov 2021 20:35:03 +0000
> Joseph Myers <joseph@codesourcery.com> wrote:
>
> > On Sun, 21 Nov 2021, Daniil Stas via Gcc-patches wrote:
> >
> > > 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.
> >
> > I'd expect this to apply to 'b' and 'B' as well (affects commit
> > message, ChangeLog entry, option help string, documentation).
> >
>
> Hi Joseph,
>
> I can't find any description of these specifiers anywhere. And looks
They're new specifiers in C23. See the most recent working draft
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2731.pdf>.
> like gcc doesn't recognize them when I try to compile a sample program
GCC should recognize them (i.e., not warn about them with -Wformat) if you
have commit bd6f2c63168e89bede631daf8b673eab16acc747 (12 October).
> with them (I just get %B printed when I run the program).
If you want runtime support for those specifiers in printf, you'll need a
libc implementation with support for them. In glibc that means commit
309548bec3b89022bbc81a372ec3e9240211d799 (10 November) or later, for
example.
On Tue, 23 Nov 2021 22:48:24 +0000
Joseph Myers <joseph@codesourcery.com> wrote:
> On Tue, 23 Nov 2021, Daniil Stas via Gcc-patches wrote:
>
> > On Mon, 22 Nov 2021 20:35:03 +0000
> > Joseph Myers <joseph@codesourcery.com> wrote:
> >
> > > On Sun, 21 Nov 2021, Daniil Stas via Gcc-patches wrote:
> > >
> [...]
> > >
> > > I'd expect this to apply to 'b' and 'B' as well (affects commit
> > > message, ChangeLog entry, option help string, documentation).
> > >
> >
> > Hi Joseph,
> >
> > I can't find any description of these specifiers anywhere. And
> > looks
>
> They're new specifiers in C23. See the most recent working draft
> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2731.pdf>.
>
Ah, thank you.
I've sent an updated patch.
@@ -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)))
@@ -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.
@@ -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
new file mode 100644
@@ -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" } */
+}
new file mode 100644
@@ -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 } } */
+}