[RFC] Freezing C++03 headers in libc++ (original) (raw)

Background

With C++ getting a major release every three years, libc++ must support a continuously growing number of C++ versions. There are currently seven versions of the Standard and we support all of them using the same source code, which is achieved through careful application of #ifdefs. With the increasing size of the library and our desire to keep improving its quality of implementation, sharing the same source code is becoming a barrier to evolving the code base. In particular, a major relic of the past we’ve been dragging for a long time is the need to support Clang in its -std=c++03 language configuration.

Furthermore, the benefits of keeping the C++03 implementation in the same code base as the rest of the library is questionable. Indeed, the C++03 parts of the library are getting very few improvements nowadays, since the most beneficial improvements have been implemented over the past decade. On the other hand, to keep evolving the library, changes frequently break code that isn’t strictly conforming, which results in a maintenance burden for old projects that are only on life support. Freezing the headers would increase the stability of the library, which is a great property for legacy C++03 projects. At the same time, it would make it easier for the C++11-and-later parts to be improved. For example, we foresee improvements to compilation times, debug performance, binary size and possibly compiler diagnostics.

Proposal

We propose making a copy of the libc++ headers, with one copy only having to support the C++03 language mode, and the other copy supporting newer language modes. The Clang driver would then select the appropriate copy of the headers based on the selected language mode.

After an initial period of time where we would provide equal support for both copies of the headers, we would freeze the C++03 headers and only apply security critical bug fixes to them. The reasoning is that these headers would be optimized for stability – even fixing bugs can often end up breaking code that was written in a certain way, which can create churn for legacy projects. In the same spirit, we would also not backport LWG issue resolutions to the C++03 language mode headers. However, note that we would reserve the right to change the C++03 headers if required for compatibility with the “new” headers. Keeping the C++03 headers 100% stable would be a goal, but not a hard promise since that could easily paint us into a corner.

Q&A

What about library configuration?

Libc++ has a __config_site header, which makes it possible to customize the library. These configuration options sometimes change over time. There are currently three major categories of customizations:

We expect the ABI information and the disabled parts of the library to stay fairly stable, most likely only adding additional options that would simply not be available in C++03 mode. Information about implementation details and the hardening mode are much more likely to change. If these options change in ways that are not purely additive, we expect there to be a way to translate to similar legacy functionality. Taking the change from assertions and debug mode to hardening modes as an example, it would be possible to map the hardening modes to the old assertion/debug modes (albeit in an imperfect way).

Are there ABI implications?

In the stable ABI there should be no significant changes to the current policy. That is, the ABI should stay stable except for changes that are technically ABI breaks but don’t actually break any code. The ability to use the unstable ABI in the C++03 language mode would be removed, since the ABI would otherwise be broken between C++03 and C++11 when we continue evolving the unstable ABI. We don’t foresee this being a major problem, since folks who use the unstable ABI are generally not on life support.

What about older/other compilers?

Libc++ only supports Clang and GCC, and GCC only in C++11 mode or higher. Because of that, copying the headers shouldn’t have any impact on GCC. For Clang, the current release and the last two releases are supported. We would have to keep the “new” headers compatible with C++03 until we only support Clang versions that know to look in the alternate include directory, which represents a migration of 6 months to a year.

How are ODR violations mitigated?

Libc++ uses a lot of tools to avoid ODR violations. One of the most important utilities are [[gnu::abi_tag]]s. The C++03 headers will get a tag distinct from the C++11-and-later headers to avoid ODR violations between the two implementation.

Thanks to @ldionne, @EricWF and @AaronBallman for giving early feedback on the proposal.