This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: preprocessing question


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]