Skip to content

Update libcxx from LLVM 22.1.8 to 23.1.3 - #28149

Open
aheejin wants to merge 15 commits into
emscripten-core:mainfrom
aheejin:update_libcxx_23
Open

aheejin wants to merge 15 commits into
emscripten-core:mainfrom
aheejin:update_libcxx_23

Conversation

@aheejin

@aheejin aheejin commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

This updates libcxx from 22.1.8 to LLVM 23.1.3:
https://github.com/llvm/llvm-project/releases/tag/llvmorg-23.1.3

Additional changes:
(More detailed descriptions are in the commit messages)

This adds missing variables in `__config_site.in`. We define all of
these to 0 (because we we musl), and if not defined these are considered
to be 0, so it wasn't causing any errors, but I think it's nice to be
explicit.
llvm/llvm-project#193045 introduced
`_LIBCPP_{BEGIN/END}_EXPLICIT_ABI_ANNOTATIONS`.
`_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS` starts the area where a specified
set of attributes are automatically applied to all functions, i.e., this
ends an 'explicit' ABI region and starts an 'implicit' ABI region.
`_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS` ends the region, which means
the attributes are not applied automatically anymore.
https://github.com/llvm/llvm-project/blob/0d261d1ca552c95a8f007e061c787ac7132fbcbc/libcxx/include/__configuration/namespace.h#L49-L55

Inside a namespace block, `_LIBCPP_{BEGIN/END}_EXPLICIT_ABI_ANNOTATIONS`
can be separately used to start and end a region. But
`_LIBCPP_BEGIN_NAMESPACE_STD`, which is at the start of each header file
in libcxx, sets `_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS`, and
`_LIBCPP_END_NAMESPACE_STD` sets
`_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS`, meaning by default all headers
are inside a region where the set of attributes are automatically
applied.

There can be warnings with these attributes, such as, if there is no
function within a region, Clang warns.
```cpp
  # pragma clang attribute push (attribute, ...)
  NO FUNCTIONS HERE
  # pragma clang attribute pop
```
But llvm/llvm-project#193045 suppressed those
warnings.

Then later, llvm/llvm-project#200338 removed
those warning-suppressing pragmas when
`_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER` was not defined in order to boost
compilation time:
https://github.com/llvm/llvm-project/blob/0d261d1ca552c95a8f007e061c787ac7132fbcbc/libcxx/include/__configuration/namespace.h#L22-L57

For normal library users, if `_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER` is
not defined, `#pragma GCC system_header` kicks in, suppressing all
warnings in the headers (and only headers), so they don't need the
warning suppressions.
https://github.com/llvm/llvm-project/blob/0d261d1ca552c95a8f007e061c787ac7132fbcbc/libcxx/include/__configuration/namespace.h#L18-L20
And their source files don't have `_LIBCPP_{BEGIN/END}_NAMESPACE_STD`s
so their source files are free from the warnings.

But for us who build libc++, if we don't define
`_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER`, the library source files that
have `_LIBCPP_{BEGIN/END}_NAMESPACE_STD` are not protected from
warnings.

So we should define `_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER`. The upstream
libcxx also defines it:
https://github.com/llvm/llvm-project/blob/0d261d1ca552c95a8f007e061c787ac7132fbcbc/runtimes/cmake/Modules/WarningFlags.cmake#L5
This comment in the PR suggests the same:
llvm/llvm-project#200338 (comment)
The upstream started to build libc++ with C++26
(llvm/llvm-project#181021). And
llvm/llvm-project#141312 added text_encoding,
which does not build without C++26. This builds libc++ with C++26.
llvm/llvm-project#166074, in LLVM 22, introduced
the notion of minimum header version:
https://libcxx.llvm.org/VendorDocumentation.html#minimum-header-version

With a specific minimum version, we don't support and include symbols in
previous LLVM headers but not in the current headers anymore. Emscripten
has used `_LIBCPP_ABI_VERSION = 2`, which means we don't allow linking
with older versions of objects anyway:
https://github.com/emscripten-core/emscripten/blob/e6071d1029bcb7a5e67168ce318835de67f63297/system/lib/libcxx/include/__config_site#L3

So setting `_LIBCPP_AVAILABILITY_MINIMUM_HEADER_VERSION` to 23 (the
current LLVM release) allows us to remove old unused symbols from the
archives.
llvm/llvm-project#195509 removed unused
transitive includes by default, causing undefined identifier errors in
our Emscripten-only files (or Emscripten-specific modifications in
`cxa_noexception.cpp`). This adds the necessary includes. This also
removed the commented out `// #include <stdint.h>` line that was not
being used.
llvm/llvm-project#195509 removed unused
transitive includes by default, causing undefined identifier errors in
our files.

This also increments line numbers in the linemarkers in `wasmfs.cpp`,
because a new include was added in the beginning of the file.
llvm/llvm-project#195509 removed unused
transitive includes by default, causing undefined identifier errors in
our files. This adds necessary includes to our tests.
llvm/llvm-project#195509 removed unused
transitive includes by default, breaking port builds. Unlike our code,
we cannot change their source code by adding more includes, so we pass
`-D_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23`, which temporarily can be
used to keep the transitive includes. This macro is scheduled to be
removed in LLVM 24, so we probably need to update the ports by then.
This is an automatic change generated by tools/maint/rebaseline_tests.py.

The following (11) test expectation files were updated by
running the tests with `--rebaseline`:

```
codesize/test_codesize_cxx_ctors1.json: 153083 => 153064 [-19 bytes / -0.01%]
codesize/test_codesize_cxx_ctors2.json: 152488 => 152439 [-49 bytes / -0.03%]
codesize/test_codesize_cxx_except.json: 197151 => 197285 [+134 bytes / +0.07%]
codesize/test_codesize_cxx_except_wasm.json: 168527 => 168654 [+127 bytes / +0.08%]
codesize/test_codesize_cxx_except_wasm_legacy.json: 166387 => 166513 [+126 bytes / +0.08%]
codesize/test_codesize_cxx_lto.json: 119457 => 119285 [-172 bytes / -0.14%]
codesize/test_codesize_cxx_mangle.json: 264210 => 264395 [+185 bytes / +0.07%]
codesize/test_codesize_cxx_noexcept.json: 154990 => 155049 [+59 bytes / +0.04%]
codesize/test_codesize_cxx_wasmfs.json: 180581 => 181168 [+587 bytes / +0.33%]
codesize/test_codesize_files_wasmfs.json: 54930 => 55432 [+502 bytes / +0.91%]
codesize/test_minimal_runtime_code_size_hello_embind.json: 15146 => 15162 [+16 bytes / +0.11%]

Average change: +0.13% (-0.14% - +0.91%)
```
These changes are also needed due to
llvm/llvm-project#195509 which removed
transitive includes.
@aheejin
aheejin marked this pull request as ready for review November 3, 2026 07:10
@aheejin
aheejin requested a review from sbc100 November 3, 2026 07:10

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request performs a major update and refactoring of libc++ headers, including updating the library version to 23.1.3, reorganizing configuration and attribute macros, adding new utility headers like valid_range.h and capacity_aware_iterator.h, and modernizing various algorithms and iterators. The review feedback identifies critical issues in the newly introduced __capacity_aware_iterator, where the absolute value calculation for bounds checking can trigger undefined behavior via signed integer overflow when the offset is the minimum possible value. Additionally, a potential compilation failure was noted in ranges::swap_ranges when the two ranges have mismatched difference types, which can be resolved by explicitly specifying their common type in std::min.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant