Created attachment 58049 [details] fix stddef.h to survive multiple includes, some with __need_size_t etc. I found this when trying to build GNU diffutils on Fedora 40. This is gcc (GCC) 14.0.1 20240411 (Red Hat 14.0.1-0) on x86-64. Compile the following two-line program t.c with 'gcc -std=gnu23 -Wsystem-headers -E t.c >t.i': #include <stddef.h> #include <time.h> GCC issues the following diagnostics: In file included from /usr/include/time.h:29, from t.c:2: /usr/lib/gcc/x86_64-redhat-linux/14/include/stddef.h:457:9: warning: "__STDC_VERSION_STDDEF_H__" redefined 457 | #define __STDC_VERSION_STDDEF_H__ 202311L | ^~~~~~~~~~~~~~~~~~~~~~~~~ In file included from t.c:1: /usr/lib/gcc/x86_64-redhat-linux/14/include/stddef.h:457:9: note: this is the location of the previous definition 457 | #define __STDC_VERSION_STDDEF_H__ 202311L | ^~~~~~~~~~~~~~~~~~~~~~~~~ It seems that <stddef.h> is not properly protected against multiple includes, some with __need_size_t and __need_NULL and some without. The attached patch to stddef.h worked around the problem for me.
Confirmed. I just noticed this myself Sorry for not confirming earlier. stddef.h is under GCC control in this case too.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:8d22474af76a386eed488b3c66124134f0e41363 commit r15-7718-g8d22474af76a386eed488b3c66124134f0e41363 Author: Jakub Jelinek <jakub@redhat.com> Date: Wed Feb 26 19:29:12 2025 +0100 c: stddef.h C23 fixes [PR114870] The stddef.h header for C23 defines __STDC_VERSION_STDDEF_H__ and unreachable macros multiple times in some cases. The header doesn't have normal multiple inclusion guard, because it supports for glibc inclusion with __need_{size_t,wchar_t,ptrdiff_t,wint_t,NULL}. While the definition of __STDC_VERSION_STDDEF_H__ and unreachable is done solely in the #ifdef _STDDEF_H part, so they are defined only if stddef.h is included without those __need_* macros defined. But actually once stddef.h is included without the __need_* macros, _STDDEF_H is then defined and while further stddef.h includes without __need_* macros don't do anything: #if (!defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) \ && !defined(__STDDEF_H__)) \ || defined(__need_wchar_t) || defined(__need_size_t) \ || defined(__need_ptrdiff_t) || defined(__need_NULL) \ || defined(__need_wint_t) if one includes whole stddef.h first and then stddef.h with some of the __need_* macros defined, the #ifdef _STDDEF_H part is used again. It isn't that big deal for most cases, as it uses extra guarding macros like: #ifndef _GCC_MAX_ALIGN_T #define _GCC_MAX_ALIGN_T ... #endif etc., but for __STDC_VERSION_STDDEF_H__/unreachable nothing like that is used. So, either we do what the following patch does and just don't define __STDC_VERSION_STDDEF_H__/unreachable second time, or use #ifndef unreachable separately for the #define unreachable() case, or use new _GCC_STDC_VERSION_STDDEF_H macro to guard this (or two, one for __STDC_VERSION_STDDEF_H__ and one for unreachable), or rework the initial condition to be just #if !defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) \ && !defined(__STDDEF_H__) - I really don't understand why the header should do anything at all after it has been included once without __need_* macros. But changing how this behaves after 35 years might be risky for various OS/libc combinations. 2025-02-26 Jakub Jelinek <jakub@redhat.com> PR c/114870 * ginclude/stddef.h (__STDC_VERSION_STDDEF_H__, unreachable): Don't redefine multiple times if stddef.h is first included without __need_* defines and later with them. Move nullptr_t and unreachable and __STDC_VERSION_STDDEF_H__ definitions into the same defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L #if block. * gcc.dg/c23-stddef-2.c: New test.
Fixed on the trunk so far.
The releases/gcc-14 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:a266e7354bdae713f73c9f356bb15a387fd4d1b4 commit r14-11460-ga266e7354bdae713f73c9f356bb15a387fd4d1b4 Author: Jakub Jelinek <jakub@redhat.com> Date: Wed Feb 26 19:29:12 2025 +0100 c: stddef.h C23 fixes [PR114870] The stddef.h header for C23 defines __STDC_VERSION_STDDEF_H__ and unreachable macros multiple times in some cases. The header doesn't have normal multiple inclusion guard, because it supports for glibc inclusion with __need_{size_t,wchar_t,ptrdiff_t,wint_t,NULL}. While the definition of __STDC_VERSION_STDDEF_H__ and unreachable is done solely in the #ifdef _STDDEF_H part, so they are defined only if stddef.h is included without those __need_* macros defined. But actually once stddef.h is included without the __need_* macros, _STDDEF_H is then defined and while further stddef.h includes without __need_* macros don't do anything: #if (!defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) \ && !defined(__STDDEF_H__)) \ || defined(__need_wchar_t) || defined(__need_size_t) \ || defined(__need_ptrdiff_t) || defined(__need_NULL) \ || defined(__need_wint_t) if one includes whole stddef.h first and then stddef.h with some of the __need_* macros defined, the #ifdef _STDDEF_H part is used again. It isn't that big deal for most cases, as it uses extra guarding macros like: #ifndef _GCC_MAX_ALIGN_T #define _GCC_MAX_ALIGN_T ... #endif etc., but for __STDC_VERSION_STDDEF_H__/unreachable nothing like that is used. So, either we do what the following patch does and just don't define __STDC_VERSION_STDDEF_H__/unreachable second time, or use #ifndef unreachable separately for the #define unreachable() case, or use new _GCC_STDC_VERSION_STDDEF_H macro to guard this (or two, one for __STDC_VERSION_STDDEF_H__ and one for unreachable), or rework the initial condition to be just #if !defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) \ && !defined(__STDDEF_H__) - I really don't understand why the header should do anything at all after it has been included once without __need_* macros. But changing how this behaves after 35 years might be risky for various OS/libc combinations. 2025-02-26 Jakub Jelinek <jakub@redhat.com> PR c/114870 * ginclude/stddef.h (__STDC_VERSION_STDDEF_H__, unreachable): Don't redefine multiple times if stddef.h is first included without __need_* defines and later with them. Move nullptr_t and unreachable and __STDC_VERSION_STDDEF_H__ definitions into the same defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L #if block. * gcc.dg/c23-stddef-2.c: New test. (cherry picked from commit 8d22474af76a386eed488b3c66124134f0e41363)
Fixed for 14.3+ as well.
The releases/gcc-13 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:7980ce5dcf14eee0b3b937b9783fb02597cef384 commit r13-9593-g7980ce5dcf14eee0b3b937b9783fb02597cef384 Author: Jakub Jelinek <jakub@redhat.com> Date: Wed Feb 26 19:29:12 2025 +0100 c: stddef.h C23 fixes [PR114870] The stddef.h header for C23 defines __STDC_VERSION_STDDEF_H__ and unreachable macros multiple times in some cases. The header doesn't have normal multiple inclusion guard, because it supports for glibc inclusion with __need_{size_t,wchar_t,ptrdiff_t,wint_t,NULL}. While the definition of __STDC_VERSION_STDDEF_H__ and unreachable is done solely in the #ifdef _STDDEF_H part, so they are defined only if stddef.h is included without those __need_* macros defined. But actually once stddef.h is included without the __need_* macros, _STDDEF_H is then defined and while further stddef.h includes without __need_* macros don't do anything: #if (!defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) \ && !defined(__STDDEF_H__)) \ || defined(__need_wchar_t) || defined(__need_size_t) \ || defined(__need_ptrdiff_t) || defined(__need_NULL) \ || defined(__need_wint_t) if one includes whole stddef.h first and then stddef.h with some of the __need_* macros defined, the #ifdef _STDDEF_H part is used again. It isn't that big deal for most cases, as it uses extra guarding macros like: #ifndef _GCC_MAX_ALIGN_T #define _GCC_MAX_ALIGN_T ... #endif etc., but for __STDC_VERSION_STDDEF_H__/unreachable nothing like that is used. So, either we do what the following patch does and just don't define __STDC_VERSION_STDDEF_H__/unreachable second time, or use #ifndef unreachable separately for the #define unreachable() case, or use new _GCC_STDC_VERSION_STDDEF_H macro to guard this (or two, one for __STDC_VERSION_STDDEF_H__ and one for unreachable), or rework the initial condition to be just #if !defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) \ && !defined(__STDDEF_H__) - I really don't understand why the header should do anything at all after it has been included once without __need_* macros. But changing how this behaves after 35 years might be risky for various OS/libc combinations. 2025-02-26 Jakub Jelinek <jakub@redhat.com> PR c/114870 * ginclude/stddef.h (__STDC_VERSION_STDDEF_H__, unreachable): Don't redefine multiple times if stddef.h is first included without __need_* defines and later with them. Move nullptr_t and unreachable and __STDC_VERSION_STDDEF_H__ definitions into the same defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L #if block. * gcc.dg/c23-stddef-2.c: New test. (cherry picked from commit 8d22474af76a386eed488b3c66124134f0e41363)
Fixed also for 13.4.