llvm / llvm/llvm-project

LIBCXX: Building LLVM libcxx use of implementation dependant `strto<num>` with locale fails, when using musl libc (in freestanding or Unix BSD modes)

Open
#201,500 1 comment 0 reactions 0 assignees View on GitHub
libc libc++
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

> [!IMPORTANT]
> If this is the wrong place for this, I apologise, please go easy on me and feel free to point me at the appropriate place to post this.
> Regarding LLVM-Project's AI policy, I hear-by disclose _I have used LLM 'AI' tools to refactor and sometimes re-word some of the content (namely: parts of the external reproducible examples) related to this GHI, though not without myself as the human-in-the-loop; **however out of an abundance of caution, and in hopes of getting a response this time, _this_ issue was written, _and formatted_ completely manually by myself**. Thank you for taking the time to look at this.

Affects llvm-project versions: <= 22.1.7 (21.1.5-22.1.7 and possibly others)
_(EDIT: was first identified as of 21.1.5) Affecting platform alpine linux (with source built musl's libc) in related GHI #167977 (for linux hosts specifically; this is )_
_(EDIT: and baremetal <=21.1.5, baremetal unknown with 21.1.8-22.1.7)_
Affects subprojects: ~libcxxabi,~ libcxx (including if build with C++ abi == `None`)

## context
When building LLVM's libcxx with configurations that result in defining `_LIBCPP_HAS_MUSL_LIBC` (e.g., with `-D_LIBCPP_HAS_MUSL_LIBC`) but **LACK** `_GNU_SOURCE` (e.g., musl libc `v1.2.5`/`v1.2.6` built freestanding (or with `_BSD_SOURCE`); e.g., instead of with `_GNU_SOURCE` and those extensions) will
cascade to cause issues with 'Strtonum functions' when attempting to support locale variants (e.g., see ``/`includes/c++/v1/__locale_dir/locale_base_api.h`) namely:

* _any_ use of `strtof_l`
* _any_ use of `ststrtof_l`
* _any_ use of `strtold_l`

with result in libcxx compile time errors; e.g., `error: use of undeclared identifier`

Example with LLVM-Project/libcxx v22.1.7 & musl libc v1.2.6 ([built freestanding in docker](https://github.com/reactive-firewall/LLVM-Alpine-Musl/blob/5e843eafe6993f647cb10b85b99822a8010b0991/dockerfile#L554-L568))

Image

TL;DR; - [Full build logs can be viewed here, until expired](https://github.com/reactive-firewall/LLVM-Alpine-Musl/actions/runs/26921981493/job/79424172572#step:9:11283) (search "build-libcxx-bs 28" for the relevant step)

errors present as:

`error: use of undeclared identifier 'strtof_l'`

`error: use of undeclared identifier 'strtod_l'`

`error: use of undeclared identifier 'strtold_l'`

### Related but resolved:

* older example of side-effects from v21.1.5 can be-found in closed GHI #167977

## Root cause
The musl implementation of the functions (circa v1.2.6) just discards the `__loc` argument (even if `defined(_GNU_SOURCE)` is True) but musl `libc` omits `strto*_l` completely without it.

(obviously the workaround is to provide a compatibility layer to unconditionally expose the `strto*_l` implementations, but then what about the LLVM-project's stance on musl libc in LLVM's documentation? e.g., https://clang.llvm.org/docs/Toolchain.html)

* Request for triage by someone who is more familiar with the libcxx side. Is this a bug (as I first thought)? or do I need to approach this as a new feature? Or is this a documentation gap?

---

## References / See-Also
Relevant code in musl libc (circa v1.2.5) can be found in the following files:

* In musl libc code: `include/stdlib.h` (around lines 28-35)
```c
float strtof (const char *__restrict, char **__restrict);
double strtod (const char *__restrict, char **__restrict);
long double strtold (const char *__restrict, char **__restrict);
```
* In musl libc code: implementation is found in `src/stdlib/strtod.c` (around lines 17-30) (code seems to target c99-c11 C standard, using the strict `restrict` keyword (no-aliases))
* In musl libc code: `include/stdlib.h` (around lines 154-164)
* this is the root cause of why _GNU_SOURCE can not be assumed by other indicators when given `_LIBCPP_HAS_MUSL_LIBC`
```c
#ifdef _GNU_SOURCE
...
struct __locale_struct;
float strtof_l(const char *__restrict, char **__restrict, struct __locale_struct *);
double strtod_l(const char *__restrict, char **__restrict, struct __locale_struct *);
long double strtold_l(const char *__restrict, char **__restrict, struct __locale_struct *);
#endif
```
* In musl libc v1.2.5 code: implementation for wrappers are found in `src/locale/strtod_l.c` (around lines 5-22) (implementation just ignores the `local_t` argument and returns the two-argument (e.g., nonlocal aware) form)
* however this is possibly mangled or just omitted from the resulting `libc` binary, _unless_ `_GNU_SOURCE` is specifically defined when building (and of-course later including the standard C headers from) musl libc (which is not the case for a free-standing build of musl)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.