RFC: Switching from llvm::Any to std::any

The implementation of llvm::Any had several bugs in the past (see D101972 and D108943) and still has the same bug on Windows.
C++17 has the std::any type, which can replace llvm::Any and puts the burden to implement it correctly for all possible combinations of compiler and linker options onto the standard library.
I propose to eventually switch to std::any for this reason (it also fixes the bug I see on Windows).

Unfortunately, we can’t just switch to std::any right away (I tried in D139532), because the msvc standard library until very recently had a bug that the <any> header does not compile when exceptions are disabled.
So, to not hold onto the bugs we have, but still allow us to support old compiler versions, I propose to

  1. Make the interface of llvm::Any similar to that of std::any (as was done for llvm::Optional). The only change is in std::any_cast, which has different semantics, so I want to add llvm::std_any_cast which follows that and deprecate llvm::any_cast.
  2. Add an implementation of llvm::Any that uses std::any internally (this is ~80 lines of code) and enable this wrapper when the compiler supports it. This will fix llvm::Any on Windows, if msvc is new enough.
  3. Remove the deprecated llvm::any_cast, all users should use llvm::std_any_cast
  4. Once the minimum compiler version of LLVM is new enough, use std::any without the wrapper and remove llvm::Any

Alternatively to introducing llvm::std_any_cast in step 1., we can also keep the current llvm::any_cast interface until we switch to std::any in step 4.


Looking at your change, are there that many users of llvm::any_cast that llvm::any_cast could not be rewritten to behave as std::any_cast does? Or are we expecting a lot of downstream users to be using llvm::Any as well.
llvm::Optional is probably one of the most used types in the codebase, so the incremental changing and the deprecation period makes a lot of sense I think (in fact, we are still seeing daily commits changing llvm::Optional to std::optional).

I am just wondering whether llvm::Any is used often enough to warrant similar procedure, instead of just aligning its behaviour to std::any in one large change. Step 2 and 4 would remain unchanged.

1 Like

True, there’s not that many places to change, it can be easily done in a single commit.
Looking again at what changes when moving to std::any:

  • There is no any_isa, we can deprecate it
  • std::any_cast(any*) does not assert, but just returns a nullptr. Removing the assert should be fine
  • std::any_cast(any&) is the same

So, I agree with you, we can just change llvm::any_cast to match std::any_cast.

The migration from llvm::Option to std::optional is proceeding incrementally and it is a great improvement for the codebase. You noticed the issue with std::any. I am afraid that the minimal requirements for compilers to build LLVM make it impossible to migrate to the STL.

You’re right that the msvc bug makes it impossible for us to migrate from llvm::Any to std::any right now.
That’s the reason I proposed these multiple steps and why I want to keep the current Any implementation until we increase the minimum requirement for msvc far enough (well, it’s more a must than a want ;)).

We can have two implementations of llvm::Any:

  1. The current one that is buggy but supports all compiler versions
  2. One that is a small wrapper around std::any and has less bugs, but needs a more up-to-date msvc

We can switch between these two versions based on the _MSC_VER macro.

Once we increased the minimal requirement for msvc, we can completely replace llvm::Any with std::any.

1 Like

I found this page:
and it says : You will need Visual Studio 2019 or later, with the latest Update installed.
This page says:
Visual Studio 2019 16.7

I do not know what rules the buildbots follow.

Checking a few Windows bots I see msvc 2019, so I would assume they follow that rule.

E.g. Buildbot → “Worker” → “host”

For gcc and clang I don’t think we have any bot running the minimum versions, if that is relevant here at all.

The difference is that one page says with all updates and the other specified a precise version.

Sorry yes, which of the two rules, I missed that.

16.7 is enforced by cmake in llvm/cmake/modules/CheckCompilerVersion.cmake. So you have to abide by that. I expect people will install the latest version at the time the bot is setup and not update it unless they have good reason to.

For the subject at hand, 16.7 is the important part.

In the C++17 upgrade discussions, it was noticed that MSVC follows a different update schedule.

Reviews are up in