https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33877

--- Comment #14 from Alejandro Colomar <foss+...@alejandro-colomar.es> ---
I've been experimenting with __VA_OPT__(,) and ,##__VA_ARGS__ and I need to
make a self correction:

While the behavior of __VA_OPT__(,) is not consistent with that of __VA_ARGS__,
it is useful, to detect empty macro arguments, and differentiate them from
non-empty ones.

Now, for __VA_ARGC__, I'm not sure what we should consider for the number of
arguments.  Consistency is unclear, because __VA_OPT__ is not consistent with
__VA_ARGS__, so whichever behavior we define, it would be inconsistent with
either __VA_OPT__ or __VA_ARGS__.

So, I think existing practice should be followed.  I've been researching macros
in the wild to calculate numbers of arguments, and they differ in the value
they return.

Here's the source code I'm using to test different implementations of
COUNT_ARGS() that I've found in the wild:


#define FOO(...)     __LINE__: foo: ARGC(__VA_ARGS__)
#define BAR(a, ...)  __LINE__: bar: ARGC(__VA_ARGS__)

FOO(,,,a)
FOO(,,,)
FOO(,,a)
FOO(,,)
FOO(,a)
FOO(,)
FOO(a)
FOO()

BAR(,,,a)
BAR(,,,)
BAR(,,a)
BAR(,,)
BAR(,a)
BAR(,)
BAR(a)
BAR()


All the implementations I've seen, fall into either of these two behaviors:

Behavior A:

$ gcc -E argcA.c | grep -v ^#
80: foo: 4
81: foo: 4
82: foo: 3
83: foo: 3
84: foo: 2
85: foo: 2
86: foo: 1
87: foo: 1

89: bar: 3
90: bar: 3
91: bar: 2
92: bar: 2
93: bar: 1
94: bar: 1
95: bar: 1
96: bar: 1

Behavior B:

$ gcc -E argc2.c | grep -v ^#
16: foo: 4
17: foo: 4
18: foo: 3
19: foo: 3
20: foo: 2
21: foo: 2
22: foo: 1
23: foo: 0

25: bar: 3
26: bar: 3
27: bar: 2
28: bar: 2
29: bar: 1
30: bar: 0
31: bar: 0
32: bar: 0


So, either they consider there's always at least an argument,
or there's never one argument.
It's possible to write one that using __VA_OPT__ would differentiate 0 and 1
depending on the argument being empty or not, but probably because these macros
are older than C23, they don't do it.

$ gcc -E argc3.c | grep -v ^#
22: foo: 6
23: foo: 6
24: foo: 5
25: foo: 4
26: foo: 3
27: foo: 2
28: foo: 2
29: foo: 1
30: foo: 0

32: bar: 5
33: bar: 5
34: bar: 4
35: bar: 3
36: bar: 2
37: bar: 1
38: bar: 0
39: bar: 0
40: bar: 0


The former seems to never have 0 arguments, even for this case:

#define BAR(a, ...)  __LINE__: bar: ARGC(__VA_ARGS__)
BAR(a)
95: bar: 1

This seems very unnatural, both from the point of view of ,##__VA_ARGS__, and
from the point of view of __VA_OPT__.

The latter seems consistent with __VA_OPT__, which seems okay.

None of the macros I found seem consistent with ,##__VA_ARGS__.  So, I guess we
should have __VA_ARGC__ be consistent with __VA_OPT__.

Reply via email to