aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-02-26 19:29:12 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2025-02-26 19:29:12 +0100
commit8d22474af76a386eed488b3c66124134f0e41363 (patch)
treec37c0b109a9134607ba341b340bb3b97e12018f8
parent40bf0770563501f4c6d7e92cdaa1fa36dddd1caa (diff)
downloadgcc-8d22474af76a386eed488b3c66124134f0e41363.zip
gcc-8d22474af76a386eed488b3c66124134f0e41363.tar.gz
gcc-8d22474af76a386eed488b3c66124134f0e41363.tar.bz2
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.
-rw-r--r--gcc/ginclude/stddef.h8
-rw-r--r--gcc/testsuite/gcc.dg/c23-stddef-2.c17
2 files changed, 20 insertions, 5 deletions
diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h
index 45d615d..0d53103 100644
--- a/gcc/ginclude/stddef.h
+++ b/gcc/ginclude/stddef.h
@@ -444,18 +444,16 @@ typedef struct {
#endif
#endif /* C++11. */
-#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L)
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L
#ifndef _GCC_NULLPTR_T
#define _GCC_NULLPTR_T
typedef __typeof__(nullptr) nullptr_t;
-/* ??? This doesn't define __STDC_VERSION_STDDEF_H__ yet. */
#endif
-#endif /* C23. */
-
-#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+#ifndef __STDC_VERSION_STDDEF_H__
#define unreachable() (__builtin_unreachable ())
#define __STDC_VERSION_STDDEF_H__ 202311L
#endif
+#endif /* C23. */
#endif /* _STDDEF_H was defined this time */
diff --git a/gcc/testsuite/gcc.dg/c23-stddef-2.c b/gcc/testsuite/gcc.dg/c23-stddef-2.c
new file mode 100644
index 0000000..53509b6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-stddef-2.c
@@ -0,0 +1,17 @@
+/* Test __STDC_VERSION_STDDEF_H__ in C23. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c23 -pedantic-errors -Wsystem-headers" } */
+
+#include <stddef.h>
+/* Simulate what glibc <time.h> does without actually including it. */
+#define __need_size_t
+#define __need_NULL
+#include <stddef.h>
+
+#ifndef __STDC_VERSION_STDDEF_H__
+#error "__STDC_VERSION_STDDEF_H__ not defined"
+#endif
+
+#if __STDC_VERSION_STDDEF_H__ != 202311L
+#error "bad value of __STDC_VERSION_STDDEF_H__"
+#endif