C++11 nested macro invocation?

c, c++, c++11, macros

Solution

This explains the original intent, and why no clarifications have been added to the standard about this subject:

http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#268

268. Macro name suppression in rescanned replacement text

Section: 16.3.4 [cpp.rescan] Status: open Submitter: Bjarne Stroustrup Date: 18 Jan 2001

It is not clear from the Standard what the result of the following example should be:

#define NIL(xxx) xxx
#define G_0(arg) NIL(G_1)(arg)
#define G_1(arg) NIL(arg)
G_0(42)

The relevant text from the Standard is found in 16.3.4 [cpp.rescan] paragraph 2:

[snipped]

The sequence of expansion of `G0(42)` is as follows:

G0(42)
NIL(G_1)(42)
G_1(42)
NIL(42)

The question is whether the use of `NIL` in the last line of this sequence qualifies for non-replacement under the cited text. If it does, the result will be `NIL(42)`. If it does not, the result will be simply `42`.

The original intent of the J11 committee in this text was that the result should be `42`, as demonstrated by the original pseudo-code description of the replacement algorithm provided by Dave Prosser, its author. The English description, however, omits some of the subtleties of the pseudo-code and thus arguably gives an incorrect answer for this case.

Suggested resolution (Mike Miller): [snipped]

Notes (via Tom Plum) from April, 2004 WG14 Meeting:

Back in the 1980's it was understood by several WG14 people that there were tiny differences between the "non-replacement" verbiage and the attempts to produce pseudo-code. The committee's decision was that no realistic programs "in the wild" would venture into this area, and trying to reduce the uncertainties is not worth the risk of changing conformance status of implementations or programs.

Problem

It says in C++ std 16.3.4: The resulting preprocessing token sequence [from a macro invocation replacement] is rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace. If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced. What exactly is a nested macro replacement? Specifically consider: ``` #define f(x) 1 x #define g(x) 2 x g(f)(g)(3) ``` I would have expected the following: ``` g(f)(g)(3) <-- first replacement of g, ok 2 f(g)(3) <-- nested replacement of f, ok 2 1 g(3) <-- second nested replacement of g, don't replace, stop ``` However gcc unexpectedly goes ahead with the second replacement of g, producing: ``` 2 1 2 3 ``` Any ideas? Update: After much research, let me clear up this issue with a simpler example: ``` #define A(x) B #define B(x) A(x) A(i)(j) ``` This expands as follows: ``` A(i)(j) B(j) A(j) ``` The standard does not specify whether `A(j)` should be expanded to `B` or not. The committee decided to leave it this way because real world programs are not expected to depend on this behavior, so both leaving `A(j)` unexpanded and expanding `A(j)` to `B` are considered conformant.

Original source