This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: G++ preprocessor problem with unary ##
On Tue, Mar 20, 2001 at 07:43:33AM +0000, Neil Booth wrote:
> Dave Martindale wrote:-
>
> > I use a large C++ library called LEDA. It compiled and ran OK using
> > g++ 2.95, but parts of it will not compile under 2.96. The problem is
> > in the handling of a particular use of the "##" token pasting operator
> > in the preprocessor. Here is a simplified example of the code that
> > causes the problem:
>
> This has come up before.
>
> Simply deleting the ## should work. There is no such thing as unary ##;
> just like there is no such thing as unary division :-) ## pastes two
> surrounding tokens to form a single token; if it doesn't form a single
> token it is an error in the source code.
Um, he said he'd simply deleted the ## and it didn't work. I believe
I know why.
There are two effects of ##. The obvious one is, it pastes together
the two tokens on either side of it. The not-so-obvious one is, it
inhibits pre-expansion of both sides, if they are formal parameters to
the macro. This sample code wants to use ## to suppress formal
parameter pre-expansion, but *not* to paste tokens.
Unfortunately the C++ standard does not countenance using ## just to
suppress formal parameter pre-expansion. The key bit is paragraph 3
of [cpp.concat], section 16.3.3 of C++98; this section is identical to
C99 section 6.10.3.3.
3 For both object-like and function-like macro invocations, before
the replacement list is reexamined for more macro names to replace,
each instance of a ## preprocessing token in the replacement list
(not from an argument) is deleted and the preceding preprocessing
token is concatenated with the following preprocessing token.
[...] If the result is not a valid preprocessing token, the
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
behavior is undefined. The resulting token is available for further
^^^^^^^^^^^^^^^^^^^^^^
macro replacement. The order of evaluation of ## operators is
unspecified.
Emphasis is mine. If ## is used in a context where its result is not
a valid single pp-token, the compiler is permitted to do absolutely
anything it sees fit. It may reject the code outright; it may
interpret it differently from your expectations, producing
compile-time or run-time failures; it may do what you expected it to.
GCC chooses to issue a warning and pretend the ## wasn't there.
The sample code does exactly this, because it wants to suppress
pre-expansion. But you can't have pre-expansion without token
pasting, in standard C++.
zw