Varargs macros subtly broken

Neil Booth NeilB@earthling.net
Tue Sep 26 15:21:00 GMT 2000


Jamie Lokier wrote:-

> If GCC _has_ to change to comply with a standard, fair enough but I
> think that in this case there is a genuine bug somewhere in the
> preprocessor, to do with nested varargs processing.  My macros happen to
> trigger it.  Hopefully Neil can work out what's going on.

It's a bug, and it's nasty.  "subtly broken" is fitting.  The
expansion algorithm assumes that if it has come across an identifier
during macro expansion that has previously failed expansion, then it
cannot be expanded again.  There are 2 possibilities: either the
identifier has already been expanded, and hence is permanently "off",
or maybe it was a function-like macro without a following '('.  If it
didn't have a following '(' previously one won't magically appear in
future expansions.  Seems reasonable if you think about it, but sadly
your testcase has proven this last assumption wrong.  Consider an
argument to a (necessarily varargs) macro of the form

"F, b"

where F is a function-like macro (very common in your *cough* macros).
F cannot be expanded here because no '(' follows it.  However, this
argument can be substituted within the expansion list of a macro, say
SomeMacro, causing it to be *split up* as so:

#define SomeMacro(...) A(__VA_ARGS__)
#define A(a, b) a(b)

SomeMacro(F, b)

And here, in the expansion of A, F now has the required '(' after it,
and so undergoes expansion itself.  What a shame.

Needless to say, I don't think I can fix this within the current code.
It's convinced me that even staying within the C99 standard
single-pass expansion is doomed to fail.  We need to revert to re-scan
passes, and this will take a while.  The nice thing is that the code
will be easier to understand again.

At least we get 99.9999% of macro expansions correct, so it's not too
bad if it remains broken for a short while longer.

Neil.


More information about the Gcc-bugs mailing list