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