This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: A token pasting corner case?
- To: David August <august at CS dot Princeton dot EDU>
- Subject: Re: A token pasting corner case?
- From: Neil Booth <neil at daikokuya dot demon dot co dot uk>
- Date: Sat, 13 Jan 2001 13:08:02 +0000
- Cc: gcc at gcc dot gnu dot org
- References: <20010112194248.A26126@chinstrap.CS.Princeton.EDU>
David August wrote:-
> I am sure everyone is sick of hearing people complain about the "valid
> preprocessing token" warning.
No, we love it :-) Actually, the warning has been improved a bit, so I
think the amount of reports will go down. We'll still get them from
those who don't understand what ## really does. And probably more
like yours, too.
> Please consider the following:
>
> #define DUDE STACK
> #define FUNC2(val1, val2) val1 HEY_ ## val2
> #define FUNC1(val1, val2) FUNC2(val1, ## val2)
>
> FUNC1(I SAY, DUDE)
>
> On egcs-2.91.66, this expands to:
>
> I SAY HEY_DUDE
>
> On 2.96, this expands to (and gives a warning of course):
>
> I SAY HEY_STACK
Right. 2.96 (Redhat?) had quite a few preprocessor bugs. Here's what
current cpp says:-
bash-2.04$ ./cpp0 /tmp/test.c
/tmp/test.c:5:1: warning: pasting "," and "DUDE" does not give a valid preprocessing token
# 5 "/tmp/test.c"
I SAY HEY_DUDE
Fair enough, in my opinion 8-)
> Essentially, we need to delay the expansion of DUDE to STACK until
> the lowest level by using the pasting:
>
> #define FUNC1(val1, val2) FUNC2(val1, ## val2)
>
> which seems to do the trick. It is really nice to be able to delay
> the expansion (or final pasting) of DUDE until the lowest level.
Right. I will assume you don't care about using GCC extensions, since
what you've got is not portable anyway, and that there's no other way
to write your macros.
There's a GCC extension we've documented now, that says variable
arguments can be "pasted" with a comma, and that that this "pasting"
is the same as just supplying the variable arguments after the comma.
The reason this exists is for the case where the varargs are empty or
missing - in that case a further extension says that in these cases
the ## swallows the comma.
So, with this in mind, let's try:-
#define DUDE STACK
#define FUNC2(val1, val2) val1 HEY_ ## val2
#define FUNC1(val1, val2...) FUNC2(val1, ## val2)
FUNC1(I SAY, DUDE)
The above file gives:-
bash-2.04$ ./cpp0 /tmp/test.c
# 5 "/tmp/test.c"
I SAY HEY_DUDE
Without warnings :-)
But now you've got a variadic macro you don't realy want. Let's see
what happens if we try stuff you don't want, like no arguments or more
than one argument. Adding
FUNC1(I SAY)
FUNC1(I SAY, THERE, DUDE)
adds the following to output:-
/tmp/test.c:6:1: macro "FUNC2" requires 2 arguments, but only 1 given
/tmp/test.c:7:1: macro "FUNC2" passed 3 arguments, but takes just 2
FUNC2
FUNC2
Note that the FUNC1 macro works fine. So I think this does what you
want.
The best solution, though, is not to abuse CPP in the first place.
Neil.