Reputation: 241
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?
Upvotes: 17
Views: 2582
Reputation: 29966
The only logic that explains such a behavior looks like this.
CL way:
M(a,b)
M2(a,P(a,b))
M3(a,P(a,b))
M3(a,{a,b}) -> M3 gets 2 arguments ( 'a' and '{a,b}') instead of 3.
| \ /
arg1 |
arg2
Gcc way:
M(a,b)
M2(a,P(a,b))
M3(a,P(a,b))
M3(a,{a,b}) -> Gcc probably thinks there are 3 arguments here ('a', '{a', 'b}').
| | |
arg1 | |
arg2 |
arg3
Upvotes: 4
Reputation: 39089
# 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.
Upvotes: 9
Reputation: 2007
I think gcc gets it right, what Microsoft does is incorrect.
When macro substitution is done for the line
M2(a, P(a, b))
the standard (section 6.10.3.1) requires that before replacing the second parameter ("y") in the macro's replacement list ("M3(x, y)") with its argument ("P(a, b)"), macro replacement is to be performed for that argument. This means "P(a, b)" is processed to "{a, b}" before it is inserted, resulting in
M3(a, {a, b})
which is then further replaced to
a + {a + b}
Upvotes: 1