On Tue, Aug 4, 2026 at 6:01 PM Jonathan Wakely <[email protected]> wrote:
> > > On Tue, 4 Aug 2026, 12:10 Tomasz Kaminski, <[email protected]> wrote: > >> >> >> On Mon, Aug 3, 2026 at 6:58 PM Jonathan Wakely <[email protected]> >> wrote: >> >>> The <cerrno> header is freestanding in C++26. Since we don't have to be >>> compatible with a C library or a kernel for freestanding, we can just >>> define the error number macros to arbitrary values. >>> >>> We need to provide a consistent set of definitions whether <cerrno> or >>> <errno.h> is included, and whether a freestanding header is included by >>> using -ffreestanding with a full hosted installation, or with a >>> non-hosted (i.e. --disable-hosted-libstdcxx) installation. We do not >>> want a situation where including <errno.h> uses a system libc header and >>> defines one set of values, but <cerrno> provides our own freestanding >>> values. >>> >>> The approach taken here is to install our own copy of <errno.h> which >>> does #include_next <errno.h> for hosted and which defines its own values >>> for freestanding. Our <cerrno> will then find our own <errno.h> and so >>> <cerrno> and <errno.h> will be consistent, and the macro values will >>> always be the same for the freestanding headers. >>> >>> libstdc++-v3/ChangeLog: >>> >>> * include/Makefile.am (c_base_freestanding): Move cerrno to >>> here from ... >>> (c_base_headers): ... here. >>> (c_compatibility_headers): Add errno.h. >>> * include/Makefile.in: Regenerate. >>> * include/c_compatibility/errno.h: Replace include <cerrno> with >>> include_next <errno.h>. >>> [!_GLIBCXX_HOSTED] (E2BIG,EACCES,EADDRINUSE,EADDRNOTAVAIL) >>> (EAFNOSUPPORT,EAGAIN,EALREADY,EBADF,EBADMSG,EBUSY,ECANCELED) >>> (ECHILD,ECONNABORTED,ECONNREFUSED,ECONNRESET,EDEADLK) >>> (EDESTADDRREQ,EDOM,EEXIST,EFAULT,EFBIG,EHOSTUNREACH,EIDRM) >>> (EILSEQ,EINPROGRESS,EINTR,EINVAL,EIO,EISCONN,EISDIR,ELOOP) >>> (EMFILE,EMLINK,EMSGSIZE,ENAMETOOLONG,ENETDOWN,ENETRESET) >>> (ENETUNREACH,ENFILE,ENOBUFS,ENODEV,ENOENT,ENOEXEC,ENOLCK) >>> (ENOLINK,ENOMEM,ENOMSG,ENOPROTOOPT,ENOSPC,ENOSYS,ENOTCONN) >>> (ENOTDIR,ENOTEMPTY,ENOTRECOVERABLE,ENOTSOCK,ENOTSUP,ENOTTY) >>> (ENXIO,EOPNOTSUPP,EOVERFLOW,EOWNERDEAD,EPERM,EPIPE,EPROTO) >>> (EPROTONOSUPPORT,EPROTOTYPE,ERANGE,EROFS,ESPIPE,ESRCH) >>> (ETIMEDOUT,ETXTBSY,EWOULDBLOCK,EXDEV): Define. >>> --- >>> >>> I don't really like this patch, but sending it for comment. >>> >>> Every time we add our own <name.h> C header it complicates things, and >>> we have various bug reports (and patches) related to those files causing >>> problems during bootstrap of obscure canadian-cross configurations. >>> >>> So I'm a bit concerned that adding <errno.h> just for Freestanding would >>> end up causing regressions that affect Hosted builds too. >>> >> We are already conditionally installing more headers for Hosted builds, so >> could we conditionally install the new header only for environments that >> are >> not hosted? This should avoid any potential impact on existing platforms. >> > > That won't work, not consistently anyway. For freestanding, you can either > build GCC with --disable-hosted-libstdcxx or you can build a hosted > implementation but then use -ffreestanding. > > If we install different headers for the non-hosted build, you would not be > able to include errno.h with -ffreestanding, or you would get the libc one > which would have different error numbers. > > Maybe that's ok, and users would need to use a consistent "really > freestanding" or "hosted but used as freestanding" installation. But I > think it would be surprising. > That where my suggestion for using has_include_next where comming from. If you build with --disable-hosted-libstdcxx you will get system errno.h regardless if you use -ffreestanding or not. And if you enable --disable-hosted-libstdcxx then you get a errno.h file installed, that will use __has_include_next and also pull libc errno.h file on the same target. So result will be consistent. And errno.h does not really have operating system dependencies, so I assume it could exist on some freenstanding enviroments, and provide some system specific constants. > > >>> >>> libstdc++-v3/include/Makefile.am | 3 +- >>> libstdc++-v3/include/Makefile.in | 3 +- >>> libstdc++-v3/include/c_compatibility/errno.h | 91 +++++++++++++++++++- >>> 3 files changed, 94 insertions(+), 3 deletions(-) >>> >>> diff --git a/libstdc++-v3/include/Makefile.am >>> b/libstdc++-v3/include/Makefile.am >>> index 3c30aa21d6b5..18bb9f224563 100644 >>> --- a/libstdc++-v3/include/Makefile.am >>> +++ b/libstdc++-v3/include/Makefile.am >>> @@ -902,6 +902,7 @@ endif >>> c_base_srcdir = $(C_INCLUDE_DIR) >>> c_base_builddir = . >>> c_base_freestanding = \ >>> + ${c_base_srcdir}/cerrno \ >>> ${c_base_srcdir}/cfloat \ >>> ${c_base_srcdir}/climits \ >>> ${c_base_srcdir}/cstdalign \ >>> @@ -919,7 +920,6 @@ c_base_headers = \ >>> ${c_base_srcdir}/cassert \ >>> ${c_base_srcdir}/ccomplex \ >>> ${c_base_srcdir}/cctype \ >>> - ${c_base_srcdir}/cerrno \ >>> ${c_base_srcdir}/cfenv \ >>> ${c_base_srcdir}/cinttypes \ >>> ${c_base_srcdir}/ciso646 \ >>> @@ -947,6 +947,7 @@ endif >>> if GLIBCXX_C_HEADERS_C_GLOBAL >>> c_compatibility_headers = \ >>> ${c_compatibility_srcdir}/complex.h \ >>> + ${c_compatibility_srcdir}/errno.h \ >>> ${c_compatibility_srcdir}/fenv.h \ >>> ${c_compatibility_srcdir}/tgmath.h \ >>> ${c_compatibility_srcdir}/math.h \ >>> diff --git a/libstdc++-v3/include/Makefile.in >>> b/libstdc++-v3/include/Makefile.in >>> index d081481293ff..feb6665ca401 100644 >>> --- a/libstdc++-v3/include/Makefile.in >>> +++ b/libstdc++-v3/include/Makefile.in >>> @@ -1250,6 +1250,7 @@ experimental_bits_headers = \ >>> c_base_srcdir = $(C_INCLUDE_DIR) >>> c_base_builddir = . >>> c_base_freestanding = \ >>> + ${c_base_srcdir}/cerrno \ >>> ${c_base_srcdir}/cfloat \ >>> ${c_base_srcdir}/climits \ >>> ${c_base_srcdir}/cstdalign \ >>> @@ -1265,7 +1266,6 @@ c_base_freestanding = \ >>> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cassert \ >>> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/ccomplex \ >>> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cctype \ >>> -@GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cerrno \ >>> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cfenv \ >>> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cinttypes \ >>> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/ciso646 \ >>> @@ -1287,6 +1287,7 @@ c_compatibility_srcdir = >>> ${glibcxx_srcdir}/include/c_compatibility >>> c_compatibility_builddir = . >>> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@c_compatibility_headers = \ >>> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ >>> ${c_compatibility_srcdir}/complex.h \ >>> +@GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ >>> ${c_compatibility_srcdir}/errno.h \ >>> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ >>> ${c_compatibility_srcdir}/fenv.h \ >>> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ >>> ${c_compatibility_srcdir}/tgmath.h \ >>> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ >>> ${c_compatibility_srcdir}/math.h \ >>> diff --git a/libstdc++-v3/include/c_compatibility/errno.h >>> b/libstdc++-v3/include/c_compatibility/errno.h >>> index 07e3c17e9173..3eea20e081bb 100644 >>> --- a/libstdc++-v3/include/c_compatibility/errno.h >>> +++ b/libstdc++-v3/include/c_compatibility/errno.h >>> @@ -29,6 +29,95 @@ >>> #ifndef _GLIBCXX_ERRNO_H >>> #define _GLIBCXX_ERRNO_H 1 >>> >>> -#include <cerrno> >>> +#include <bits/c++config.h> >>> + >>> +#if _GLIBCXX_HOSTED >>> >> Should whe use _has_include_next(<errno.h>)? So pull this header >> if it is provided? >> > > It's required for hosted implementations, and we know it's always present > because everybody can already include it today. > > > +#include_next <errno.h> >>> +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 >>> +#ifndef errno >>> +#define errno errno >>> +#endif >>> + >>> +#else >>> +__thread inline int __errno_v = 0; >>> + >>> +#define errno __errno_v >>> + >>> +#define E2BIG 10007 >>> +#define EACCES 10013 >>> +#define EADDRINUSE 10098 >>> +#define EADDRNOTAVAIL 10099 >>> +#define EAFNOSUPPORT 10097 >>> +#define EAGAIN 10011 >>> +#define EALREADY 10114 >>> +#define EBADF 10009 >>> +#define EBADMSG 10074 >>> +#define EBUSY 10016 >>> +#define ECANCELED 10125 >>> +#define ECHILD 10010 >>> +#define ECONNABORTED 10103 >>> +#define ECONNREFUSED 10111 >>> +#define ECONNRESET 10104 >>> +#define EDEADLK 10035 >>> +#define EDESTADDRREQ 10089 >>> +#define EDOM 10033 >>> +#define EEXIST 10017 >>> +#define EFAULT 10014 >>> +#define EFBIG 10027 >>> +#define EHOSTUNREACH 10113 >>> +#define EIDRM 10043 >>> +#define EILSEQ 10084 >>> +#define EINPROGRESS 10115 >>> +#define EINTR 10004 >>> +#define EINVAL 10022 >>> +#define EIO 10005 >>> +#define EISCONN 10106 >>> +#define EISDIR 10021 >>> +#define ELOOP 10040 >>> +#define EMFILE 10024 >>> +#define EMLINK 10031 >>> +#define EMSGSIZE 10090 >>> +#define ENAMETOOLONG 10036 >>> +#define ENETDOWN 10100 >>> +#define ENETRESET 10102 >>> +#define ENETUNREACH 10101 >>> +#define ENFILE 10023 >>> +#define ENOBUFS 10105 >>> +#define ENODEV 10019 >>> +#define ENOENT 10002 >>> +#define ENOEXEC 10008 >>> +#define ENOLCK 10037 >>> +#define ENOLINK 10067 >>> +#define ENOMEM 10012 >>> +#define ENOMSG 10042 >>> +#define ENOPROTOOPT 10092 >>> +#define ENOSPC 10028 >>> +#define ENOSYS 10038 >>> +#define ENOTCONN 10107 >>> +#define ENOTDIR 10020 >>> +#define ENOTEMPTY 10039 >>> +#define ENOTRECOVERABLE 10131 >>> +#define ENOTSOCK 10088 >>> +#define ENOTSUP 10095 >>> +#define ENOTTY 10025 >>> +#define ENXIO 10006 >>> +#define EOPNOTSUPP 10095 >>> +#define EOVERFLOW 10075 >>> +#define EOWNERDEAD 10130 >>> +#define EPERM 10001 >>> +#define EPIPE 10032 >>> +#define EPROTO 10071 >>> +#define EPROTONOSUPPORT 10093 >>> +#define EPROTOTYPE 10091 >>> +#define ERANGE 10034 >>> +#define EROFS 10030 >>> +#define ESPIPE 10029 >>> +#define ESRCH 10003 >>> +#define ETIMEDOUT 10110 >>> +#define ETXTBSY 10026 >>> +#define EWOULDBLOCK 10011 >>> +#define EXDEV 10018 >>> + >>> +#endif // HOSTED >>> >>> #endif >>> -- >>> 2.55.0 >>> >>>
