Mark A. Odell wrote:
>
> I write a lot of drivers and there is inevitably some hardware register or
> buffer descriptor field called 'flags'. The flags are defined, typically,
> as bit positions. I was thinking I could get some compile-time type
> checking when assigning to a flag field but I don't think I can.
I'll mention the tool we use for the Linux kernel, because some people on
comp.lang.c migth actually find it interesting.
It's called "sparse" (for "semantic parse"), and it extends the C type
system with various flags (much of them for checking "address spaces" of
pointers, since the kernel has to work with pointers that are in distinct
address spaces like "user" and "iomem"), and it also solves your particular
problem.
What you do is make a integer typedef that is restricted to "bitwise"
operations:
#ifdef __CHECKER__ /* Magic sparse flag */
#define __bitwise __attribute__((bitwise))
#else
#define __bitwise
#endif
typedef unsigned int __bitwise cmd_flag_t;
...
#define CMD_ACTIVE ((cmd_flag_t) 0x1000)
...
and you now have a magic new type that you can only do operations on with
the EXACT SAME TYPE (and only bitwise operations too, which is why it's
called "bitwise". We aren't very innovative name-wise in the kernel
So if you do multiple different "typedef"s, they'll all create new
(independent and incompatible) types, so you can create any number of these
different "flags" you want, with different rules.
After that, trying to pass a "cmd_flag_t" variable as an integer will warn
you in various ways. Very convenient. In the kernel we use it to
automatically check that variables that have been marked to be of a
specific byte-order are properly accessed (ie that you don't just take a
little-endian value and think you can use it directly - you have to convert
it to CPU endianness first).
Latest sparse sources available at
http://www.codemonkey.org.uk/projects/bitkeeper/sparse/
(and if you use bitkeeper, at various other sites).
Linus