[PATCH][RFC] libstdc++ Provide <cerrno> and <errno.h> for freestanding
Jonathan Wakely <[email protected]> Mon, 3 Aug 2026 17:55:57 +0100
| Newsgroups | gmane.comp.gcc.patches,gmane.comp.gcc.libstdc++.devel |
|---|---|
| Message-ID | <[email protected]> |
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.
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
+#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