Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/include/typeinfo
Line
Count
Source (jump to first uncovered line)
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
#include <type_traits>
64
#ifdef _LIBCPP_NO_EXCEPTIONS
65
#include <cstdlib>
66
#endif
67
68
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
69
#pragma GCC system_header
70
#endif
71
72
#if defined(_LIBCPP_ABI_VCRUNTIME)
73
#include <vcruntime_typeinfo.h>
74
#else
75
76
namespace std  // purposefully not using versioning namespace
77
{
78
79
80
#if defined(_LIBCPP_ABI_MICROSOFT)
81
82
class _LIBCPP_EXCEPTION_ABI type_info
83
{
84
    type_info& operator=(const type_info&);
85
    type_info(const type_info&);
86
87
    mutable struct {
88
      const char *__undecorated_name;
89
      const char __decorated_name[1];
90
    } __data;
91
92
    int __compare(const type_info &__rhs) const _NOEXCEPT;
93
94
public:
95
    _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
96
    virtual ~type_info();
97
98
    const char *name() const _NOEXCEPT;
99
100
    _LIBCPP_INLINE_VISIBILITY
101
    bool before(const type_info& __arg) const _NOEXCEPT {
102
      return __compare(__arg) < 0;
103
    }
104
105
    size_t hash_code() const _NOEXCEPT;
106
107
    _LIBCPP_INLINE_VISIBILITY
108
    bool operator==(const type_info& __arg) const _NOEXCEPT {
109
      return __compare(__arg) == 0;
110
    }
111
112
    _LIBCPP_INLINE_VISIBILITY
113
    bool operator!=(const type_info& __arg) const _NOEXCEPT
114
    { return !operator==(__arg); }
115
};
116
117
#else // !defined(_LIBCPP_ABI_MICROSOFT)
118
119
// ========================================================================== //
120
//                           Implementations
121
// ========================================================================== //
122
// ------------------------------------------------------------------------- //
123
//                               Unique
124
// ------------------------------------------------------------------------- //
125
// This implementation of type_info assumes a unique copy of the RTTI for a
126
// given type inside a program. This is a valid assumption when abiding to
127
// Itanium ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-components).
128
// Under this assumption, we can always compare the addresses of the type names
129
// to implement equality-comparison of type_infos instead of having to perform
130
// a deep string comparison.
131
// -------------------------------------------------------------------------- //
132
//                             NonUnique
133
// -------------------------------------------------------------------------- //
134
// This implementation of type_info does not assume there is always a unique
135
// copy of the RTTI for a given type inside a program. For various reasons
136
// the linker may have failed to merge every copy of a types RTTI
137
// (For example: -Bsymbolic or llvm.org/PR37398). Under this assumption, two
138
// type_infos are equal if their addresses are equal or if a deep string
139
// comparison is equal.
140
// -------------------------------------------------------------------------- //
141
//                          NonUniqueARMRTTIBit
142
// -------------------------------------------------------------------------- //
143
// This implementation of type_info does not assume always a unique copy of
144
// the RTTI for a given type inside a program. It packs the pointer to the
145
// type name into a uintptr_t and reserves the high bit of that pointer (which
146
// is assumed to be free for use under the ABI in use) to represent whether
147
// that specific copy of the RTTI can be assumed unique inside the program.
148
// To implement equality-comparison of type_infos, we check whether BOTH
149
// type_infos are guaranteed unique, and if so, we simply compare the addresses
150
// of their type names instead of doing a deep string comparison, which is
151
// faster. If at least one of the type_infos can't guarantee uniqueness, we
152
// have no choice but to fall back to a deep string comparison.
153
//
154
// This implementation is specific to ARM64 on Apple platforms.
155
//
156
// Note that the compiler is the one setting (or unsetting) the high bit of
157
// the pointer when it constructs the type_info, depending on whether it can
158
// guarantee uniqueness for that specific type_info.
159
160
struct __type_info_implementations {
161
  struct __string_impl_base {
162
    typedef const char* __type_name_t;
163
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
164
0
    _LIBCPP_CONSTEXPR static const char* __type_name_to_string(__type_name_t __v) _NOEXCEPT {
165
0
      return __v;
166
0
    }
167
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
168
0
    _LIBCPP_CONSTEXPR static __type_name_t __string_to_type_name(const char* __v) _NOEXCEPT {
169
0
      return __v;
170
0
    }
171
  };
172
173
  struct __unique_impl : __string_impl_base {
174
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
175
0
    static size_t __hash(__type_name_t __v) _NOEXCEPT {
176
0
      return reinterpret_cast<size_t>(__v);
177
0
    }
178
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
179
0
    static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
180
0
      return __lhs == __rhs;
181
0
    }
182
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
183
0
    static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
184
0
      return __lhs < __rhs;
185
0
    }
186
  };
187
188
  struct __non_unique_impl : __string_impl_base {
189
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
190
0
    static size_t __hash(__type_name_t __ptr) _NOEXCEPT {
191
0
      size_t __hash = 5381;
192
0
      while (unsigned char __c = static_cast<unsigned char>(*__ptr++))
193
0
        __hash = (__hash * 33) ^ __c;
194
0
      return __hash;
195
0
    }
196
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
197
0
    static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
198
0
      return __lhs == __rhs || __builtin_strcmp(__lhs, __rhs) == 0;
199
0
    }
200
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
201
0
    static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
