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-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_TYPEINFO 11#define _LIBCPP_TYPEINFO 12 13/* 14 15 typeinfo synopsis 16 17namespace std { 18 19class type_info 20{ 21public: 22 virtual ~type_info(); 23 24 bool operator==(const type_info& rhs) const noexcept; // constexpr since C++23 25 bool operator!=(const type_info& rhs) const noexcept; // removed in C++20 26 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_cast 36 : public exception 37{ 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_typeid 46 : public exception 47{ 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} // std 56 57*/ 58 59#include <__config> 60#include <__exception/exception.h> 61#include <__type_traits/is_constant_evaluated.h> 62#include <__verbose_abort> 63#include <cstddef> 64#include <cstdint> 65 66#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 67# pragma GCC system_header 68#endif 69 70#if defined(_LIBCPP_ABI_VCRUNTIME) 71# include <vcruntime_typeinfo.h> 72#else 73 74namespace std // purposefully not using versioning namespace 75{ 76 77# if defined(_LIBCPP_ABI_MICROSOFT) 78 79class _LIBCPP_EXPORTED_FROM_ABI type_info { 80 type_info& operator=(const type_info&); 81 type_info(const type_info&); 82 83 mutable struct { 84 const char* __undecorated_name; 85 const char __decorated_name[1]; 86 } __data; 87 88 int __compare(const type_info& __rhs) const _NOEXCEPT; 89 90public: 91 virtual ~type_info(); 92 93 const char* name() const _NOEXCEPT; 94 95 _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT { return __compare(__arg) < 0; } 96 97 size_t hash_code() const _NOEXCEPT; 98 99 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT { 100 // When evaluated in a constant expression, both type infos simply can't come 101 // from different translation units, so it is sufficient to compare their addresses. 102 if (__libcpp_is_constant_evaluated()) { 103 return this == &__arg; 104 } 105 return __compare(__arg) == 0; 106 } 107 108# if _LIBCPP_STD_VER <= 17 109 _LIBCPP_HIDE_FROM_ABI bool operator!=(const type_info& __arg) const _NOEXCEPT { return !operator==(__arg); } 110# endif 111}; 112 113# else // !defined(_LIBCPP_ABI_MICROSOFT) 114 115// ========================================================================== // 116// Implementations 117// ========================================================================== // 118// ------------------------------------------------------------------------- // 119// Unique 120// (_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 1) 121// ------------------------------------------------------------------------- // 122// This implementation of type_info assumes a unique copy of the RTTI for a 123// given type inside a program. This is a valid assumption when abiding to the 124// Itanium ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-components). 125// Under this assumption, we can always compare the addresses of the type names 126// to implement equality-comparison of type_infos instead of having to perform 127// a deep string comparison. 128// -------------------------------------------------------------------------- // 129// NonUnique 130// (_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 2) 131// -------------------------------------------------------------------------- // 132// This implementation of type_info does not assume there is always a unique 133// copy of the RTTI for a given type inside a program. For various reasons 134// the linker may have failed to merge every copy of a types RTTI 135// (For example: -Bsymbolic or llvm.org/PR37398). Under this assumption, two 136// type_infos are equal if their addresses are equal or if a deep string 137// comparison is equal. 138// -------------------------------------------------------------------------- // 139// NonUniqueARMRTTIBit 140// (_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 3) 141// -------------------------------------------------------------------------- // 142// This implementation is specific to ARM64 on Apple platforms. 143// 144// This implementation of type_info does not assume always a unique copy of 145// the RTTI for a given type inside a program. When constructing the type_info, 146// the compiler packs the pointer to the type name into a uintptr_t and reserves 147// the high bit of that pointer, which is assumed to be free for use under that 148// ABI. If that high bit is set, that specific copy of the RTTI can't be assumed 149// to be unique within the program. If the high bit is unset, then the RTTI can 150// be assumed to be unique within the program. 151// 152// When comparing type_infos, if both RTTIs can be assumed to be unique, it 153// suffices to compare their addresses. If both the RTTIs can't be assumed to 154// be unique, we must perform a deep string comparison of the type names. 155// However, if one of the RTTIs is guaranteed unique and the other one isn't, 156// then both RTTIs are necessarily not to be considered equal. 157// 158// The intent of this design is to remove the need for weak symbols. Specifically, 159// if a type would normally have a default-visibility RTTI emitted as a weak 160// symbol, it is given hidden visibility instead and the non-unique bit is set. 161// Otherwise, types declared with hidden visibility are always considered to have 162// a unique RTTI: the RTTI is emitted with linkonce_odr linkage and is assumed 163// to be deduplicated by the linker within the linked image. Across linked image 164// boundaries, such types are thus considered different types. 165 166// This value can be overriden in the __config_site. When it's not overriden, 167// we pick a default implementation based on the platform here. 168# ifndef _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION 169 170// Windows and AIX binaries can't merge typeinfos, so use the NonUnique implementation. 171# if defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF) 172# define _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION 2 173 174// On arm64 on Apple platforms, use the special NonUniqueARMRTTIBit implementation. 175# elif defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__) 176# define _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION 3 177 178// On all other platforms, assume the Itanium C++ ABI and use the Unique implementation. 179# else 180# define _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION 1 181# endif 182# endif 183 184struct __type_info_implementations { 185 struct __string_impl_base { 186 typedef const char* __type_name_t; 187 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR static const char* 188 __type_name_to_string(__type_name_t __v) _NOEXCEPT { 189 return __v; 190 } 191 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR static __type_name_t 192 __string_to_type_name(const char* __v) _NOEXCEPT { 193 return __v; 194 } 195 }; 196 197 struct __unique_impl : __string_impl_base { 198 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __v) _NOEXCEPT { 199 return reinterpret_cast<size_t>(__v); 200 } 201 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { 202 return __lhs == __rhs; 203 } 204 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { 205 return __lhs < __rhs; 206 } 207 }; 208 209 struct __non_unique_impl : __string_impl_base { 210 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __ptr) _NOEXCEPT { 211 size_t __hash = 5381; 212 while (unsigned char __c = static_cast<unsigned char>(*__ptr++)) 213 __hash = (__hash * 33) ^ __c; 214 return __hash; 215 } 216 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { 217 return __lhs == __rhs || __builtin_strcmp(__lhs, __rhs) == 0; 218 } 219 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { 220 return __builtin_strcmp(__lhs, __rhs) < 0; 221 } 222 }; 223 224 struct __non_unique_arm_rtti_bit_impl { 225 typedef uintptr_t __type_name_t; 226 227 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static const char* __type_name_to_string(__type_name_t __v) _NOEXCEPT { 228 return reinterpret_cast<const char*>(__v & ~__non_unique_rtti_bit::value); 229 } 230 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static __type_name_t __string_to_type_name(const char* __v) _NOEXCEPT { 231 return reinterpret_cast<__type_name_t>(__v); 232 } 233 234 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __v) _NOEXCEPT { 235 if (__is_type_name_unique(__v)) 236 return __v; 237 return __non_unique_impl::__hash(__type_name_to_string(__v)); 238 } 239 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { 240 if (__lhs == __rhs) 241 return true; 242 if (__is_type_name_unique(__lhs) || __is_type_name_unique(__rhs)) 243 // Either both are unique and have a different address, or one of them 244 // is unique and the other one isn't. In both cases they are unequal. 245 return false; 246 return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) == 0; 247 } 248 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { 249 if (__is_type_name_unique(__lhs) || __is_type_name_unique(__rhs)) 250 return __lhs < __rhs; 251 return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) < 0; 252 } 253 254 private: 255 // The unique bit is the top bit. It is expected that __type_name_t is 64 bits when 256 // this implementation is actually used. 257 typedef integral_constant<__type_name_t, (1ULL << ((__CHAR_BIT__ * sizeof(__type_name_t)) - 1))> 258 __non_unique_rtti_bit; 259 260 _LIBCPP_HIDE_FROM_ABI static bool __is_type_name_unique(__type_name_t __lhs) _NOEXCEPT { 261 return !(__lhs & __non_unique_rtti_bit::value); 262 } 263 }; 264 265 typedef 266# if _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 1 267 __unique_impl 268# elif _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 2 269 __non_unique_impl 270# elif _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 3 271 __non_unique_arm_rtti_bit_impl 272# else 273# error invalid configuration for _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION 274# endif 275 __impl; 276}; 277 278# if __has_cpp_attribute(_Clang::__ptrauth_vtable_pointer__) 279# if __has_feature(ptrauth_type_info_vtable_pointer_discrimination) 280# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \ 281 [[_Clang::__ptrauth_vtable_pointer__(process_independent, address_discrimination, type_discrimination)]] 282# else 283# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \ 284 [[_Clang::__ptrauth_vtable_pointer__( \ 285 process_independent, no_address_discrimination, no_extra_discrimination)]] 286# endif 287# else 288# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH 289# endif 290 291class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info { 292 type_info& operator=(const type_info&); 293 type_info(const type_info&); 294 295protected: 296 typedef __type_info_implementations::__impl __impl; 297 298 __impl::__type_name_t __type_name; 299 300 _LIBCPP_HIDE_FROM_ABI explicit type_info(const char* __n) : __type_name(__impl::__string_to_type_name(__n)) {} 301 302public: 303 virtual ~type_info(); 304 305 _LIBCPP_HIDE_FROM_ABI const char* name() const _NOEXCEPT { return __impl::__type_name_to_string(__type_name); } 306 307 _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT { 308 return __impl::__lt(__type_name, __arg.__type_name); 309 } 310 311 _LIBCPP_HIDE_FROM_ABI size_t hash_code() const _NOEXCEPT { return __impl::__hash(__type_name); } 312 313 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT { 314 // When evaluated in a constant expression, both type infos simply can't come 315 // from different translation units, so it is sufficient to compare their addresses. 316 if (__libcpp_is_constant_evaluated()) { 317 return this == &__arg; 318 } 319 return __impl::__eq(__type_name, __arg.__type_name); 320 } 321 322# if _LIBCPP_STD_VER <= 17 323 _LIBCPP_HIDE_FROM_ABI bool operator!=(const type_info& __arg) const _NOEXCEPT { return !operator==(__arg); } 324# endif 325}; 326# endif // defined(_LIBCPP_ABI_MICROSOFT) 327 328class _LIBCPP_EXPORTED_FROM_ABI bad_cast : public exception { 329public: 330 bad_cast() _NOEXCEPT; 331 _LIBCPP_HIDE_FROM_ABI bad_cast(const bad_cast&) _NOEXCEPT = default; 332 _LIBCPP_HIDE_FROM_ABI bad_cast& operator=(const bad_cast&) _NOEXCEPT = default; 333 ~bad_cast() _NOEXCEPT override; 334 const char* what() const _NOEXCEPT override; 335}; 336 337class _LIBCPP_EXPORTED_FROM_ABI bad_typeid : public exception { 338public: 339 bad_typeid() _NOEXCEPT; 340 _LIBCPP_HIDE_FROM_ABI bad_typeid(const bad_typeid&) _NOEXCEPT = default; 341 _LIBCPP_HIDE_FROM_ABI bad_typeid& operator=(const bad_typeid&) _NOEXCEPT = default; 342 ~bad_typeid() _NOEXCEPT override; 343 const char* what() const _NOEXCEPT override; 344}; 345 346} // namespace std 347 348#endif // defined(_LIBCPP_ABI_VCRUNTIME) 349 350#if defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0 351 352namespace std { 353 354class bad_cast : public exception { 355public: 356 bad_cast() _NOEXCEPT : exception("bad cast") {} 357 358private: 359 bad_cast(const char* const __message) _NOEXCEPT : exception(__message) {} 360}; 361 362class bad_typeid : public exception { 363public: 364 bad_typeid() _NOEXCEPT : exception("bad typeid") {} 365 366private: 367 bad_typeid(const char* const __message) _NOEXCEPT : exception(__message) {} 368}; 369 370} // namespace std 371 372#endif // defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0 373 374_LIBCPP_BEGIN_NAMESPACE_STD 375_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_cast() { 376#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 377 throw bad_cast(); 378#else 379 _LIBCPP_VERBOSE_ABORT("bad_cast was thrown in -fno-exceptions mode"); 380#endif 381} 382_LIBCPP_END_NAMESPACE_STD 383 384#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 385# include <cstdlib> 386# include <type_traits> 387#endif 388 389#endif // _LIBCPP_TYPEINFO 390