Given this sample code:
#define vX(a, ...) ((a)(__VA_ARGS__) ? 1 : 0)
{
int f();
vX(f);
}
I get error C2155: '?': invalid left operand, expected arithmetic or pointer type
On the other hand if I provide a second argument to the macro it compiles fin - eg.:
vX(f,1)
is OK. I'm compiling C code with the msvc compiler.
Sorry to bother everyone but the mistake was on my side - the 2 functions that were giving me error not only had no argument but were of void return type also - that was causing my problem and not anything macro related.
From the GCC documentation:
When the macro is invoked, all the tokens in its argument list after the last named argument (this macro has none), including any commas, become the variable argument. This sequence of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears.
So, basically the __VA_ARGS__ part cannot be empty, that requires GNU extensions (__VA_OPT__).
The specification of the preprocessor about this is somewhat verbose, but suffice it to say, that you specified vX must accept at least two arguments.
The reason is that the number of arguments is largely determined by the number of commas in the macro. So for instance vX(f,) would cause your error to go away as well. The reason is that we again provide two arguments, namely f and an empty sequence of tokens after the comma.
One trick to get around it, is to split the macro across two expansions:
#define vX_(a, ...) ((a)(__VA_ARGS__) ? 1 : 0)
#define vX(...) vX_(__VA_ARGS__,)
Note how I added that comma? Now when you write vX(f) it will expand to vX_(f,) which will expand again to give you the expression you wanted. Although, that will not work in the general case, since you'll get a trailing comma. That is why GCC introduced __VA_OPT__ (#unwind's answer), so that the comma could be added conditionally.
Related
I want to use a variadic macro but it appears to be designed to only treat the first parameter specially. I want the first two parameters to be named and the rest not, like so:
#define FOO(AA,BB,...) AA->BB(AA,##...)
FOO(mystruct,funcname,123)
However this is not working with LLVM. Am I doing something wrong, or is there a limitation to how the variadic macro works?
UPDATE
The correct answer is, use ##VA_ARGS instead of ##...
There are some webpages that claim that "..." is valid but at least with the MacOS llvm it is not.
The macro arguments are not expanded with ... in the macro expansion - how could they, because then you couldn't have a macro that used ellipsis in the expansion. Instead it will be available as a special parameter __VA_ARGS__.
With this, the following program
#define FOO(AA,BB,...) AA->BB(AA, __VA_ARGS__)
FOO(mystruct,funcname,123)
FOO(mystruct,funcname,123,456)
will be preprocessed to
The ## is a token-pasting operator. It will make a single preprocessing token out of 2 parts. , ## ... attempts to make a preprocessing token ,.... It is not a valid C token, and that is why Clang will report
<source>:3:1: error: pasting formed ',...', an invalid preprocessing token
... macro arguments are pasted into macro bodies with __VA_ARGS__.
The problem is how to allow for it to be empty.
If it is empty, you'll usually want to comma before it erased and
you can use the GNU ##__VA_ARGS__ extension to achieve that.
#define FOO(AA,BB,...) AA->BB(AA,##__VA_ARGS__) /*GNU extension*/
FOO(mystruct,funcname) //warning with -pedantic
FOO(mystruct,funcname,123)
The above, however, will trigger warnings if compiled with -pedantic.
If you want your macro usable without warnings at -pedantic, you could perhaps achieve that by swapping the first two arguments in the macro definition.
#define FIRST(...) FIRST_(__VA_ARGS__,)
#define FIRST_(X,...) X
#define BAR_(CallExpr,...) CallExpr(__VA_ARGS__)
#define BAR(BB,/*AA,*/...) BAR_(FIRST(__VA_ARGS__)->BB,__VA_ARGS__)
BAR(funcname,mystruct) //no warning
BAR(funcname,mystruct,123)
I have a library I am porting from Windows to Linux, and I am required to make the minimal number of changes necessary.
There are some function calls in the library that I need to call variants of, with one less parameter and I am trying to use a macro to perform the substitutions.
The issue is that these calls are passing the address of a structure and I'm getting the error "error: "&" may not appear in macro parameter list"
For example, if the library has the following call:
foo(param1, ¶m2);
and I need to replace it with
foo_variant(¶m2);
I am adding a conditional compile at the top of the file as follows:
#if defined LINUX_VARIANT
#define foo(param1, ¶m2) foo_variant(¶m2)
#endif
Is there any way to "escape" the ampersand to avoid this error?
If not, I did see another post that mentioned that a pointer to the struct could be defined, and use the pointer instead of taking the structure's address, but I'd like to avoid that unless there is no other option.
Thanks ahead for any enlightenment!
Just forward the whole argument expression:
#define foo(param1, param2) foo_variant(param2)
Note that, due to limitations of the preprocessor, this macro will fail if any of the arguments contains commas.
Quentin's answer is correct, but to give a bit more background: the preprocessor will textually replace any foo(... with foo_variant(... and will also textually replace the parameters. If one parameter in the C source file has an ampersand, it will just see that as part of the parameter.
So the preprocessor cannot accept an ampersand in its definition, it can accept an ampersand in its expansion. With:
#if defined LINUX_VARIANT
#define foo(param1, param2) foo_variant(¶m2)
#endif
then
foo(p1, p2);
will be replaced by
foo_variant(&p2);
The code I'm working on uses some very convoluted macro voodoo in order to generate code, but in the end there is a construct that looks like this
#define ARGS 1,2,3
#define MACROFUNC_OUTER(PARAMS) MACROFUNC_INNER(PARAMS)
#define MACROFUNC_INNER(A,B,C) A + B + C
int a = MACROFUNC_OUTER(ARGS);
What is expected is to get
int a = 1 + 2 + 3;
This works well for the compiler it has originally been written for (GHS) and also for GCC, but MSVC (2008) considers PARAMS as a single preprocessing token that it won't expand, setting then A to the whole PARAM and B and C to nothing. The result is this
int a = 1,2,3 + + ;
while MSVC warns that not enough actual parameters for macro 'MACROFUNC_INNER'.
Is it possible to get MSVC do the expansion with some tricks (another layer of macro to force a second expansion, some well placed ## or #, ...). Admitting that changing the way the construct work is not an option. (i.e.: can I solve the problem myself?)
What does the C standard say about such corner case? I couldn't find in the C11 norm anything that explicitly tells how to handle arguments that contains a list of arguments. (i.e.: can I argue with the author of the code that he has to write it again, or is just MVSC non-conform?)
MSVC is non-conformant. The standard is actually clear on the point, although it does not feel the need to mention this particular case, which is not exceptional.
When a function-like macro invocation is encountered, the preprocessor:
§6.10.3/11 identifies the arguments, which are possibly empty sequences of tokens separated by non-protected commas , (a comma is protected if it is inside parentheses ()).
§6.10.3.1/1 does a first pass over the macro body, substituting each parameter which is not used in a # or ## operation with the corresponding fully macro-expanded argument. (It does no other substitutions in the macro body in this step.)
§6.10.3.4/1 rescans the substituted replacement token sequence, performing more macro replacements as necessary.
(The above mostly ignores stringification (#) and token concatenation (##), which are not relevant to this question.)
This order of operations unambiguously leads to the behaviour expected by whoever wrote the software.
Apparently (according to #dxiv, and verified here) the following standards-compliant workaround works on some versions of MS Visual Studio:
#define CALL(A,B) A B
#define OUTER(PARAM) CALL(INNER,(PARAM))
#define INNER(A,B,C) whatever
For reference, the actual language from the C11 standard, skipping over the references to # and ## handling:
§6.10.3 11 The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments.…
§6.10.3.1 1 After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list… is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file…
§6.10.3.4 1 After all parameters in the replacement list have been substituted… [t]he resulting preprocessing token sequence is then rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.
C11 says that each appearance of an object-like macro's name
[is] replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive. The replacement list is then rescanned for more macro names as specified below.
[6.10.3/9]
Of function-like macros it says this:
If the identifier-list in the macro definition does not end with an ellipsis, the number of arguments [...] in an invocation of a function-like macro shall equal the number of parameters in the macro definition.
[6.10.3/4]
and this:
The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro.
[6.10.3/11]
and this:
After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list [...] is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.
[6.10.3.1/1]
Of macros in general it also says this:
After all parameters in the replacement list have been substituted [... t]he resulting preprocessing token sequence is then rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.
[6.10.3.4/1]
MSVC++ does not properly expand the arguments to function-like macros before rescanning the expansion of such macros. It seems unlikely that there is any easy workaround.
UPDATE:
In light of #dxiv's answer, however, it may be that there is a solution after all. The problem with his solution with respect to standard-conforming behavior is that there needs to be one more expansion than is actually performed. That can easily enough be supplied. This variation on his approach works with GCC, as it should, and inasmuch as it is based on code that dxiv claims works with MSVC++, it seems likely to work there, too:
#define EXPAND(x) x
#define PAREN(...) (__VA_ARGS__)
#define EXPAND_F(m, ...) EXPAND(m PAREN(__VA_ARGS__))
#define SUM3(a,b,c) a + b + c
#define ARGS 1,2,3
int sum = EXPAND_F(SUM3, ARGS);
I have of course made it a little more generic than perhaps it needs to be, but that may serve you well if you have a lot of these to deal with..
Curiuosly enough, the following appears to work in MSVC (tested with 2010 and 2015).
#define ARGS 1,2,3
#define OUTER(...) INNER PARAN(__VA_ARGS__)
#define PARAN(...) (__VA_ARGS__)
#define INNER(A,B,C) A + B + C
int a = OUTER(ARGS);
I don't know that it's supposed to work by the letter of the standard, in fact I have a hunch it's not. Could still be conditionally compiled just for MSVC, as a workaround.
[EDIT] P.S. As pointed out in the comments, the above is (another) non-standard MSVC behavior. Instead, the alternative workarounds posted by #rici and #JohnBollinger in the respective replies are compliant, thus recommended.
Given
#define cat(x,y) x##y
The call cat(a,1) returns a1, but cat(cat(1,2),3) is undefined.
However if I also define #define xcat(x,y) cat(x,y), then the result of xcat(xcat(1,2),3) is now 123. Can anybody please explain in detail why this is so?
I tested this using both GCC and Clang.
GCC gives the error:
test.c:6:1: error: pasting ")" and "3" does not give a valid preprocessing token
Clang gives the error:
test.c:6:11: error: pasting formed ')3', an invalid preprocessing token
int b = cat(cat(1,2),3);
What appears to be happening is that the compiler wraps the result of cat(1,2) in parentheses as soon as it is expanded; so when you call cat(1,2) in your code, it really gives you (12). Then, calling cat((12),3) again leads to ((12)3), which is not a valid token, and this results in a compile error.
The common opinion is "when using the token-pasting operator (##), you should use two levels of indirection" (i.e., use your xcat workaround). See Why do I need double layer of indirection for macros? and What should be done with macros that need to paste two tokens together?.
In xcat(x,y), the x and y are not adjacent to the ## operator, and
so they undergo macro expansion before being substituted.
So x is identified as xcat(1,2) and y is identified as 3. But prior
to substitution, x is macro-expanded to cat(1,2), which turns into 1##2
which turns into 12. So ultimately, xcat(xcat(1,2),3) will expand
to cat(12,3), which will turn out 123.
This Works --> cat(xcat(1,2),3) --> cat(cat(1,2),3) --> cat(12,3)
The behavior is well-defined because all of the token pastings
result in valid preprocessor tokens i.e any expanded xpression should be a valid token at any stage.
I don't think if cat is actually gonna be expanded for 2 consecutive times. That's why I wonder why would compiler even produce such a message like 'pasting ")" and "3" does not give a valid preprocessing token'.
Also, I don't think the inner cat is gonna be expanded first. So, I presume the output would be cat(1,2)3. That direct me to cogitate how would the compiler interpret this.
In an example project, I defined the macro
#define FOO(x, y) x + y .
This works perfectly well. For example, FOO(42, 1337) is evaluated to 1379.
However, I now want to use another #define:
#define SAMPLE 42, 1337
When I now call FOO(SAMPLE), this won't work. The compiler tells me that FOO takes two arguments, but is only called with one argument.
I guess that the reason for this is that, although, the arguments of a macro are evaluated in advance of the function itself, that the preprocessor does not parse the whole instruction again after this evaluation. This is a similar to the fact that it is not possible to output additional preprocessor directives from a macro.
Is there any possibility to get the desired functionality?
Replacing the FOO macro with a C function is not a possibility. The original macro is located in third party code I cannot change, and it outputs a comma-separated list of values to be directly used in array initializers. Therefore, a C function cannot replicate the same behaviour.
If it is not possible to accomplish this task by using simple means: How would you store the (x, y) pairs in a maintainable form? In my case, there are 8 arguments. Therefore, storing the individual parts in separate #define-s is also not easy maintainable.
You're running into a problem where the preprocessor is not matching and expanding macros in the order you want. Now you can generally get it to do what you want by inserting some extra macros to force it to get the order right, but in order to that you need to understand what the normal order is.
when the compiler sees the name of a macro with arguments followed by a ( it first scans in that argument list, breaking it into arguments WITHOUT recognizing or expanding any macros in the arguments.
after parsing and separating the arguments, it then rescans each argument for macros, and expands any it finds withing the argument UNLESS the argument is used with # or ## in the macro body
it then replaces each instance of the argument in the body with the (now possibly expanded) argument
finally, it rescans the body for any OTHER macros that may exist with the body for expansion. In this one scan, the original macro WILL NOT be recognized and reexpanded, so you can't have recursive macro expansions
So you can get the effect you want by careful use of an EXPAND macro that takes a single argument and expands it, allowing you to force extra expansions at the right point in the process:
#define EXPAND(X) X
#define FOO(x,y) x + y
#define SAMPLE 42, 1337
EXPAND(FOO EXPAND((SAMPLE)))
In this case you first explicitly expand macros in the argument list, and then manually expand the resulting macro call afterwards.
Update by question poster
#define INVOKE(macro, ...) macro(__VA_ARGS__)
INVOKE(FOO, SAMPLE)
provides an extended solution that works without cluttering the code with EXPANDs.