Re: [PATCH] lib/test_printf.c: fix clang -Wformat warnings

From: Nathan Chancellor
Date: Thu Jun 30 2022 - 12:03:13 EST


Hi Justin,

On Wed, Jun 29, 2022 at 04:53:26PM -0700, Justin Stitt wrote:
> see warnings:
> | lib/test_printf.c:157:52: error: format specifies type 'unsigned char'
> | but the argument has type 'int' [-Werror,-Wformat] test("0|1|1|128|255",
> | "%hhu|%hhu|%hhu|%hhu|%hhu", 0, 1, 257, 128, -1);
> -
> | lib/test_printf.c:158:55: error: format specifies type 'char' but the
> | argument has type 'int' [-Werror,-Wformat] test("0|1|1|-128|-1",
> | "%hhd|%hhd|%hhd|%hhd|%hhd", 0, 1, 257, 128, -1);
> -
> | lib/test_printf.c:159:41: error: format specifies type 'unsigned short'
> | but the argument has type 'int' [-Werror,-Wformat]
> | test("2015122420151225", "%ho%ho%#ho", 1037, 5282, -11627);
>
> There's an ongoing movement to eventually enable the -Wformat flag for
> clang. Previous patches have targeted incorrect usage of
> format specifiers. In this case, however, the "incorrect" format
> specifiers are intrinsically part of the test cases. Hence, fixing them
> would be misaligned with their intended purpose. My proposed fix is to
> simply disable the warnings so that one day a clean build of the kernel
> with clang (and -Wformat enabled) would be possible. It would also keep
> us in the green for alot of the CI bots.
>
> Suggested-by: Nick Desaulniers <ndesaulniers@xxxxxxxxxx>
> Signed-off-by: Justin Stitt <justinstitt@xxxxxxxxxx>
> ---
> lib/test_printf.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/lib/test_printf.c b/lib/test_printf.c
> index 07309c45f327..748591a0c55c 100644
> --- a/lib/test_printf.c
> +++ b/lib/test_printf.c
> @@ -4,6 +4,12 @@
> */
>
> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +#define DO_PRAGMA(x) _Pragma(#x)
> +#define NOWARN(warnoption, ...)
> + DO_PRAGMA(GCC diagnostic push)
> + DO_PRAGMA(GCC diagnostic ignored #warnoption)
> + __VA_ARGS__
> + DO_PRAGMA(GCC diagnostic pop)

This is basically a duplicate of the __diag infrastructure that exists
in include/linux/compiler_types.h and include/linux/compiler-clang.h, I
think we should just reuse that here. It eliminates this hunk and the
hunk below...

> #include <linux/init.h>
> #include <linux/kernel.h>
> @@ -154,9 +160,13 @@ test_number(void)
> test("0x1234abcd ", "%#-12x", 0x1234abcd);
> test(" 0x1234abcd", "%#12x", 0x1234abcd);
> test("0|001| 12|+123| 1234|-123|-1234", "%d|%03d|%3d|%+d|% d|%+d|% d", 0, 1, 12, 123, 1234, -123, -1234);
> + /* disable -Wformat for this chunk */
> + NOWARN(-Wformat,
> test("0|1|1|128|255", "%hhu|%hhu|%hhu|%hhu|%hhu", 0, 1, 257, 128, -1);
> test("0|1|1|-128|-1", "%hhd|%hhd|%hhd|%hhd|%hhd", 0, 1, 257, 128, -1);
> test("2015122420151225", "%ho%ho%#ho", 1037, 5282, -11627);
> + )
> + /* end chunk */
> /*
> * POSIX/C99: »The result of converting zero with an explicit
> * precision of zero shall be no characters.« Hence the output

...becomes a lot simpler in my opinion (feel free to reword the comment
however you want).

Cheers,
Nathan

diff --git a/lib/test_printf.c b/lib/test_printf.c
index 8010de49b6c5..86e088ad9e48 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -154,9 +154,12 @@ test_number(void)
test("0x1234abcd ", "%#-12x", 0x1234abcd);
test(" 0x1234abcd", "%#12x", 0x1234abcd);
test("0|001| 12|+123| 1234|-123|-1234", "%d|%03d|%3d|%+d|% d|%+d|% d", 0, 1, 12, 123, 1234, -123, -1234);
+ __diag_push();
+ __diag_ignore(clang, 11, "-Wformat", "These trigger clang's -Wformat and the specifiers should not be changed.");
test("0|1|1|128|255", "%hhu|%hhu|%hhu|%hhu|%hhu", 0, 1, 257, 128, -1);
test("0|1|1|-128|-1", "%hhd|%hhd|%hhd|%hhd|%hhd", 0, 1, 257, 128, -1);
test("2015122420151225", "%ho%ho%#ho", 1037, 5282, -11627);
+ __diag_pop();
/*
* POSIX/C99: »The result of converting zero with an explicit
* precision of zero shall be no characters.« Hence the output