Reputation: 6740
I believe that the answer to my question is tied to C Preprocessor, Stringify the result of a macro. However, I'm having trouble applying the solution to my use case.
I have this function:
astNodePtr createNode(int lineno, int nodeType, ...);
I have this macro which goes along with it:
#define NODE(nodeType, ...) createNode(yylineno,nodeType,##__VA_ARGS__)
All works fine until I get to a line like this:
NODE(1,x,NODE(2,y,z))
My linker gives me an error: undefined reference to 'NODE'
EDIT:
I've tried (inspired by the fore-mentioned link)
#define EXPAND(x) ##x
#define NODE(nodeType, ...) createNode(yylineno,nodeType, EXPAND(__VA_ARGS__))
However, I got the same error.
EDIT:
I should mention that I also use the macro thus: NODE(5)
Therefore, I need the ##
in front of __VA_ARGS__
in order to avoid the trailing comma problem.
Upvotes: 1
Views: 264
Reputation: 24052
Get rid of the ##
in the macro body. That's blocking the expansion of the nested call. I.e. try:
#define NODE(nodeType, ...) createNode(yylineno,nodeType,__VA_ARGS__)
Update: With the edit to your question, I now understand the need
for the ##
in your macro. Chris Dodd's solution solves this
problem nicely.
Here is another way to do it. This solution adds a layer of expansion which handles the nested macros at the top level, then addresses the trailing comma problem at the lower level:
#define NODE2(nodeType, ...) createNode(yylineno,nodeType,##__VA_ARGS__)
#define NODE(...) NODE2(__VA_ARGS__)
This handles the following sample cases as desired, with no trailing comma:
NODE(a,NODE(b,c))
NODE(x)
NODE(NODE(y))
The advantage to this approach is that it is slightly more general.
In particular, it will work even if there is no mandatory nodeType
argument. For example, if the name is changed to FOO
and the
nodeType
argument is eliminated, the following will work:
#define FOO2(...) createNode(yylineno,##__VA_ARGS__)
#define FOO(...) FOO2(__VA_ARGS__)
This handles the following sample cases, with no trailing comma:
FOO(FOO(b))
FOO()
FOO(FOO())
Upvotes: 4
Reputation: 126203
You actually just need
#define NODE(...) createNode(yylineno, __VA_ARGS__)
The problem is that using ##
also prevents the expansion of macros in the __VA_ARGS__
argument prior to substitution, and, while macros can be exapanded after substitution, they can't be expanded recursively, so if you want to have a NODE
macro in an argument to another NODE
macro, you can't use ##
. Fortunately in your case, you can avoit the need for ##
to get rid of the trailing comma in NODE calls with no extra arguments (which is a non-standard gcc extension anyways) by always having at least one argument for the ...
-- the nodeType
argument.
Upvotes: 2