Hi Basil,

On Sat, Jun 07, 2025 at 09:47:49PM +0200, Basil L. Contovounesios wrote:
> 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__}))

Huh!  This is quite interesting.  :-)

You may want to write about it here:
<https://software.codidact.com/posts/294093>

> 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?

Nope, that seems to be a Clang bug.  Here's a smaller reproducer of the
Clang bug:

        alx@devuan:~/tmp$ cat cnt.c 
        #include <stdlib.h>
        #include <assert.h>


        #define must_be(e)                                                    \
        (                                                                     \
                0 * (int) sizeof(                                             \
                        struct {                                              \
                                static_assert(e, "");                         \
                                int ISO_C_forbids_a_struct_with_no_members_;  \
                        }                                                     \
                )                                                             \
        )

        #define is_same_type(a, b)                                            \
        (                                                                     \
                __builtin_types_compatible_p(a, b)                            \
        )

        #define is_same_typeof(a, b)                                          \
        (                                                                     \
                is_same_type(typeof(a), typeof(b))                            \
        )

        #define is_array(a)                                                   \
        (                                                                     \
                !is_same_typeof(a, &(a)[0])                                   \
        )


        int
        main(void)
        {
                return must_be(is_array(((int []) {rand(), rand()})));
        }
        alx@devuan:~/tmp$ gcc -Wall -Wextra -S cnt.c 
        alx@devuan:~/tmp$ clang -Wall -Wextra -S cnt.c 
        cnt.c:34:37: error: initializer element is not a compile-time constant
           34 |         return must_be(is_array(((int []) {rand(), rand()})));
              |                                            ^~~~~~
        cnt.c:27:25: note: expanded from macro 'is_array'
           27 |         !is_same_typeof(a, &(a)[0])                             
      \
              |                         ^
        cnt.c:22:29: note: expanded from macro 'is_same_typeof'
           22 |         is_same_type(typeof(a), typeof(b))                      
      \
              |                             ^
        cnt.c:17:38: note: expanded from macro 'is_same_type'
           17 |         __builtin_types_compatible_p(a, b)                      
      \
              |                                      ^
        cnt.c:9:39: note: expanded from macro 'must_be'
            9 |                         static_assert(e, "");                   
      \
              |                                       ^
        1 error generated.

I've reported it here:
<https://github.com/llvm/llvm-project/issues/143284>


Have a lovely night!
Alex

-- 
<https://www.alejandro-colomar.es/>

Attachment: signature.asc
Description: PGP signature

Reply via email to