When I was first learning C, one thing that confused me was how you can just use plain "unsigned" as a type, without specifying the length (long, short, int, etc.). Thus, I thought that casting to unsigned would just change the sign like a call to abs(), without realizing that there was an implicit "int" involved. I made a testcase:
$ cat bare_unsigned.c
unsigned var; /* debatable */
unsigned long foo(void)
long variable = LONG_MAX;
unsigned long uvariable = (unsigned)variable; /* warn here */
The one where I added the "debatable" comment is debatable because I actually see a lot of declarations in that form pretty often, and it's probably not very harmful in that case, but the case with the cast, where it says "warn here", is probably more deserving of a warning, as there's a change of size involved. It might make sense to include this under -Wimplicit-int, or maybe create a new warning -Wbare-unsigned for it?
Maybe just diagnose at the point of conversions that are not just sign conversions but truncations/extensions?
Note even then this will have a high rate of false positives (I'm myself
always short-cutting 'unsigned int' to 'unsigned' ...) so it's more of
a coding-style diagnostic where then warning for all plain 'unsigned'
might be appropriate as well.
So, maybe split it even. -Wconversion-bare-unsigned and -Wbare-unsigned?
Oh, one other thing I'd note here is that gcc/README.portability contains a part about this, too; I'm copying and pasting it here:
In C, the 'int' keyword can often be omitted from type declarations.
For instance, you can write
as shorthand for
unsigned int variable;
There are several places where this can cause trouble. First, suppose
'variable' is a long; then you might think
would convert it to unsigned long. It does not. It converts to
unsigned int. This mostly causes problems on 64-bit platforms, where
long and int are not the same size.