01 April 2009

Type checking macros

#define to_cpumask(bitmap)                                              \
((struct cpumask *)(1 ? (bitmap) \
: (void *)sizeof(__check_is_bitmap(bitmap))))
static inline int __check_is_bitmap(const unsigned long *bitmap)
{
return 1;
}


The above macro is nothing but just
#define to_cpumask(bitmap) (struct cpumask *)(bitmap)

But it also does a compile-time checking that the parameter passed is of type
(const unsigned long *). If it is defined as an function all these ugly magic is not
needed. But a function cannot be used as a static initializer. Try declaring a variable,
static int a = printf("ok");
and one would get an error, "Initializer element is not constant".

I really wonder whether gcc might one day optimize out your type-checking call to the unused
function in tha above macro?! A solution could be providing an official gcc extension to assert types?!
Also the above code compiles fine without sizeof constification as well i.e., just return a void * from the
__check_is_bitmap() and remove the sizeof and casting.

I found the above code in the linux kernel. See http://lkml.org/lkml/2009/3/25/22
for the discussion. Even the ubiquitous printf, printk or any vararg code does not check for types. So
I wonder whether kernel developers need such tricky^Wugly code just for type checking, given that
the callers would likely read the definition of the macro as well. It is not a closed api.

Any other project uses such type-checking macros?

No comments: