3
votes

I am writing a x-macro based register file layout description system for a project of mine. Most of the time, the macros expand to a hierarchy of template classes. However, I also want an enumeration of all the registers, like this:

#define RINT(num,name,flags,width) name,
...

enum Regs
{
#include REGDEF
};

This works just fine. However, I also specify aliasing registers using a variadic macro. Since there is no trivial way to strip commas between elements of __VA_ARGS__ (not that I know of, please correct me if I'm wrong), I write:

#define RALIAS_10(r0,r1,r2,r3,r4,r5,r6,r7,r8,r9) r0 r1 r2 r3 r4 r5 r6 r7 r8 r9
#define RALIAS_9(r0,r1,r2,r3,r4,r5,r6,r7,r8) r0 r1 r2 r3 r4 r5 r6 r7 r8
...
#define RALIAS_1(r0) r0
#define RALIAS_N(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,aliasn,...) aliasn
#define RALIAS(...) RALIAS_N(__VA_ARGS__, RALIAS_10(__VA_ARGS__), RALIAS_9(__VA_ARGS__), ..., RALIAS_1(__VA_ARGS__))

Now, if I write

RALIAS(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))

the commas in the RINT macro disappear:

enum Reg
{
...
RSP ESP SP SPL
...
};

If, in turn, I use the RALIAS_4 macro directly

RALIAS_4(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))

I get what I expect:

enum Reg
{
...
RSP, ESP, SP, SPL,
...
};

I know GCC applies some non-standard comma stripping logic to variadic macros, but that shouldn't happen when I explicitly specify -std=c++11. Furthermore, Clang gave me the exact same results. Yet I couldn't find anything that would explain this behavior in the standard (draft), nor in the GCC documentation.

What am I missing?

I tried GCC 6.1.1 and Clang 3.8.1 on Arch Linux (x86-64). Both compilers were installed from the repository.

1

1 Answers

2
votes

This:

RALIAS(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))

is going to expand into:

RALIAS(RSP,,ESP,,SP,,SPL,)

which is a macro that takes 8 arguments, of which 4 are empty. You don't get the argument "RSP,", you get the argument RSP and then separately the argument "".