When building with `make DEVELOPER=1` we explicitly pass "-std=gnu99" to the compiler so that we don't start leaning on features exposed by more recent versions of the C standard. Unfortunately though, glibc 2.43 started to use type-generic expressions. This works alright with GCC, but when compiling with Clang this leads to errors:
$ make DEVELOPER=1 CC=clang
CC daemon.o
In file included from daemon.c:3:
./git-compat-util.h:344:11: error: '_Generic' is a C11 extension [-Werror,-Wc11-extensions]
344 | return !!strchr(path, '/');
| ^
/usr/include/string.h:265:3: note: expanded from macro 'strchr'
265 | __glibc_const_generic (S, const char *, strchr (S, C))
| ^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:838:3: note: expanded from macro '__glibc_const_generic'
838 | _Generic (0 ? (PTR) : (void *) 1, \
| ^In theory, the `__glibc_const_generic` macro does have feature gating:
#if !defined __cplusplus \
&& (__GNUC_PREREQ (4, 9) \
|| __glibc_has_extension (c_generic_selections) \
|| (!defined __GNUC__ && defined __STDC_VERSION__ \
&& __STDC_VERSION__ >= 201112L))
# define __HAVE_GENERIC_SELECTION 1
#else
# define __HAVE_GENERIC_SELECTION 0
#endifBut this feature gating isn't effective because `_has_extension()` will always evaluate to true as C generics _are_ available as a language extension to GNU C99 when using Clang. This would have been different if `_has_feature()` was used instead, in which case it would have properly evaluated to `false`.
Unfortunately, there is no easy way for us to work around the warning. We cannot define `__HAVE_GENERIC_SELECTION` ourselves as that would lead to a redefinition, and given that the conditions are or'd together we cannot disable any of those, either.
Instead, work around the issue by not using -std=gnu99 with Clang when using the Makefile and by disabling warnings about C11 extensions when using Meson. This isn't ideal, but we at least retain the ability to detect the (mis-)use of features from newer standards with GCC.
An alternative to this might be to simply bump the required C standard to C11, which is 15 years old by now and should have support on most platforms out there. But some more esoteric platforms may not have it.
Signed-off-by: Patrick Steinhardt <ps@pks.im> --- Hi,
this patch fixes CI failures that have started to occur due to the upgrade to Ubuntu 26.04. Thanks!
Patrick --- config.mak.dev | 5 ++++- meson.build | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-)
Show changes to 2 files +10 −1
config.mak.dev, meson.build
diff --git a/config.mak.dev b/config.mak.dev index c8dcf78779..8830b78c1b 100644 --- a/config.mak.dev +++ b/config.mak.dev @@ -21,12 +21,15 @@ endif endif ifneq ($(uname_S),FreeBSD) -ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),) +ifneq ($(filter gcc6,$(COMPILER_FEATURES)),) DEVELOPER_CFLAGS += -std=gnu99 endif else # FreeBSD cannot limit to C99 because its system headers unconditionally # rely on C11 features. +# +# Clang cannot limit to C99 when using glibc 2.43 because its system headers +# depend on the _Generic C11 feature. This works with GCC though. endif DEVELOPER_CFLAGS += -Wdeclaration-after-statement diff --git a/meson.build b/meson.build index 11488623bf..2997d4f90f 100644 --- a/meson.build +++ b/meson.build @@ -866,6 +866,12 @@ if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argum libgit_c_args += cflag endif endforeach + + # Clang generates warnings when compiling glibc 2.43 because of the use of + # _Generic. + if compiler.get_id() == 'clang' + libgit_c_args += '-Wno-c11-extensions' + endif endif if get_option('breaking_changes') --- base-commit: 94f057755b7941b321fd11fec1b2e3ca5313a4e0 change-id: 20260505-b4-pks-ci-tolerate-glibc-generic-0815aff39ff7