brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.0 KiB · f608c94 Raw
397 lines · plain
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP_TYPEINFO11#define _LIBCPP_TYPEINFO12 13/*14 15    typeinfo synopsis16 17namespace std {18 19class type_info20{21public:22    virtual ~type_info();23 24    bool operator==(const type_info& rhs) const noexcept; // constexpr since C++2325    bool operator!=(const type_info& rhs) const noexcept; // removed in C++2026 27    bool before(const type_info& rhs) const noexcept;28    size_t hash_code() const noexcept;29    const char* name() const noexcept;30 31    type_info(const type_info& rhs) = delete;32    type_info& operator=(const type_info& rhs) = delete;33};34 35class bad_cast36    : public exception37{38public:39    bad_cast() noexcept;40    bad_cast(const bad_cast&) noexcept;41    bad_cast& operator=(const bad_cast&) noexcept;42    virtual const char* what() const noexcept;43};44 45class bad_typeid46    : public exception47{48public:49    bad_typeid() noexcept;50    bad_typeid(const bad_typeid&) noexcept;51    bad_typeid& operator=(const bad_typeid&) noexcept;52    virtual const char* what() const noexcept;53};54 55}  // std56 57*/58 59#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)60#  include <__cxx03/typeinfo>61#else62#  include <__config>63#  include <__cstddef/size_t.h>64#  include <__exception/exception.h>65#  include <__type_traits/integral_constant.h>66#  include <__type_traits/is_constant_evaluated.h>67#  include <__verbose_abort>68#  include <cstdint>69#  include <version>70 71#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)72#    pragma GCC system_header73#  endif74 75#  if defined(_LIBCPP_ABI_VCRUNTIME)76#    include <vcruntime_typeinfo.h>77#  else78 79namespace std // purposefully not using versioning namespace80{81 82#    if defined(_LIBCPP_ABI_MICROSOFT)83 84class _LIBCPP_EXPORTED_FROM_ABI type_info {85  type_info& operator=(const type_info&);86  type_info(const type_info&);87 88  mutable struct {89    const char* __undecorated_name;90    const char __decorated_name[1];91  } __data;92 93  int __compare(const type_info& __rhs) const _NOEXCEPT;94 95public:96  virtual ~type_info();97 98  const char* name() const _NOEXCEPT;99 100  _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT { return __compare(__arg) < 0; }101 102  size_t hash_code() const _NOEXCEPT;103 104  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT {105    // When evaluated in a constant expression, both type infos simply can't come106    // from different translation units, so it is sufficient to compare their addresses.107    if (__libcpp_is_constant_evaluated()) {108      return this == &__arg;109    }110    return __compare(__arg) == 0;111  }112 113#      if _LIBCPP_STD_VER <= 17114  _LIBCPP_HIDE_FROM_ABI bool operator!=(const type_info& __arg) const _NOEXCEPT { return !operator==(__arg); }115#      endif116};117 118#    else // !defined(_LIBCPP_ABI_MICROSOFT)119 120// ========================================================================== //121//                           Implementations122// ========================================================================== //123// ------------------------------------------------------------------------- //124//                               Unique125//               (_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 1)126// ------------------------------------------------------------------------- //127// This implementation of type_info assumes a unique copy of the RTTI for a128// given type inside a program. This is a valid assumption when abiding to the129// Itanium ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-components).130// Under this assumption, we can always compare the addresses of the type names131// to implement equality-comparison of type_infos instead of having to perform132// a deep string comparison.133// -------------------------------------------------------------------------- //134//                             NonUnique135//               (_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 2)136// -------------------------------------------------------------------------- //137// This implementation of type_info does not assume there is always a unique138// copy of the RTTI for a given type inside a program. For various reasons139// the linker may have failed to merge every copy of a types RTTI140// (For example: -Bsymbolic or llvm.org/PR37398). Under this assumption, two141// type_infos are equal if their addresses are equal or if a deep string142// comparison is equal.143// -------------------------------------------------------------------------- //144//                          NonUniqueARMRTTIBit145//               (_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 3)146// -------------------------------------------------------------------------- //147// This implementation is specific to ARM64 on Apple platforms.148//149// This implementation of type_info does not assume always a unique copy of150// the RTTI for a given type inside a program. When constructing the type_info,151// the compiler packs the pointer to the type name into a uintptr_t and reserves152// the high bit of that pointer, which is assumed to be free for use under that153// ABI. If that high bit is set, that specific copy of the RTTI can't be assumed154// to be unique within the program. If the high bit is unset, then the RTTI can155// be assumed to be unique within the program.156//157// When comparing type_infos, if both RTTIs can be assumed to be unique, it158// suffices to compare their addresses. If both the RTTIs can't be assumed to159// be unique, we must perform a deep string comparison of the type names.160// However, if one of the RTTIs is guaranteed unique and the other one isn't,161// then both RTTIs are necessarily not to be considered equal.162//163// The intent of this design is to remove the need for weak symbols. Specifically,164// if a type would normally have a default-visibility RTTI emitted as a weak165// symbol, it is given hidden visibility instead and the non-unique bit is set.166// Otherwise, types declared with hidden visibility are always considered to have167// a unique RTTI: the RTTI is emitted with linkonce_odr linkage and is assumed168// to be deduplicated by the linker within the linked image. Across linked image169// boundaries, such types are thus considered different types.170 171// This value can be overriden in the __config_site. When it's not overriden,172// we pick a default implementation based on the platform here.173#      ifndef _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION174 175// Windows and AIX binaries can't merge typeinfos, so use the NonUnique implementation.176#        if defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)177#          define _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION 2178 179// On arm64 on Apple platforms, use the special NonUniqueARMRTTIBit implementation.180#        elif defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__)181#          define _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION 3182 183// On all other platforms, assume the Itanium C++ ABI and use the Unique implementation.184#        else185#          define _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION 1186#        endif187#      endif188 189namespace __type_info_implementations {190struct __string_impl_base {191  typedef const char* __type_name_t;192  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR static const char*193  __type_name_to_string(__type_name_t __v) _NOEXCEPT {194    return __v;195  }196  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR static __type_name_t197  __string_to_type_name(const char* __v) _NOEXCEPT {198    return __v;199  }200};201 202struct __unique_impl : __string_impl_base {203  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __v) _NOEXCEPT {204    return reinterpret_cast<size_t>(__v);205  }206  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {207    return __lhs == __rhs;208  }209  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {210    return __lhs < __rhs;211  }212};213 214struct __non_unique_impl : __string_impl_base {215  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __ptr) _NOEXCEPT {216    size_t __hash = 5381;217    while (unsigned char __c = static_cast<unsigned char>(*__ptr++))218      __hash = (__hash * 33) ^ __c;219    return __hash;220  }221  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {222    return __lhs == __rhs || __builtin_strcmp(__lhs, __rhs) == 0;223  }224  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {225    return __builtin_strcmp(__lhs, __rhs) < 0;226  }227};228 229struct __non_unique_arm_rtti_bit_impl {230  typedef uintptr_t __type_name_t;231 232  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static const char* __type_name_to_string(__type_name_t __v) _NOEXCEPT {233    return reinterpret_cast<const char*>(__v & ~__non_unique_rtti_bit::value);234  }235  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static __type_name_t __string_to_type_name(const char* __v) _NOEXCEPT {236    return reinterpret_cast<__type_name_t>(__v);237  }238 239  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __v) _NOEXCEPT {240    if (__is_type_name_unique(__v))241      return __v;242    return __non_unique_impl::__hash(__type_name_to_string(__v));243  }244  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {245    if (__lhs == __rhs)246      return true;247    if (__is_type_name_unique(__lhs) || __is_type_name_unique(__rhs))248      // Either both are unique and have a different address, or one of them249      // is unique and the other one isn't. In both cases they are unequal.250      return false;251    return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) == 0;252  }253  _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {254    if (__is_type_name_unique(__lhs) || __is_type_name_unique(__rhs))255      return __lhs < __rhs;256    return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) < 0;257  }258 259private:260  // The unique bit is the top bit. It is expected that __type_name_t is 64 bits when261  // this implementation is actually used.262  typedef integral_constant<__type_name_t, (1ULL << ((__CHAR_BIT__ * sizeof(__type_name_t)) - 1))>263      __non_unique_rtti_bit;264 265  _LIBCPP_HIDE_FROM_ABI static bool __is_type_name_unique(__type_name_t __lhs) _NOEXCEPT {266    return !(__lhs & __non_unique_rtti_bit::value);267  }268};269 270typedef271#      if _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 1272    __unique_impl273#      elif _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 2274    __non_unique_impl275#      elif _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 3276    __non_unique_arm_rtti_bit_impl277#      else278#        error invalid configuration for _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION279#      endif280        __impl;281} // namespace __type_info_implementations282 283#      if __has_cpp_attribute(_Clang::__ptrauth_vtable_pointer__)284#        if __has_feature(ptrauth_type_info_vtable_pointer_discrimination)285#          define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH                                                                \286            [[_Clang::__ptrauth_vtable_pointer__(process_independent, address_discrimination, type_discrimination)]]287#        else288#          define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH                                                                \289            [[_Clang::__ptrauth_vtable_pointer__(                                                                      \290                process_independent, no_address_discrimination, no_extra_discrimination)]]291#        endif292#      else293#        define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH294#      endif295 296class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info {297  type_info& operator=(const type_info&);298  type_info(const type_info&);299 300protected:301  typedef __type_info_implementations::__impl __impl;302 303  __impl::__type_name_t __type_name;304 305  _LIBCPP_HIDE_FROM_ABI explicit type_info(const char* __n) : __type_name(__impl::__string_to_type_name(__n)) {}306 307public:308  virtual ~type_info();309 310  _LIBCPP_HIDE_FROM_ABI const char* name() const _NOEXCEPT { return __impl::__type_name_to_string(__type_name); }311 312  _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT {313    return __impl::__lt(__type_name, __arg.__type_name);314  }315 316  _LIBCPP_HIDE_FROM_ABI size_t hash_code() const _NOEXCEPT { return __impl::__hash(__type_name); }317 318  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT {319    // When evaluated in a constant expression, both type infos simply can't come320    // from different translation units, so it is sufficient to compare their addresses.321    if (__libcpp_is_constant_evaluated()) {322      return this == &__arg;323    }324    return __impl::__eq(__type_name, __arg.__type_name);325  }326 327#      if _LIBCPP_STD_VER <= 17328  _LIBCPP_HIDE_FROM_ABI bool operator!=(const type_info& __arg) const _NOEXCEPT { return !operator==(__arg); }329#      endif330};331#    endif // defined(_LIBCPP_ABI_MICROSOFT)332 333class _LIBCPP_EXPORTED_FROM_ABI bad_cast : public exception {334public:335  bad_cast() _NOEXCEPT;336  _LIBCPP_HIDE_FROM_ABI bad_cast(const bad_cast&) _NOEXCEPT            = default;337  _LIBCPP_HIDE_FROM_ABI bad_cast& operator=(const bad_cast&) _NOEXCEPT = default;338  ~bad_cast() _NOEXCEPT override;339  const char* what() const _NOEXCEPT override;340};341 342class _LIBCPP_EXPORTED_FROM_ABI bad_typeid : public exception {343public:344  bad_typeid() _NOEXCEPT;345  _LIBCPP_HIDE_FROM_ABI bad_typeid(const bad_typeid&) _NOEXCEPT            = default;346  _LIBCPP_HIDE_FROM_ABI bad_typeid& operator=(const bad_typeid&) _NOEXCEPT = default;347  ~bad_typeid() _NOEXCEPT override;348  const char* what() const _NOEXCEPT override;349};350 351} // namespace std352 353#  endif // defined(_LIBCPP_ABI_VCRUNTIME)354 355#  if defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0356 357_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD358 359class bad_cast : public exception {360public:361  bad_cast() _NOEXCEPT : exception("bad cast") {}362 363private:364  bad_cast(const char* const __message) _NOEXCEPT : exception(__message) {}365};366 367class bad_typeid : public exception {368public:369  bad_typeid() _NOEXCEPT : exception("bad typeid") {}370 371private:372  bad_typeid(const char* const __message) _NOEXCEPT : exception(__message) {}373};374 375_LIBCPP_END_UNVERSIONED_NAMESPACE_STD376 377#  endif // defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0378 379_LIBCPP_BEGIN_NAMESPACE_STD380[[__noreturn__]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_cast() {381#  if _LIBCPP_HAS_EXCEPTIONS382  throw bad_cast();383#  else384  _LIBCPP_VERBOSE_ABORT("bad_cast was thrown in -fno-exceptions mode");385#  endif386}387_LIBCPP_END_NAMESPACE_STD388 389#  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20390#    include <cstddef>391#    include <cstdlib>392#    include <type_traits>393#  endif394#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)395 396#endif // _LIBCPP_TYPEINFO397