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