Difference between gcc and Microsoft preprocessor

c, c-preprocessor, gcc, visual-studio

Solution

# define M3(x, y, z) x + y + z
# define M2(x, y) M3(x, y)
# define P(x, y) {x, y}
# define M(x, y) M2(x, P(x, y))
M(a, b)

Let us roll this out manually, step by step:

M(a, b)
--> M2(a, P(a, b))
--> M2(a, {a, b})

The standard says:

The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate

only parentheses are mentioned, so ...

--> M3(a, {a, b})
--> a + {a + b}

Important:

M3(a, {a, b})

Here, according to the previous quote from the standard, three "arguments" are passed to M3 (using single-quotes to describe tokens/arguments):

M3('a', '{a', 'b}')

which are expanded to

'a' + '{a' + 'b}'

And this is what `cpp` (4.6.1) gives verbatim:

# 1 "cpp.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "cpp.cpp"




a + {a + b}

`cpp` (or `gcc` and `g++`) are correct, MSVC isn't.

As a nobleman make sure a bug report exists.

Problem

I discovered that Microsoft Visual Studio compiler and gcc preprocess the following small snippet differently: ``` # define M3(x, y, z) x + y + z # define M2(x, y) M3(x, y) # define P(x, y) {x, y} # define M(x, y) M2(x, P(x, y)) M(a, b) ``` 'gcc -E' gives the following: ``` a + {a + b} ``` , while 'cl /E' issues a warning about missing macro argument and produces the following output: ``` a + {a, b} + ``` It seems that commas that came from nested macro expansions are not considered to be argument separators. Unfortunately, I found no description of the algorithm implemented in cl preprocessor, and so I'm not sure that my suggestion is correct. Does anyone know how cl preprocessor works and what's the difference between its algorithm and gcc's? And how the observed behaviour can be explained?

Original source