#include <vcruntime_typeinfo.h>
#else
-#if defined(_LIBCPP_NONUNIQUE_RTTI_BIT) && !defined(_LIBCPP_ABI_MICROSOFT)
-# define _LIBCPP_HAS_NONUNIQUE_TYPEINFO
-#endif
-
namespace std // purposefully not using versioning namespace
{
+
#if defined(_LIBCPP_ABI_MICROSOFT)
class _LIBCPP_EXCEPTION_ABI type_info
{ return !operator==(__arg); }
};
-#elif defined(_LIBCPP_HAS_NONUNIQUE_TYPEINFO)
+#else // !defined(_LIBCPP_ABI_MICROSOFT)
+// ========================================================================== //
+// Implementations
+// ========================================================================== //
+// ------------------------------------------------------------------------- //
+// Unique
+// ------------------------------------------------------------------------- //
+// This implementation of type_info assumes a unique copy of the RTTI for a
+// given type inside a program. This is a valid assumption when abiding to
+// Itanium ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-components).
+// Under this assumption, we can always compare the addresses of the type names
+// to implement equality-comparison of type_infos instead of having to perform
+// a deep string comparison.
+// -------------------------------------------------------------------------- //
+// NonUnique
+// -------------------------------------------------------------------------- //
+// This implementation of type_info does not assume there is always a unique
+// copy of the RTTI for a given type inside a program. For various reasons
+// the linker may have failed to merge every copy of a types RTTI
+// (For example: -Bsymbolic or llvm.org/PR37398). Under this assumption, two
+// type_infos are equal if their addresses are equal or if a deep string
+// comparison is equal.
+// -------------------------------------------------------------------------- //
+// NonUniqueARMRTTIBit
+// -------------------------------------------------------------------------- //
// This implementation of type_info does not assume always a unique copy of
// the RTTI for a given type inside a program. It packs the pointer to the
// type name into a uintptr_t and reserves the high bit of that pointer (which
// faster. If at least one of the type_infos can't guarantee uniqueness, we
// have no choice but to fall back to a deep string comparison.
//
+// This implementation is specific to ARM64 on Apple platforms.
+//
// Note that the compiler is the one setting (or unsetting) the high bit of
// the pointer when it constructs the type_info, depending on whether it can
// guarantee uniqueness for that specific type_info.
-class _LIBCPP_EXCEPTION_ABI type_info
-{
- type_info& operator=(const type_info&);
- type_info(const type_info&);
-
- _LIBCPP_INLINE_VISIBILITY
- int __compare_nonunique_names(const type_info &__arg) const _NOEXCEPT
- { return __builtin_strcmp(name(), __arg.name()); }
-
-protected:
- uintptr_t __type_name;
-
- _LIBCPP_INLINE_VISIBILITY
- explicit type_info(const char* __n)
- : __type_name(reinterpret_cast<uintptr_t>(__n)) {}
-public:
- _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
- virtual ~type_info();
-
- _LIBCPP_INLINE_VISIBILITY
- const char* name() const _NOEXCEPT
- {
- return reinterpret_cast<const char*>(__type_name &
- ~_LIBCPP_NONUNIQUE_RTTI_BIT);
+struct __type_info_implementations {
+ struct __string_impl_base {
+ typedef const char* __type_name_t;
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ _LIBCPP_CONSTEXPR static const char* __type_name_to_string(__type_name_t __v) _NOEXCEPT {
+ return __v;
}
-
- _LIBCPP_INLINE_VISIBILITY
- bool before(const type_info& __arg) const _NOEXCEPT
- {
- if (!((__type_name & __arg.__type_name) & _LIBCPP_NONUNIQUE_RTTI_BIT))
- return __type_name < __arg.__type_name;
- return __compare_nonunique_names(__arg) < 0;
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ _LIBCPP_CONSTEXPR static __type_name_t __string_to_type_name(const char* __v) _NOEXCEPT {
+ return __v;
}
+ };
- _LIBCPP_INLINE_VISIBILITY
- size_t hash_code() const _NOEXCEPT
- {
- if (!(__type_name & _LIBCPP_NONUNIQUE_RTTI_BIT))
- return __type_name;
+ struct __unique_impl : __string_impl_base {
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static size_t __hash(__type_name_t __v) _NOEXCEPT {
+ return reinterpret_cast<size_t>(__v);
+ }
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
+ return __lhs == __rhs;
+ }
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
+ return __lhs < __rhs;
+ }
+ };
- const char* __ptr = name();
+ struct __non_unique_impl : __string_impl_base {
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static size_t __hash(__type_name_t __ptr) _NOEXCEPT {
size_t __hash = 5381;
while (unsigned char __c = static_cast<unsigned char>(*__ptr++))
__hash = (__hash * 33) ^ __c;
return __hash;
}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
+ return __lhs == __rhs || __builtin_strcmp(__lhs, __rhs) == 0;
+ }
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
+ return __builtin_strcmp(__lhs, __rhs) < 0;
+ }
+ };
- _LIBCPP_INLINE_VISIBILITY
- bool operator==(const type_info& __arg) const _NOEXCEPT
- {
- if (__type_name == __arg.__type_name)
- return true;
+ struct __non_unique_arm_rtti_bit_impl {
+ typedef uintptr_t __type_name_t;
+
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static const char* __type_name_to_string(__type_name_t __v) _NOEXCEPT {
+ return reinterpret_cast<const char*>(__v &
+ ~__non_unique_rtti_bit::value);
+ }
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static __type_name_t __string_to_type_name(const char* __v) _NOEXCEPT {
+ return reinterpret_cast<__type_name_t>(__v);
+ }
- if (!((__type_name & __arg.__type_name) & _LIBCPP_NONUNIQUE_RTTI_BIT))
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static size_t __hash(__type_name_t __v) _NOEXCEPT {
+ if (__is_type_name_unique(__v))
+ return reinterpret_cast<size_t>(__v);
+ return __non_unique_impl::__hash(__type_name_to_string(__v));
+ }
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
+ if (__lhs == __rhs)
+ return true;
+ if (__is_type_name_unique(__lhs, __rhs))
return false;
- return __compare_nonunique_names(__arg) == 0;
+ return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) == 0;
}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
+ static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
+ if (__is_type_name_unique(__lhs, __rhs))
+ return __lhs < __rhs;
+ return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) < 0;
+ }
+
+ private:
+ typedef std::integral_constant<__type_name_t, (1ULL << 63)> __non_unique_rtti_bit;
_LIBCPP_INLINE_VISIBILITY
- bool operator!=(const type_info& __arg) const _NOEXCEPT
- { return !operator==(__arg); }
+ static bool __is_type_name_unique(__type_name_t __lhs) _NOEXCEPT {
+ return !(__lhs & __non_unique_rtti_bit::value);
+ }
+ _LIBCPP_INLINE_VISIBILITY
+ static bool __is_type_name_unique(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
+ return !((__lhs & __rhs) & __non_unique_rtti_bit::value);
+ }
+ };
+
+ typedef
+#if defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__)
+ __non_unique_arm_rtti_bit_impl
+#elif _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT == 0
+ __non_unique_impl
+#elif _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT == 1
+ __unique_impl
+#else
+# error invalid configuration for _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT
+#endif
+ __impl;
};
-#else // !_LIBCPP_ABI_MICROSOFT && !_LIBCPP_HAS_NONUNIQUE_TYPEINFO
-
-// This implementation of type_info assumes a unique copy of the RTTI for a
-// given type inside a program. This is a valid assumption when abiding to
-// Itanium ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-components).
-// Under this assumption, we can always compare the addresses of the type names
-// to implement equality-comparison of type_infos instead of having to perform
-// a deep string comparison.
class _LIBCPP_EXCEPTION_ABI type_info
{
- type_info& operator=(const type_info&);
- type_info(const type_info&);
+ type_info& operator=(const type_info&);
+ type_info(const type_info&);
+
+ protected:
+ typedef __type_info_implementations::__impl __impl;
-protected:
- const char *__type_name;
+ __impl::__type_name_t __type_name;
_LIBCPP_INLINE_VISIBILITY
- explicit type_info(const char* __n) : __type_name(__n) {}
+ explicit type_info(const char* __n)
+ : __type_name(__impl::__string_to_type_name(__n)) {}
public:
_LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
_LIBCPP_INLINE_VISIBILITY
const char* name() const _NOEXCEPT
- { return __type_name; }
+ {
+ return __impl::__type_name_to_string(__type_name);
+ }
_LIBCPP_INLINE_VISIBILITY
bool before(const type_info& __arg) const _NOEXCEPT
- { return __type_name < __arg.__type_name; }
+ {
+ return __impl::__lt(__type_name, __arg.__type_name);
+ }
_LIBCPP_INLINE_VISIBILITY
size_t hash_code() const _NOEXCEPT
- { return reinterpret_cast<size_t>(__type_name); }
+ {
+ return __impl::__hash(__type_name);
+ }
_LIBCPP_INLINE_VISIBILITY
bool operator==(const type_info& __arg) const _NOEXCEPT
- { return __type_name == __arg.__type_name; }
+ {
+ return __impl::__eq(__type_name, __arg.__type_name);
+ }
_LIBCPP_INLINE_VISIBILITY
bool operator!=(const type_info& __arg) const _NOEXCEPT
{ return !operator==(__arg); }
};
-
-#endif
+#endif // defined(_LIBCPP_ABI_MICROSOFT)
class _LIBCPP_EXCEPTION_ABI bad_cast
: public exception
{
-public:
- bad_cast() _NOEXCEPT;
- virtual ~bad_cast() _NOEXCEPT;
- virtual const char* what() const _NOEXCEPT;
+ public:
+ bad_cast() _NOEXCEPT;
+ virtual ~bad_cast() _NOEXCEPT;
+ virtual const char* what() const _NOEXCEPT;
};
class _LIBCPP_EXCEPTION_ABI bad_typeid
: public exception
{
-public:
- bad_typeid() _NOEXCEPT;
- virtual ~bad_typeid() _NOEXCEPT;
- virtual const char* what() const _NOEXCEPT;
+ public:
+ bad_typeid() _NOEXCEPT;
+ virtual ~bad_typeid() _NOEXCEPT;
+ virtual const char* what() const _NOEXCEPT;
};
} // std