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