I was looking at a bit of code, the problematic portion, after wading through many layers of nested macro hell, was roughly of the form:
void traceFunction( int n, ... )
{
}
int main()
{
#define TUPLE( size, arg ) (size), (arg)
#define traceInt( sz1, ptr1 ) traceFunction( 1, sz1, ptr1 )
#define trace( arg1 ) traceInt( arg1 )
int x = 3 ;
trace( TUPLE( sizeof(x), &x ) ) ;
return 0 ;
}
Observe that one of the macros produces a comma separated list of arguments, and that the `trace` macro, which ends up actually called with two parameters (the result of the `TUPLE` macro), is declared as if it has a single parameter.
Somewhat mysteriously, this actually compiles on many different platforms and compilers (about 16 different combinations), but breaks with the intel 13 compiler beta (although that compiler does have a compatibility mode that I’d prefer not to depend on)
I figured I could fix this with:
#define trace( sz1, ptr1 ) traceFunction( 1, sz1, ptr1 )
eliminating the middle man, but this gives me, for C++:
t.C(23): error: identifier “trace” is undefined
and for C compilation:
t.c(23): error #54: too few arguments in invocation of macro “trace”
error, indicating that the attempt to expand the macro `trace` occurs before the attempt to expand the `TUPLE` macro. I think I can fix this provided I rely on C99 macro varargs like so:
#define traceInt( sz1, ptr1 ) traceFunction( 1, sz1, ptr1 )
#define trace( ... ) traceInt( __VA_ARGS__ )
That’s likely an acceptable solution, given that we’ve now got other dependencies on C99 __VA_ARGS__ in the code.
It appears that, rather luckily, I never needed to know exactly what order nested macro expansion happens in before this.