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#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
60# include <__cxx03/typeinfo>
61#else
62# include <__config>
63# include <__cstddef/size_t.h>
64# include <__exception/exception.h>
65# include <__type_traits/integral_constant.h>
66# include <__type_traits/is_constant_evaluated.h>
67# include <__verbose_abort>
68# include <cstdint>
69# include <version>
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# if defined(_LIBCPP_ABI_MICROSOFT)
83
84class _LIBCPP_EXPORTED_FROM_ABI type_info {
85 type_info& operator=(const type_info&);
86 type_info(const type_info&);
87
88 mutable struct {
89 const char* __undecorated_name;
90 const char __decorated_name[1];
91 } __data;
92
93 int __compare(const type_info& __rhs) const _NOEXCEPT;
94
95public:
96 virtual ~type_info();
97
98 [[__nodiscard__]] const char* name() const _NOEXCEPT;
99
100 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT {
101 return __compare(__arg) < 0;
102 }
103
104 [[__nodiscard__]] size_t hash_code() const _NOEXCEPT;
105
106 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT {
107 // When evaluated in a constant expression, both type infos simply can't come
108 // from different translation units, so it is sufficient to compare their addresses.
109 if (__libcpp_is_constant_evaluated()) {
110 return this == &__arg;
111 }
112 return __compare(__arg) == 0;
113 }
114
115# if _LIBCPP_STD_VER <= 17
116 _LIBCPP_HIDE_FROM_ABI bool operator!=(const type_info& __arg) const _NOEXCEPT { return !operator==(__arg); }
117# endif
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 and AIX binaries can't merge typeinfos, so use the NonUnique implementation.
178# if defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)
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
191namespace __type_info_implementations {
192struct __string_impl_base {
193 typedef const char* __type_name_t;
194 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR static const char*
195 __type_name_to_string(__type_name_t __v) _NOEXCEPT {
196 return __v;
197 }
198 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR static __type_name_t
199 __string_to_type_name(const char* __v) _NOEXCEPT {
200 return __v;
201 }
202};
203
204struct __unique_impl : __string_impl_base {
205 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __v) _NOEXCEPT {
206 return reinterpret_cast<size_t>(__v);
207 }
208 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
209 return __lhs == __rhs;
210 }
211 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
212 return __lhs < __rhs;
213 }
214};
215
216struct __non_unique_impl : __string_impl_base {
217 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __ptr) _NOEXCEPT {
218 size_t __hash = 5381;
219 while (unsigned char __c = static_cast<unsigned char>(*__ptr++))
220 __hash = (__hash * 33) ^ __c;
221 return __hash;
222 }
223 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
224 return __lhs == __rhs || __builtin_strcmp(__lhs, __rhs) == 0;
225 }
226 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
227 return __builtin_strcmp(__lhs, __rhs) < 0;
228 }
229};
230
231struct __non_unique_arm_rtti_bit_impl {
232 typedef uintptr_t __type_name_t;
233
234 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static const char* __type_name_to_string(__type_name_t __v) _NOEXCEPT {
235 return reinterpret_cast<const char*>(__v & ~__non_unique_rtti_bit::value);
236 }
237 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static __type_name_t __string_to_type_name(const char* __v) _NOEXCEPT {
238 return reinterpret_cast<__type_name_t>(__v);
239 }
240
241 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static size_t __hash(__type_name_t __v) _NOEXCEPT {
242 if (__is_type_name_unique(__v))
243 return __v;
244 return __non_unique_impl::__hash(__type_name_to_string(__v));
245 }
246 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
247 if (__lhs == __rhs)
248 return true;
249 if (__is_type_name_unique(__lhs) || __is_type_name_unique(__rhs))
250 // Either both are unique and have a different address, or one of them
251 // is unique and the other one isn't. In both cases they are unequal.
252 return false;
253 return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) == 0;
254 }
255 _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
256 if (__is_type_name_unique(__lhs) || __is_type_name_unique(__rhs))
257 return __lhs < __rhs;
258 return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) < 0;
259 }
260
261private:
262 // The unique bit is the top bit. It is expected that __type_name_t is 64 bits when
263 // this implementation is actually used.
264 typedef integral_constant<__type_name_t, (1ULL << ((__CHAR_BIT__ * sizeof(__type_name_t)) - 1))>
265 __non_unique_rtti_bit;
266
267 _LIBCPP_HIDE_FROM_ABI static bool __is_type_name_unique(__type_name_t __lhs) _NOEXCEPT {
268 return !(__lhs & __non_unique_rtti_bit::value);
269 }
270};
271
272typedef
273# if _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 1
274 __unique_impl
275# elif _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 2
276 __non_unique_impl
277# elif _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION == 3
278 __non_unique_arm_rtti_bit_impl
279# else
280# error invalid configuration for _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION
281# endif
282 __impl;
283} // namespace __type_info_implementations
284
285# if __has_cpp_attribute(_Clang::__ptrauth_vtable_pointer__)
286# if __has_feature(ptrauth_type_info_vtable_pointer_discrimination)
287# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \
288 [[_Clang::__ptrauth_vtable_pointer__(process_independent, address_discrimination, type_discrimination)]]
289# else
290# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \
291 [[_Clang::__ptrauth_vtable_pointer__( \
292 process_independent, no_address_discrimination, no_extra_discrimination)]]
293# endif
294# else
295# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH
296# endif
297
298class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info {
299 type_info& operator=(const type_info&);
300 type_info(const type_info&);
301
302protected:
303 typedef __type_info_implementations::__impl __impl;
304
305 __impl::__type_name_t __type_name;
306
307 _LIBCPP_HIDE_FROM_ABI explicit type_info(const char* __n) : __type_name(__impl::__string_to_type_name(__n)) {}
308
309public:
310 virtual ~type_info();
311 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const char* name() const _NOEXCEPT {
312 return __impl::__type_name_to_string(__type_name);
313 }
314
315 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT {
316 return __impl::__lt(__type_name, __arg.__type_name);
317 }
318
319 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t hash_code() const _NOEXCEPT { return __impl::__hash(__type_name); }
320
321 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT {
322 // When evaluated in a constant expression, both type infos simply can't come
323 // from different translation units, so it is sufficient to compare their addresses.
324 if (__libcpp_is_constant_evaluated()) {
325 return this == &__arg;
326 }
327 return __impl::__eq(__type_name, __arg.__type_name);
328 }
329
330# if _LIBCPP_STD_VER <= 17
331 _LIBCPP_HIDE_FROM_ABI bool operator!=(const type_info& __arg) const _NOEXCEPT { return !operator==(__arg); }
332# endif
333};
334# endif // defined(_LIBCPP_ABI_MICROSOFT)
335
336class _LIBCPP_EXPORTED_FROM_ABI bad_cast : public exception {
337public:
338 bad_cast() _NOEXCEPT;
339 _LIBCPP_HIDE_FROM_ABI bad_cast(const bad_cast&) _NOEXCEPT = default;
340 _LIBCPP_HIDE_FROM_ABI bad_cast& operator=(const bad_cast&) _NOEXCEPT = default;
341 ~bad_cast() _NOEXCEPT override;
342 [[__nodiscard__]] const char* what() const _NOEXCEPT override;
343};
344
345class _LIBCPP_EXPORTED_FROM_ABI bad_typeid : public exception {
346public:
347 bad_typeid() _NOEXCEPT;
348 _LIBCPP_HIDE_FROM_ABI bad_typeid(const bad_typeid&) _NOEXCEPT = default;
349 _LIBCPP_HIDE_FROM_ABI bad_typeid& operator=(const bad_typeid&) _NOEXCEPT = default;
350 ~bad_typeid() _NOEXCEPT override;
351 [[__nodiscard__]] const char* what() const _NOEXCEPT override;
352};
353
354} // namespace std
355
356# endif // defined(_LIBCPP_ABI_VCRUNTIME)
357
358# if defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0
359
360_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
361
362class bad_cast : public exception {
363public:
364 bad_cast() _NOEXCEPT : exception("bad cast") {}
365
366private:
367 bad_cast(const char* const __message) _NOEXCEPT : exception(__message) {}
368};
369
370class bad_typeid : public exception {
371public:
372 bad_typeid() _NOEXCEPT : exception("bad typeid") {}
373
374private:
375 bad_typeid(const char* const __message) _NOEXCEPT : exception(__message) {}
376};
377
378_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
379
380# endif // defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0
381
382_LIBCPP_BEGIN_NAMESPACE_STD
383[[__noreturn__]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_cast() {
384# if _LIBCPP_HAS_EXCEPTIONS
385 throw bad_cast();
386# else
387 _LIBCPP_VERBOSE_ABORT("bad_cast was thrown in -fno-exceptions mode");
388# endif
389}
390_LIBCPP_END_NAMESPACE_STD
391
392# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
393# include <cstddef>
394# include <cstdlib>
395# include <type_traits>
396# endif
397#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
398
399#endif // _LIBCPP_TYPEINFO