{"thread":{"id":"65594","subject":"[PATCH] build: tolerate use of _Generic from glibc 2.43 with Clang","startedAt":"2026-05-05T12:26:25Z","lastAt":"2026-05-11T06:10:27Z","messageCount":5,"participants":["Patrick Steinhardt","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"542759","messageId":"20260505-b4-pks-ci-tolerate-glibc-generic-v1-1-5786386fe512@pks.im","threadId":"65594","inReplyTo":null,"subject":"[PATCH] build: tolerate use of _Generic from glibc 2.43 with Clang","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-05-05T12:26:03Z","receivedAt":"2026-05-05T12:26:25Z","isPatch":true,"body":"When building with `make DEVELOPER=1` we explicitly pass \"-std=gnu99\" to\nthe compiler so that we don't start leaning on features exposed by more\nrecent versions of the C standard. Unfortunately though, glibc 2.43\nstarted to use type-generic expressions. This works alright with GCC,\nbut when compiling with Clang this leads to errors:\n\n  $ make DEVELOPER=1 CC=clang\n  CC daemon.o\n  In file included from daemon.c:3:\n  ./git-compat-util.h:344:11: error: '_Generic' is a C11 extension [-Werror,-Wc11-extensions]\n    344 |         return !!strchr(path, '/');\n        |                  ^\n  /usr/include/string.h:265:3: note: expanded from macro 'strchr'\n    265 |   __glibc_const_generic (S, const char *, strchr (S, C))\n        |   ^\n  /usr/include/x86_64-linux-gnu/sys/cdefs.h:838:3: note: expanded from macro '__glibc_const_generic'\n    838 |   _Generic (0 ? (PTR) : (void *) 1,                     \\\n        |   ^\n\nIn theory, the `__glibc_const_generic` macro does have feature gating:\n\n  #if !defined __cplusplus \\\n      && (__GNUC_PREREQ (4, 9) \\\n          || __glibc_has_extension (c_generic_selections) \\\n          || (!defined __GNUC__ && defined __STDC_VERSION__ \\\n              && __STDC_VERSION__ >= 201112L))\n  # define __HAVE_GENERIC_SELECTION 1\n  #else\n  # define __HAVE_GENERIC_SELECTION 0\n  #endif\n\nBut this feature gating isn't effective because `_has_extension()` will\nalways evaluate to true as C generics _are_ available as a language\nextension to GNU C99 when using Clang. This would have been different if\n`_has_feature()` was used instead, in which case it would have properly\nevaluated to `false`.\n\nUnfortunately, there is no easy way for us to work around the warning.\nWe cannot define `__HAVE_GENERIC_SELECTION` ourselves as that would lead\nto a redefinition, and given that the conditions are or'd together we\ncannot disable any of those, either.\n\nInstead, work around the issue by not using -std=gnu99 with Clang when\nusing the Makefile and by disabling warnings about C11 extensions when\nusing Meson. This isn't ideal, but we at least retain the ability to\ndetect the (mis-)use of features from newer standards with GCC.\n\nAn alternative to this might be to simply bump the required C standard\nto C11, which is 15 years old by now and should have support on most\nplatforms out there. But some more esoteric platforms may not have it.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\nHi,\n\nthis patch fixes CI failures that have started to occur due to the\nupgrade to Ubuntu 26.04. Thanks!\n\nPatrick\n---\n config.mak.dev | 5 ++++-\n meson.build    | 6 ++++++\n 2 files changed, 10 insertions(+), 1 deletion(-)\n\ndiff --git a/config.mak.dev b/config.mak.dev\nindex c8dcf78779..8830b78c1b 100644\n--- a/config.mak.dev\n+++ b/config.mak.dev\n@@ -21,12 +21,15 @@ endif\n endif\n \n ifneq ($(uname_S),FreeBSD)\n-ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang7,$(COMPILER_FEATURES))),)\n+ifneq ($(filter gcc6,$(COMPILER_FEATURES)),)\n DEVELOPER_CFLAGS += -std=gnu99\n endif\n else\n # FreeBSD cannot limit to C99 because its system headers unconditionally\n # rely on C11 features.\n+#\n+# Clang cannot limit to C99 when using glibc 2.43 because its system headers\n+# depend on the _Generic C11 feature. This works with GCC though.\n endif\n \n DEVELOPER_CFLAGS += -Wdeclaration-after-statement\ndiff --git a/meson.build b/meson.build\nindex 11488623bf..2997d4f90f 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -866,6 +866,12 @@ if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argum\n       libgit_c_args += cflag\n     endif\n   endforeach\n+\n+  # Clang generates warnings when compiling glibc 2.43 because of the use of\n+  # _Generic.\n+  if compiler.get_id() == 'clang'\n+    libgit_c_args += '-Wno-c11-extensions'\n+  endif\n endif\n \n if get_option('breaking_changes')\n\n---\nbase-commit: 94f057755b7941b321fd11fec1b2e3ca5313a4e0\nchange-id: 20260505-b4-pks-ci-tolerate-glibc-generic-0815aff39ff7\n\n"},{"id":"543009","messageId":"xmqqzf26sk80.fsf@gitster.g","threadId":"65594","inReplyTo":"20260505-b4-pks-ci-tolerate-glibc-generic-v1-1-5786386fe512@pks.im","subject":"Re: [PATCH] build: tolerate use of _Generic from glibc 2.43 with Clang","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-05-11T03:23:11Z","receivedAt":"2026-05-11T03:23:14Z","isPatch":true,"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Instead, work around the issue by not using -std=gnu99 with Clang when\n> using the Makefile and by disabling warnings about C11 extensions when\n> using Meson. This isn't ideal, but we at least retain the ability to\n> detect the (mis-)use of features from newer standards with GCC.\n>\n> An alternative to this might be to simply bump the required C standard\n> to C11, which is 15 years old by now and should have support on most\n> platforms out there. But some more esoteric platforms may not have it.\n\nWouldn't the approach you took on the meson side to pass\n\"-Wno-c11-extensions\" be yet another alternative?  I think that is\nwhat the other proposal (which was only for Makefile world and not\nfor meson world) did, even though it may not have been a great\nimplemenation to help only those who use config.mak.dev\n\n   <pull.2291.git.git.1778120192298.gitgitgadget@gmail.com>\n\nWe would need a patch to apply at lesat on v2.54.0 but possibly\nolder tracks if we plan to keep them also buildable.\n\nThanks.\n"},{"id":"543010","messageId":"xmqqqzniset2.fsf@gitster.g","threadId":"65594","inReplyTo":"xmqqzf26sk80.fsf@gitster.g","subject":"Re: [PATCH] build: tolerate use of _Generic from glibc 2.43 with Clang","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-05-11T05:20:09Z","receivedAt":"2026-05-11T05:20:12Z","isPatch":true,"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Wouldn't the approach you took on the meson side to pass\n> \"-Wno-c11-extensions\" be yet another alternative?\n\nIn other words, I would imagine something like this patch that uses\nthe same strategy on both sides may be easier to reason about.\n\n----- >8 -----\nFrom: Patrick Steinhardt <ps@pks.im>\nSubject: [PATCH] build: tolerate use of _Generic from glibc 2.43 with Clang\n\nWhen building with `make DEVELOPER=1` we explicitly pass \"-std=gnu99\" to\nthe compiler so that we don't start leaning on features exposed by more\nrecent versions of the C standard. Unfortunately though, glibc 2.43\nstarted to use type-generic expressions. This works alright with GCC,\nbut when compiling with Clang this leads to errors:\n\n  $ make DEVELOPER=1 CC=clang\n  CC daemon.o\n  In file included from daemon.c:3:\n  ./git-compat-util.h:344:11: error: '_Generic' is a C11 extension [-Werror,-Wc11-extensions]\n    344 |         return !!strchr(path, '/');\n        |                  ^\n  /usr/include/string.h:265:3: note: expanded from macro 'strchr'\n    265 |   __glibc_const_generic (S, const char *, strchr (S, C))\n        |   ^\n  /usr/include/x86_64-linux-gnu/sys/cdefs.h:838:3: note: expanded from macro '__glibc_const_generic'\n    838 |   _Generic (0 ? (PTR) : (void *) 1,                     \\\n        |   ^\n\nIn theory, the `__glibc_const_generic` macro does have feature gating:\n\n  #if !defined __cplusplus \\\n      && (__GNUC_PREREQ (4, 9) \\\n          || __glibc_has_extension (c_generic_selections) \\\n          || (!defined __GNUC__ && defined __STDC_VERSION__ \\\n              && __STDC_VERSION__ >= 201112L))\n  # define __HAVE_GENERIC_SELECTION 1\n  #else\n  # define __HAVE_GENERIC_SELECTION 0\n  #endif\n\nBut this feature gating isn't effective because `_has_extension()` will\nalways evaluate to true as C generics _are_ available as a language\nextension to GNU C99 when using Clang. This would have been different if\n`_has_feature()` was used instead, in which case it would have properly\nevaluated to `false`.\n\nGCC has a workaround to squelch this warning from standard system\nheaders, but because clang fails due to [-Werror,-Wc11-extensions],\nas it lacks the corresponding workaround.\n\nFor both meson and Makefile, pass -Wno-c11-extensions when we are\nbuilding with clang.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\nHelped-by: Shardul Natu <snatu@google.com>\n[jc: replaced Makefile side with Shardul's approach]\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n config.mak.dev | 7 +++++++\n meson.build    | 6 ++++++\n 2 files changed, 13 insertions(+)\n\ndiff --git a/config.mak.dev b/config.mak.dev\nindex e86b6e1b34..794b1c9627 100644\n--- a/config.mak.dev\n+++ b/config.mak.dev\n@@ -98,6 +98,13 @@ endif\n endif\n endif\n \n+# glibc 2.43 headers unconditionally use _Generic even when we ask the\n+# compiler to stick to -std=gnu99 and unlike GCC, clang lacks a\n+# workaround to squelch warnings from system headers.\n+ifneq ($(filter clang1,$(COMPILER_FEATURES)),)     # if we are using clang\n+DEVELOPER_CFLAGS += -Wno-c11-extensions\n+endif\n+\n # https://bugzilla.redhat.com/show_bug.cgi?id=2075786\n ifneq ($(filter gcc12,$(COMPILER_FEATURES)),)\n DEVELOPER_CFLAGS += -Wno-error=stringop-overread\ndiff --git a/meson.build b/meson.build\nindex dd52efd1c8..536bd2679c 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -854,6 +854,12 @@ if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argum\n       libgit_c_args += cflag\n     endif\n   endforeach\n+\n+  # Clang generates warnings when compiling glibc 2.43 because of the use of\n+  # _Generic.\n+  if compiler.get_id() == 'clang'\n+    libgit_c_args += '-Wno-c11-extensions'\n+  endif\n endif\n \n if get_option('breaking_changes')\n-- \n2.54.0-170-g88022b8681\n\n"},{"id":"543011","messageId":"agFtGM0H4S87ZxwR@pks.im","threadId":"65594","inReplyTo":"xmqqqzniset2.fsf@gitster.g","subject":"Re: [PATCH] build: tolerate use of _Generic from glibc 2.43 with Clang","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-05-11T05:46:00Z","receivedAt":"2026-05-11T05:46:07Z","isPatch":true,"body":"On Mon, May 11, 2026 at 02:20:09PM +0900, Junio C Hamano wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n> > Wouldn't the approach you took on the meson side to pass\n> > \"-Wno-c11-extensions\" be yet another alternative?\n> \n> In other words, I would imagine something like this patch that uses\n> the same strategy on both sides may be easier to reason about.\n\nI was going back and forth on this myself. I simply wasn't sure whether\nit even buys us anything anymore if we have both \"-std=gnu99\" _and_\n\"-Wno-c11-extensions\". But maybe this combination at least also detects\nthe use of newer (C23) extensions?\n\nIn any case, I'm also happy with the patch you posted. Thanks!\n\nPatrick\n"},{"id":"543013","messageId":"xmqqecjischc.fsf@gitster.g","threadId":"65594","inReplyTo":"agFtGM0H4S87ZxwR@pks.im","subject":"Re: [PATCH] build: tolerate use of _Generic from glibc 2.43 with Clang","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-05-11T06:10:23Z","receivedAt":"2026-05-11T06:10:27Z","isPatch":true,"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Mon, May 11, 2026 at 02:20:09PM +0900, Junio C Hamano wrote:\n>> Junio C Hamano <gitster@pobox.com> writes:\n>> \n>> > Wouldn't the approach you took on the meson side to pass\n>> > \"-Wno-c11-extensions\" be yet another alternative?\n>> \n>> In other words, I would imagine something like this patch that uses\n>> the same strategy on both sides may be easier to reason about.\n>\n> I was going back and forth on this myself. I simply wasn't sure whether\n> it even buys us anything anymore if we have both \"-std=gnu99\" _and_\n> \"-Wno-c11-extensions\". But maybe this combination at least also detects\n> the use of newer (C23) extensions?\n\nWe shouldn't be the only project hit by the unconditional use of\n_Generic in glibc 2.43 headers, should we?  I was hoping that this\nwould be fixed upstream, and that anything we do locally is merely\na workaround of a tentative nature.\n\n> In any case, I'm also happy with the patch you posted. Thanks!\n\nThanks for a quick response.\n\nYou may have guessed correctly that I want to fast-track this topic\ndown to 'next' and 'master' soonish to salvage CI jobs running for\nthem.\n"}]}