summaryrefslogtreecommitdiffstats
path: root/libcxx/include/typeinfo
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2019-05-29 02:21:37 +0000
committerEric Fiselier <eric@efcs.ca>2019-05-29 02:21:37 +0000
commit2405bd6898151e0a7ffede78b0d0c7c85c0b66d3 (patch)
tree2fde5f2bbd22223264b72b1d49ce810f98be6107 /libcxx/include/typeinfo
parent818c652643411667c054fd9a929c4c07941832b5 (diff)
downloadbcm5719-llvm-2405bd6898151e0a7ffede78b0d0c7c85c0b66d3.tar.gz
bcm5719-llvm-2405bd6898151e0a7ffede78b0d0c7c85c0b66d3.zip
Rework std::type_info definition to support systems without fully
merged type info names. Previously std::type_info always expected type info string to be unique. But this isn't always the case. Like when -Bsymbolic is passed to the linker or due to llvm.org/PR37398. This patch adds the LIBCXX_HAS_MERGED_TYPEINFO_NAMES_DEFAULT CMake option which, when specified, overrides the default configuration for the library. The current defaults still assume unique names even though this isn't strictly correct for ELF binaries. We should consider changing the default in a follow up commit. llvm-svn: 361913
Diffstat (limited to 'libcxx/include/typeinfo')
-rw-r--r--libcxx/include/typeinfo224
1 files changed, 146 insertions, 78 deletions
diff --git a/libcxx/include/typeinfo b/libcxx/include/typeinfo
index a52c984961b..5d2f03effc5 100644
--- a/libcxx/include/typeinfo
+++ b/libcxx/include/typeinfo
@@ -72,13 +72,10 @@ public:
#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
@@ -116,8 +113,32 @@ public:
{ 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
@@ -129,91 +150,131 @@ public:
// 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
@@ -221,43 +282,50 @@ public:
_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
OpenPOWER on IntegriCloud