Hi! On Mon, Feb 25, 2019 at 11:18:31AM -0800, Jon Flatley wrote: > Hello, > > I am doing a some investigation into some of the format options used > in the upstream Linux Kbuilds in both GCC and Clang. This started when > I noticed -Wformat is used when building the kernel with GCC, but not > with Clang. As it turns out, this is important. Enabling format > warnings in Clang leads to hundreds of warnings when building the > Linux kernel, see here: > > https://gist.github.com/nathanchance/443db156e56cd3c0f6b21d9d77728d80 > > After some more investigating I found a little code snippet that > demonstrates the discrepancy. > For example consider the following: > int i = 5; > printf("%hu\n", i); > printf("%zu\n", i); > > GCC produces only one warning under -Wformat on the second print > statement, where Clang produces warnings for both. > > Compiling that example with GCC under -Wformat prints: > format_test.c:7:13: warning: format ‘%zu’ expects argument of type > ‘size_t’, but argument 2 has type ‘int’ [-Wformat=] > printf("%zu\n", i); > ~~^ > %u > > But compiling with Clang under -Wformat prints: > format_test.c:6:19: warning: format specifies type 'unsigned short' but the > argument has type 'int' [-Wformat] > printf("%hu\n", i); > ~~~ ^ > %d > format_test.c:7:19: warning: format specifies type 'size_t' > (aka 'unsigned long') but the argument has type 'int' [-Wformat] > printf("%zu\n", i); > ~~~ ^ > %d > 2 warnings generated. > > > I was hoping I could reach out and gain some insight as to why GCC > ignores these scenarios where Clang produces warnings. This would be > very helpful as we move to enable -Wformat for both GCC and Clang in > the upstream kernel, which is an issue we're tracking here: > https://github.com/ClangBuiltLinux/linux/issues/378 You cannot pass a short int to a varargs function like printf, it is always promoted to int. As the C standard says for the h flag character: h Specifies that a following d, i, o, u, x, or X conversion specifier applies to a short int or unsigned short int argument (the argument will have been promoted according to the integer promotions, but its value shall be converted to short int or unsigned short int before printing); or that a following n conversion specifier applies to a pointer to a short int argument. Assuming the integer started out as short int before passing it to the printf function is something GCC does not do; it will warn on a lot of perfectly valid code. Segher