202
0
      return __builtin_strcmp(__lhs, __rhs) < 0;
203
0
    }
204
  };
205
206
  struct __non_unique_arm_rtti_bit_impl {
207
    typedef uintptr_t __type_name_t;
208
209
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
210
0
    static const char* __type_name_to_string(__type_name_t __v) _NOEXCEPT {
211
0
      return reinterpret_cast<const char*>(__v &
212
0
          ~__non_unique_rtti_bit::value);
213
0
    }
214
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
215
0
    static __type_name_t __string_to_type_name(const char* __v) _NOEXCEPT {
216
0
      return reinterpret_cast<__type_name_t>(__v);
217
0
    }
218
219
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
220
0
    static size_t __hash(__type_name_t __v) _NOEXCEPT {
221
0
      if (__is_type_name_unique(__v))
222
0
        return reinterpret_cast<size_t>(__v);
223
0
      return __non_unique_impl::__hash(__type_name_to_string(__v));
224
0
    }
225
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
226
0
    static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
227
0
      if (__lhs == __rhs)
228
0
        return true;
229
0
      if (__is_type_name_unique(__lhs, __rhs))
230
0
        return false;
231
0
      return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) == 0;
232
0
    }
233
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
234
0
    static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
235
0
      if (__is_type_name_unique(__lhs, __rhs))
236
0
        return __lhs < __rhs;
237
0
      return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) < 0;
238
0
    }
239
240
   private:
241
    // The unique bit is the top bit. It is expected that __type_name_t is 64 bits when
242
    // this implementation is actually used.
243
    typedef std::integral_constant<__type_name_t,
244
      (1ULL << ((__CHAR_BIT__ * sizeof(__type_name_t)) - 1))> __non_unique_rtti_bit;
245
246
    _LIBCPP_INLINE_VISIBILITY
247
0
    static bool __is_type_name_unique(__type_name_t __lhs) _NOEXCEPT {
248
0
      return !(__lhs & __non_unique_rtti_bit::value);
249
0
    }
250
    _LIBCPP_INLINE_VISIBILITY
251
0
    static bool __is_type_name_unique(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
252
0
      return !((__lhs & __rhs) & __non_unique_rtti_bit::value);
253
0
    }
254
  };
255
256
  typedef
257
#if defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__)
258
    __non_unique_arm_rtti_bit_impl
259
#elif _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT == 0
260
    __non_unique_impl
261
#elif _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT == 1
262
    __unique_impl
263
#else
264
#   error invalid configuration for _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT
265
#endif
266
     __impl;
267
};
268
269
class _LIBCPP_EXCEPTION_ABI type_info
270
{
271
  type_info& operator=(const type_info&);
272
  type_info(const type_info&);
273
274
 protected:
275
    typedef __type_info_implementations::__impl __impl;
276
277
    __impl::__type_name_t __type_name;
278
279
    _LIBCPP_INLINE_VISIBILITY
280
    explicit type_info(const char* __n)
281
0
      : __type_name(__impl::__string_to_type_name(__n)) {}
282
283
public:
284
    _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
285
    virtual ~type_info();
286
287
    _LIBCPP_INLINE_VISIBILITY
288
    const char* name() const _NOEXCEPT
289
0
    {
290
0
      return __impl::__type_name_to_string(__type_name);
291
0
    }
292
293
    _LIBCPP_INLINE_VISIBILITY
294
    bool before(const type_info& __arg) const _NOEXCEPT
295
0
    {
296
0
      return __impl::__lt(__type_name, __arg.__type_name);
297
0
    }
298
299
    _LIBCPP_INLINE_VISIBILITY
300
    size_t hash_code() const _NOEXCEPT
301
0
    {
302
0
      return __impl::__hash(__type_name);
303
0
    }
304
305
    _LIBCPP_INLINE_VISIBILITY
306
    bool operator==(const type_info& __arg) const _NOEXCEPT
307
0
    {
308
0
      return __impl::__eq(__type_name, __arg.__type_name);
309
0
    }
310
311
    _LIBCPP_INLINE_VISIBILITY
312
    bool operator!=(const type_info& __arg) const _NOEXCEPT
313
0
    { return !operator==(__arg); }
314
};
315
#endif // defined(_LIBCPP_ABI_MICROSOFT)
316
317
class _LIBCPP_EXCEPTION_ABI bad_cast
318
    : public exception
319
{
320
 public:
321
  bad_cast() _NOEXCEPT;
322
  virtual ~bad_cast() _NOEXCEPT;
323
  virtual const char* what() const _NOEXCEPT;
324
};
325
326
class _LIBCPP_EXCEPTION_ABI bad_typeid
327
    : public exception
328
{
329
 public:
330
  bad_typeid() _NOEXCEPT;
331
  virtual ~bad_typeid() _NOEXCEPT;
332
  virtual const char* what() const _NOEXCEPT;
333
};
334
335
}  // std
336
337
#endif // defined(_LIBCPP_ABI_VCRUNTIME)
338
339
_LIBCPP_BEGIN_NAMESPACE_STD
340
_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
341
void __throw_bad_cast()
342
0
{
343
0
#ifndef _LIBCPP_NO_EXCEPTIONS
344
0
    throw bad_cast();
345
#else
346
    _VSTD::abort();
347
#endif
348
}
349
_LIBCPP_END_NAMESPACE_STD
350
351
#endif  // __LIBCPP_TYPEINFO