https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80060
Bug ID: 80060 Summary: RFE: -Wformat knob to ignore same-width incorrect types Product: gcc Version: 6.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: eblake at redhat dot com Target Milestone: --- When porting from one machine to another, especially when porting from 32-bit to 64-bit software, getting warnings about mismatches such as printf("%ld", (uint32_t)1) is awesome. But once something has been ported to a given platform, if two types have the same size but different rank, getting warnings about something that is not portable to other machines but which works in practice on the given machine is very noisy. And sometimes, the noise is unavoidable - there are many situations in which different implementations can pick a type that is consistent for their platform, but uses a different rank than what another platform chose - not all the world uses the <stdint.h> types, but has a variety of other typedefs in place. Here's some examples: on 64-bit Linux, the header <linux/userfaultfd.h> declares a struct with members specified with a typedef __u64: struct uffd_msg msg; struct uffd_msg { .. union { struct { __u64 flags; __u64 address; } pagefault; .. } arg; } Printing one of these values is obvious - the typedef name tells you it should be an unsigned 64-bit quantity, so let's try printf("%"PRIx64, msg.arg.pagefault.flags). Oops, on 64-bit Linux, that fails under -Wformat, because "%ld" is incompatible with 'unsigned long long'. But since the kernel headers typedef'd __u64 without any counterpart to something like PRIx64, there is no sane way to print a __u64 without writing an extra cast at every caller, which is prone to introduce more bugs than the warnings it silences: printf("%"PRIx64, (uint64_t)msg.arg.pagefault.flags). Another case: on 32-bit mingw, the declaration for ntohl() says that it returns a 'u_long', which is a 32-bit type. But POSIX says that ntohl() returns 'uint32_t'. So the obvious printf("%"PRIx32, ntohl(1)) fails to compile on mingw, because 'u_long' (which is 'unsigned long') is incompatible with 'uint32_t' (which is 'unsigned int') on that platform (arguably a bug in mingw's headers, but such is life). Again, the mismatch warning can be avoided with a cast, but that does not scale well: printf("%"PRIx32, (uint32_t)ntohl(1)) gcc recently introduced -Wformat-signedness (and it's counterpart -Wno-format-signedness) to let developers fine-tune how MUCH verbosity they want during warning checks. Are you porting code to a platform where 'int' and 'unsigned int' have different widths? (Some weirdnix hardware might exist like that, and C seems to make it possible, even though I can't name such a system) - then turn the warning on. But if you really DON'T care about "%d" used with 'unsigned', or "%x" used with 'int' (because in the end, the 32-bit value passed through varargs gets reinterpreted into the correct 32-bit value that gets printed, regardless of intermediate sign-incorrectness), then turn it off. So I'd love to have a new knob, maybe named -Wformat-same-rank, which controls whether gcc warns about using the wrong format specifier EVEN THOUGH the type passed to varargs has the same rank and therefore will print accurately; and projects can then use -Wno-format-same-rank to silence __u64/uint64_t or u_long/uint32_t differences while still getting warnings about real bugs of 32-bit vs. 64-bit mismatches.