Libc++ 18.0.0 (In-Progress) Release Notes¶
Written by the Libc++ Team
Warning
These are in-progress notes for the upcoming libc++ 18.0.0 release. Release notes for previous releases can be found on the Download Page.
Introduction¶
This document contains the release notes for the libc++ C++ Standard Library, part of the LLVM Compiler Infrastructure, release 18.0.0. Here we describe the status of libc++ in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see the LLVM documentation. All LLVM releases may be downloaded from the LLVM releases web site.
For more information about libc++, please see the Libc++ Web Site or the LLVM Web Site.
Note that if you are reading this file from a Git checkout or the main Libc++ web page, this document applies to the next release, not the current one. To see the release notes for a specific release, please see the releases page.
What’s New in Libc++ 18.0.0?¶
The main focus of the libc++ team has been to implement new C++20, C++23, and C++26 features.
New hardened modes for the library have been added, replacing the legacy debug mode that was removed in the LLVM 17 release. Unlike the legacy debug mode, some of these hardening modes are also intended to be used in production. See Hardening Modes for more details.
Work on the ranges support has progressed. See libc++ Ranges Status for the current status.
Work on the experimental C++23 module support has progressed. The std.compat
module is available and the feature is retroactively available in C++20. See
Modules in libc++ for more information.
Work on the experimental C++17 Parallel STL has progressed. See libc++ Parallel STL Status for the current status.
Work on the experimental C++17 SIMD support has progressed. See libc++ Parallelism TS Status (N4808) for the current status.
Implemented Papers¶
P2093R14 - Formatted output
P2539R4 - Should the output of
std::printto a terminal be synchronized with the underlying stream?P2497R0 - Testing for success or failure of
<charconv>functionsP2697R1 - Interfacing
bitsetwithstring_viewP2443R1 -
views::chunk_byP2538R1 - ADL-proof
std::projectedP2614R2 - Deprecate
numeric_limits::has_denormP0053R7 - C++ Synchronized Buffered Ostream (in the experimental library)
P2467R1 - Support exclusive mode for fstreams
P0020R6 - Floating Point Atomic
P2905R2 - Runtime format strings
P2918R2 - Runtime format strings II
P2871R3 - Remove Deprecated Unicode Conversion Facets from C++26
P2870R3 - Remove
basic_string::reserve()P2909R4 - Fix formatting of code units as integers (Dude, where’s my
char?)P2821R5 -
span.at()P0521R0 - Proposed Resolution for CA 14 (
shared_ptruse_count/unique)P0543R3 - Saturation arithmetic
P1759R6 - Native handles and file streams
P2868R3 - Remove Deprecated
std::allocatorTypedef From C++26P2517R1 - Add a conditional
noexceptspecification tostd::applyP2447R6 -
spanover initializer list
Improvements and New Features¶
std::ranges::countandstd::ranges::findare now optimized forstd::vector<bool>::iterator, which can lead up to 350x performance improvements.std::for_eachhas been optimized for segmented iterators likestd::deque::iteratorin C++23 and later, which can lead up to 40x performance improvements.The library now provides several hardening modes under which common cases of library undefined behavior will be turned into a reliable program termination. The
fasthardening mode enables a set of security-critical checks with minimal runtime overhead; theextensivehardening mode additionally enables relatively cheap checks that catch common logic errors but aren’t necessarily security-critical; and thedebughardening mode enables all available checks, some of which might be very expensive. Vendors can configure which hardening mode is enabled by default with theLIBCXX_HARDENING_MODEvariable at CMake configuration time. Users can control which hardening mode is enabled on a per translation unit basis using the_LIBCPP_HARDENING_MODEmacro. See the hardening documentation for more details.The
_LIBCPP_ENABLE_CXX26_REMOVED_CODECVTmacro has been added to make the declarations in<codecvt>available.The
_LIBCPP_ENABLE_CXX26_REMOVED_STRING_RESERVEmacro has been added to make the functionstd::basic_string<...>::reserve()available.The
_LIBCPP_ENABLE_CXX26_REMOVED_ALLOCATOR_MEMBERSmacro has been added to make the functionallocator<T>::is_always_equalavailable.The
_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUEmacro has been added to make the functionstd::shared_ptr<...>::unique()available.The cmake option
LIBCXX_ENABLE_STD_MODULEShas been removed. The test infrastructure no longer depends on a modern CMake, it works with the minimal required LLVM version (3.20.0).The
.cppmfiles of experimental standard library modules can now be installed. By default, they are not installed. This can be enabled by configuring CMake with-DLIBCXX_INSTALL_MODULES=ON. The installation directory can be configured with the CMake option-DLIBCXX_INSTALL_MODULE_DIR=<path>. The default location is${PREFIX}/share/libc++/v1.AddressSanitizer annotations have been added to
std::basic_string.The libc++ source code has been formatted with
clang-format. This discourse thread contains information how to rebase downstream patches.
Deprecations and Removals¶
Availability macros which will never trigger an error have been removed. This includes anything that has been introduced before macOS 10.13, iOS 12, tvOS 12 and watchOS 4. This shouldn’t affect anybody, since AppleClang 15 doesn’t support any older OSes. If you are a vendor and make use of these macros, please inform the libc++ team so we can re-introduce them and consider upstreaming support for your platform.
The non-conforming constructor
std::future_error(std::error_code)has been removed. Please use thestd::future_error(std::future_errc)constructor provided in C++17 instead.P1957 has been implemented in Clang and libc++ removed a code path that led to narrowing conversions in
std::variantbehaving in a non-standard way. This may change how some uses ofstd::variant’s constructor behave in user code. The_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANTmacro is provided to restore the previous behavior, and it will be supported in the LLVM 18 release only. In LLVM 19 and beyond,_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANTwill not be honored anymore.Overriding
__libcpp_verbose_abortno longer has any effect on library assertions. The only supported way to customize the assertion handler that gets invoked when a hardening assertion fails is now by setting theLIBCXX_ASSERTION_HANDLER_FILECMake variable and providing a custom header. See the documentation on overriding the default assertion handler for details. The ability to override__libcpp_verbose_abortwill be removed in an upcoming release in favor of the new overriding mechanism.In safe mode (which is now equivalent to the
extensivehardening mode), a failed assertion will now generate a trap rather than a call to verbose abort.The
_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDEDmacro is not honored anymore in LLVM 18. Please see the updated documentation about the hardening modes in libc++ and in particular on overriding the default assertion handler.The headers
<experimental/deque>,<experimental/forward_list>,<experimental/list>,<experimental/map>,<experimental/memory_resource>,<experimental/regex>,<experimental/set>,<experimental/string>,<experimental/unordered_map>,<experimental/unordered_set>, and<experimental/vector>have been removed in LLVM 18, as all their contents will have been implemented in namespacestdfor at least two releases.The macro
_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERShas been deprecated and will be removed in LLVM 19. This macro used to re-enable redundant members ofstd::allocator<T>likepointer,reference,rebind,address,max_size,construct,destroy, and the two-argument overload ofallocate. However, this led to the library being non-conforming due to incorrect constexpr-ness.The macros
_LIBCPP_ENABLE_CXX17_REMOVED_FEATURESand_LIBCPP_ENABLE_CXX20_REMOVED_FEATUREShave been deprecated and will be removed in LLVM 19. These macros used to re-enable all features that were removed in the C++17 and C++20 standards. Instead of using these macros, please use the macros to re-enable individual features.The macro
_LIBCPP_INLINE_VISIBILITYhas been deprecated in LLVM 18 and will be removed entirely in LLVM 19. The macro_LIBCPP_HIDE_FROM_ABIis the drop-in replacement.The macro
_VSTDhas been deprecated in LLVM 18 and will be removed entirely in LLVM 19. The codestdis the drop-in replacement.
Upcoming Deprecations and Removals¶
The ability to override
__libcpp_verbose_abortwill be removed in an upcoming release.
LLVM 19¶
The
LIBCXX_EXECUTORCMake variable has been deprecated. LLVM 19 will completely remove support for the*_EXECUTORvariables.The
LIBCXX_ENABLE_ASSERTIONSCMake variable that was used to enable the safe mode will be deprecated and setting it will trigger an error; use theLIBCXX_HARDENING_MODEvariable with the valueextensiveinstead. Similarly, the_LIBCPP_ENABLE_ASSERTIONSmacro will be deprecated (setting it to1still enables the extensive mode in the LLVM 19 release while also issuing a deprecation warning). See the hardening documentation for more details.The base template for
std::char_traitshas been marked as deprecated and will be removed in LLVM 19. If you are usingstd::char_traitswith types other thanchar,wchar_t,char8_t,char16_t,char32_tor a custom character type for which you specializedstd::char_traits, your code will stop working when we remove the base template. The Standard does not mandate that a base template is provided, and such a base template is bound to be incorrect for some types, which could currently cause unexpected behavior while going undetected. Note that the_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATIONmacro can be defined in LLVM 18 to eagerly remove the specialization and prepare code bases for the unconditional removal in LLVM 19.The
_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANTmacro that changed the behavior for narrowing conversions instd::variantwill be removed in LLVM 19.The
_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERSmacro has been deprecated in LLVM 18 and will be removed entirely in LLVM 19.The
_LIBCPP_ENABLE_CXX17_REMOVED_FEATURESand_LIBCPP_ENABLE_CXX20_REMOVED_FEATURESmacros have been deprecated in LLVM 18 and will be removed entirely in LLVM 19.The macro
_LIBCPP_INLINE_VISIBILITYhas been deprecated in LLVM 18 and will be removed entirely in LLVM 19.The macro
_VSTDhas been deprecated in LLVM 18 and will be removed entirely in LLVM 19.
LLVM 20¶
The
LIBCXX_ENABLE_ASSERTIONSCMake variable and the_LIBCPP_ENABLE_ASSERTIONSmacro that were used to enable the safe mode will be removed.
ABI Affecting Changes¶
When the shared/static library is built with
-fno-exceptions, the behavior ofoperator newwas changed to make it standards-conforming. In LLVM 17 and before, the throwing versions ofoperator newwould returnnullptrupon failure to allocate, when the shared/static library was built with exceptions disabled. This was non-conforming, since the throwing versions ofoperator neware never expected to returnnullptr, and this non-conformance could actually lead to miscompiles in subtle cases.Starting in LLVM 18, the throwing versions of
operator newwill abort the program when they fail to allocate if the shared/static library has been built with-fno-exceptions. This is consistent with the behavior of all other potentially-throwing functions in the library, which abort the program instead of throwing when-fno-exceptionsis used.Furthermore, when the shared/static library is built with
-fno-exceptions, users who override the throwing version ofoperator newwill now need to also override thestd::nothrow_tversion ofoperator newif they want to use it. Indeed, this is because there is no way to implement a conformingoperator new(nothrow)from a conforming potentially-throwingoperator newwhen compiled with-fno-exceptions. In that case, usingoperator new(nothrow)without overriding it explicitly but after overriding the throwingoperator newwill result in an error.Note that this change only impacts vendors/users that build the shared/static library themselves and pass
-DLIBCXX_ENABLE_EXCEPTIONS=OFF, which is not the default configuration. If you are using the default configuration of the library, the libc++ shared/static library will be built with exceptions enabled, and there is no change between LLVM 17 and LLVM 18, even for users who build their own code using-fno-exceptions.The symbol of a non-visible function part of
std::system_errorwas removed. This is not a breaking change as the private function__initwas never referenced internally outside of the dylib.This release of libc++ added missing visibility annotations on some types in the library. Users compiling with
-fvisbility=hiddenmay notice that additional type infos from libc++ are being exported from their ABI. This is the correct behavior in almost all cases since exporting the RTTI is required for these types to work properly withdynamic_cast, exceptions and other mechanisms across binaries. However, if you intend to use libc++ purely as an internal implementation detail (i.e. you use libc++ as a static archive and never export libc++ symbols from your ABI) and you notice changes to your exported symbols list, then this means that you were not properly preventing libc++ symbols from being part of your ABI.The name mangling for instantiations of
std::projectedhas changed in order to implement P2538R1. This technically results in an ABI break, however in practice we expect uses ofstd::projectedin ABI-sensitive places to be extremely rare. Any error resulting from this change should result in a link-time error.The internal alignment requirements for heap allocations inside
std::stringhas decreased from 16 to 8. This saves memory since string requests fewer additional bytes than it did previously. However, this also changes the return value ofstd::string::max_sizeand can cause code compiled against older libc++ versions but linked at runtime to a new version to throw a different exception when attempting allocations that are too large (std::bad_allocvsstd::length_error).The layout of some range adaptors that use the
movable-boxexposition-only type as an implementation detail has changed in order to fix a bug which could result in overwriting user data following themovable-box. This bug was caused by incorrect usage of the[[no_unique_address]]attribute inside the implementation ofmovable-box. This fix affects the layout of the following views:take_while_view,filter_view,single_view,drop_while_view,repeat_view,transform_view,chunk_by_view. In order to avoid silent breakage as a result of this fix, an ABI tag has been added to these views such that their mangled name will be different starting in this version of libc++. As a result, attempting to call a function that expects one of these views will fail to link until the code has been rebuilt against a matching version of libc++. In practice, we believe it is unusual for these views to appear at ABI boundaries so this should not be a major problem for most users. However it is probably worth auditing ranges-heavy code for ABI boundaries that would contain these views, or for types that contain these views as members and which are passed across ABI boundaries.Some properties of libc++ may cause ODR-violations when mixing multiple libc++ instances. To avoid these, often benign, ODR-violations the ODR-affecting properties are now part of the ABI tag. The ODR-affecting properties are:
library version (This was part of the ABI tag prior to LLVM 18.)
exceptions vs no-exceptions
hardening mode
This should not be ABI-affecting except that libc++ will be more robust against different configurations of it being used in different translation units.
The amount of padding bytes available for use at the end of certain
std::expectedinstantiations has changed in this release. This is an ABI break for any code that held astd::expectedmember with[[no_unique_address]]in an ABI-facing type. In those cases, the layout of the enclosing type will change, breaking the ABI. However, thestd::expected<T, E>member requires a few characteristics in order to be affected by this change:A type equivalent to
union {T ; E}needs to have more than one byte of padding available.The
std::expected<T, E>member must have been in a situation where its padding bytes were previously reused by another object, which can happen in a few cases (this is probably not exhaustive):It is a member with
[[no_unique_address]]applied to it, and it is followed by another data member, orIt is a member with
[[no_unique_address]]applied to it, and it is the last member of the user-defined type, and that user-defined type is used in ways that its padding bytes can be reused, orIt is inherited from
We expect that this will not be a very frequent occurrence. However, there is unfortunately no technique we can use in the library to catch such misuse. Indeed, even applying an ABI tag to
std::expectedwould not help since ABI tags are not propagated to containing types. As a result, if you notice very difficult to explain bugs around the usage of astd::expected, you should consider checking whether you are hitting this ABI break. This change was done to fix #70494 and the vendor communication is handled in #70820.
Build System Changes¶
The
LIBCXX_EXECUTORCMake variable has been deprecated. If you are relying on this, the new replacement is passing-Dexecutor=...tollvm-lit. Alternatively, this flag can be made persistent in the generated test configuration file by passing-DLIBCXX_TEST_PARAMS=executor=.... This also applies to theLIBUWIND_EXECTORandLIBCXXABI_EXECUTORCMake variables. LLVM 19 will completely remove support for the*_EXECUTORvariables.LIBCXXABI_USE_LLVM_UNWINDERandCOMPILER_RT_USE_LLVM_UNWINDERswitched defaults fromOFFtoON. This means that by default, libc++abi and compiler-rt will link against the LLVM providedlibunwindlibrary instead of the system-provided unwinding library. If you are building the LLVM runtimes with the goal of shipping them so that they can interoperate with other system-provided libraries that might be using a different unwinding library (such aslibgcc_s), you should passLIBCXXABI_USE_LLVM_UNWINDER=OFFandCOMPILER_RT_USE_LLVM_UNWINDER=OFFto make sure the system-provided unwinding library is used by the LLVM runtimes.In Clang-cl configurations, libc++ can now be built against the static and/or debug MSVC C runtimes