Libc++ 20.0.0 (In-Progress) Release Notes¶
Written by the Libc++ Team
Warning
These are in-progress notes for the upcoming libc++ 20.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 20.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++ 20.0.0?¶
The main focus of the libc++ team has been to implement new C++20, C++23, and C++26 features.
Implemented Papers¶
P0619R4: Reviewing Deprecated Facilities of C++17 for C++20 (Github)
P2747R2:
constexprplacement new (Github)P2609R3: Relaxing Ranges Just A Smidge (Github)
P2985R0: A type trait for detecting virtual base classes (Github)
std::jthreadand<stop_token>are not guarded behind-fexperimental-libraryanymoreP2674R1: A trait for implicit lifetime types (Github)
P0429R9: A Standard
flat_map(Github)
Improvements and New Features¶
The
lexicographical_compareandranges::lexicographical_comparealgorithms have been optimized for trivially equality comparable types, resulting in a performance improvement of up to 40x.The
_LIBCPP_ENABLE_CXX20_REMOVED_TEMPORARY_BUFFERmacro has been added to makestd::get_temporary_bufferandstd::return_temporary_bufferavailable.The
std::uncaught_exceptionfunction was marked as deprecated since C++17 and removed since C++20. The_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTIONmacro has been added to makestd::uncaught_exceptionavailable in C++20 and later modes.The internal structure
__compressed_pairhas been replaced with[[no_unique_address]], resulting in reduced compile times and smaller debug information as well as better code generation if optimizations are disabled. The Chromium project measured a 5% reduction in object file and debug information size.The
_LIBCPP_ABI_BOUNDED_UNIQUE_PTRABI configuration was added, which allowsstd::unique_ptr<T[]>to detect out-of-bounds accesses in certain circumstances.std::unique_ptr<T[]>can now also detect out-of-bounds accesses for a limited set of types (non-trivially destructible types) when the ABI configuration is disabled.The
_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAYABI configuration was added, which allows storing valid bounds instd::array::iteratorand detecting OOB accesses when the appropriate hardening mode is enabled.The
input_iterator-pair overload ofvoid assign(InputIt, InputIt)has been optimized forstd::vector, resulting in a performance improvement of up to 2x for trivial element types (e.g.,std::vector<int>), and up to 3.4x for non-trivial element types (e.g.,std::vector<std::vector<int>>).The
input_iterator-pair overload ofiterator insert(const_iterator, InputIt, InputIt)has been optimized forstd::vector, resulting in a performance improvement of up to 10x forstd::vector<int>, and up to 2.3x forstd::vector<std::vector<int>>.On Windows,
<system_error>’sstd::system_categoryis now distinct fromstd::generic_category. The behavior on other operating systems is unchanged.On Windows – unlike on Unix systems – the libc and system APIs use distinct error codes. The libc functions return
errno.herror codes via theerrnoglobal, while Win32 API functions returnwinerror.herror codes viaGetLastError().The C++ standard’s
std::error_codeandstd::error_categoryfunctionality was designed to support multiple error domains, precisely in order to handle situations such as this. However, libc++ formerly treatedgeneric_category()andsystem_category()as equivalent, even on Windows. It now implements the intended split, wheresystem_categoryrepresents nativewinerror.herror codes, andgeneric_categoryrepresents libc error codes (and, equivalently,std::errc::*errors).This change enables code like
std::error_code(GetLastError(), std::system_category()) == std::errc::invalid_argumentto function as desired: constructing anerror_codewith the Windows error number in the “system” category, and then mapping it to a generic code witherror_condition, for comparison with thestd::errcconstant.This is an incompatible change:
std::error_code(ENOSYS, std::system_category()) == std::errc::function_not_supportedwould formerly have returned true, but now returns false on Windows. Code providing a number from theerrno.hdomain should be migrated to construct ageneric_categoryerror_code, instead. (E.g., usestd::error_code(ENOSYS, std::generic_category())). The new behavior matches MSVC.On Windows, the
std::filesystemlibrary now returns the Win32system_categoryerror codes, where it’s feasible to do so. This allows interrogation and reporting of the original error code, which is useful if multiple Windows errors map to a single generic error (such as withstd::errc::no_such_file_or_directory).This is also a slightly-incompatible API change: code inspecting the raw integer value from the returned error_code expecting an integer from
generic_category(e.g.err.value() == ENOTDIR) will not work as desired. Instead, such code should use the comparison operators which implicitly handle eror mappings,err == std::errc::not_a_directory, or useerr.default_error_condition()to map to anerror_condition, and then test itsvalue()andcategory().std::stable_sortuses radix sort for integral types now, which can improve the performance up to 10 times, depending on type of sorted elements and the initial state of the sorted array.Reduced the amount of debug information generated for internal typedefs. This reduces the size of debug builds.
Added hardening mode support for
forward_listandbitset.
Deprecations and Removals¶
The
LIBCXX_ENABLE_ASSERTIONSCMake variable and the_LIBCPP_ENABLE_ASSERTIONSmacro that were used to enable the safe mode have been removed in LLVM 20. Please use support for hardening instead.Support for the C++20 synchronization library (
<barrier>,<latch>,atomic::wait, etc.) has been removed in language modes prior to C++20. If you are using these features prior to C++20, you will need to update to-std=c++20.The relational operators for
std::chrono::weekdayhas been removed entirely, and the_LIBCPP_ENABLE_REMOVED_WEEKDAY_RELATIONAL_OPERATORSmacro is now ignored.The
_LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONSTmacro no longer has any effect.std::allocator<const T>is not supported as an extension anymore, please migrate any code that uses e.g.std::vector<const T>to be standards conforming.Non-conforming member typedefs
base,iterator,const_iterator,size_type,difference_type, andconst_referenceofstd::bitset, and member typedefbaseofstd::forward_listandstd::listare removed. Previously, these member typedefs (exceptconst_reference) were private but could cause ambiguity in name lookup. Code that expects such ambiguity will possibly not compile in LLVM 20.The function
__libcpp_verbose_abort()is nownoexcept, to matchstd::terminate(). (The combination ofnoexceptand[[noreturn]]has special significance for function effects analysis.) For backwards compatibility, the_LIBCPP_VERBOSE_ABORT_NOT_NOEXCEPTmacro can be defined to make the function non-noexcept. That macro will be removed in LLVM 21.<ccomplex>,<cstdalign>(previously missing),<cstdbool>, and<ctgmath>are deprecated since C++17 as specified by the standard. They, together with<ciso646>, are removed in C++20, but libc++ still provides these headers as an extension and only deprecates them. The_LIBCPP_DISABLE_DEPRECATION_WARNINGSmacro can be defined to suppress deprecation for these headers.The
_LIBCPP_DISABLE_AVAILABILITYmacro that was used to force-disable availability markup has now been removed. Whether availability markup is used by the library is now solely controlled at configuration-time.The pointer safety functions
declare_reachable,declare_no_pointers,undeclare_no_pointersand__undeclare_reachablehave been removed from the library. These functions were never implemented in a non-trivial way, making it very unlikely that any binary depends on them.Non-conforming extension
packaged_task::result_typeis deprecated. It will be removed in LLVM 21.
Upcoming Deprecations and Removals¶
LLVM 21¶
The status of the C++03 implementation will be frozen after the LLVM 21 release. This means that starting in LLVM 22, non-critical bug fixes may not be back-ported to C++03, including LWG issues. C++03 is a legacy platform, where most projects are no longer actively maintained. To reduce the amount of fixes required to keep such legacy projects compiling with up-to-date toolchains, libc++ will aim to freeze the status of the headers in C++03 mode to avoid unintended breaking changes. See https://discourse.llvm.org/t/rfc-freezing-c-03-headers-in-libc for more details.
If you are using C++03 in your project, you should consider moving to a newer version of the Standard to get the most out of libc++.
The
_LIBCPP_VERBOSE_ABORT_NOT_NOEXCEPTmacro will be removed in LLVM 21, makingstd::__libcpp_verbose_abortunconditionallynoexcept.Non-conforming extension
packaged_task::result_typewill be removed in LLVM 21.
ABI Affecting Changes¶
The ABI breaks for removing undefined behaviour in
std::forward_list,std::list,std::map,std::set,std::multimap,std::multiset,std::unordered_map,std::unordered_set,std::unordered_multimapandstd::unordered_multisetare now applied unconditionally. This only affects fancy pointers which have a different value representation when pointing at the base of an internal node type instead of the type itself. A size or alignment difference is diagnosed, but more subtle ABI breaks may result in unexpected behaviour.The internal structure
__compressed_pairhas been replaced with[[no_unique_address]]. The ABI impact is:When using the Itanium ABI (most non-MSVC platforms), empty types are now placed at the beginning of the enclosing object instead of where the beginning of the
__compressed_pairsubobject was. This is only observable by checking the address of the empty allocator, equality comparator or hasher.Additionally, using an overaligned empty type as an allocator, comparator or hasher in the associative containers (and only those containers) may result in the container’s object object size and data layout changing beyond only the address of the empty member.
When using the MSVC ABI, this change results in some classes having a completely different memory layout, so this is a genuine ABI break. However, the library does not currently guarantee ABI stability on MSVC platforms.
The localization support base API has been reimplemented, leading to different functions being exported from the libc++ built library on Windows and Windows-like platforms.