diff --git a/llvm/include/llvm/ADT/Any.h b/llvm/include/llvm/ADT/Any.h --- a/llvm/include/llvm/ADT/Any.h +++ b/llvm/include/llvm/ADT/Any.h @@ -23,8 +23,100 @@ #include #include +#if !defined(_MSC_VER) || _MSC_VER >= 1934 +// The msvc standard library had a bug so could not be included when +// exceptions are disabled. Only enable the std::any wrapper for new enough +// versions. +// https://developercommunity.visualstudio.com/t/stdany-doesnt-link-when-exceptions-are-disabled/376072 +#define LLVM_ANY_WRAPS_STD_ANY +#endif + +#ifdef LLVM_ANY_WRAPS_STD_ANY +#include +#endif + namespace llvm { +#ifdef LLVM_ANY_WRAPS_STD_ANY + +class Any { +public: + Any() = default; + + Any(const Any &Other) : Storage(Other.Storage) {} + + Any(Any &&Other) : Storage(std::move(Other.Storage)) {} + + // When T is Any or T is not copy-constructible we need to explicitly disable + // the forwarding constructor so that the copy constructor gets selected + // instead. + template , Any>>, + // We also disable this overload when an `Any` object can be + // converted to the parameter type because in that case, + // this constructor may combine with that conversion during + // overload resolution for determining copy + // constructibility, and then when we try to determine copy + // constructibility below we may infinitely recurse. This is + // being evaluated by the standards committee as a potential + // DR in `std::any` as well, but we're going ahead and + // adopting it to work-around usage of `Any` with types that + // need to be implicitly convertible from an `Any`. + std::negation>>, + std::is_copy_constructible>>::value, + int> = 0> + Any(T &&Value) : Storage(std::forward(Value)) {} + + Any &operator=(Any Other) { + Storage = Other.Storage; + return *this; + } + + bool has_value() const { return Storage.has_value(); } + + void reset() { return Storage.reset(); } + +private: + template friend bool any_isa(const Any &Value); + template friend const T any_cast(const Any &Value); + template friend T any_cast(Any &Value); + template friend T any_cast(Any &&Value); + template friend const T *any_cast(const Any *Value) noexcept; + template friend T *any_cast(Any *Value) noexcept; + + std::any Storage; +}; + +template +LLVM_DEPRECATED("Use any_cast(Any*) != nullptr instead", "any_cast") +bool any_isa(const Any &Value) { + return std::any_cast(&Value.Storage); +} + +template const T any_cast(const Any &Value) { + return std::any_cast(Value.Storage); +} + +template T any_cast(Any &Value) { + return std::any_cast(Value.Storage); +} + +template T any_cast(Any &&Value) { + return std::any_cast(std::move(Value.Storage)); +} + +template const T *any_cast(const Any *Value) noexcept { + return std::any_cast(&Value->Storage); +} + +template T *any_cast(Any *Value) noexcept { + return std::any_cast(&Value->Storage); +} + +#else + class LLVM_EXTERNAL_VISIBILITY Any { // The `Typeid::Id` static data member below is a globally unique @@ -161,6 +253,8 @@ return &static_cast &>(*Value->Storage).Value; } +#endif // LLVM_ANY_WRAPS_STD_ANY + } // end namespace llvm #endif // LLVM_ADT_ANY_H