Hi! The Linux kernel uses its own copy of stdarg.h. Now, before GCC 15, our stdarg.h had #if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L #define va_start(v, ...) __builtin_va_start(v, 0) #else #define va_start(v,l) __builtin_va_start(v,l) #endif va_start definition but GCC 15 has: #if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L #define va_start(...) __builtin_c23_va_start(__VA_ARGS__) #else #define va_start(v,l) __builtin_va_start(v,l) #endif
I wanted to suggest to the kernel people during their porting to C23 that they'd better use C23 compatible va_start macro definition, but to make it portable, I think they really want something like #if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L #define va_start(v, ...) __builtin_va_start(v, 0) #ifdef __has_builtin #if __has_builtin(__builtin_c23_va_start) #undef va_start #define va_start(...) __builtin_c23_va_start(__VA_ARGS__) #endif #else #define va_start(v,l) __builtin_va_start(v,l) #endif or so (or with >= 202311L), as GCC 13-14 and clang don't support __builtin_c23_va_start (yet?) and one gets better user experience with that. Except it seems __has_builtin(__builtin_c23_va_start) doesn't actually work, it works for most of the stdarg.h __builtin_va_*, doesn't work for __builtin_va_arg (neither C nor C++) and didn't work for __builtin_c23_va_start if it was available. The following patch wires __has_builtin for those. Bootstrapped on x86_64-linux and i686-linux, regtest ongoing, ok for trunk if it passes? 2025-01-17 Jakub Jelinek <ja...@redhat.com> gcc/c/ * c-decl.cc (names_builtin_p): Return 1 for RID_C23_VA_START and RID_VA_ARG. gcc/cp/ * cp-objcp-common.cc (names_builtin_p): Return 1 for RID_VA_ARG. gcc/testsuite/ * c-c++-common/cpp/has-builtin-4.c: New test. --- gcc/c/c-decl.cc.jj 2025-01-17 11:29:33.276694451 +0100 +++ gcc/c/c-decl.cc 2025-01-17 15:13:44.497856864 +0100 @@ -11804,6 +11804,8 @@ names_builtin_p (const char *name) case RID_CHOOSE_EXPR: case RID_OFFSETOF: case RID_TYPES_COMPATIBLE_P: + case RID_C23_VA_START: + case RID_VA_ARG: return 1; default: break; --- gcc/cp/cp-objcp-common.cc.jj 2025-01-02 11:47:10.703494721 +0100 +++ gcc/cp/cp-objcp-common.cc 2025-01-17 15:16:07.218885238 +0100 @@ -587,6 +587,7 @@ names_builtin_p (const char *name) case RID_BUILTIN_ASSOC_BARRIER: case RID_BUILTIN_BIT_CAST: case RID_OFFSETOF: + case RID_VA_ARG: return 1; case RID_BUILTIN_OPERATOR_NEW: case RID_BUILTIN_OPERATOR_DELETE: --- gcc/testsuite/c-c++-common/cpp/has-builtin-4.c.jj 2025-01-17 15:15:44.077204928 +0100 +++ gcc/testsuite/c-c++-common/cpp/has-builtin-4.c 2025-01-17 15:15:02.520779011 +0100 @@ -0,0 +1,16 @@ +/* { dg-do preprocess } */ + +#if __has_builtin (__builtin_va_start) != 1 +#error "No __builtin_va_start" +#endif +#if __has_builtin (__builtin_va_end) != 1 +#error "No __builtin_va_end" +#endif +#if __has_builtin (__builtin_va_arg) != 1 +#error "no __builtin_va_arg" +#endif +#if __STDC_VERSION__ >= 202311L +#if __has_builtin (__builtin_c23_va_start) != 1 +#error "no __builtin_c23_va_start" +#endif +#endif Jakub