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 75#if defined(_LIBCPP_NONUNIQUE_RTTI_BIT) && !defined(_LIBCPP_ABI_MICROSOFT) 76# define _LIBCPP_HAS_NONUNIQUE_TYPEINFO 77#endif 78 79namespace std // purposefully not using versioning namespace 80{ 81 82#if defined(_LIBCPP_ABI_MICROSOFT) 83 84class _LIBCPP_EXCEPTION_ABI type_info 85{ 86 type_info& operator=(const type_info&); 87 type_info(const type_info&); 88 89 mutable struct { 90 const char *__undecorated_name; 91 const char __decorated_name[1]; 92 } __data; 93 94 int __compare(const type_info &__rhs) const _NOEXCEPT; 95 96public: 97 _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE 98 virtual ~type_info(); 99 100 const char *name() const _NOEXCEPT; 101 102 _LIBCPP_INLINE_VISIBILITY 103 bool before(const type_info& __arg) const _NOEXCEPT { 104 return __compare(__arg) < 0; 105 } 106 107 size_t hash_code() const _NOEXCEPT; 108 109 _LIBCPP_INLINE_VISIBILITY 110 bool operator==(const type_info& __arg) const _NOEXCEPT { 111 return __compare(__arg) == 0; 112 } 113 114 _LIBCPP_INLINE_VISIBILITY 115 bool operator!=(const type_info& __arg) const _NOEXCEPT 116 { return !operator==(__arg); } 117}; 118 119#elif defined(_LIBCPP_HAS_NONUNIQUE_TYPEINFO) 120 121// This implementation of type_info does not assume always a unique copy of 122// the RTTI for a given type inside a program. It packs the pointer to the 123// type name into a uintptr_t and reserves the high bit of that pointer (which 124// is assumed to be free for use under the ABI in use) to represent whether 125// that specific copy of the RTTI can be assumed unique inside the program. 126// To implement equality-comparison of type_infos, we check whether BOTH 127// type_infos are guaranteed unique, and if so, we simply compare the addresses 128// of their type names instead of doing a deep string comparison, which is 129// faster. If at least one of the type_infos can't guarantee uniqueness, we 130// have no choice but to fall back to a deep string comparison. 131// 132// Note that the compiler is the one setting (or unsetting) the high bit of 133// the pointer when it constructs the type_info, depending on whether it can 134// guarantee uniqueness for that specific type_info. 135class _LIBCPP_EXCEPTION_ABI type_info 136{ 137 type_info& operator=(const type_info&); 138 type_info(const type_info&); 139 140 _LIBCPP_INLINE_VISIBILITY 141 int __compare_nonunique_names(const type_info &__arg) const _NOEXCEPT 142 { return __builtin_strcmp(name(), __arg.name()); } 143 144protected: 145 uintptr_t __type_name; 146 147 _LIBCPP_INLINE_VISIBILITY 148 explicit type_info(const char* __n) 149 : __type_name(reinterpret_cast<uintptr_t>(__n)) {} 150 151public: 152 _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE 153 virtual ~type_info(); 154 155 _LIBCPP_INLINE_VISIBILITY 156 const char* name() const _NOEXCEPT 157 { 158 return reinterpret_cast<const char*>(__type_name & 159 ~_LIBCPP_NONUNIQUE_RTTI_BIT); 160 } 161 162 _LIBCPP_INLINE_VISIBILITY 163 bool before(const type_info& __arg) const _NOEXCEPT 164 { 165 if (!((__type_name & __arg.__type_name) & _LIBCPP_NONUNIQUE_RTTI_BIT)) 166 return __type_name < __arg.__type_name; 167 return __compare_nonunique_names(__arg) < 0; 168 } 169 170 _LIBCPP_INLINE_VISIBILITY 171 size_t hash_code() const _NOEXCEPT 172 { 173 if (!(__type_name & _LIBCPP_NONUNIQUE_RTTI_BIT)) 174 return __type_name; 175 176 const char* __ptr = name(); 177 size_t __hash = 5381; 178 while (unsigned char __c = static_cast<unsigned char>(*__ptr++)) 179 __hash = (__hash * 33) ^ __c; 180 return __hash; 181 } 182 183 _LIBCPP_INLINE_VISIBILITY 184 bool operator==(const type_info& __arg) const _NOEXCEPT 185 { 186 if (__type_name == __arg.__type_name) 187 return true; 188 189 if (!((__type_name & __arg.__type_name) & _LIBCPP_NONUNIQUE_RTTI_BIT)) 190 return false; 191 return __compare_nonunique_names(__arg) == 0; 192 } 193 194 _LIBCPP_INLINE_VISIBILITY 195 bool operator!=(const type_info& __arg) const _NOEXCEPT 196 { return !operator==(__arg); } 197}; 198 199#else // !_LIBCPP_ABI_MICROSOFT && !_LIBCPP_HAS_NONUNIQUE_TYPEINFO 200 201// This implementation of type_info assumes a unique copy of the RTTI for a 202// given type inside a program. This is a valid assumption when abiding to 203// Itanium ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-components). 204// Under this assumption, we can always compare the addresses of the type names 205// to implement equality-comparison of type_infos instead of having to perform 206// a deep string comparison. 207class _LIBCPP_EXCEPTION_ABI type_info 208{ 209 type_info& operator=(const type_info&); 210 type_info(const type_info&); 211 212protected: 213 const char *__type_name; 214 215 _LIBCPP_INLINE_VISIBILITY 216 explicit type_info(const char* __n) : __type_name(__n) {} 217 218public: 219 _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE 220 virtual ~type_info(); 221 222 _LIBCPP_INLINE_VISIBILITY 223 const char* name() const _NOEXCEPT 224 { return __type_name; } 225 226 _LIBCPP_INLINE_VISIBILITY 227 bool before(const type_info& __arg) const _NOEXCEPT 228 { return __type_name < __arg.__type_name; } 229 230 _LIBCPP_INLINE_VISIBILITY 231 size_t hash_code() const _NOEXCEPT 232 { return reinterpret_cast<size_t>(__type_name); } 233 234 _LIBCPP_INLINE_VISIBILITY 235 bool operator==(const type_info& __arg) const _NOEXCEPT 236 { return __type_name == __arg.__type_name; } 237 238 _LIBCPP_INLINE_VISIBILITY 239 bool operator!=(const type_info& __arg) const _NOEXCEPT 240 { return !operator==(__arg); } 241}; 242 243#endif 244 245class _LIBCPP_EXCEPTION_ABI bad_cast 246 : public exception 247{ 248public: 249 bad_cast() _NOEXCEPT; 250 virtual ~bad_cast() _NOEXCEPT; 251 virtual const char* what() const _NOEXCEPT; 252}; 253 254class _LIBCPP_EXCEPTION_ABI bad_typeid 255 : public exception 256{ 257public: 258 bad_typeid() _NOEXCEPT; 259 virtual ~bad_typeid() _NOEXCEPT; 260 virtual const char* what() const _NOEXCEPT; 261}; 262 263} // std 264 265#endif // defined(_LIBCPP_ABI_VCRUNTIME) 266 267_LIBCPP_BEGIN_NAMESPACE_STD 268_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY 269void __throw_bad_cast() 270{ 271#ifndef _LIBCPP_NO_EXCEPTIONS 272 throw bad_cast(); 273#else 274 _VSTD::abort(); 275#endif 276} 277_LIBCPP_END_NAMESPACE_STD 278 279#endif // __LIBCPP_TYPEINFO 280