On Wed, Oct 19, 2022 at 11:10 AM Nick Desaulniers <ndesaulniers@xxxxxxxxxx> wrote: > > On Wed, Oct 19, 2022 at 10:26 AM Linus Torvalds > > > > Side note: several years ago I tried to make up some sane rules to > > have 'sparse' actually be able to warn when a 'char' was used in a > > context where the sign mattered. > > Do you have examples? Maybe we could turn this into a compiler feature > request. Having prior art on the problem would be a boon. It's been over a decade since I seriously worked on sparse (Hmm. Probably two, actually). And I never got the 'char' logic to work well enough for it to have ever made it into the kernel. I'm also fairly sure I did it wrong - if I recall correctly, I did it on the type system level, and the logic was in the tree simplification, which was always much too weak. Sparse does *some* expression simplification as it builds up the parse tree and does all the type evaluations ("evaludate.c" in sparse), but most of the real optimization work is done on the SSA format. So what I probably *should* have done was to have a special "BEXT" opcode (for "byte extend", the same way sparse has ZEXT and SEXT for well-defined integer zero extend and sign extend), and linearized it with all the simplifications that we do on the SSA level, and then if the BEXT opcode still exists after all our optimization work, we'd warn about it, because that means that the signedness ends up mattering. But sparse originally did almost everything just based on the type system, which was the original intent of sparse (ie the whole "extend the pointer types to have different address spaces" was really what sparse was all about). > Clang's -Wbitfield-constant-conversion can catch that. Yeah, so bitfield signedness is really trivial, and works all on the type system. It's very easy to say: "you defined this member as an implicitly signed bitfield, did you *really* mean to do that?" because signed bitfields simply do not exists in the kernel. So that warning is trivial, and the fix is basically universally change 'int a:1' to 'unsigned a:1', because even *if* you do want signed bitfields, it's just better to make that very very explicit, and write it as 'signed int x:10'. We do have a couple of signed bitfields in the kernel, but they are unusual enough that it's actually a good thing that sparse just made people be explicit about it. Do git grep '\<signed\>.*:[1-9]' to see the (few) examples and a few false positives that trigger in the trace docs. So sparse doesn't actually have to be clever about bitfield signs. It can literally just say "did you really mean to do that", and that's it. Very simple. Not at all the complexity that 'char' has, where every single use technically tends to cause a sign-extension (due to the integer conversion), but that doesn't mean that it *matters* in the end. Linus