This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: A token pasting corner case?


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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]