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