Bruno Haible via Gnulib discussion list [2025-06-03 00:00 +0200] wrote:
> Alejandro Colomar wrote:
>> # define countof(a) (sizeof(a) / sizeof((a)[0]) + must_be(is_array(a)))
>> #endif
>>
>> must_be(is_array(a)) is a trick to assert that the argument is an array.
>> <https://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c/57537491#57537491>
>
> Now that is very nice! The ability to detect wrong use of function parameters
> is valuable already now. You referenced <https://lkml.org/lkml/2015/9/3/428>.
Thanks for this.
I'm facing an issue with _gl_verify_is_array in Clang, however.
I tried using Gnulib's countof macro for counting the number of
arguments passed to a variadic function, e.g.:
#define CALL(fn, args) ((fn) (countof (args), (args)))
#define CALLN(fn, ...) CALL (fn, ((int []) {__VA_ARGS__}))
This works with both GCC 14 and Clang 19 as long as __VA_ARGS__
comprises compile-time constants:
CALLN (foo, 1, 2, 3);
However Clang fails to compile something like:
CALLN (foo, rand(), rand(), rand());
with the precise diagnostics listed below.
Am I misunderstanding something or doing something wrong?
In case it helps, I'm compiling the following sample project:
0. git clone 'https://git.sr.ht/~blc/foo' && cd foo
1. ./bootstrap --skip-po && ./configure CC=clang && make
Thanks,
--
Basil
src/foo.c:23:26: error: initializer element is not a compile-time constant
23 | return FOO_CALLN (foo, rand(), rand(), rand());
| ^~~~~~
src/foo.h:26:53: note: expanded from macro 'FOO_CALLN'
26 | #define FOO_CALLN(fn, ...) FOO_CALL (fn, ((int []) {__VA_ARGS__}))
| ^~~~~~~~~~~
src/foo.h:25:44: note: expanded from macro 'FOO_CALL'
25 | #define FOO_CALL(fn, args) ((fn) (countof (args), (args)))
| ^~~~
./lib/stdcountof.h:35:70: note: expanded from macro 'countof'
35 | ((size_t) (sizeof (a) / sizeof ((a)[0]) + 0 * _gl_verify_is_array
(a)))
| ^
./lib/stdcountof.h:87:104: note: expanded from macro '_gl_verify_is_array'
87 | sizeof (struct { unsigned int _gl_verify_error_if_negative :
__builtin_types_compatible_p (typeof (a), typeof (&*(a))) ? -1 : 1; })
|
^