[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-sparse
Subject:    Re: more sparse borkage.
From:       Linus Torvalds <torvalds () osdl ! org>
Date:       2004-03-25 20:19:07
Message-ID: Pine.LNX.4.58.0403251157300.1106 () ppc970 ! osdl ! org
[Download RAW message or body]


Ok, 

 as I fixed a confusion I had about type-name visibility that Dave Jones
found, and that affected the hisax/st5481_usb ISDN driver, I realized just
how easy it is to support types as "real entities" in expressions, because
I needed to trigger a warning on such a condition anyway.

So instead of warning about it, I just implemented a limited form of
"types as first-class citizens".

What I wanted to do is to basically do the type equality testign that the
kernel "max()" macro does with that strange "(void) (&_x == &_y)"  
comparison:

	#define max(x,y) ({ \
	        typeof(x) _x = (x);     \
	        typeof(y) _y = (y);     \
	        (void) (&_x == &_y);    \
	        _x > _y ? _x : _y; })

and make it a real type comparison that could be used to actually 
parameterize a macro.

The strange comparison works fine for gettign the warning we want in
"max()", but it doesn't allow us to _behave_ differently depending on the
types. The kernel user access macros use "sizeof" to behave pseudo-
differently depending on types, but you can't do anything fancy with it.

In other words, I wanted to be able to do something like this

	#define format(x) 				\
		(typeof(x) == int ? "%d" :		\
		 typeof(x) == long ? "%ld" : "%x")

	#define print(x) printf(format(x),x)

and it should just work (and work even if "int" and "long" happen to be
the same size).

Now, the above doesn't actually work right now, for a silly reason: the
"(typeof(x)" thing is parsed as a cast, and then the code is unhappy about
not getting the ending ")". In other cases the "typeof" is expected to be
the start of a variable declaration, not an expression. But both those
cases can be worked around with a strange syntactic trick:

	#define format(x)				\
		(0, typeof(x) == int ? "%d" :		\
		 typeof(x) == long ? "%ld" : "%x")

	#define print(x) printf(format(x),x)

and this does indeed work, and because all of it is obviously compile-time 
constants, it even folds correctly.

You can try the above with the x86 toy backend in the current BK tree, and
you'll see how it all is done correctly.

I think the above is a cool feature. It's _especially_ cool if I ever 
actually get around to implementing the untyped inline functions, ie what 
I really want to work is something like

	static inline max(a,b)
	{
		if (typeof(a) != typeof(b))
			__compile_time_warning();
		return a > b ? a : b;
	}

where all argument types are inherited from the context of the calling
process (I may have problems with the return type, sadly).

Cool, or crazy.. You decide.

		Linus
-
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic