forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			352 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			352 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
| // -*- C++ -*-
 | |
| //===-------------------------- typeinfo ----------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef __LIBCPP_TYPEINFO
 | |
| #define __LIBCPP_TYPEINFO
 | |
| 
 | |
| /*
 | |
| 
 | |
|     typeinfo synopsis
 | |
| 
 | |
| namespace std {
 | |
| 
 | |
| class type_info
 | |
| {
 | |
| public:
 | |
|     virtual ~type_info();
 | |
| 
 | |
|     bool operator==(const type_info& rhs) const noexcept;
 | |
|     bool operator!=(const type_info& rhs) const noexcept;
 | |
| 
 | |
|     bool before(const type_info& rhs) const noexcept;
 | |
|     size_t hash_code() const noexcept;
 | |
|     const char* name() const noexcept;
 | |
| 
 | |
|     type_info(const type_info& rhs) = delete;
 | |
|     type_info& operator=(const type_info& rhs) = delete;
 | |
| };
 | |
| 
 | |
| class bad_cast
 | |
|     : public exception
 | |
| {
 | |
| public:
 | |
|     bad_cast() noexcept;
 | |
|     bad_cast(const bad_cast&) noexcept;
 | |
|     bad_cast& operator=(const bad_cast&) noexcept;
 | |
|     virtual const char* what() const noexcept;
 | |
| };
 | |
| 
 | |
| class bad_typeid
 | |
|     : public exception
 | |
| {
 | |
| public:
 | |
|     bad_typeid() noexcept;
 | |
|     bad_typeid(const bad_typeid&) noexcept;
 | |
|     bad_typeid& operator=(const bad_typeid&) noexcept;
 | |
|     virtual const char* what() const noexcept;
 | |
| };
 | |
| 
 | |
| }  // std
 | |
| 
 | |
| */
 | |
| 
 | |
| #include <__config>
 | |
| #include <exception>
 | |
| #include <cstddef>
 | |
| #include <cstdint>
 | |
| #include <type_traits>
 | |
| #ifdef _LIBCPP_NO_EXCEPTIONS
 | |
| #include <cstdlib>
 | |
| #endif
 | |
| 
 | |
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 | |
| #pragma GCC system_header
 | |
| #endif
 | |
| 
 | |
| #if defined(_LIBCPP_ABI_VCRUNTIME)
 | |
| #include <vcruntime_typeinfo.h>
 | |
| #else
 | |
| 
 | |
| namespace std  // purposefully not using versioning namespace
 | |
| {
 | |
| 
 | |
| 
 | |
| #if defined(_LIBCPP_ABI_MICROSOFT)
 | |
| 
 | |
| class _LIBCPP_EXCEPTION_ABI type_info
 | |
| {
 | |
|     type_info& operator=(const type_info&);
 | |
|     type_info(const type_info&);
 | |
| 
 | |
|     mutable struct {
 | |
|       const char *__undecorated_name;
 | |
|       const char __decorated_name[1];
 | |
|     } __data;
 | |
| 
 | |
|     int __compare(const type_info &__rhs) const _NOEXCEPT;
 | |
| 
 | |
| public:
 | |
|     _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
 | |
|     virtual ~type_info();
 | |
| 
 | |
|     const char *name() const _NOEXCEPT;
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     bool before(const type_info& __arg) const _NOEXCEPT {
 | |
|       return __compare(__arg) < 0;
 | |
|     }
 | |
| 
 | |
|     size_t hash_code() const _NOEXCEPT;
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     bool operator==(const type_info& __arg) const _NOEXCEPT {
 | |
|       return __compare(__arg) == 0;
 | |
|     }
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     bool operator!=(const type_info& __arg) const _NOEXCEPT
 | |
|     { return !operator==(__arg); }
 | |
| };
 | |
| 
 | |
| #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
 | |
| // is assumed to be free for use under the ABI in use) to represent whether
 | |
| // that specific copy of the RTTI can be assumed unique inside the program.
 | |
| // To implement equality-comparison of type_infos, we check whether BOTH
 | |
| // type_infos are guaranteed unique, and if so, we simply compare the addresses
 | |
| // of their type names instead of doing a deep string comparison, which is
 | |
| // 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.
 | |
| 
 | |
| 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 _LIBCPP_ALWAYS_INLINE
 | |
|     _LIBCPP_CONSTEXPR static __type_name_t __string_to_type_name(const char* __v) _NOEXCEPT {
 | |
|       return __v;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   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;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   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;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   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);
 | |
|     }
 | |
| 
 | |
|     _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 __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:
 | |
|     // The unique bit is the top bit. It is expected that __type_name_t is 64 bits when
 | |
|     // this implementation is actually used.
 | |
|     typedef std::integral_constant<__type_name_t,
 | |
|       (1ULL << ((__CHAR_BIT__ * sizeof(__type_name_t)) - 1))> __non_unique_rtti_bit;
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     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;
 | |
| };
 | |
| 
 | |
| class _LIBCPP_EXCEPTION_ABI type_info
 | |
| {
 | |
|   type_info& operator=(const type_info&);
 | |
|   type_info(const type_info&);
 | |
| 
 | |
|  protected:
 | |
|     typedef __type_info_implementations::__impl __impl;
 | |
| 
 | |
|     __impl::__type_name_t __type_name;
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     explicit type_info(const char* __n)
 | |
|       : __type_name(__impl::__string_to_type_name(__n)) {}
 | |
| 
 | |
| public:
 | |
|     _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
 | |
|     virtual ~type_info();
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     const char* name() const _NOEXCEPT
 | |
|     {
 | |
|       return __impl::__type_name_to_string(__type_name);
 | |
|     }
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     bool before(const type_info& __arg) const _NOEXCEPT
 | |
|     {
 | |
|       return __impl::__lt(__type_name, __arg.__type_name);
 | |
|     }
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     size_t hash_code() const _NOEXCEPT
 | |
|     {
 | |
|       return __impl::__hash(__type_name);
 | |
|     }
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     bool operator==(const type_info& __arg) const _NOEXCEPT
 | |
|     {
 | |
|       return __impl::__eq(__type_name, __arg.__type_name);
 | |
|     }
 | |
| 
 | |
|     _LIBCPP_INLINE_VISIBILITY
 | |
|     bool operator!=(const type_info& __arg) const _NOEXCEPT
 | |
|     { return !operator==(__arg); }
 | |
| };
 | |
| #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;
 | |
| };
 | |
| 
 | |
| class _LIBCPP_EXCEPTION_ABI bad_typeid
 | |
|     : public exception
 | |
| {
 | |
|  public:
 | |
|   bad_typeid() _NOEXCEPT;
 | |
|   virtual ~bad_typeid() _NOEXCEPT;
 | |
|   virtual const char* what() const _NOEXCEPT;
 | |
| };
 | |
| 
 | |
| }  // std
 | |
| 
 | |
| #endif // defined(_LIBCPP_ABI_VCRUNTIME)
 | |
| 
 | |
| _LIBCPP_BEGIN_NAMESPACE_STD
 | |
| _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
 | |
| void __throw_bad_cast()
 | |
| {
 | |
| #ifndef _LIBCPP_NO_EXCEPTIONS
 | |
|     throw bad_cast();
 | |
| #else
 | |
|     _VSTD::abort();
 | |
| #endif
 | |
| }
 | |
| _LIBCPP_END_NAMESPACE_STD
 | |
| 
 | |
| #endif  // __LIBCPP_TYPEINFO
 |