Re: [PATCH 00/16] mm: prepare for converting vm->vm_flags to 64-bit

Linus Torvalds
2012-03-22T22:39:23Z

On Thu, Mar 22, 2012 at 3:24 PM, Konstantin Khlebnikov
<khlebnikov@openvz.org> wrote:
>
> # define __nocast       __attribute__((nocast))
>
> typedef long __nocast long_t;

So the intention is that this really creates a *new* type.

So "long_t" really is a different type from "long", but because
__nocast is so weak, it happily casts to another integer type of the
same size.

But a pointer to it is different, the same way "int *" is different
from "long *" even if "int" and "long" happen to have the same size.
So I do think that the warning you quote is correct and expected:

> 1.c:13:12: warning: incorrect type in argument 1 (different modifiers)
> 1.c:13:12:    expected int [nocast] [usertype] *x
> 1.c:13:12:    got int *<noident>
> 1.c:13:12: warning: implicit cast to nocast type
>
> Is this ok?

Yes.

The thing about __nocast is that it's so *very* very easy to lose it.
For example, do this:

typedef long __nocast long_t;

int main(long_t a)
{
return a;
}

and you get the (expected) warning.

HOWEVER. Now do "return a+1" instead, and the warning goes away. Why?
Because the expression ends up having just the type "long", because
the "a" mixed happily with the "1" (that was cast from 'int' to 'long'
by the normal C type rules).

That is arguably a bug, but this kind of thing really wasn't what
__nocast was designed for. The __nocast design ended up being too
weak, though, and we hardly use it in the kernel.

Linus