@@ -72,13 +72,10 @@ public:
72
72
#include < vcruntime_typeinfo.h>
73
73
#else
74
74
75
- #if defined(_LIBCPP_NONUNIQUE_RTTI_BIT) && !defined(_LIBCPP_ABI_MICROSOFT)
76
- # define _LIBCPP_HAS_NONUNIQUE_TYPEINFO
77
- #endif
78
-
79
75
namespace std // purposefully not using versioning namespace
80
76
{
81
77
78
+
82
79
#if defined(_LIBCPP_ABI_MICROSOFT)
83
80
84
81
class _LIBCPP_EXCEPTION_ABI type_info
@@ -116,8 +113,32 @@ public:
116
113
{ return !operator ==(__arg); }
117
114
};
118
115
119
- #elif defined(_LIBCPP_HAS_NONUNIQUE_TYPEINFO )
116
+ #else // ! defined(_LIBCPP_ABI_MICROSOFT )
120
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
+ // -------------------------------------------------------------------------- //
121
142
// This implementation of type_info does not assume always a unique copy of
122
143
// the RTTI for a given type inside a program. It packs the pointer to the
123
144
// type name into a uintptr_t and reserves the high bit of that pointer (which
@@ -129,135 +150,182 @@ public:
129
150
// faster. If at least one of the type_infos can't guarantee uniqueness, we
130
151
// have no choice but to fall back to a deep string comparison.
131
152
//
153
+ // This implementation is specific to ARM64 on Apple platforms.
154
+ //
132
155
// Note that the compiler is the one setting (or unsetting) the high bit of
133
156
// the pointer when it constructs the type_info, depending on whether it can
134
157
// guarantee uniqueness for that specific type_info.
135
- class _LIBCPP_EXCEPTION_ABI type_info
136
- {
137
- type_info& operator =(const type_info&);
138
- type_info (const type_info&);
139
-
140
- _LIBCPP_INLINE_VISIBILITY
141
- int __compare_nonunique_names (const type_info &__arg) const _NOEXCEPT
142
- { return __builtin_strcmp (name (), __arg.name ()); }
143
-
144
- protected:
145
- uintptr_t __type_name;
146
-
147
- _LIBCPP_INLINE_VISIBILITY
148
- explicit type_info (const char * __n)
149
- : __type_name(reinterpret_cast <uintptr_t >(__n)) {}
150
158
151
- public:
152
- _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
153
- virtual ~type_info ();
154
-
155
- _LIBCPP_INLINE_VISIBILITY
156
- const char * name () const _NOEXCEPT
157
- {
158
- return reinterpret_cast <const char *>(__type_name &
159
- ~_LIBCPP_NONUNIQUE_RTTI_BIT);
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;
160
165
}
161
-
162
- _LIBCPP_INLINE_VISIBILITY
163
- bool before (const type_info& __arg) const _NOEXCEPT
164
- {
165
- if (!((__type_name & __arg.__type_name ) & _LIBCPP_NONUNIQUE_RTTI_BIT))
166
- return __type_name < __arg.__type_name ;
167
- return __compare_nonunique_names (__arg) < 0 ;
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;
168
169
}
170
+ };
169
171
170
- _LIBCPP_INLINE_VISIBILITY
171
- size_t hash_code () const _NOEXCEPT
172
- {
173
- if (!(__type_name & _LIBCPP_NONUNIQUE_RTTI_BIT))
174
- return __type_name;
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
+ };
175
186
176
- const char * __ptr = name ();
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 {
177
190
size_t __hash = 5381 ;
178
191
while (unsigned char __c = static_cast <unsigned char >(*__ptr++))
179
192
__hash = (__hash * 33 ) ^ __c;
180
193
return __hash;
181
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
+ };
182
204
183
- _LIBCPP_INLINE_VISIBILITY
184
- bool operator ==(const type_info& __arg) const _NOEXCEPT
185
- {
186
- if (__type_name == __arg.__type_name )
187
- return true ;
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
+ }
188
217
189
- if (!((__type_name & __arg.__type_name ) & _LIBCPP_NONUNIQUE_RTTI_BIT))
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))
190
229
return false ;
191
- return __compare_nonunique_names (__arg ) == 0 ;
230
+ return __builtin_strcmp ( __type_name_to_string (__lhs), __type_name_to_string (__rhs) ) == 0 ;
192
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
+ typedef std::integral_constant<__type_name_t , (1ULL << 63 )> __non_unique_rtti_bit;
193
241
194
242
_LIBCPP_INLINE_VISIBILITY
195
- bool operator !=(const type_info& __arg) const _NOEXCEPT
196
- { return !operator ==(__arg); }
243
+ static bool __is_type_name_unique (__type_name_t __lhs) _NOEXCEPT {
244
+ return !(__lhs & __non_unique_rtti_bit::value);
245
+ }
246
+ _LIBCPP_INLINE_VISIBILITY
247
+ static bool __is_type_name_unique (__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT {
248
+ return !((__lhs & __rhs) & __non_unique_rtti_bit::value);
249
+ }
250
+ };
251
+
252
+ typedef
253
+ #if defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__)
254
+ __non_unique_arm_rtti_bit_impl
255
+ #elif _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT == 0
256
+ __non_unique_impl
257
+ #elif _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT == 1
258
+ __unique_impl
259
+ #else
260
+ # error invalid configuration for _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT
261
+ #endif
262
+ __impl;
197
263
};
198
264
199
- #else // !_LIBCPP_ABI_MICROSOFT && !_LIBCPP_HAS_NONUNIQUE_TYPEINFO
200
-
201
- // This implementation of type_info assumes a unique copy of the RTTI for a
202
- // given type inside a program. This is a valid assumption when abiding to
203
- // Itanium ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-components).
204
- // Under this assumption, we can always compare the addresses of the type names
205
- // to implement equality-comparison of type_infos instead of having to perform
206
- // a deep string comparison.
207
265
class _LIBCPP_EXCEPTION_ABI type_info
208
266
{
209
- type_info& operator =(const type_info&);
210
- type_info (const type_info&);
267
+ type_info& operator =(const type_info&);
268
+ type_info (const type_info&);
269
+
270
+ protected:
271
+ typedef __type_info_implementations::__impl __impl;
211
272
212
- protected:
213
- const char *__type_name;
273
+ __impl::__type_name_t __type_name;
214
274
215
275
_LIBCPP_INLINE_VISIBILITY
216
- explicit type_info (const char * __n) : __type_name(__n) {}
276
+ explicit type_info (const char * __n)
277
+ : __type_name(__impl::__string_to_type_name(__n)) {}
217
278
218
279
public:
219
280
_LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
220
281
virtual ~type_info ();
221
282
222
283
_LIBCPP_INLINE_VISIBILITY
223
284
const char * name () const _NOEXCEPT
224
- { return __type_name; }
285
+ {
286
+ return __impl::__type_name_to_string (__type_name);
287
+ }
225
288
226
289
_LIBCPP_INLINE_VISIBILITY
227
290
bool before (const type_info& __arg) const _NOEXCEPT
228
- { return __type_name < __arg.__type_name ; }
291
+ {
292
+ return __impl::__lt (__type_name, __arg.__type_name );
293
+ }
229
294
230
295
_LIBCPP_INLINE_VISIBILITY
231
296
size_t hash_code () const _NOEXCEPT
232
- { return reinterpret_cast <size_t >(__type_name); }
297
+ {
298
+ return __impl::__hash (__type_name);
299
+ }
233
300
234
301
_LIBCPP_INLINE_VISIBILITY
235
302
bool operator ==(const type_info& __arg) const _NOEXCEPT
236
- { return __type_name == __arg.__type_name ; }
303
+ {
304
+ return __impl::__eq (__type_name, __arg.__type_name );
305
+ }
237
306
238
307
_LIBCPP_INLINE_VISIBILITY
239
308
bool operator !=(const type_info& __arg) const _NOEXCEPT
240
309
{ return !operator ==(__arg); }
241
310
};
242
-
243
- #endif
311
+ #endif // defined(_LIBCPP_ABI_MICROSOFT)
244
312
245
313
class _LIBCPP_EXCEPTION_ABI bad_cast
246
314
: public exception
247
315
{
248
- public:
249
- bad_cast () _NOEXCEPT;
250
- virtual ~bad_cast () _NOEXCEPT;
251
- virtual const char * what () const _NOEXCEPT;
316
+ public:
317
+ bad_cast () _NOEXCEPT;
318
+ virtual ~bad_cast () _NOEXCEPT;
319
+ virtual const char * what () const _NOEXCEPT;
252
320
};
253
321
254
322
class _LIBCPP_EXCEPTION_ABI bad_typeid
255
323
: public exception
256
324
{
257
- public:
258
- bad_typeid () _NOEXCEPT;
259
- virtual ~bad_typeid () _NOEXCEPT;
260
- virtual const char * what () const _NOEXCEPT;
325
+ public:
326
+ bad_typeid () _NOEXCEPT;
327
+ virtual ~bad_typeid () _NOEXCEPT;
328
+ virtual const char * what () const _NOEXCEPT;
261
329
};
262
330
263
331
} // std
0 commit comments