There's an unpleasant case in conditional operator we are getting wrong. int *p; const void *v; int n; n ? p : (const void *)0 According to C standard, the type of that expression is const void *. Note that n ? p : (void *)0 is an entirely different story - it's int *. What's going on here is pretty simple: there are two degenerate cases of conditional operator: pointer vs. null pointer constant and pointer vs. possibly qualified pointer to void. Look at these cases: n ? p : NULL => should be the same type as p n ? p : v => clearly const void * - pointer to void with union of qualifiers; in this case we obviously lose any information about the type of object being pointed to. The tricky part comes from definition of what null pointer constant _is_. C allows two variants - integer constant expression with value 0 (we accept it, but warn about bad taste) and the same cast to void * (we also accept that, of course). Note that this is specific type - pointer to void. Without any qualifiers. We are guaranteed that we can convert it to any pointer type and get a pointer distinct from address of any object. So (const void *)0 is the same thing as (const void *)(void *)0 and it is the null pointer to const void. *HOWEVER*, it is not a null pointer constant. The standard is clear here and frankly, it's reasonable. If you cast to anything other than void *, then you presumably mean it and want the conversion rules as for any pointer of that type. Think of something like #ifdef FOO const void *f(int n); #else #define f(n) ((const void *)NULL) #endif You don't want to have types suddenly change under you depending on FOO. sparse is more liberal than standard C in what it accepts as null pointer constant. It almost never matters; however, in case of conditional operator we end up with a different type for an expression both sparse and any C compiler will accept as valid. I'm fixing other fun stuff in that area (e.g. we ought to take a union of qualifiers, ought _not_ to mix different structs or unions, etc.), so unless there are serious objections I'd rather go with standard behaviour in that case. What will change: int n; int *p; n ? p : (const void *)NULL int * => const void * n ? p : (const void *)0 ditto n ? p : (char *)0 int * => a warning on mixing int * with char * n ? p : (char *)NULL ditto n ? p : (void *)NULL int * => void * n ? p : (void *)0 unchanged n ? p : NULL unchanged Objections? - To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html