| Current | Proposed | Release Date | |
|---|---|---|---|
| clang | 5.0 | 15 | 2022-09-06 |
| XCode | 10.0 | 14.3 | 2023-03-30 |
| gcc | 7.4 | 12.2 | 2022-08-19 |
| msvc | 2019 16.8 (1928 _MSC_VER) | 2022 17.14 (1944 _MSC_VER) | 2022-11-08 |
We have a general guideline to support building the llvm project with clang and gcc from at least 3 years ago. These versions are the newest versions of clang and gcc that meet that requirement. The XCode version was chosen to match that clang version. There is also an informal guideline of supporting the two most recent versions of msvc, which are 2022 and 2026.
Linux Distributions
This shows the versions of gcc and clang available through the package manager in various distributions. The first version number is the default, later version numbers are available through other packages such as clang-20.
| Linux distribution | GCC Version | Clang Version | Release Date | Support Status |
|---|---|---|---|---|
| Ubuntu 18.04 LTS – Bionic Beaver | 7.4 | 10 | 2018-04-26 | Extended Security Maintenance |
| Ubuntu 20.04 LTS – Focal Fossa | 10 | 10 | 2020-04-21 | Extended Security Maintenance |
| Ubuntu 22.04 LTS – Jammy Jellyfish | 11.2.0, 12.3 | 14.0, 15.0.7 | 2022-04-21 | Full support |
| Ubuntu 24.04 LTS – Noble Numbat | 13.2.0 | 18.1.3, 19.1.1, 20.1.2 | 2024-04-25 | Full support |
| Ubuntu 25.04 – Plucky Puffin | 14.2.0 | 20.1.2 | 2025-04-17 | Full support |
| Ubuntu 25.10 – Questing Quokka | 15.2.0 | 20.1.2, 21.1.2 | 2025-10-09 | Full support |
| RHEL 7 | 4.8, ??? | 7.0.1, ??? | 2014-06-10 | Extended Life Cycle Support |
| RHEL 8 | 8, 9, 10, 11, 12, 13, 14, 15 | 19.1.7 | 2019-05-07 | Maintenance Support |
| RHEL 9 | 11, 12, 13, 14, 15 | 19.1.7 | 2022-05-18 | Full support |
| RHEL 10 | 14.2, 15.1 | 19.1.7 | 2025-05-20 | Full support |
| Debian 11 Bullseye | 10.2.1 | 11.0.1, 13.0.1, 16.0.6, 19.1.7 | 2021-08-14 | LTS |
| Debian 12 Bookworm | 12.2.0 | 14.0.6, 15.0.6, 16.0.6, 19.1.7 | 2023-06-10 | Full support |
| Debian 13 Trixie | 14.2.0 | 19.0, 19.1.7 | 2025-08-09 | Full support |
| SUSE Enterprise Linux 12.5 | 4.8, 10, 14.2 | 3.4, ??? | 2019-12-09 | Long Term Service Pack Support |
| SUSE Enterprise Linux 15.7 | 7.5.0, 12.3.0, 13.3.1, 14.2.0 | 14.0.6, 15.0.7, 17.0.6, 19.1.7 | 2025-06-17 | Full support |
What does this get us
This is mostly sourced from the C++17 compatibility chart and the compatibility chart for all newer versions of C++. For this section, I am mostly just copying over the full set of things as listed in the table without judgment over which of them will be used.
C++17 Language
- Replacement of class objects containing reference members
C++17 Standard Library
- C11 standard library
- Splicing maps and sets
std::has_unique_object_representationsstd::launder- Some of
std::to_charsandstd::from_chars - Array support for
std::shared_ptrandstd::weak_ptr - constexpr
std::char_traits std::filesystem- Partial support for hardware interference size
C++20 Language
- Allow lambda capture
[=, this] __VA_OPT__- Full support for designated initializers
- Explicit template parameters on lambdas
- Default member initializers for bit fields
- Initializer list constructors work with CTAD
const &pointer to member- Concepts
- Partial support for lambdas in unevaluated contexts
<=>- Defaulted
operator==and implicitoperator!= - init statement in range-based
for - default constructible and assignable stateless lambdas
- Partial support for
constmismatch in defaulted special member functions - Access checking on specializations
- ADL and function templates that are not visible
- Specify when constexpr function definitions are needed for constant evaluation
[[likely]]and[[unlikely]]- Pack expansion in lambda init-capture
[[no_unique_address]]- Relaxing structured bindings customization point rules
- Relaxing range-based for loop customization point finding rules
- Allow structured bindings to accessible members
- Destroying
operator delete - Partial support for class types as non-type template parameters
- Deprecate implicit capture of
thisvia[=] explicit(bool)- Prohibit aggregates with user-declared constructors
constexpr virtualfunctionschar8_tstd::is_constant_evaluatedconstexprfortryandcatch- Partial support for
consteval - Nested inline namespaces
- Signed integers are two’s complement
dynamic_castand polymorphictypeidin constant expressions- Changing the active member of a union in
constexpr - Array size deduction in
newexpressions - Explicitly defaulted functions with different exception specifications
- Partial support for lambda capture of structured bindings
- Conversions to arrays of unknown bound
constexprallocation- Deprecate some uses of
volatile constinit- Deprecate comma operator in subscripts
[[nodiscard]]with message- Trivial default initialization in constexpr
- Unevaluated
asmin constexpr using enum[[nodiscard]]for constructors- More implicit moves
- Pseudo-destructors end object lifetimes
T *toboolis a narrowing conversion
C++20 Library
std::endianstd::make_sharedfor arraysconstexprfor<algorithm>,<utility>, and some of<complex>std::memory_orderis a scoped enumstarts_withandends_withfor strings- Partial library support for
<=> std::remove_cvref- Use of
std::movein numeric algorithms - Utility to convert a pointer to a raw pointer
std::span<version>ConstexprIteratorrequirementsstd::string::reserveshould not shrink- map
contains - Guaranteed copy elision for piecewise construction
std::bit_cast- Integral power-of-two operations
- Improving the return type of erase algorithms
std::is_convertiblestd::shift_leftandstd::shift_rightconstexprforswapstd::type_identity- Concepts library
constexprcomparisons forstd::arraystd::unwrap_ref_decayandstd::unwrap_referencestd::bind_frontstd::reference_wrapper<incomplete type>std::variantandstd::optionalpropagate triviality of special member functions- A sane
std::variantconverting constructor - Ranges
- Heterogeneous lookup for ordered associative containers
- More
noexceptin<chrono> constexprinpointer_traitsstd::assume_aligned- More miscellaneous
constexpr std::eraseandstd::erase_ifstd::lerpandstd::midpoint- Make
std::create_directoryintuitive std::ssize- Traits for arrays
std::to_array- Bit operations
- Math constants
constexprforstd::allocatorconstexprforstd::stringconstexprforstd::vectorconstexprforstd::invoke- Atomic waiting and notifying
constexprdefault constructor forstd::atomicandstd::atomic_flagconstexprnumeric algorithms- Safe integral comparisons
C++23 Language
- Literal suffix for
size_t - Make
()more optional in lambdas if consteval- Narrowing contextual conversions in
static_assertandif constexpr #elifdefand#elifndef- Non-literal variables and labels and gotos in
constexprfunctions - Consistent character literal encoding
- Multidimensional subscript operator
- Attributes on lambdas
static operator()- Support UTF-8 as a portable source file encoding
C++23 Library
<stdatomic.h>std::is_scoped_enumstd::string::containsandstd::string_view::containsstd::to_underlying- Iterator pair constructors for
std::stackandstd::queue - Prohibiting
std::stringandstd::string_viewconstruction fromnullptr - Range constructor for
std::string_view std::byteswap- Printing
T volatile * std::string::resize_and_overwrite- Monadic operations for
std::optional - Conditional
noexceptonstd::exchange std::unreachablestd::visitfor classes derived fromstd::variantstd::views::joinshould join all views of ranges- Range adaptor objects bind arguments by value
- Partial support for
constexprforstd::optionalandstd::variant - view with ownership
C++26 Library
- Algorithm function objects
Notes on Later Standard Versions
We currently compile with C++17 support. There are jobs that ensure that LLVM can also compile in C++20 mode with a sufficiently new compiler. As of right now, we require clang 17.0.6 at a minimum to compile LLVM in C++20 mode. This is obviously newer than the clang 15 in this proposal. However, looking at the code that caused the problem, I believe that there are workarounds that we could use to allow compiling our code in C++20 mode without a noticeable change in the time it takes to compile LLVM itself. Should we want to update to C++20 as the minimum C++ standard before the next compiler upgrade, I’d be happy to do that work.
Additionally, some of the C++20 features are theoretically supported by the minimum compiler versions, but in actuality users are likely to run into bugs. I decided to not even mention modules as partially supported, for instance, because I know that there is no reasonable use of them until much later versions of clang (and I don’t know enough to judge gcc and msvc). Using the new C++20 and later features as the justification for the upgrade does mean the case is not quite as strong as it appears just looking at the full list, but I expect to still be able to use a large chunk of those features without needing another compiler upgrade, so we are at least preparing for that change.
Other Reasons to Upgrade
With fewer supported versions, we are less likely to run into a bug in any one of them that blocks a build. This simplifies the developer experience and reduces the frustration of trying to debug your code against a very old compiler.
Reasons to Not Upgrade
This requires users of older, completely unsupported versions of distributions (such as RHEL 6) to have a two-stage process to build LLVM: first build clang 15.0 using the system compiler, then use that to build modern LLVM.
This also puts that requirement on Ubuntu 18.04 and 20.04, which are past their normal LTS support window and into the “Extended Security Maintenance” window (meaning the users receive only security-critical updates) and possibly for RHEL 7 as well. I say “possibly” because RHEL 7 is in “Extended Lifecycle Support” (which is the third and final tier before fully unsupported which I believe also means critical security updates only) and therefore the official pages to check which packages are available don’t even list what you can install on RHEL 7.
Debian 11 “Bullseye” would require installing clang to build LLVM from a package-manager-supported compiler, or a two-stage build for gcc.
SUSE Enterprise Linux 12.5 users would probably require a two-stage compile to compile with clang (but not gcc). I say “probably” because it is now in “Long Term Service Pack Support” so the official documentation no longer lists the available packages.
Windows users will possibly need to upgrade their version of Visual Studio.
Mac users will possibly need to upgrade their version of XCode.
Upgrade Process
From LLVM Developer Policy — LLVM 22.0.0git documentation
We intend to require newer toolchains as time goes by. This means LLVM’s codebase can use newer versions of C++ as they get standardized. Requiring newer toolchains to build LLVM can be painful for those building LLVM; therefore, it will only be done through the following process:
- It is a general goal to support LLVM and GCC versions from the last 3 years at a minimum. This time-based guideline is not strict: we may support much older compilers, or decide to support fewer versions.
- An RFC is sent to the LLVM Discourse forums
- Detail upsides of the version increase (e.g. which newer C++ language or library features LLVM should use; avoid miscompiles in particular compiler versions, etc).
- Detail downsides on important platforms (e.g. Ubuntu LTS status).
- Once the RFC reaches consensus, update the CMake toolchain version checks as well as the getting started guide. This provides a softer transition path for developers compiling LLVM, because the error can be turned into a warning using a CMake flag. This is an important step: LLVM still doesn’t have code which requires the new toolchains, but it soon will. If you compile LLVM but don’t read the forums, we should tell you!
- Ensure that at least one LLVM release has had this soft-error. Not all developers compile LLVM top-of-tree. These release-bound developers should also be told about upcoming changes.
- Turn the soft-error into a hard-error after said LLVM release has branched.
- Update the coding standards to allow the new features we’ve explicitly approved in the RFC.
- Start using the new features in LLVM’s codebase.
This RFC is the first step in that process.
Discussion Still Needed
- Do we generally want to do this? The change follows existing policy, but that just says we can, not whether we should.
- Do we first need to see the changes that allow building in C++20 mode with clang 15, given that we know right now we require clang 17.0.6 to build, or is it acceptable for that to progress separately? I’m happy to do this work, but if the feeling is the upgrade isn’t worth it until we can get clang 17 anyway for other reasons, then there’s no point.
- Which C++20 features do we want to allow / reject? The majority of C++20 is theoretically supported, but some of them might be too buggy in the listed versions. Some of that is probably OK to allow anyway (if the bug is just that some more complicated uses of the feature will fail to compile), so this requires some discussion. I’ll include my thoughts on that in a later post.
- A fair amount of C++23 is also theoretically supported by all of these compilers. Do we want to jump straight there or do we want to stop in C++20 for now and do a C++23 RFC later?
- It’s unclear to me what “Ensure that at least one LLVM release has had this soft-error” means. For instance, would LLVM 21.1.7 count as a “release” should this RFC be approved very quickly (21.1.7 is scheduled for 2025-12-02), or is the next “release” 22.1.0? I’m guessing it means version 22 is the next release, but I want to confirm.
