llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Jeff Bailey (kaladron)
<details>
<summary>Changes</summary>
Update the developer coding style documentation to detail the proper handling of errno across runtime entrypoints, support libraries, and unit tests:
* Require "src/__support/libc_errno.h" and libc_errno rather than raw <errno.h> to prevent thread-local storage mismatches.
* Specify that entrypoints should depend on both libc.src.__support.libc_errno and libc.src.errno.errno in CMake.
* Note the build system exception permitting entrypoint dependencies on libc.src.errno.errno.
* Add cross-references in the entrypoint and function implementation guides.
Assisted-by: Automated tooling, human reviewed.
---
Full diff: https://github.com/llvm/llvm-project/pull/230274.diff
3 Files Affected:
- (modified) libc/docs/dev/code_style.md (+63-17)
- (modified) libc/docs/dev/entrypoints.md (+6)
- (modified) libc/docs/dev/implementing_a_function.md (+6-2)
``````````diff
diff --git a/libc/docs/dev/code_style.md b/libc/docs/dev/code_style.md
index f403564fc5fd67..62ff0e543fbb37 100644
--- a/libc/docs/dev/code_style.md
+++ b/libc/docs/dev/code_style.md
@@ -85,41 +85,87 @@ rules:
class methods (static and non-static) defined inline and `constexpr`
functions.
+(setting_errno)=
+
## Setting `errno` from runtime code
Many libc functions set `errno` to indicate an error condition. If LLVM's libc
is being used as the only libc, then the `errno` from LLVM's libc is affected.
-If LLVM's libc is being used in the {ref}`overlay_mode`, then the `errno` from
-the system libc is affected. When a libc function, which can potentially affect
-the `errno`, is called from a unit test, we do not want the global `errno`
+If LLVM's libc is being used in {ref}`overlay_mode`, then the `errno` from
+the system libc is affected. When a libc function that can potentially affect
+`errno` is called from a unit test, we do not want the global `errno`
(as in, the `errno` of the process thread running the unit test) to be
affected. If the global `errno` is affected, then the operation of the unit
-test infrastructure itself can be affected. To avoid perturbing the unit test
-infrastructure around the setting of `errno`, the following rules are to be
-followed:
+test infrastructure itself can be affected.
+
+To handle `errno` correctly across all build modes and avoid silent thread-local
+storage mismatches, the following rules must be followed:
+
+1. **Header Inclusion:**
+ Runtime code and unit tests must **ONLY** `#include "src/__support/libc_errno.h"`
+ and refer to `libc_errno`.
+ - Never `#include <errno.h>`.
+ - Never `#include "src/errno/libc_errno.h"` (this is a legacy path; the header
+ lives in `src/__support/`).
+ - For standard error constants (such as `EINVAL`, `ENOMEM`), include
+ `"hdr/errno_macros.h"`.
-1. A special macro named `libc_errno` defined in `src/__support/libc_errno.h`
- should be used when setting `errno` from libc runtime code. For example,
- code to set `errno` to `EINVAL` should be:
+ Setting `errno` should be done directly via `libc_errno`:
```c++
libc_errno = EINVAL;
```
-2. `errno` should be set just before returning from the implementation of the
- public function. It should not be set from within helper functions. Helper
+2. **Where to set `errno`:**
+ `errno` should only be set just before returning from the implementation of
+ the public function. It should not be set from within helper functions. Helper
functions should use idiomatic C++ constructs like
[cpp::optional](https://github.com/llvm/llvm-project/blob/main/libc/src/__support/CPP/optional.h)
and
[ErrorOr](https://github.com/llvm/llvm-project/blob/main/libc/src/__support/error_or.h)
to return error values.
-3. The header file `src/__support/libc_errno.h` is shipped as part of the target
- corresponding to the `errno` entrypoint `libc.src.errno.errno`. We do
- not in general allow dependencies between entrypoints. However, the `errno`
- entrypoint is the only exceptional entrypoint on which other entrypoints
- should explicitly depend on if they set `errno` to indicate error
- conditions.
+3. **CMake Dependencies for Public Entrypoints:**
+ Any entrypoint that reads or sets `errno` should ideally declare **BOTH** of the
+ following in the `DEPENDS` list of its `add_entrypoint_object`:
+ - **`libc.src.__support.libc_errno`**: Satisfies the header dependency for
+ `src/__support/libc_errno.h`.
+ - **`libc.src.errno.errno`**: Satisfies the link-time requirement for the compiled
+ runtime storage (`libc_errno.cpp`) defining `thread_errno`, `__llvm_libc_errno()`,
+ and the C++ `Errno` class.
+
+ While LLVM-libc generally disallows dependencies between public entrypoints,
+ `libc.src.errno.errno` is an **explicitly allowed exception** in the build system
+ (see `ALLOWED_DEPS` in `libc/cmake/modules/LLVMLibCObjectRules.cmake`). Downstream
+ consumers and test suites that link the entrypoint require this dependency so that
+ the storage for `libc_errno` is linked.
+
+4. **CMake Dependencies for Internal Support Libraries:**
+ Header-only utility libraries under `libc/src/__support/` (such as `OSUtil` syscall
+ wrappers or `FPUtil`) that reference `libc_errno.h` should depend on
+ **`libc.src.__support.libc_errno`** so they remain pure header libraries without
+ introducing compiled entrypoint object dependencies.
+
+5. **Unit and Hermetic Testing:**
+ Unit tests verifying functions that set `errno` must use the `ErrnoCheckingTest`
+ fixture (`test/UnitTest/ErrnoCheckingTest.h`) and `ErrnoSetterMatcher`
+ (`test/UnitTest/ErrnoSetterMatcher.h`).
+ - Both `ErrnoCheckingTest` and `ErrnoSetterMatcher` already declare `DEPENDS libc.src.errno.errno`,
+ so tests using them inherit the compiled `errno` object transitively.
+ - Tests that check `libc_errno` directly without those matchers must declare
+ `libc.src.errno.errno` in their test `DEPENDS`.
+ - Tests must never `#include <errno.h>`.
+
+6. **The "Dual-TLS" Pitfall in Overlay Mode:**
+ Why is strictly adhering to `libc_errno` and `"src/__support/libc_errno.h"` critical?
+ In overlay mode, the host system libc (e.g., glibc) maintains its own thread-local
+ `errno` location (accessed via `*__errno_location()`). In unit tests, LLVM-libc
+ runs in internal thread-local mode (`LIBC_ERRNO_MODE_THREAD_LOCAL`), writing to
+ LLVM-libc's own `thread_errno`.
+ If implementation code or tests mistakenly `#include <errno.h>` and use raw `errno`,
+ the code will compile cleanly without warnings, but reads and writes will target
+ different thread-local storage locations in the same thread. This results in silent
+ test failures or error values that appear to vanish or go to the wrong thread.
## Assertions in libc runtime code
diff --git a/libc/docs/dev/entrypoints.md b/libc/docs/dev/entrypoints.md
index 80fa728d6a764b..09cc1181b2a575 100644
--- a/libc/docs/dev/entrypoints.md
+++ b/libc/docs/dev/entrypoints.md
@@ -87,6 +87,12 @@ add_entrypoint_object(
For redirecting entrypoints (e.g., when one function is a simple alias for
another), the `REDIRECTED` option can be specified to the rule.
+Entrypoint objects are generally forbidden from depending on other entrypoint
+objects. The single allowed exception is `libc.src.errno.errno`: entrypoints
+that read or set `errno` should declare both `libc.src.__support.libc_errno`
+(the internal header) and `libc.src.errno.errno` (the compiled runtime storage)
+in their `DEPENDS` list. See {ref}`setting_errno` for detailed rules.
+
### `add_entrypoint_library`
Standard library files like `libc.a` and `libm.a` are produced by
diff --git a/libc/docs/dev/implementing_a_function.md b/libc/docs/dev/implementing_a_function.md
index 9cdae90ebb8bcb..26e5468cde0280 100644
--- a/libc/docs/dev/implementing_a_function.md
+++ b/libc/docs/dev/implementing_a_function.md
@@ -41,7 +41,9 @@ Add a CMake target for the new function so it can be compiled.
- **File**: `libc/src/<header>/CMakeLists.txt`
- Add an `add_entrypoint_object` rule for the new file.
-- List all internal dependencies correctly to ensure proper build order.
+- List all internal dependencies correctly to ensure proper build order. If the
+ function reads or sets `errno`, include both `libc.src.__support.libc_errno`
+ and `libc.src.errno.errno` in `DEPENDS` (see {ref}`setting_errno`).
### 5. Platform Registration
@@ -55,5 +57,7 @@ Register the new entrypoint for the target platforms to include it in the build.
Create tests to verify the implementation.
- **File**: `libc/test/src/<header>/<func>_test.cpp`
-- Add corresponding tests using the internal testing framework.
+- Add corresponding tests using the internal testing framework. For functions
+ setting `errno`, use `ErrnoCheckingTest` and `ErrnoSetterMatcher`
+ (see {ref}`setting_errno`).
- Update the `CMakeLists.txt` in the test directory (`libc/test/src/<header>/CMakeLists.txt`) to include the new test target.
``````````
</details>
https://github.com/llvm/llvm-project/pull/230274