1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "private_typeinfo.h"
10
11// The flag _LIBCXXABI_FORGIVING_DYNAMIC_CAST is used to make dynamic_cast
12// more forgiving when type_info's mistakenly have hidden visibility and
13// thus multiple type_infos can exist for a single type.
14//
15// When _LIBCXXABI_FORGIVING_DYNAMIC_CAST is defined, and only in the case where
16// there is a detected inconsistency in the type_info hierarchy during a
17// dynamic_cast, then the equality operation will fall back to using strcmp
18// on type_info names to determine type_info equality.
19//
20// This change happens *only* under dynamic_cast, and only when
21// dynamic_cast is faced with the choice: abort, or possibly give back the
22// wrong answer. If when the dynamic_cast is done with this fallback
23// algorithm and an inconsistency is still detected, dynamic_cast will call
24// abort with an appropriate message.
25//
26// The current implementation of _LIBCXXABI_FORGIVING_DYNAMIC_CAST requires a
27// printf-like function called syslog:
28//
29// void syslog(int facility_priority, const char* format, ...);
30//
31// If you want this functionality but your platform doesn't have syslog,
32// just implement it in terms of fprintf(stderr, ...).
33//
34// _LIBCXXABI_FORGIVING_DYNAMIC_CAST is currently off by default.
35
36// On Windows, typeids are different between DLLs and EXEs, so comparing
37// type_info* will work for typeids from the same compiled file but fail
38// for typeids from a DLL and an executable. Among other things, exceptions
39// are not caught by handlers since can_catch() returns false.
40//
41// Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST does not help since can_catch() calls
42// is_equal() with use_strcmp=false so the string names are not compared.
43
44#include <cstdint>
45#include <cassert>
46#include <string.h>
47#include "abort_message.h"
48
49#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
50#include <sys/syslog.h>
51#include <atomic>
52#endif
53
54static inline
55bool
56is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
57{
58 // Use std::type_info's default comparison unless we've explicitly asked
59 // for strcmp.
60 if (!use_strcmp)
61 return *x == *y;
62 // Still allow pointer equality to short circut.
63 return x == y || strcmp(x->name(), y->name()) == 0;
64}
65
66static inline ptrdiff_t update_offset_to_base(const char* vtable,
67 ptrdiff_t offset_to_base) {
68#if __has_feature(cxx_abi_relative_vtable)
69 // VTable components are 32 bits in the relative vtables ABI.
70 return *reinterpret_cast<const int32_t*>(vtable + offset_to_base);
71#else
72 return *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
73#endif
74}
75
76namespace __cxxabiv1
77{
78
79namespace {
80
81struct derived_object_info {
82 const void* dynamic_ptr;
83 const __class_type_info* dynamic_type;
84 std::ptrdiff_t offset_to_derived;
85};
86
87/// A helper function that gets (dynamic_ptr, dynamic_type, offset_to_derived) from static_ptr.
88void dyn_cast_get_derived_info(derived_object_info* info, const void* static_ptr)
89{
90#if __has_feature(cxx_abi_relative_vtable)
91 // The vtable address will point to the first virtual function, which is 8
92 // bytes after the start of the vtable (4 for the offset from top + 4 for
93 // the typeinfo component).
94 const int32_t* vtable =
95 *reinterpret_cast<const int32_t* const*>(static_ptr);
96 info->offset_to_derived = static_cast<std::ptrdiff_t>(vtable[-2]);
97 info->dynamic_ptr = static_cast<const char*>(static_ptr) + info->offset_to_derived;
98
99 // The typeinfo component is now a relative offset to a proxy.
100 int32_t offset_to_ti_proxy = vtable[-1];
101 const uint8_t* ptr_to_ti_proxy =
102 reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
103 info->dynamic_type = *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
104#else
105 void **vtable = *static_cast<void ** const *>(static_ptr);
106 info->offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
107 info->dynamic_ptr = static_cast<const char*>(static_ptr) + info->offset_to_derived;
108 info->dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
109#endif
110}
111
112/// A helper function for __dynamic_cast that casts a base sub-object pointer
113/// to the object's dynamic type.
114///
115/// This function returns the casting result directly. No further processing
116/// required.
117///
118/// Specifically, this function can only be called if the following pre-
119/// condition holds:
120/// * The dynamic type of the object pointed to by `static_ptr` is exactly
121/// the same as `dst_type`.
122const void* dyn_cast_to_derived(const void* static_ptr,
123 const void* dynamic_ptr,
124 const __class_type_info* static_type,
125 const __class_type_info* dst_type,
126 std::ptrdiff_t offset_to_derived,
127 std::ptrdiff_t src2dst_offset)
128{
129 // We're downcasting from src_type to the complete object's dynamic type.
130 // This is a really hot path that can be further optimized with the
131 // `src2dst_offset` hint.
132 // In such a case, dynamic_ptr already gives the casting result if the
133 // casting ever succeeds. All we have to do now is to check static_ptr
134 // points to a public base sub-object of dynamic_ptr.
135
136 if (src2dst_offset >= 0)
137 {
138 // The static type is a unique public non-virtual base type of
139 // dst_type at offset `src2dst_offset` from the origin of dst.
140 // Note that there might be other non-public static_type bases. The
141 // hint only guarantees that the public base is non-virtual and
142 // unique. So we have to check whether static_ptr points to that
143 // unique public base sub-object.
144 if (offset_to_derived != -src2dst_offset)
145 return nullptr;
146 return dynamic_ptr;
147 }
148
149 if (src2dst_offset == -2)
150 {
151 // static_type is not a public base of dst_type.
152 return nullptr;
153 }
154
155 // If src2dst_offset == -3, then:
156 // src_type is a multiple public base type but never a virtual
157 // base type. We can't conclude that static_ptr points to those
158 // public base sub-objects because there might be other non-
159 // public static_type bases. The search is inevitable.
160
161 // Fallback to the slow path to check that static_type is a public
162 // base type of dynamic_type.
163 // Using giant short cut. Add that information to info.
164 __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0, 0, 0,
165 1, // number_of_dst_type
166 false, false, false, true, nullptr};
167 // Do the search
168 dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
169#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
170 // The following if should always be false because we should
171 // definitely find (static_ptr, static_type), either on a public
172 // or private path
173 if (info.path_dst_ptr_to_static_ptr == unknown)
174 {
175 // We get here only if there is some kind of visibility problem
176 // in client code.
177 static_assert(std::atomic<size_t>::is_always_lock_free, "");
178 static std::atomic<size_t> error_count(0);
179 size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
180 if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
181 syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
182 "should have public visibility. At least one of them is hidden. %s"
183 ", %s.\n", static_type->name(), dst_type->name());
184 // Redo the search comparing type_info's using strcmp
185 info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
186 0, 0, 0, false, false, false, true, nullptr};
187 info.number_of_dst_type = 1;
188 dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
189 }
190#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
191 // Query the search.
192 if (info.path_dst_ptr_to_static_ptr != public_path)
193 return nullptr;
194
195 return dynamic_ptr;
196}
197
198/// A helper function for __dynamic_cast that tries to perform a downcast
199/// before giving up and falling back to the slow path.
200const void* dyn_cast_try_downcast(const void* static_ptr,
201 const void* dynamic_ptr,
202 const __class_type_info* dst_type,
203 const __class_type_info* dynamic_type,
204 std::ptrdiff_t src2dst_offset)
205{
206 if (src2dst_offset < 0)
207 {
208 // We can only optimize the case if the static type is a unique public
209 // base of dst_type. Give up.
210 return nullptr;
211 }
212
213 // Pretend there is a dst_type object that leads to static_ptr. Later we
214 // will check whether this imagined dst_type object exists. If it exists
215 // then it will be the casting result.
216 const void* dst_ptr_to_static = reinterpret_cast<const char*>(static_ptr) - src2dst_offset;
217
218 if (reinterpret_cast<std::intptr_t>(dst_ptr_to_static) < reinterpret_cast<std::intptr_t>(dynamic_ptr))
219 {
220 // The imagined dst_type object does not exist. Bail-out quickly.
221 return nullptr;
222 }
223
224 // Try to search a path from dynamic_type to dst_type.
225 __dynamic_cast_info dynamic_to_dst_info = {dynamic_type,
226 dst_ptr_to_static,
227 dst_type,
228 src2dst_offset,
229 0,
230 0,
231 0,
232 0,
233 0,
234 0,
235 0,
236 0,
237 1, // number_of_dst_type
238 false,
239 false,
240 false,
241 true,
242 nullptr};
243 dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
244 if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
245 // We have found at least one path from dynamic_ptr to dst_ptr. The
246 // downcast can succeed.
247 return dst_ptr_to_static;
248 }
249
250 return nullptr;
251}
252
253const void* dyn_cast_slow(const void* static_ptr,
254 const void* dynamic_ptr,
255 const __class_type_info* static_type,
256 const __class_type_info* dst_type,
257 const __class_type_info* dynamic_type,
258 std::ptrdiff_t src2dst_offset)
259{
260 // Not using giant short cut. Do the search
261
262 // Initialize info struct for this search.
263 __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
264 0, 0, 0, false, false, false, true, nullptr};
265
266 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
267#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
268 // The following if should always be false because we should
269 // definitely find (static_ptr, static_type), either on a public
270 // or private path
271 if (info.path_dst_ptr_to_static_ptr == unknown &&
272 info.path_dynamic_ptr_to_static_ptr == unknown)
273 {
274 static_assert(std::atomic<size_t>::is_always_lock_free, "");
275 static std::atomic<size_t> error_count(0);
276 size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
277 if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
278 syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
279 "has hidden visibility or is defined in more than one translation "
280 "unit. They should all have public visibility. "
281 "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
282 dst_type->name());
283 // Redo the search comparing type_info's using strcmp
284 info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
285 0, 0, 0, false, false, false, true, nullptr};
286 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
287 }
288#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
289 // Query the search.
290 switch (info.number_to_static_ptr)
291 {
292 case 0:
293 if (info.number_to_dst_ptr == 1 &&
294 info.path_dynamic_ptr_to_static_ptr == public_path &&
295 info.path_dynamic_ptr_to_dst_ptr == public_path)
296 return info.dst_ptr_not_leading_to_static_ptr;
297 break;
298 case 1:
299 if (info.path_dst_ptr_to_static_ptr == public_path ||
300 (
301 info.number_to_dst_ptr == 0 &&
302 info.path_dynamic_ptr_to_static_ptr == public_path &&
303 info.path_dynamic_ptr_to_dst_ptr == public_path
304 )
305 )
306 return info.dst_ptr_leading_to_static_ptr;
307 break;
308 }
309
310 return nullptr;
311}
312
313} // namespace
314
315// __shim_type_info
316
317__shim_type_info::~__shim_type_info()
318{
319}
320
321void __shim_type_info::noop1() const {}
322void __shim_type_info::noop2() const {}
323
324// __fundamental_type_info
325
326// This miraculously (compiler magic) emits the type_info's for:
327// 1. all of the fundamental types
328// 2. pointers to all of the fundamental types
329// 3. pointers to all of the const fundamental types
330__fundamental_type_info::~__fundamental_type_info()
331{
332}
333
334// __array_type_info
335
336__array_type_info::~__array_type_info()
337{
338}
339
340// __function_type_info
341
342__function_type_info::~__function_type_info()
343{
344}
345
346// __enum_type_info
347
348__enum_type_info::~__enum_type_info()
349{
350}
351
352// __class_type_info
353
354__class_type_info::~__class_type_info()
355{
356}
357
358// __si_class_type_info
359
360__si_class_type_info::~__si_class_type_info()
361{
362}
363
364// __vmi_class_type_info
365
366__vmi_class_type_info::~__vmi_class_type_info()
367{
368}
369
370// __pbase_type_info
371
372__pbase_type_info::~__pbase_type_info()
373{
374}
375
376// __pointer_type_info
377
378__pointer_type_info::~__pointer_type_info()
379{
380}
381
382// __pointer_to_member_type_info
383
384__pointer_to_member_type_info::~__pointer_to_member_type_info()
385{
386}
387
388// can_catch
389
390// A handler is a match for an exception object of type E if
391// 1. The handler is of type cv T or cv T& and E and T are the same type
392// (ignoring the top-level cv-qualifiers), or
393// 2. the handler is of type cv T or cv T& and T is an unambiguous public
394// base class of E, or
395// 3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
396// converted to the type of the handler by either or both of
397// A. a standard pointer conversion (4.10) not involving conversions to
398// pointers to private or protected or ambiguous classes
399// B. a qualification conversion
400// 4. the handler is a pointer or pointer to member type and E is
401// std::nullptr_t.
402
403// adjustedPtr:
404//
405// catch (A& a) : adjustedPtr == &a
406// catch (A* a) : adjustedPtr == a
407// catch (A** a) : adjustedPtr == a
408//
409// catch (D2& d2) : adjustedPtr == &d2 (d2 is base class of thrown object)
410// catch (D2* d2) : adjustedPtr == d2
411// catch (D2*& d2) : adjustedPtr == d2
412//
413// catch (...) : adjustedPtr == & of the exception
414//
415// If the thrown type is nullptr_t and the caught type is a pointer to
416// member type, adjustedPtr points to a statically-allocated null pointer
417// representation of that type.
418
419// Handles bullet 1
420bool
421__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
422 void*&) const
423{
424 return is_equal(x: this, y: thrown_type, use_strcmp: false);
425}
426
427bool
428__array_type_info::can_catch(const __shim_type_info*, void*&) const
429{
430 // We can get here if someone tries to catch an array by reference.
431 // However if someone tries to throw an array, it immediately gets
432 // converted to a pointer, which will not convert back to an array
433 // at the catch clause. So this can never catch anything.
434 return false;
435}
436
437bool
438__function_type_info::can_catch(const __shim_type_info*, void*&) const
439{
440 // We can get here if someone tries to catch a function by reference.
441 // However if someone tries to throw a function, it immediately gets
442 // converted to a pointer, which will not convert back to a function
443 // at the catch clause. So this can never catch anything.
444 return false;
445}
446
447// Handles bullet 1
448bool
449__enum_type_info::can_catch(const __shim_type_info* thrown_type,
450 void*&) const
451{
452 return is_equal(x: this, y: thrown_type, use_strcmp: false);
453}
454
455#ifdef __clang__
456#pragma clang diagnostic push
457#pragma clang diagnostic ignored "-Wmissing-field-initializers"
458#endif
459
460// Handles bullets 1 and 2
461bool
462__class_type_info::can_catch(const __shim_type_info* thrown_type,
463 void*& adjustedPtr) const
464{
465 // bullet 1
466 if (is_equal(x: this, y: thrown_type, use_strcmp: false))
467 return true;
468 const __class_type_info* thrown_class_type =
469 dynamic_cast<const __class_type_info*>(thrown_type);
470 if (thrown_class_type == 0)
471 return false;
472 // bullet 2
473 _LIBCXXABI_ASSERT(adjustedPtr, "catching a class without an object?");
474 __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true, nullptr};
475 info.number_of_dst_type = 1;
476 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
477 if (info.path_dst_ptr_to_static_ptr == public_path)
478 {
479 adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
480 return true;
481 }
482 return false;
483}
484
485#ifdef __clang__
486#pragma clang diagnostic pop
487#endif
488
489// When we have an object to inspect - we just pass the pointer to the sub-
490// object that matched the static_type we just checked. If that is different
491// from any previously recorded pointer to that object type, then we have
492// an ambiguous case.
493
494// When we have no object to inspect, we need to account for virtual bases
495// explicitly.
496// info->vbase_cookie is a pointer to the name of the innermost virtual base
497// type, or nullptr if there is no virtual base on the path so far.
498// adjustedPtr points to the subobject we just found.
499// If vbase_cookie != any previously recorded (including the case of nullptr
500// representing an already-found static sub-object) then we have an ambiguous
501// case. Assuming that the vbase_cookie values agree; if then we have a
502// different offset (adjustedPtr) from any previously recorded, this indicates
503// an ambiguous case within the virtual base.
504
505void
506__class_type_info::process_found_base_class(__dynamic_cast_info* info,
507 void* adjustedPtr,
508 int path_below) const
509{
510 if (info->number_to_static_ptr == 0) {
511 // First time we found this base
512 info->dst_ptr_leading_to_static_ptr = adjustedPtr;
513 info->path_dst_ptr_to_static_ptr = path_below;
514 // stash the virtual base cookie.
515 info->dst_ptr_not_leading_to_static_ptr = info->vbase_cookie;
516 info->number_to_static_ptr = 1;
517 } else if (info->dst_ptr_not_leading_to_static_ptr == info->vbase_cookie &&
518 info->dst_ptr_leading_to_static_ptr == adjustedPtr) {
519 // We've been here before. Update path to "most public"
520 if (info->path_dst_ptr_to_static_ptr == not_public_path)
521 info->path_dst_ptr_to_static_ptr = path_below;
522 } else {
523 // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
524 // to a static_type.
525 info->number_to_static_ptr += 1;
526 info->path_dst_ptr_to_static_ptr = not_public_path;
527 info->search_done = true;
528 }
529}
530
531void
532__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
533 void* adjustedPtr,
534 int path_below) const
535{
536 if (is_equal(this, info->static_type, false))
537 process_found_base_class(info, adjustedPtr, path_below);
538}
539
540void
541__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
542 void* adjustedPtr,
543 int path_below) const
544{
545 if (is_equal(this, info->static_type, false))
546 process_found_base_class(info, adjustedPtr, path_below);
547 else
548 __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
549}
550
551void
552__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
553 void* adjustedPtr,
554 int path_below) const
555{
556 bool is_virtual = __offset_flags & __virtual_mask;
557 ptrdiff_t offset_to_base = 0;
558 if (info->have_object) {
559 /* We have an object to inspect, we can look through its vtables to
560 find the layout. */
561 offset_to_base = __offset_flags >> __offset_shift;
562 if (is_virtual) {
563 const char* vtable = *static_cast<const char* const*>(adjustedPtr);
564 offset_to_base = update_offset_to_base(vtable, offset_to_base);
565 }
566 } else if (!is_virtual) {
567 /* We have no object; however, for non-virtual bases, (since we do not
568 need to inspect any content) we can pretend to have an object based
569 at '0'. */
570 offset_to_base = __offset_flags >> __offset_shift;
571 } else {
572 /* No object to inspect, and the next base is virtual.
573 We cannot indirect through the vtable to find the actual object offset.
574 So, update vbase_cookie to the new innermost virtual base using the
575 pointer to the typeinfo name as a key. */
576 info->vbase_cookie = static_cast<const void*>(__base_type->name());
577 // .. and reset the pointer.
578 adjustedPtr = nullptr;
579 }
580 __base_type->has_unambiguous_public_base(
581 info,
582 static_cast<char*>(adjustedPtr) + offset_to_base,
583 (__offset_flags & __public_mask) ? path_below : not_public_path);
584}
585
586void
587__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
588 void* adjustedPtr,
589 int path_below) const
590{
591 if (is_equal(this, info->static_type, false))
592 process_found_base_class(info, adjustedPtr, path_below);
593 else
594 {
595 typedef const __base_class_type_info* Iter;
596 const Iter e = __base_info + __base_count;
597 Iter p = __base_info;
598 p->has_unambiguous_public_base(info, adjustedPtr, path_below);
599 if (++p < e)
600 {
601 do
602 {
603 p->has_unambiguous_public_base(info, adjustedPtr, path_below);
604 if (info->search_done)
605 break;
606 } while (++p < e);
607 }
608 }
609}
610
611// Handles bullet 1 for both pointers and member pointers
612bool
613__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
614 void*&) const
615{
616 bool use_strcmp = this->__flags & (__incomplete_class_mask |
617 __incomplete_mask);
618 if (!use_strcmp) {
619 const __pbase_type_info* thrown_pbase = dynamic_cast<const __pbase_type_info*>(
620 thrown_type);
621 if (!thrown_pbase) return false;
622 use_strcmp = thrown_pbase->__flags & (__incomplete_class_mask |
623 __incomplete_mask);
624 }
625 return is_equal(x: this, y: thrown_type, use_strcmp);
626}
627
628#ifdef __clang__
629#pragma clang diagnostic push
630#pragma clang diagnostic ignored "-Wmissing-field-initializers"
631#endif
632
633// Handles bullets 1, 3 and 4
634// NOTE: It might not be safe to adjust the pointer if it is not not a pointer
635// type. Only adjust the pointer after we know it is safe to do so.
636bool
637__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
638 void*& adjustedPtr) const
639{
640 // bullet 4
641 if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) {
642 adjustedPtr = nullptr;
643 return true;
644 }
645
646 // bullet 1
647 if (__pbase_type_info::can_catch(thrown_type, adjustedPtr)) {
648 if (adjustedPtr != NULL)
649 adjustedPtr = *static_cast<void**>(adjustedPtr);
650 return true;
651 }
652 // bullet 3
653 const __pointer_type_info* thrown_pointer_type =
654 dynamic_cast<const __pointer_type_info*>(thrown_type);
655 if (thrown_pointer_type == 0)
656 return false;
657 // Do the dereference adjustment
658 if (adjustedPtr != NULL)
659 adjustedPtr = *static_cast<void**>(adjustedPtr);
660 // bullet 3B and 3C
661 if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask)
662 return false;
663 if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask)
664 return false;
665 if (is_equal(x: __pointee, y: thrown_pointer_type->__pointee, use_strcmp: false))
666 return true;
667 // bullet 3A
668 if (is_equal(__pointee, &typeid(void), false)) {
669 // pointers to functions cannot be converted to void*.
670 // pointers to member functions are not handled here.
671 const __function_type_info* thrown_function =
672 dynamic_cast<const __function_type_info*>(thrown_pointer_type->__pointee);
673 return (thrown_function == nullptr);
674 }
675 // Handle pointer to pointer
676 const __pointer_type_info* nested_pointer_type =
677 dynamic_cast<const __pointer_type_info*>(__pointee);
678 if (nested_pointer_type) {
679 if (~__flags & __const_mask) return false;
680 return nested_pointer_type->can_catch_nested(thrown_pointer_type->__pointee);
681 }
682
683 // Handle pointer to pointer to member
684 const __pointer_to_member_type_info* member_ptr_type =
685 dynamic_cast<const __pointer_to_member_type_info*>(__pointee);
686 if (member_ptr_type) {
687 if (~__flags & __const_mask) return false;
688 return member_ptr_type->can_catch_nested(thrown_pointer_type->__pointee);
689 }
690
691 // Handle pointer to class type
692 const __class_type_info* catch_class_type =
693 dynamic_cast<const __class_type_info*>(__pointee);
694 if (catch_class_type == 0)
695 return false;
696 const __class_type_info* thrown_class_type =
697 dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
698 if (thrown_class_type == 0)
699 return false;
700 bool have_object = adjustedPtr != nullptr;
701 __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
702 have_object, nullptr};
703 info.number_of_dst_type = 1;
704 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
705 if (info.path_dst_ptr_to_static_ptr == public_path)
706 {
707 // In the case of a thrown null pointer, we have no object but we might
708 // well have computed the offset to where a public sub-object would be.
709 // However, we do not want to return that offset to the user; we still
710 // want them to catch a null ptr.
711 if (have_object)
712 adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
713 else
714 adjustedPtr = nullptr;
715 return true;
716 }
717 return false;
718}
719
720bool __pointer_type_info::can_catch_nested(
721 const __shim_type_info* thrown_type) const
722{
723 const __pointer_type_info* thrown_pointer_type =
724 dynamic_cast<const __pointer_type_info*>(thrown_type);
725 if (thrown_pointer_type == 0)
726 return false;
727 // bullet 3B
728 if (thrown_pointer_type->__flags & ~__flags)
729 return false;
730 if (is_equal(x: __pointee, y: thrown_pointer_type->__pointee, use_strcmp: false))
731 return true;
732 // If the pointed to types differ then the catch type must be const
733 // qualified.
734 if (~__flags & __const_mask)
735 return false;
736
737 // Handle pointer to pointer
738 const __pointer_type_info* nested_pointer_type =
739 dynamic_cast<const __pointer_type_info*>(__pointee);
740 if (nested_pointer_type) {
741 return nested_pointer_type->can_catch_nested(
742 thrown_pointer_type->__pointee);
743 }
744
745 // Handle pointer to pointer to member
746 const __pointer_to_member_type_info* member_ptr_type =
747 dynamic_cast<const __pointer_to_member_type_info*>(__pointee);
748 if (member_ptr_type) {
749 return member_ptr_type->can_catch_nested(thrown_pointer_type->__pointee);
750 }
751
752 return false;
753}
754
755bool __pointer_to_member_type_info::can_catch(
756 const __shim_type_info* thrown_type, void*& adjustedPtr) const {
757 // bullet 4
758 if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) {
759 // We assume that the pointer to member representation is the same for
760 // all pointers to data members and for all pointers to member functions.
761 struct X {};
762 if (dynamic_cast<const __function_type_info*>(__pointee)) {
763 static int (X::*const null_ptr_rep)() = nullptr;
764 adjustedPtr = const_cast<int (X::**)()>(&null_ptr_rep);
765 } else {
766 static int X::*const null_ptr_rep = nullptr;
767 adjustedPtr = const_cast<int X::**>(&null_ptr_rep);
768 }
769 return true;
770 }
771
772 // bullet 1
773 if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
774 return true;
775
776 const __pointer_to_member_type_info* thrown_pointer_type =
777 dynamic_cast<const __pointer_to_member_type_info*>(thrown_type);
778 if (thrown_pointer_type == 0)
779 return false;
780 if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask)
781 return false;
782 if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask)
783 return false;
784 if (!is_equal(x: __pointee, y: thrown_pointer_type->__pointee, use_strcmp: false))
785 return false;
786 if (is_equal(x: __context, y: thrown_pointer_type->__context, use_strcmp: false))
787 return true;
788
789 // [except.handle] does not allow the pointer-to-member conversions mentioned
790 // in [mem.conv] to take place. For this reason we don't check Derived->Base
791 // for Derived->Base conversions.
792
793 return false;
794}
795
796bool __pointer_to_member_type_info::can_catch_nested(
797 const __shim_type_info* thrown_type) const
798{
799 const __pointer_to_member_type_info* thrown_member_ptr_type =
800 dynamic_cast<const __pointer_to_member_type_info*>(thrown_type);
801 if (thrown_member_ptr_type == 0)
802 return false;
803 if (~__flags & thrown_member_ptr_type->__flags)
804 return false;
805 if (!is_equal(x: __pointee, y: thrown_member_ptr_type->__pointee, use_strcmp: false))
806 return false;
807 if (!is_equal(x: __context, y: thrown_member_ptr_type->__context, use_strcmp: false))
808 return false;
809 return true;
810}
811
812#ifdef __clang__
813#pragma clang diagnostic pop
814#endif
815
816#ifdef __clang__
817#pragma clang diagnostic push
818#pragma clang diagnostic ignored "-Wmissing-field-initializers"
819#endif
820
821// __dynamic_cast
822
823// static_ptr: pointer to an object of type static_type; nonnull, and since the
824// object is polymorphic, *(void**)static_ptr is a virtual table pointer.
825// static_ptr is &v in the expression dynamic_cast<T>(v).
826// static_type: static type of the object pointed to by static_ptr.
827// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
828// src2dst_offset: a static hint about the location of the
829// source subobject with respect to the complete object;
830// special negative values are:
831// -1: no hint
832// -2: static_type is not a public base of dst_type
833// -3: static_type is a multiple public base type but never a
834// virtual base type
835// otherwise, the static_type type is a unique public nonvirtual
836// base type of dst_type at offset src2dst_offset from the
837// origin of dst_type.
838//
839// (dynamic_ptr, dynamic_type) are the run time type of the complete object
840// referred to by static_ptr and a pointer to it. These can be found from
841// static_ptr for polymorphic types.
842// static_type is guaranteed to be a polymorphic type.
843//
844// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward. Each
845// node of the tree represents a base class/object of its parent (or parents) below.
846// Each node is uniquely represented by a pointer to the object, and a pointer
847// to a type_info - its type. Different nodes may have the same pointer and
848// different nodes may have the same type. But only one node has a specific
849// (pointer-value, type) pair. In C++ two objects of the same type can not
850// share the same address.
851//
852// There are two flavors of nodes which have the type dst_type:
853// 1. Those that are derived from (below) (static_ptr, static_type).
854// 2. Those that are not derived from (below) (static_ptr, static_type).
855//
856// Invariants of the DAG:
857//
858// There is at least one path from the root (dynamic_ptr, dynamic_type) to
859// the node (static_ptr, static_type). This path may or may not be public.
860// There may be more than one such path (some public some not). Such a path may
861// or may not go through a node having type dst_type.
862//
863// No node of type T appears above a node of the same type. That means that
864// there is only one node with dynamic_type. And if dynamic_type == dst_type,
865// then there is only one dst_type in the DAG.
866//
867// No node of type dst_type appears above a node of type static_type. Such
868// DAG's are possible in C++, but the compiler computes those dynamic_casts at
869// compile time, and only calls __dynamic_cast when dst_type lies below
870// static_type in the DAG.
871//
872// dst_type != static_type: The compiler computes the dynamic_cast in this case too.
873// dynamic_type != static_type: The compiler computes the dynamic_cast in this case too.
874//
875// Returns:
876//
877// If there is exactly one dst_type of flavor 1, and
878// If there is a public path from that dst_type to (static_ptr, static_type), or
879// If there are 0 dst_types of flavor 2, and there is a public path from
880// (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
881// path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
882// a pointer to that dst_type.
883// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
884// if there is a public path from (dynamic_ptr, dynamic_type) to
885// (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
886// to the one dst_type, then return a pointer to that one dst_type.
887// Else return nullptr.
888//
889// If dynamic_type == dst_type, then the above algorithm collapses to the
890// following cheaper algorithm:
891//
892// If there is a public path from (dynamic_ptr, dynamic_type) to
893// (static_ptr, static_type), then return dynamic_ptr.
894// Else return nullptr.
895
896extern "C" _LIBCXXABI_FUNC_VIS void *
897__dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
898 const __class_type_info *dst_type,
899 std::ptrdiff_t src2dst_offset) {
900 // Get (dynamic_ptr, dynamic_type) from static_ptr
901 derived_object_info derived_info;
902 dyn_cast_get_derived_info(info: &derived_info, static_ptr);
903
904 // Initialize answer to nullptr. This will be changed from the search
905 // results if a non-null answer is found. Regardless, this is what will
906 // be returned.
907 const void* dst_ptr = 0;
908
909 // Find out if we can use a giant short cut in the search
910 if (is_equal(x: derived_info.dynamic_type, y: dst_type, use_strcmp: false))
911 {
912 dst_ptr = dyn_cast_to_derived(static_ptr,
913 dynamic_ptr: derived_info.dynamic_ptr,
914 static_type,
915 dst_type,
916 offset_to_derived: derived_info.offset_to_derived,
917 src2dst_offset);
918 }
919 else
920 {
921 // Optimize toward downcasting: let's first try to do a downcast before
922 // falling back to the slow path.
923 dst_ptr = dyn_cast_try_downcast(static_ptr,
924 dynamic_ptr: derived_info.dynamic_ptr,
925 dst_type,
926 dynamic_type: derived_info.dynamic_type,
927 src2dst_offset);
928
929 if (!dst_ptr)
930 {
931 dst_ptr = dyn_cast_slow(static_ptr,
932 dynamic_ptr: derived_info.dynamic_ptr,
933 static_type,
934 dst_type,
935 dynamic_type: derived_info.dynamic_type,
936 src2dst_offset);
937 }
938 }
939
940 return const_cast<void*>(dst_ptr);
941}
942
943#ifdef __clang__
944#pragma clang diagnostic pop
945#endif
946
947// Call this function when you hit a static_type which is a base (above) a dst_type.
948// Let caller know you hit a static_type. But only start recording details if
949// this is (static_ptr, static_type) -- the node we are casting from.
950// If this is (static_ptr, static_type)
951// Record the path (public or not) from the dst_type to here. There may be
952// multiple paths from the same dst_type to here, record the "most public" one.
953// Record the dst_ptr as pointing to (static_ptr, static_type).
954// If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
955// then mark this dyanmic_cast as ambiguous and stop the search.
956void
957__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
958 const void* dst_ptr,
959 const void* current_ptr,
960 int path_below) const
961{
962 // Record that we found a static_type
963 info->found_any_static_type = true;
964 if (current_ptr == info->static_ptr)
965 {
966 // Record that we found (static_ptr, static_type)
967 info->found_our_static_ptr = true;
968 if (info->dst_ptr_leading_to_static_ptr == 0)
969 {
970 // First time here
971 info->dst_ptr_leading_to_static_ptr = dst_ptr;
972 info->path_dst_ptr_to_static_ptr = path_below;
973 info->number_to_static_ptr = 1;
974 // If there is only one dst_type in the entire tree and the path from
975 // there to here is public then we are done!
976 if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
977 info->search_done = true;
978 }
979 else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
980 {
981 // We've been here before. Update path to "most public"
982 if (info->path_dst_ptr_to_static_ptr == not_public_path)
983 info->path_dst_ptr_to_static_ptr = path_below;
984 // If there is only one dst_type in the entire tree and the path from
985 // there to here is public then we are done!
986 if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
987 info->search_done = true;
988 }
989 else
990 {
991 // We've detected an ambiguous cast from (static_ptr, static_type)
992 // to a dst_type
993 info->number_to_static_ptr += 1;
994 info->search_done = true;
995 }
996 }
997}
998
999// Call this function when you hit a static_type which is not a base (above) a dst_type.
1000// If this is (static_ptr, static_type)
1001// Record the path (public or not) from (dynamic_ptr, dynamic_type) to here. There may be
1002// multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
1003void
1004__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
1005 const void* current_ptr,
1006 int path_below) const
1007{
1008 if (current_ptr == info->static_ptr)
1009 {
1010 // Record the most public path from (dynamic_ptr, dynamic_type) to
1011 // (static_ptr, static_type)
1012 if (info->path_dynamic_ptr_to_static_ptr != public_path)
1013 info->path_dynamic_ptr_to_static_ptr = path_below;
1014 }
1015}
1016
1017// Call this function when searching below a dst_type node. This function searches
1018// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
1019// If it finds a static_type node, there is no need to further search base classes
1020// above.
1021// If it finds a dst_type node it should search base classes using search_above_dst
1022// to find out if this dst_type points to (static_ptr, static_type) or not.
1023// Either way, the dst_type is recorded as one of two "flavors": one that does
1024// or does not point to (static_ptr, static_type).
1025// If this is neither a static_type nor a dst_type node, continue searching
1026// base classes above.
1027// All the hoopla surrounding the search code is doing nothing but looking for
1028// excuses to stop the search prematurely (break out of the for-loop). That is,
1029// the algorithm below is simply an optimization of this:
1030// void
1031// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
1032// const void* current_ptr,
1033// int path_below) const
1034// {
1035// typedef const __base_class_type_info* Iter;
1036// if (this == info->static_type)
1037// process_static_type_below_dst(info, current_ptr, path_below);
1038// else if (this == info->dst_type)
1039// {
1040// // Record the most public access path that got us here
1041// if (info->path_dynamic_ptr_to_dst_ptr != public_path)
1042// info->path_dynamic_ptr_to_dst_ptr = path_below;
1043// bool does_dst_type_point_to_our_static_type = false;
1044// for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
1045// {
1046// p->search_above_dst(info, current_ptr, current_ptr, public_path);
1047// if (info->found_our_static_ptr)
1048// does_dst_type_point_to_our_static_type = true;
1049// // break out early here if you can detect it doesn't matter if you do
1050// }
1051// if (!does_dst_type_point_to_our_static_type)
1052// {
1053// // We found a dst_type that doesn't point to (static_ptr, static_type)
1054// // So record the address of this dst_ptr and increment the
1055// // count of the number of such dst_types found in the tree.
1056// info->dst_ptr_not_leading_to_static_ptr = current_ptr;
1057// info->number_to_dst_ptr += 1;
1058// }
1059// }
1060// else
1061// {
1062// // This is not a static_type and not a dst_type.
1063// for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
1064// {
1065// p->search_below_dst(info, current_ptr, public_path);
1066// // break out early here if you can detect it doesn't matter if you do
1067// }
1068// }
1069// }
1070void
1071__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
1072 const void* current_ptr,
1073 int path_below,
1074 bool use_strcmp) const
1075{
1076 typedef const __base_class_type_info* Iter;
1077 if (is_equal(this, info->static_type, use_strcmp))
1078 process_static_type_below_dst(info, current_ptr, path_below);
1079 else if (is_equal(this, info->dst_type, use_strcmp))
1080 {
1081 // We've been here before if we've recorded current_ptr in one of these
1082 // two places:
1083 if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
1084 current_ptr == info->dst_ptr_not_leading_to_static_ptr)
1085 {
1086 // We've seen this node before, and therefore have already searched
1087 // its base classes above.
1088 // Update path to here that is "most public".
1089 if (path_below == public_path)
1090 info->path_dynamic_ptr_to_dst_ptr = public_path;
1091 }
1092 else // We have haven't been here before
1093 {
1094 // Record the access path that got us here
1095 // If there is more than one dst_type this path doesn't matter.
1096 info->path_dynamic_ptr_to_dst_ptr = path_below;
1097 bool does_dst_type_point_to_our_static_type = false;
1098 // Only search above here if dst_type derives from static_type, or
1099 // if it is unknown if dst_type derives from static_type.
1100 if (info->is_dst_type_derived_from_static_type != no)
1101 {
1102 // Set up flags to record results from all base classes
1103 bool is_dst_type_derived_from_static_type = false;
1104
1105 // We've found a dst_type with a potentially public path to here.
1106 // We have to assume the path is public because it may become
1107 // public later (if we get back to here with a public path).
1108 // We can stop looking above if:
1109 // 1. We've found a public path to (static_ptr, static_type).
1110 // 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
1111 // This is detected at the (static_ptr, static_type).
1112 // 3. We can prove that there is no public path to (static_ptr, static_type)
1113 // above here.
1114 const Iter e = __base_info + __base_count;
1115 for (Iter p = __base_info; p < e; ++p)
1116 {
1117 // Zero out found flags
1118 info->found_our_static_ptr = false;
1119 info->found_any_static_type = false;
1120 p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
1121 if (info->search_done)
1122 break;
1123 if (info->found_any_static_type)
1124 {
1125 is_dst_type_derived_from_static_type = true;
1126 if (info->found_our_static_ptr)
1127 {
1128 does_dst_type_point_to_our_static_type = true;
1129 // If we found what we're looking for, stop looking above.
1130 if (info->path_dst_ptr_to_static_ptr == public_path)
1131 break;
1132 // We found a private path to (static_ptr, static_type)
1133 // If there is no diamond then there is only one path
1134 // to (static_ptr, static_type) and we just found it.
1135 if (!(__flags & __diamond_shaped_mask))
1136 break;
1137 }
1138 else
1139 {
1140 // If we found a static_type that isn't the one we're looking
1141 // for, and if there are no repeated types above here,
1142 // then stop looking.
1143 if (!(__flags & __non_diamond_repeat_mask))
1144 break;
1145 }
1146 }
1147 }
1148 // If we found no static_type,s then dst_type doesn't derive
1149 // from static_type, else it does. Record this result so that
1150 // next time we hit a dst_type we will know not to search above
1151 // it if it doesn't derive from static_type.
1152 if (is_dst_type_derived_from_static_type)
1153 info->is_dst_type_derived_from_static_type = yes;
1154 else
1155 info->is_dst_type_derived_from_static_type = no;
1156 }
1157 if (!does_dst_type_point_to_our_static_type)
1158 {
1159 // We found a dst_type that doesn't point to (static_ptr, static_type)
1160 // So record the address of this dst_ptr and increment the
1161 // count of the number of such dst_types found in the tree.
1162 info->dst_ptr_not_leading_to_static_ptr = current_ptr;
1163 info->number_to_dst_ptr += 1;
1164 // If there exists another dst with a private path to
1165 // (static_ptr, static_type), then the cast from
1166 // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
1167 // so stop search.
1168 if (info->number_to_static_ptr == 1 &&
1169 info->path_dst_ptr_to_static_ptr == not_public_path)
1170 info->search_done = true;
1171 }
1172 }
1173 }
1174 else
1175 {
1176 // This is not a static_type and not a dst_type.
1177 const Iter e = __base_info + __base_count;
1178 Iter p = __base_info;
1179 p->search_below_dst(info, current_ptr, path_below, use_strcmp);
1180 if (++p < e)
1181 {
1182 if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
1183 {
1184 // If there are multiple paths to a base above from here, or if
1185 // a dst_type pointing to (static_ptr, static_type) has been found,
1186 // then there is no way to break out of this loop early unless
1187 // something below detects the search is done.
1188 do
1189 {
1190 if (info->search_done)
1191 break;
1192 p->search_below_dst(info, current_ptr, path_below, use_strcmp);
1193 } while (++p < e);
1194 }
1195 else if (__flags & __non_diamond_repeat_mask)
1196 {
1197 // There are not multiple paths to any base class from here and a
1198 // dst_type pointing to (static_ptr, static_type) has not yet been
1199 // found.
1200 do
1201 {
1202 if (info->search_done)
1203 break;
1204 // If we just found a dst_type with a public path to (static_ptr, static_type),
1205 // then the only reason to continue the search is to make sure
1206 // no other dst_type points to (static_ptr, static_type).
1207 // If !diamond, then we don't need to search here.
1208 if (info->number_to_static_ptr == 1 &&
1209 info->path_dst_ptr_to_static_ptr == public_path)
1210 break;
1211 p->search_below_dst(info, current_ptr, path_below, use_strcmp);
1212 } while (++p < e);
1213 }
1214 else
1215 {
1216 // There are no repeated types above this node.
1217 // There are no nodes with multiple parents above this node.
1218 // no dst_type has been found to (static_ptr, static_type)
1219 do
1220 {
1221 if (info->search_done)
1222 break;
1223 // If we just found a dst_type with a public path to (static_ptr, static_type),
1224 // then the only reason to continue the search is to make sure
1225 // no other dst_type points to (static_ptr, static_type).
1226 // If !diamond, then we don't need to search here.
1227 // if we just found a dst_type with a private path to (static_ptr, static_type),
1228 // then we're only looking for a public path to (static_ptr, static_type)
1229 // and to check for other dst_types.
1230 // If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
1231 // and not a dst_type under here.
1232 if (info->number_to_static_ptr == 1)
1233 break;
1234 p->search_below_dst(info, current_ptr, path_below, use_strcmp);
1235 } while (++p < e);
1236 }
1237 }
1238 }
1239}
1240
1241// This is the same algorithm as __vmi_class_type_info::search_below_dst but
1242// simplified to the case that there is only a single base class.
1243void
1244__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
1245 const void* current_ptr,
1246 int path_below,
1247 bool use_strcmp) const
1248{
1249 if (is_equal(this, info->static_type, use_strcmp))
1250 process_static_type_below_dst(info, current_ptr, path_below);
1251 else if (is_equal(this, info->dst_type, use_strcmp))
1252 {
1253 // We've been here before if we've recorded current_ptr in one of these
1254 // two places:
1255 if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
1256 current_ptr == info->dst_ptr_not_leading_to_static_ptr)
1257 {
1258 // We've seen this node before, and therefore have already searched
1259 // its base classes above.
1260 // Update path to here that is "most public".
1261 if (path_below == public_path)
1262 info->path_dynamic_ptr_to_dst_ptr = public_path;
1263 }
1264 else // We have haven't been here before
1265 {
1266 // Record the access path that got us here
1267 // If there is more than one dst_type this path doesn't matter.
1268 info->path_dynamic_ptr_to_dst_ptr = path_below;
1269 bool does_dst_type_point_to_our_static_type = false;
1270 // Only search above here if dst_type derives from static_type, or
1271 // if it is unknown if dst_type derives from static_type.
1272 if (info->is_dst_type_derived_from_static_type != no)
1273 {
1274 // Set up flags to record results from all base classes
1275 bool is_dst_type_derived_from_static_type = false;
1276 // Zero out found flags
1277 info->found_our_static_ptr = false;
1278 info->found_any_static_type = false;
1279 __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
1280 if (info->found_any_static_type)
1281 {
1282 is_dst_type_derived_from_static_type = true;
1283 if (info->found_our_static_ptr)
1284 does_dst_type_point_to_our_static_type = true;
1285 }
1286 // If we found no static_type,s then dst_type doesn't derive
1287 // from static_type, else it does. Record this result so that
1288 // next time we hit a dst_type we will know not to search above
1289 // it if it doesn't derive from static_type.
1290 if (is_dst_type_derived_from_static_type)
1291 info->is_dst_type_derived_from_static_type = yes;
1292 else
1293 info->is_dst_type_derived_from_static_type = no;
1294 }
1295 if (!does_dst_type_point_to_our_static_type)
1296 {
1297 // We found a dst_type that doesn't point to (static_ptr, static_type)
1298 // So record the address of this dst_ptr and increment the
1299 // count of the number of such dst_types found in the tree.
1300 info->dst_ptr_not_leading_to_static_ptr = current_ptr;
1301 info->number_to_dst_ptr += 1;
1302 // If there exists another dst with a private path to
1303 // (static_ptr, static_type), then the cast from
1304 // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
1305 if (info->number_to_static_ptr == 1 &&
1306 info->path_dst_ptr_to_static_ptr == not_public_path)
1307 info->search_done = true;
1308 }
1309 }
1310 }
1311 else
1312 {
1313 // This is not a static_type and not a dst_type
1314 __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
1315 }
1316}
1317
1318// This is the same algorithm as __vmi_class_type_info::search_below_dst but
1319// simplified to the case that there is no base class.
1320void
1321__class_type_info::search_below_dst(__dynamic_cast_info* info,
1322 const void* current_ptr,
1323 int path_below,
1324 bool use_strcmp) const
1325{
1326 if (is_equal(this, info->static_type, use_strcmp))
1327 process_static_type_below_dst(info, current_ptr, path_below);
1328 else if (is_equal(this, info->dst_type, use_strcmp))
1329 {
1330 // We've been here before if we've recorded current_ptr in one of these
1331 // two places:
1332 if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
1333 current_ptr == info->dst_ptr_not_leading_to_static_ptr)
1334 {
1335 // We've seen this node before, and therefore have already searched
1336 // its base classes above.
1337 // Update path to here that is "most public".
1338 if (path_below == public_path)
1339 info->path_dynamic_ptr_to_dst_ptr = public_path;
1340 }
1341 else // We have haven't been here before
1342 {
1343 // Record the access path that got us here
1344 // If there is more than one dst_type this path doesn't matter.
1345 info->path_dynamic_ptr_to_dst_ptr = path_below;
1346 // We found a dst_type that doesn't point to (static_ptr, static_type)
1347 // So record the address of this dst_ptr and increment the
1348 // count of the number of such dst_types found in the tree.
1349 info->dst_ptr_not_leading_to_static_ptr = current_ptr;
1350 info->number_to_dst_ptr += 1;
1351 // If there exists another dst with a private path to
1352 // (static_ptr, static_type), then the cast from
1353 // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
1354 if (info->number_to_static_ptr == 1 &&
1355 info->path_dst_ptr_to_static_ptr == not_public_path)
1356 info->search_done = true;
1357 // We found that dst_type does not derive from static_type
1358 info->is_dst_type_derived_from_static_type = no;
1359 }
1360 }
1361}
1362
1363// Call this function when searching above a dst_type node. This function searches
1364// for a public path to (static_ptr, static_type).
1365// This function is guaranteed not to find a node of type dst_type.
1366// Theoretically this is a very simple function which just stops if it finds a
1367// static_type node: All the hoopla surrounding the search code is doing
1368// nothing but looking for excuses to stop the search prematurely (break out of
1369// the for-loop). That is, the algorithm below is simply an optimization of this:
1370// void
1371// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1372// const void* dst_ptr,
1373// const void* current_ptr,
1374// int path_below) const
1375// {
1376// if (this == info->static_type)
1377// process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1378// else
1379// {
1380// typedef const __base_class_type_info* Iter;
1381// // This is not a static_type and not a dst_type
1382// for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
1383// {
1384// p->search_above_dst(info, dst_ptr, current_ptr, public_path);
1385// // break out early here if you can detect it doesn't matter if you do
1386// }
1387// }
1388// }
1389void
1390__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1391 const void* dst_ptr,
1392 const void* current_ptr,
1393 int path_below,
1394 bool use_strcmp) const
1395{
1396 if (is_equal(this, info->static_type, use_strcmp))
1397 process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1398 else
1399 {
1400 typedef const __base_class_type_info* Iter;
1401 // This is not a static_type and not a dst_type
1402 // Save flags so they can be restored when returning to nodes below.
1403 bool found_our_static_ptr = info->found_our_static_ptr;
1404 bool found_any_static_type = info->found_any_static_type;
1405 // We've found a dst_type below with a path to here. If the path
1406 // to here is not public, there may be another path to here that
1407 // is public. So we have to assume that the path to here is public.
1408 // We can stop looking above if:
1409 // 1. We've found a public path to (static_ptr, static_type).
1410 // 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
1411 // This is detected at the (static_ptr, static_type).
1412 // 3. We can prove that there is no public path to (static_ptr, static_type)
1413 // above here.
1414 const Iter e = __base_info + __base_count;
1415 Iter p = __base_info;
1416 // Zero out found flags
1417 info->found_our_static_ptr = false;
1418 info->found_any_static_type = false;
1419 p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1420 found_our_static_ptr |= info->found_our_static_ptr;
1421 found_any_static_type |= info->found_any_static_type;
1422 if (++p < e)
1423 {
1424 do
1425 {
1426 if (info->search_done)
1427 break;
1428 if (info->found_our_static_ptr)
1429 {
1430 // If we found what we're looking for, stop looking above.
1431 if (info->path_dst_ptr_to_static_ptr == public_path)
1432 break;
1433 // We found a private path to (static_ptr, static_type)
1434 // If there is no diamond then there is only one path
1435 // to (static_ptr, static_type) from here and we just found it.
1436 if (!(__flags & __diamond_shaped_mask))
1437 break;
1438 }
1439 else if (info->found_any_static_type)
1440 {
1441 // If we found a static_type that isn't the one we're looking
1442 // for, and if there are no repeated types above here,
1443 // then stop looking.
1444 if (!(__flags & __non_diamond_repeat_mask))
1445 break;
1446 }
1447 // Zero out found flags
1448 info->found_our_static_ptr = false;
1449 info->found_any_static_type = false;
1450 p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1451 found_our_static_ptr |= info->found_our_static_ptr;
1452 found_any_static_type |= info->found_any_static_type;
1453 } while (++p < e);
1454 }
1455 // Restore flags
1456 info->found_our_static_ptr = found_our_static_ptr;
1457 info->found_any_static_type = found_any_static_type;
1458 }
1459}
1460
1461// This is the same algorithm as __vmi_class_type_info::search_above_dst but
1462// simplified to the case that there is only a single base class.
1463void
1464__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
1465 const void* dst_ptr,
1466 const void* current_ptr,
1467 int path_below,
1468 bool use_strcmp) const
1469{
1470 if (is_equal(this, info->static_type, use_strcmp))
1471 process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1472 else
1473 __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1474}
1475
1476// This is the same algorithm as __vmi_class_type_info::search_above_dst but
1477// simplified to the case that there is no base class.
1478void
1479__class_type_info::search_above_dst(__dynamic_cast_info* info,
1480 const void* dst_ptr,
1481 const void* current_ptr,
1482 int path_below,
1483 bool use_strcmp) const
1484{
1485 if (is_equal(this, info->static_type, use_strcmp))
1486 process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1487}
1488
1489// The search functions for __base_class_type_info are simply convenience
1490// functions for adjusting the current_ptr and path_below as the search is
1491// passed up to the base class node.
1492
1493void
1494__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
1495 const void* dst_ptr,
1496 const void* current_ptr,
1497 int path_below,
1498 bool use_strcmp) const
1499{
1500 ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
1501 if (__offset_flags & __virtual_mask)
1502 {
1503 const char* vtable = *static_cast<const char*const*>(current_ptr);
1504 offset_to_base = update_offset_to_base(vtable, offset_to_base);
1505 }
1506 __base_type->search_above_dst(info, dst_ptr,
1507 static_cast<const char*>(current_ptr) + offset_to_base,
1508 (__offset_flags & __public_mask) ?
1509 path_below :
1510 not_public_path,
1511 use_strcmp);
1512}
1513
1514void
1515__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
1516 const void* current_ptr,
1517 int path_below,
1518 bool use_strcmp) const
1519{
1520 ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
1521 if (__offset_flags & __virtual_mask)
1522 {
1523 const char* vtable = *static_cast<const char*const*>(current_ptr);
1524 offset_to_base = update_offset_to_base(vtable, offset_to_base);
1525 }
1526 __base_type->search_below_dst(info,
1527 static_cast<const char*>(current_ptr) + offset_to_base,
1528 (__offset_flags & __public_mask) ?
1529 path_below :
1530 not_public_path,
1531 use_strcmp);
1532}
1533
1534} // __cxxabiv1
1535

source code of libcxxabi/src/private_typeinfo.cpp