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