Index: include/typeinfo =================================================================== --- include/typeinfo +++ include/typeinfo @@ -72,6 +72,49 @@ namespace std // purposefully not using versioning namespace { +#if defined(_WIN32) +class _LIBCPP_EXCEPTION_ABI type_info +{ + type_info & operator=(const type_info &) _LIBCPP_EQUAL_DELETE; + type_info (const type_info &) _LIBCPP_EQUAL_DELETE; + + mutable struct data { + const char *__undecorated_name; + const char __decorated_name[1]; + } __data; + + static const char *name(type_info::data *__data); + static size_t hash(const type_info::data *__data); + static int compare(const type_info::data *__l, const type_info::data *__r); + +public: + virtual ~type_info() _NOEXCEPT; + + _LIBCPP_INLINE_VISIBILITY + const char *name() const _NOEXCEPT { + return name(&__data); + } + + _LIBCPP_INLINE_VISIBILITY + bool before(const type_info &__arg) const _NOEXCEPT { + return compare(&__data, &__arg.__data) < 0; + } + + _LIBCPP_INLINE_VISIBILITY + size_t hash_code() const _NOEXCEPT { + return hash(&__data); + } + + _LIBCPP_INLINE_VISIBILITY + bool operator==(const type_info &__arg) const _NOEXCEPT { + return compare(&__data, &__arg.__data) == 0; + } + + bool operator!=(const type_info &__arg) const _NOEXCEPT { + return compare(&__data, &__arg.__data) != 0; + } +}; +#else class _LIBCPP_EXCEPTION_ABI type_info { type_info& operator=(const type_info&); @@ -148,6 +191,7 @@ {return __builtin_strcmp(name(), __arg.name());} #endif }; +#endif class _LIBCPP_EXCEPTION_ABI bad_cast : public exception Index: src/typeinfo.cpp =================================================================== --- src/typeinfo.cpp +++ src/typeinfo.cpp @@ -15,6 +15,44 @@ #include "typeinfo" +#if defined(_WIN32) +#include + +const char *std::type_info::name(std::type_info::data *__data) { + // TODO(compnerd) cache demangled &__data.__decorated_name[1] + return &__data->__decorated_name[1]; +} + +size_t std::type_info::hash(const std::type_info::data *__data) { +#if defined(_WIN64) + static constexpr const size_t fnv_offset_basis = 14695981039346656037ull; + static constexpr const size_t fnv_prime = 10995116282110ull; +#else + static constexpr const size_t fnv_offset_basis = 2166136261ull; + static constexpr const size_t fnv_prime = 16777619ull; +#endif + + size_t value = fnv_offset_basis; + for (const char *c = &__data->__decorated_name[1]; *c; ++c) { + value ^= static_cast(static_cast(*c)); + value *= fnv_prime; + } + +#if defined(_WIN64) + value ^= value >> 32; +#endif + + return value; +} + +int std::type_info::compare(const std::type_info::data *__lhs, + const std::type_info::data *__rhs) { + if (__lhs == __rhs) + return 0; + return strcmp(&__lhs->__decorated_name[1], &__rhs->__decorated_name[1]); +} +#endif + #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) std::type_info::~type_info()