Clang conforms to the standard; Visual Studio doesn't. I think you will have a lot of trouble getting Clang to not conform to the standard, so I won't attempt to answer "how do I get Clang to act like Visual Studio?". Maybe that wasn't really what you wanted to know.
When the compiler identifies the invocation of a function-like macro (that is, a macro with parameters) it expands the macro using the procedure explained in detail in §16.3 [cpp.replace]
of the C++ standard. In the following, I've simplified the procedure by not considering the #
and ##
operators, because they do not appear in your example and the full procedure is more complicated.
We'll examine the invocation MC(int, COMMA, int)
. Here's what happens after the compiler sees the tokens MC
and (
, which indicate an invocation of the macro.
The compiler identifies what the arguments are, which involves finding the closing parenthesis. There are three arguments, which corresponds to the number of parameters, so that's OK. The arguments have not yet been expanded, so the compiler only sees the punctuation actually in the source file. It identifies the arguments as int
, COMMA
and int
.
Every argument (except the ones whose corresponding parameter participates in token concatenation or stringification -- but, as I said, I'm not going to go into that scenario here) are then fully expanded. This happens before they are substituted into the macro body, so that the names of the macro's parameters don't leak out of the macro. So now the three arguments are int
, ,
and int
.
A copy of the macro body is made, in which each parameter is substituted with the corresponding (fully expanded) argument. The macro body ("replacement list", in standardese) was MC(A B C)
; after substituting the arguments, that becomes MC(A , C)
.
The sequence of tokens created in step 3 is inserted into the input in place of the macro invocation, and preprocessing continues.
At this point, the compiler will see the invocation of the function-like macro MC(A, B)
, and will proceed as above. However, this time the first step fails because two arguments are identified but the macro MC
only has one parameter.