diff options
author | Tim Northover <tnorthover@apple.com> | 2014-03-30 11:34:26 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2014-03-30 11:34:26 +0000 |
commit | 6fdde8764097baee5612342166099925176ea84f (patch) | |
tree | e71a96c504d1c4929bdeff05c7b5388d8b963be3 | |
parent | c030063cc2b7a749a0e5b89e7a32d5d10b5f3fe9 (diff) | |
download | libcxx_35a-6fdde8764097baee5612342166099925176ea84f.tar.gz |
ARM64: compare RTTI names as strings
ARM64 generates RTTI with hidden visibility, which means that typeinfo
must be compared char-by-char since it's not guaranteed to be uniqued
across the whole program.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@205139 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/__config | 4 | ||||
-rw-r--r-- | include/typeinfo | 54 |
2 files changed, 57 insertions, 1 deletions
diff --git a/include/__config b/include/__config index c8bf9c88..63580ae2 100644 --- a/include/__config +++ b/include/__config @@ -568,6 +568,10 @@ template <unsigned> struct __static_assert_check {}; #define _LIBCPP_EXTERN_TEMPLATE2(...) extern template __VA_ARGS__; #endif +#if __APPLE__ && defined(__LP64__) && !defined(__x86_64__) +#define _LIBCPP_NONUNIQUE_RTTI_BIT (1ULL << 63) +#endif + #if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) || defined(__sun__) || defined(__NetBSD__) #define _LIBCPP_LOCALE__L_EXTENSIONS 1 #endif diff --git a/include/typeinfo b/include/typeinfo index 6ffee0f8..7fcc8244 100644 --- a/include/typeinfo +++ b/include/typeinfo @@ -60,6 +60,7 @@ public: #include <__config> #include <exception> #include <cstddef> +#include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -73,32 +74,83 @@ class _LIBCPP_EXCEPTION_ABI type_info type_info& operator=(const type_info&); type_info(const type_info&); protected: +#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT const char* __type_name; +#else + // A const char* with the non-unique RTTI bit possibly set. + uintptr_t __type_name; +#endif _LIBCPP_INLINE_VISIBILITY explicit type_info(const char* __n) +#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT : __type_name(__n) {} +#else + : __type_name(reinterpret_cast<uintptr_t>(__n)) {} +#endif public: virtual ~type_info(); _LIBCPP_INLINE_VISIBILITY - const char* name() const _NOEXCEPT {return __type_name;} + const char* name() const _NOEXCEPT +#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT + {return __type_name;} +#else + {return reinterpret_cast<const char*>(__type_name & ~_LIBCPP_NONUNIQUE_RTTI_BIT);} +#endif _LIBCPP_INLINE_VISIBILITY bool before(const type_info& __arg) const _NOEXCEPT +#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT {return __type_name < __arg.__type_name;} +#else + {if (!((__type_name & __arg.__type_name) & _LIBCPP_NONUNIQUE_RTTI_BIT)) + return __type_name < __arg.__type_name; + return __compare_nonunique_names(__arg) < 0;} +#endif + _LIBCPP_INLINE_VISIBILITY size_t hash_code() const _NOEXCEPT +#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT {return *reinterpret_cast<const size_t*>(&__type_name);} +#else + {if (!(__type_name & _LIBCPP_NONUNIQUE_RTTI_BIT)) return __type_name; + const char *__ptr = __name_for_load(); + size_t __hash = 5381; + while (unsigned char __c = static_cast<unsigned char>(*__ptr++)) + __hash = (__hash * 33) ^ __c; + return __hash;} +#endif _LIBCPP_INLINE_VISIBILITY bool operator==(const type_info& __arg) const _NOEXCEPT +#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT {return __type_name == __arg.__type_name;} +#else + {if (__type_name == __arg.__type_name) return true; + if (!((__type_name & __arg.__type_name) & _LIBCPP_NONUNIQUE_RTTI_BIT)) + return false; + return __compare_nonunique_names(__arg) == 0;} +#endif _LIBCPP_INLINE_VISIBILITY bool operator!=(const type_info& __arg) const _NOEXCEPT {return !operator==(__arg);} +#ifdef _LIBCPP_NONUNIQUE_RTTI_BIT + private: + _LIBCPP_INLINE_VISIBILITY + int __compare_nonunique_names(const type_info &__arg) const _NOEXCEPT + {return __builtin_strcmp(__name_for_load(), __arg.__name_for_load());} + + _LIBCPP_INLINE_VISIBILITY + const char *__name_for_load() const _NOEXCEPT + {uintptr_t __data = __type_name; +#if 1 + __data &= ~_LIBCPP_NONUNIQUE_RTTI_BIT; +#endif + return reinterpret_cast<const char*>(__data);} +#endif }; class _LIBCPP_EXCEPTION_ABI bad_cast |