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 | |
17 | namespace std { |
18 | |
19 | class type_info |
20 | { |
21 | public: |
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 | |
35 | class bad_cast |
36 | : public exception |
37 | { |
38 | public: |
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 | |
45 | class bad_typeid |
46 | : public exception |
47 | { |
48 | public: |
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 | namespace std // purposefully not using versioning namespace |
76 | { |
77 | |
78 | |
79 | #if defined(_LIBCPP_ABI_MICROSOFT) |
80 | |
81 | class _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 | |
93 | public: |
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 | |
159 | struct __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 | |
268 | class _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 | |
282 | public: |
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 | |
316 | class _LIBCPP_EXCEPTION_ABI bad_cast |
317 | : public exception |
318 | { |
319 | public: |
320 | bad_cast() _NOEXCEPT; |
321 | virtual ~bad_cast() _NOEXCEPT; |
322 | virtual const char* what() const _NOEXCEPT; |
323 | }; |
324 | |
325 | class _LIBCPP_EXCEPTION_ABI bad_typeid |
326 | : public exception |
327 | { |
328 | public: |
329 | bad_typeid() _NOEXCEPT; |
330 | virtual ~bad_typeid() _NOEXCEPT; |
331 | virtual const char* what() const _NOEXCEPT; |
332 | }; |
333 | |
334 | } // std |
335 | |
336 | #endif // defined(_LIBCPP_ABI_VCRUNTIME) |
337 | |
338 | _LIBCPP_BEGIN_NAMESPACE_STD |
339 | _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY |
340 | void __throw_bad_cast() |
341 | { |
342 | #ifndef _LIBCPP_NO_EXCEPTIONS |
343 | throw bad_cast(); |
344 | #else |
345 | _VSTD::abort(); |
346 | #endif |
347 | } |
348 | _LIBCPP_END_NAMESPACE_STD |
349 | |
350 | #endif // __LIBCPP_TYPEINFO |
351 | |