Jan Beulich wrote:- > Can anyone set me strait on why, in the following code fragment > > int x(unsigned); > > struct alt_x { > unsigned val; > }; > > #define x alt_x > #define alt_x(p) x(p+1) > > int test(struct x *p) { > return x(p->val); > } > > the function invoked in test() is alt_x (rather than x)? I would have > expected that the preprocessor > - finds that x is an object like macro, and replaces it with alt_x > - finds that alt_x is a function-like macro and replaces it with x(...) > - finds that again x is an object like macro, but recognizes that it > already participated in expansion, so doesn't replace x by alt_x a > second time. > > Our compiler team also considers this misbehavior, but since I > tested three other compilers, and they all behave the same, I > continue to wonder if I'm mis-reading something in the standard.
The way GCC works is, once you've had to suck in the '(' for the expansion of alt_x, you've left x, and further replacements are not considered nested within x. This is the behaviour of Dave Prosser's algorithm that the C90 committee agreed on, and then converted to (ambiguous) words. Their general approach was to expand as much as possible when you could be sure of not recursing. Since the '(' leaves the original expansion to suck in more tokens this is the case. You will find GCC behaves the same even if just the ')' leaves the original x. This tends also to be the most useful behaviour when writing macros, and *is* relied upon by a lot of software. Changing the expansion rules will break a lot of GCC's testcases, which I intentionally wrote to cover its algorithm pretty well, so it couldn't be accidentally broken in future. Neil.