(errno)=

errno and libc_errno in LLVM-libc

Many C and POSIX functions report errors by setting errno. Because LLVM-libc supports multiple build and deployment modes ({doc}../full_host_build, {doc}../full_cross_build, {doc}../overlay_mode, baremetal, GPU, and header-only libc/shared/), internal code and unit tests access errno through libc_errno.

Targets Overview

errno support is split across three targets:

CMake TargetBazel TargetHeader / SourcePurpose
libc.hdr.errno_macros:hdr_errno_macroslibc/hdr/errno_macros.hError constants (EINVAL, ERANGE, EDOM, ENOMEM, etc.) without libc_errno.
libc.src.__support.libc_errno:__support_libc_errnolibc/src/__support/libc_errno.hDeclares libc_errno (either as #define libc_errno errno or as LIBC_INLINE_VAR constexpr Errno libc_errno{}).
libc.src.errno.errno:errnolibc/src/errno/libc_errno.cppDefines the backing storage (thread_errno or shared_errno), extern "C" int *__llvm_libc_errno() noexcept, and (when LIBC_COPT_PROVIDE_GNU_ALIASES is enabled) the __errno_location alias.

Usage Guidelines

1. Header Inclusion

  • Never #include <errno.h> in libc/src/** or unit tests (libc/test/src/**).

  • Only need error constants (EINVAL, ERANGE, EDOM, etc.)? Include "hdr/errno_macros.h":

    #include "hdr/errno_macros.h"
    
  • Read or write errno? Include "src/__support/libc_errno.h" (which also includes "hdr/errno_macros.h") and use libc_errno:

    #include "src/__support/libc_errno.h"
    
    libc_errno = EINVAL;
    

2. Where to Set libc_errno

  • Set libc_errno only at the public entrypoint boundary (LLVM_LIBC_FUNCTION) just before returning an error, or via fputil::set_errno_if_required in math implementations.

  • Internal helpers in libc/src/__support/ should not set libc_errno directly; return ErrorOr<T> or cpp::optional<T> instead and set libc_errno in the entrypoint:

    LLVM_LIBC_FUNCTION(int, close, (int fd)) {
      auto res = linux_syscalls::close(fd);
      if (!res) {
        libc_errno = res.error();
        return -1;
      }
      return 0;
    }
    

3. Build Dependencies

Target TypeOnly Needs Error Constants (EINVAL, etc.)Reads or Writes libc_errno
libc/src/__support/**libc.hdr.errno_macroslibc.src.__support.libc_errno (never libc.src.errno.errno)
Public Entrypoints (libc/src/**)libc.hdr.errno_macroslibc.src.__support.libc_errno (and libc.src.errno.errno for non-math libc.a entrypoints)
Tests / Fuzzers / Benchmarkslibc.hdr.errno_macrosLinked automatically (libc.src.__support.libc_errno and libc.src.errno.errno)
  • While public entrypoints normally cannot depend on other entrypoints, libc.src.errno.errno is explicitly allowed in ALLOWED_DEPS in libc/cmake/modules/LLVMLibCObjectRules.cmake.

4. Testing errno

  • Test rules (add_libc_test, add_fp_unittest, add_integration_test, add_libc_fuzzer, and perf_test) automatically link libc.src.errno.errno.
  • Unit tests that check errno should use ErrnoCheckingTest (test/UnitTest/ErrnoCheckingTest.h) or ErrnoSetterMatcher (test/UnitTest/ErrnoSetterMatcher.h):
    • ErrnoCheckingTest resets libc_errno = 0 before each test and verifies libc_errno == 0 at the end.
    • ErrnoSetterMatcher (ASSERT_THAT(..., Fails(EINVAL)) / Succeeds()) checks and resets libc_errno automatically.
  • Header-only libc/shared/* tests (libc/test/shared/*): Compiled with LIBC_ERRNO_MODE_SYSTEM_INLINE in overlay mode; check errno directly when testing error conditions.

LIBC_ERRNO_MODE Configurations

LIBC_CONF_ERRNO_MODE (passed to the compiler as -DLIBC_ERRNO_MODE=<mode>) controls how libc_errno is implemented:

Modelibc_errno in libc_errno.hBacking Storage in libc_errno.cppTypical Use Case
LIBC_ERRNO_MODE_DEFAULTResolves to THREAD_LOCAL or SYSTEM_INLINE (see below).thread_errnoDefault configuration.
LIBC_ERRNO_MODE_THREAD_LOCALInline Errno wrapper calling *__llvm_libc_errno().LIBC_THREAD_LOCAL int thread_errno;Full builds; overlay unit tests.
LIBC_ERRNO_MODE_SHAREDInline Errno wrapper calling *__llvm_libc_errno().Global int shared_errno;Single-threaded or thread-local-free targets (GPU, UEFI).
LIBC_ERRNO_MODE_EXTERNALInline Errno wrapper calling *__llvm_libc_errno().Provided by external embedder.Baremetal (libc/config/baremetal/config.json).
LIBC_ERRNO_MODE_UNDEFINEDInline no-op (operator= is a no-op, operator int() returns 0).None (empty TU).Minimal embedded environments without errno.
LIBC_ERRNO_MODE_SYSTEM_INLINE#define libc_errno errno (from system <errno.h>).None (empty TU).Overlay public archive (libllvmlibc.a) and libc/shared/*.

How LIBC_ERRNO_MODE_DEFAULT Resolves

When LIBC_ERRNO_MODE is unset or set to LIBC_ERRNO_MODE_DEFAULT:

  • Full build (LIBC_FULL_BUILD): resolves to LIBC_ERRNO_MODE_THREAD_LOCAL.
  • Overlay public archive (LIBC_COPT_PUBLIC_PACKAGING): resolves to LIBC_ERRNO_MODE_SYSTEM_INLINE (libc/shared/libc_common.h and libc/test/shared/ also configure LIBC_ERRNO_MODE_SYSTEM_INLINE in non-full builds).
  • Overlay tests, fuzzers, and benchmarks: resolves to LIBC_ERRNO_MODE_THREAD_LOCAL.

Why libc_errno Header and Runtime Storage Are Separated

Keeping libc.src.__support.libc_errno (header) separate from libc.src.errno.errno (runtime object) is necessary for several reasons:

  1. Isolating unit tests from host errno in overlay mode: Public overlay archives (libllvmlibc.a) are built with -DLIBC_COPT_PUBLIC_PACKAGING and use the host‘s <errno.h> (LIBC_ERRNO_MODE_SYSTEM_INLINE). Unit tests are built without -DLIBC_COPT_PUBLIC_PACKAGING and use LLVM-libc’s internal thread_errno (LIBC_ERRNO_MODE_THREAD_LOCAL), preventing tested functions from clobbering the host errno used by the test harness. Conversely, if internal code or tests mistakenly #include <errno.h> and use errno directly, reads and writes will hit different thread-local variables in the same thread.
  2. Header-only libc/shared/* consumption: External LLVM subprojects (such as libc++ and offload) include headers under libc/shared/, which set LIBC_ERRNO_MODE_SYSTEM_INLINE and map libc_errno to <errno.h> without compiling or linking libc_errno.cpp.
  3. errno-free math and archive separation (libc.a vs. libm.a / libmvec.a): FEnvImpl.h includes src/__support/libc_errno.h to define fputil::set_errno_if_required, which is guarded by #ifndef LIBC_MATH_HAS_NO_ERRNO. Because Errno methods are inline, functions that never call set_errno_if_required (such as ceil, floor, copysign, vector math, or LIBC_MATH_NO_ERRNO builds) emit no reference to __llvm_libc_errno(), and libc.src.errno.errno stays in libc.a rather than being pulled into libm.a or libmvec.a.
  4. CMake directory ordering: libc/src/CMakeLists.txt adds src/__support before src/errno because libc.src.errno.errno depends on libc.src.__support.*. Targets under libc/src/__support/ therefore cannot depend on libc.src.errno.errno.