What C++03 support should <atomic> have?

Sorry, that quote is from my patch, but there’s identical code elsewhere in the file. I swear!

Olivier

Doing atomics before 11 was pretty wild… So I understand that people using an old C++ want some nice atomics. At the same time… They really should update to C++11 or later.

What does libc++ try to do with new library features on old languages? Seems easy enough so support most of say optional or variant (without CTAD) before C++17. Is this done consistently? And how far back, do we even try to support C++98?

It seems like we can be nice where it’s easy, but at some point in time are we just supporting stuff nobody cares about?

Maybe another way to test these waters is to ask what is actually being *tested*?

Olivier

Libc++ is a C++11 STL implementation that tolerates C++03 compilers.
If a feature can be reasonably implemented in C++03, then we provide it.
is one example, , <unordered_map> and std::shared_ptr are others.

All of these components should have tests that run in C++03 (Tests are disabled in C++03 using the comment // UNSUPPORTED: c++98, c++03).

Is there a special step to test with c++03? Because I could pass make check-cxx with lambdas in .

Olivier

Yes. See the Testing libc++ docs for instructions [1].
One setup you invoke lit manually passing --param=std=c++03.

We also have a C++03 bot. The latest test results give an indication of what’s not supported. [2]

[1] http://libcxx.llvm.org/docs/TestingLibcxx.html
[2] http://lab.llvm.org:8011/builders/libcxx-libcxxabi-x86_64-linux-ubuntu-cxx03/builds/2044/steps/test.libcxx/logs/stdio

Libc++ is a C++11 STL implementation that tolerates C++03 compilers.
If a feature can be reasonably implemented in C++03, then we provide it.

It can be implemented in C++03, however there will be a visible code complexity cost in doing so with Olivier’s patch (mostly because of the lack of lambdas).

is one example, , <unordered_map> and std::shared_ptr are others.

Yes, but this was decided in a time where not many compilers supported C++11 properly, right? 8 years later, we have many compilers supporting C++11 properly.

I suspect the number of people that use a recent libc++ with a compiler that does not support C++11 is very, very close to 0. One would have to deliberately update libc++ while keeping the compiler old, and then point the compiler to the updated libc++ headers manually. Additionally, the number of people that are in that setup AND that want to use std::atomic is likely to be even smaller.

I have an impression that we might be making our lives harder just to provide something that nobody cares about. Is there a common use-case of libc++ I’m missing here? Maybe some Linux distribution doing something funky that makes the old-compiler-with-new-libc++ more widely used than I imagine?

Unless we have a reason to do otherwise, I’d vote for not caring about C++03 support in .

Louis

Playing Devil’s advocate, it’s possible there are potential users for a Freestanding library who are stuck on old compilers thanks to C+±hostile vendors. I’m willing to put the effort in for the greater good there.

But back to advocating against the Devil: the header only works when specific builtins are provided, and those builtins are not available on a compiler that has truly 0% support for C++11, because they appeared specifically to support . Hence it only works in C++03 mode on a compiler that also has some kind of C++11 mode, so that’s a pretty narrow window of time that one has to be frozen into by the hostile vendor.

Playing Devil’s advocate, it’s possible there are potential users for a Freestanding library who are stuck on old compilers thanks to C++-hostile vendors. I’m willing to put the effort in for the greater good there.

But back to advocating against the Devil: the <atomic> header only works when specific builtins are provided, and those builtins are _not_ available on a compiler that has truly 0% support for C++11, because they appeared specifically to support <atomic>. Hence it only works in C++03 mode on a compiler that also has some kind of C++11 mode, so that’s a pretty narrow window of time that one has to be frozen into by the hostile vendor.

volatile was supported before C++11 :clown_face:

More seriously: that’s an extremely compelling argument to justify not supporting <atomic> before C++11: there’s no way the compiler supports the required atomic builtins and doesn’t support C++11.

It would be odd for a codebase to purposefully be stuck in C++03 on a recent compiler, yet choose to use <atomic>: before C++11 people had their own implementation of atomic using inline assembly, so I expect <atomic> is the last thing to change in codebases upgrading to C++11 because whatever inline assembly they had before probably works fine and has oddly (and scarily) different semantics from <atomic>.

IMO, Libc++ in C++03 is pretty weird in general – it’s odd that it tries to provide c++11 stdlib features in c++98/03 modes. That’s certainly been the intended design from the beginning, but I’m not sure how useful it actually is or ever has been. I’ve personally found it both surprising and annoying, back when I actually used to care about pre-c++11 at all. :slight_smile:

For example, a unique_ptr class is provided even pre-c++11. But, as soon as you try to do just about anything with it, it becomes clear that it doesn’t (can’t!) actually work as it should.

Or, std::promise and std::future are provided, but without move constructors, can you actually use it? Is there really even a point?

For , I can imagine a world where a C++03 atomic is conservatively backed by the old _sync* builtins. I don’t recall if libc++ atomic is setup in such a way to be able to take advantage of the _sync* builtins when the _atomic* builtins and _Atomic keywords aren’t present.

It is not.

Most users have a new Clang compiler, but still specify C++03. Old compilers aren’t the problem,

and our tolerance for C++03 must match Clang. Thankfully Clang provides much of C++11 as an extension;
including _Atomic… GCC is much stricter and problematic. Currently 75% of libc++'s C++03 tests fail with GCC.

The greatest benefactor of the Clang and libc++'s C++11 extensions is libc++. We use unique_ptr to write
exception safe code in vector and map. We require C++11 reference collapsing, and we exploit decltype,
nullptr, and variadic templates being available as extensions. All to avoid C++03 shortcomings.

We should plan for the day we drop C++03 support entirely. We shouldn’t create a conforming C++03 mode
15 years later.

How much of the initial problem is mitigated if you assume the host compiler is a modern Clang?

/Eric

Most users have a new Clang compiler, but still specify C++03. Old compilers aren’t the problem,

and our tolerance for C++03 must match Clang. Thankfully Clang provides much of C++11 as an extension;
including _Atomic… GCC is much stricter and problematic. Currently 75% of libc++'s C++03 tests fail with GCC.

The greatest benefactor of the Clang and libc++'s C++11 extensions is libc++. We use unique_ptr to write
exception safe code in vector and map. We require C++11 reference collapsing, and we exploit decltype,
nullptr, and variadic templates being available as extensions. All to avoid C++03 shortcomings.

I agree that C++11 extensions in the COMPILER are useful, but extensions in the LIBRARY are not. We could use our own internal __unique_ptr type instead, that wouldn’t be a problem.

In fact, I think most of the time it’s a disservice to libc++ because we can’t provide good support for those C++11 extensions, and that’s a source of confusion and bugs. Also, it sometimes happens that simply providing the extension makes us non-conforming, as is the case for std::string_view.

You already know that, but I’m really not a big fan of extensions.

We should plan for the day we drop C++03 support entirely. We shouldn’t create a conforming C++03 mode
15 years later.

How much of the initial problem is mitigated if you assume the host compiler is a modern Clang?

Even a modern Clang does not support lambdas in C++03 mode:

$ echo ‘int main() { [](int x) { }; }’ | clang++ -xc++ - -std=c++03

It therefore doesn’t make our life easier in this specific case.

Louis