-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Description
When defining NDEBUG in a Debug build of clang, I found some important differences with GCC.
Input
#define FOO(a,b,c) ;b########c,b##########c,a########a,a##########a,\
b##a##a##a##c,b##a##a##a##a##c,a##a##a##a##a,a##a##a##a##a##a
FOO(,y,z)
FOO(x,y,z)clang -E produces
;y####z,y####z,##,##, yz,yz,,
;y####z,y####z,x####x,x####x, yxxxz,yxxxxz,xxxxx,xxxxxxgcc -E produces
;yz,yz,,, yz,yz,,
;yz,yz,xx,xx, yxxxz,yxxxxz,xxxxx,xxxxxxIt is apparent (without reading the actual GCC source code) that when it sees ####, this is treated exactly the same as ##a## with a being an empty parameter.
On the other hand, clang treats the second ## as an ordinary token.
Suggestion
When a parameter is empty, it would be simpler (and less error-prone) to make an actual placeholder token and follow the rules in the C standard for pasting. Likewise, consecutive ## tokens should be separated by a placeholder. The only special cases you need are for the actual pasting of two tokens and the removal of placeholders later. A placeholder only remains after pasting in a case like a##a or a##a##a.
Similarly, use a placeholder for __VA_OPT__( tokens... ) when __VA_ARGS__ is empty.