Re: Unsigned widening casts of binary "not" operations..

From: Linus Torvalds
Date: Tue Apr 23 2013 - 11:42:55 EST


On Tue, Apr 23, 2013 at 8:24 AM, David Laight <David.Laight@xxxxxxxxxx> wrote:
>
> Thinks ... converting:
> foo &= ~bar;
> to:
> foo = ~(~foo | bar);
> would generally DTRT.

Quite frankly, I'd rather just try to make people (re)move the widening cast.

So while

foo &= ~bar;

is unsafe if bar is narrower than foo, it's unsafe simply because the
implicit cast from the C type conversions comes *after* the binary
not.

An explicit cast fixes it, and shows that you were aware of the issue:

foo &= ~(foo_t)bar;

and gcc will generate the right logic. Of course, casts then have
their own problems, which your thing avoids (as would just having a
"andn" operation in C)

The best case is for code that does bitmasking ops like this to avoid
any casts (implicit or explicit) by just avoiding mixed types. That
was, to a large degree, my hope for the sparse patch, but it's
nontrivial. Many types are rather "natural" (ie constants have a
natural "int" type, sizeof() is size_t, etc) and in other cases you
want to do the same ops for two different types (with the case that
caused me to start to look at it being the "align to page boundary"
for a virtual address vs a PAE phys_addr_t) so you can't really avoid
mixing things in some circumstances.

Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/