1
//===----------------------- private_typeinfo.cpp -------------------------===//
3
// The LLVM Compiler Infrastructure
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
#include "private_typeinfo.h"
12
// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more
13
// forgiving when type_info's mistakenly have hidden visibility and thus
14
// multiple type_infos can exist for a single type.
16
// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where
17
// there is a detected inconsistency in the type_info hierarchy during a
18
// dynamic_cast, then the equality operation will fall back to using strcmp
19
// on type_info names to determine type_info equality.
21
// This change happens *only* under dynamic_cast, and only when
22
// dynamic_cast is faced with the choice: abort, or possibly give back the
23
// wrong answer. If when the dynamic_cast is done with this fallback
24
// algorithm and an inconsistency is still detected, dynamic_cast will call
25
// abort with an appropriate message.
27
// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a
28
// printf-like function called syslog:
30
// void syslog(const char* format, ...);
32
// If you want this functionality but your platform doesn't have syslog,
33
// just implement it in terms of fprintf(stderr, ...).
35
// _LIBCXX_DYNAMIC_FALLBACK is currently off by default.
37
#if _LIBCXX_DYNAMIC_FALLBACK
38
#include "abort_message.h"
40
#include <sys/syslog.h>
46
#pragma GCC visibility push(hidden)
48
#if _LIBCXX_DYNAMIC_FALLBACK
52
is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
56
return strcmp(x->name(), y->name()) == 0;
59
#else // !_LIBCXX_DYNAMIC_FALLBACK
63
is_equal(const std::type_info* x, const std::type_info* y, bool)
68
#endif // _LIBCXX_DYNAMIC_FALLBACK
72
__shim_type_info::~__shim_type_info()
76
void __shim_type_info::noop1() const {}
77
void __shim_type_info::noop2() const {}
79
// __fundamental_type_info
81
// This miraculously (compiler magic) emits the type_info's for:
82
// 1. all of the fundamental types
83
// 2. pointers to all of the fundamental types
84
// 3. pointers to all of the const fundamental types
85
__fundamental_type_info::~__fundamental_type_info()
91
__array_type_info::~__array_type_info()
95
// __function_type_info
97
__function_type_info::~__function_type_info()
103
__enum_type_info::~__enum_type_info()
109
__class_type_info::~__class_type_info()
113
// __si_class_type_info
115
__si_class_type_info::~__si_class_type_info()
119
// __vmi_class_type_info
121
__vmi_class_type_info::~__vmi_class_type_info()
127
__pbase_type_info::~__pbase_type_info()
131
// __pointer_type_info
133
__pointer_type_info::~__pointer_type_info()
137
// __pointer_to_member_type_info
139
__pointer_to_member_type_info::~__pointer_to_member_type_info()
145
// A handler is a match for an exception object of type E if
146
// 1. The handler is of type cv T or cv T& and E and T are the same type
147
// (ignoring the top-level cv-qualifiers), or
148
// 2. the handler is of type cv T or cv T& and T is an unambiguous public
149
// base class of E, or
150
// 3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
151
// converted to the type of the handler by either or both of
152
// A. a standard pointer conversion (4.10) not involving conversions to
153
// pointers to private or protected or ambiguous classes
154
// B. a qualification conversion
155
// 4. the handler is a pointer or pointer to member type and E is
160
// catch (A& a) : adjustedPtr == &a
161
// catch (A* a) : adjustedPtr == a
162
// catch (A** a) : adjustedPtr == a
164
// catch (D2& d2) : adjustedPtr == &d2 (d2 is base class of thrown object)
165
// catch (D2* d2) : adjustedPtr == d2
166
// catch (D2*& d2) : adjustedPtr == d2
168
// catch (...) : adjustedPtr == & of the exception
172
__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
175
return is_equal(this, thrown_type, false);
179
__array_type_info::can_catch(const __shim_type_info*, void*&) const
181
// We can get here if someone tries to catch an array by reference.
182
// However if someone tries to throw an array, it immediately gets
183
// converted to a pointer, which will not convert back to an array
184
// at the catch clause. So this can never catch anything.
189
__function_type_info::can_catch(const __shim_type_info*, void*&) const
191
// We can get here if someone tries to catch a function by reference.
192
// However if someone tries to throw a function, it immediately gets
193
// converted to a pointer, which will not convert back to a function
194
// at the catch clause. So this can never catch anything.
200
__enum_type_info::can_catch(const __shim_type_info* thrown_type,
203
return is_equal(this, thrown_type, false);
206
#pragma clang diagnostic push
207
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
209
// Handles bullets 1 and 2
211
__class_type_info::can_catch(const __shim_type_info* thrown_type,
212
void*& adjustedPtr) const
215
if (is_equal(this, thrown_type, false))
217
const __class_type_info* thrown_class_type =
218
dynamic_cast<const __class_type_info*>(thrown_type);
219
if (thrown_class_type == 0)
222
__dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0};
223
info.number_of_dst_type = 1;
224
thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
225
if (info.path_dst_ptr_to_static_ptr == public_path)
227
adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
233
#pragma clang diagnostic pop
236
__class_type_info::process_found_base_class(__dynamic_cast_info* info,
238
int path_below) const
240
if (info->dst_ptr_leading_to_static_ptr == 0)
243
info->dst_ptr_leading_to_static_ptr = adjustedPtr;
244
info->path_dst_ptr_to_static_ptr = path_below;
245
info->number_to_static_ptr = 1;
247
else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
249
// We've been here before. Update path to "most public"
250
if (info->path_dst_ptr_to_static_ptr == not_public_path)
251
info->path_dst_ptr_to_static_ptr = path_below;
255
// We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
257
info->number_to_static_ptr += 1;
258
info->path_dst_ptr_to_static_ptr = not_public_path;
259
info->search_done = true;
264
__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
266
int path_below) const
268
if (is_equal(this, info->static_type, false))
269
process_found_base_class(info, adjustedPtr, path_below);
273
__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
275
int path_below) const
277
if (is_equal(this, info->static_type, false))
278
process_found_base_class(info, adjustedPtr, path_below);
280
__base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
284
__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
286
int path_below) const
288
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
289
if (__offset_flags & __virtual_mask)
291
const char* vtable = *static_cast<const char*const*>(adjustedPtr);
292
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
294
__base_type->has_unambiguous_public_base(info,
295
static_cast<char*>(adjustedPtr) + offset_to_base,
296
(__offset_flags & __public_mask) ?
302
__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
304
int path_below) const
306
if (is_equal(this, info->static_type, false))
307
process_found_base_class(info, adjustedPtr, path_below);
310
typedef const __base_class_type_info* Iter;
311
const Iter e = __base_info + __base_count;
312
Iter p = __base_info;
313
p->has_unambiguous_public_base(info, adjustedPtr, path_below);
318
p->has_unambiguous_public_base(info, adjustedPtr, path_below);
319
if (info->search_done)
326
// Handles bullets 1 and 4 for both pointers and member pointers
328
__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
331
if (is_equal(this, thrown_type, false))
333
return is_equal(thrown_type, &typeid(std::nullptr_t), false);
336
#pragma clang diagnostic push
337
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
339
// Handles bullets 1, 3 and 4
341
__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
342
void*& adjustedPtr) const
344
// Do the dereference adjustment
345
adjustedPtr = *static_cast<void**>(adjustedPtr);
347
if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
350
const __pointer_type_info* thrown_pointer_type =
351
dynamic_cast<const __pointer_type_info*>(thrown_type);
352
if (thrown_pointer_type == 0)
355
if (thrown_pointer_type->__flags & ~__flags)
357
if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
360
if (is_equal(__pointee, &typeid(void), false))
362
const __class_type_info* catch_class_type =
363
dynamic_cast<const __class_type_info*>(__pointee);
364
if (catch_class_type == 0)
366
const __class_type_info* thrown_class_type =
367
dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
368
if (thrown_class_type == 0)
370
__dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0};
371
info.number_of_dst_type = 1;
372
thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
373
if (info.path_dst_ptr_to_static_ptr == public_path)
375
adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
381
#pragma clang diagnostic pop
383
#pragma GCC visibility pop
384
#pragma GCC visibility push(default)
386
#pragma clang diagnostic push
387
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
391
// static_ptr: pointer to an object of type static_type; nonnull, and since the
392
// object is polymorphic, *(void**)static_ptr is a virtual table pointer.
393
// static_ptr is &v in the expression dynamic_cast<T>(v).
394
// static_type: static type of the object pointed to by static_ptr.
395
// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
396
// src2dst_offset: a static hint about the location of the
397
// source subobject with respect to the complete object;
398
// special negative values are:
400
// -2: static_type is not a public base of dst_type
401
// -3: static_type is a multiple public base type but never a
403
// otherwise, the static_type type is a unique public nonvirtual
404
// base type of dst_type at offset src2dst_offset from the
405
// origin of dst_type.
407
// (dynamic_ptr, dynamic_type) are the run time type of the complete object
408
// referred to by static_ptr and a pointer to it. These can be found from
409
// static_ptr for polymorphic types.
410
// static_type is guaranteed to be a polymorphic type.
412
// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward. Each
413
// node of the tree represents a base class/object of its parent (or parents) below.
414
// Each node is uniquely represented by a pointer to the object, and a pointer
415
// to a type_info - its type. Different nodes may have the same pointer and
416
// different nodes may have the same type. But only one node has a specific
417
// (pointer-value, type) pair. In C++ two objects of the same type can not
418
// share the same address.
420
// There are two flavors of nodes which have the type dst_type:
421
// 1. Those that are derived from (below) (static_ptr, static_type).
422
// 2. Those that are not derived from (below) (static_ptr, static_type).
424
// Invariants of the DAG:
426
// There is at least one path from the root (dynamic_ptr, dynamic_type) to
427
// the node (static_ptr, static_type). This path may or may not be public.
428
// There may be more than one such path (some public some not). Such a path may
429
// or may not go through a node having type dst_type.
431
// No node of type T appears above a node of the same type. That means that
432
// there is only one node with dynamic_type. And if dynamic_type == dst_type,
433
// then there is only one dst_type in the DAG.
435
// No node of type dst_type appears above a node of type static_type. Such
436
// DAG's are possible in C++, but the compiler computes those dynamic_casts at
437
// compile time, and only calls __dynamic_cast when dst_type lies below
438
// static_type in the DAG.
440
// dst_type != static_type: The compiler computes the dynamic_cast in this case too.
441
// dynamic_type != static_type: The compiler computes the dynamic_cast in this case too.
445
// If there is exactly one dst_type of flavor 1, and
446
// If there is a public path from that dst_type to (static_ptr, static_type), or
447
// If there are 0 dst_types of flavor 2, and there is a public path from
448
// (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
449
// path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
450
// a pointer to that dst_type.
451
// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
452
// if there is a public path from (dynamic_ptr, dynamic_type) to
453
// (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
454
// to the one dst_type, then return a pointer to that one dst_type.
455
// Else return nullptr.
457
// If dynamic_type == dst_type, then the above algorithm collapses to the
458
// following cheaper algorithm:
460
// If there is a public path from (dynamic_ptr, dynamic_type) to
461
// (static_ptr, static_type), then return dynamic_ptr.
462
// Else return nullptr.
465
__dynamic_cast(const void* static_ptr,
466
const __class_type_info* static_type,
467
const __class_type_info* dst_type,
468
std::ptrdiff_t src2dst_offset)
470
// Possible future optimization: Take advantage of src2dst_offset
471
// Currently clang always sets src2dst_offset to -1 (no hint).
473
// Get (dynamic_ptr, dynamic_type) from static_ptr
474
void** vtable = *(void***)static_ptr;
475
ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
476
const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
477
const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
479
// Initialize answer to nullptr. This will be changed from the search
480
// results if a non-null answer is found. Regardless, this is what will
482
const void* dst_ptr = 0;
483
// Initialize info struct for this search.
484
__dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
486
// Find out if we can use a giant short cut in the search
487
if (is_equal(dynamic_type, dst_type, false))
489
// Using giant short cut. Add that information to info.
490
info.number_of_dst_type = 1;
492
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
493
#if _LIBCXX_DYNAMIC_FALLBACK
494
// The following if should always be false because we should definitely
495
// find (static_ptr, static_type), either on a public or private path
496
if (info.path_dst_ptr_to_static_ptr == unknown)
498
// We get here only if there is some kind of visibility problem
500
syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
501
"should have public visibility. At least of of them is hidden. %s"
502
", %s.\n", static_type->name(), dynamic_type->name());
503
// Redo the search comparing type_info's using strcmp
504
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
505
info.number_of_dst_type = 1;
506
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
508
#endif // _LIBCXX_DYNAMIC_FALLBACK
510
if (info.path_dst_ptr_to_static_ptr == public_path)
511
dst_ptr = dynamic_ptr;
515
// Not using giant short cut. Do the search
516
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
517
#if _LIBCXX_DYNAMIC_FALLBACK
518
// The following if should always be false because we should definitely
519
// find (static_ptr, static_type), either on a public or private path
520
if (info.path_dst_ptr_to_static_ptr == unknown &&
521
info.path_dynamic_ptr_to_static_ptr == unknown)
523
syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
524
" has hidden visibility. They should all have public visibility. "
525
" %s, %s, %s.\n", static_type->name(), dynamic_type->name(),
527
// Redo the search comparing type_info's using strcmp
528
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
529
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
531
#endif // _LIBCXX_DYNAMIC_FALLBACK
533
switch (info.number_to_static_ptr)
536
if (info.number_to_dst_ptr == 1 &&
537
info.path_dynamic_ptr_to_static_ptr == public_path &&
538
info.path_dynamic_ptr_to_dst_ptr == public_path)
539
dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
542
if (info.path_dst_ptr_to_static_ptr == public_path ||
544
info.number_to_dst_ptr == 0 &&
545
info.path_dynamic_ptr_to_static_ptr == public_path &&
546
info.path_dynamic_ptr_to_dst_ptr == public_path
549
dst_ptr = info.dst_ptr_leading_to_static_ptr;
553
return const_cast<void*>(dst_ptr);
556
#pragma clang diagnostic pop
558
#pragma GCC visibility pop
559
#pragma GCC visibility push(hidden)
561
// Call this function when you hit a static_type which is a base (above) a dst_type.
562
// Let caller know you hit a static_type. But only start recording details if
563
// this is (static_ptr, static_type) -- the node we are casting from.
564
// If this is (static_ptr, static_type)
565
// Record the path (public or not) from the dst_type to here. There may be
566
// multiple paths from the same dst_type to here, record the "most public" one.
567
// Record the dst_ptr as pointing to (static_ptr, static_type).
568
// If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
569
// then mark this dyanmic_cast as ambiguous and stop the search.
571
__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
573
const void* current_ptr,
574
int path_below) const
576
// Record that we found a static_type
577
info->found_any_static_type = true;
578
if (current_ptr == info->static_ptr)
580
// Record that we found (static_ptr, static_type)
581
info->found_our_static_ptr = true;
582
if (info->dst_ptr_leading_to_static_ptr == 0)
585
info->dst_ptr_leading_to_static_ptr = dst_ptr;
586
info->path_dst_ptr_to_static_ptr = path_below;
587
info->number_to_static_ptr = 1;
588
// If there is only one dst_type in the entire tree and the path from
589
// there to here is public then we are done!
590
if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
591
info->search_done = true;
593
else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
595
// We've been here before. Update path to "most public"
596
if (info->path_dst_ptr_to_static_ptr == not_public_path)
597
info->path_dst_ptr_to_static_ptr = path_below;
598
// If there is only one dst_type in the entire tree and the path from
599
// there to here is public then we are done!
600
if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
601
info->search_done = true;
605
// We've detected an ambiguous cast from (static_ptr, static_type)
607
info->number_to_static_ptr += 1;
608
info->search_done = true;
613
// Call this function when you hit a static_type which is not a base (above) a dst_type.
614
// If this is (static_ptr, static_type)
615
// Record the path (public or not) from (dynamic_ptr, dynamic_type) to here. There may be
616
// multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
618
__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
619
const void* current_ptr,
620
int path_below) const
622
if (current_ptr == info->static_ptr)
624
// Record the most public path from (dynamic_ptr, dynamic_type) to
625
// (static_ptr, static_type)
626
if (info->path_dynamic_ptr_to_static_ptr != public_path)
627
info->path_dynamic_ptr_to_static_ptr = path_below;
631
// Call this function when searching below a dst_type node. This function searches
632
// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
633
// If it finds a static_type node, there is no need to further search base classes
635
// If it finds a dst_type node it should search base classes using search_above_dst
636
// to find out if this dst_type points to (static_ptr, static_type) or not.
637
// Either way, the dst_type is recorded as one of two "flavors": one that does
638
// or does not point to (static_ptr, static_type).
639
// If this is neither a static_type nor a dst_type node, continue searching
640
// base classes above.
641
// All the hoopla surrounding the search code is doing nothing but looking for
642
// excuses to stop the search prematurely (break out of the for-loop). That is,
643
// the algorithm below is simply an optimization of this:
645
// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
646
// const void* current_ptr,
647
// int path_below) const
649
// typedef const __base_class_type_info* Iter;
650
// if (this == info->static_type)
651
// process_static_type_below_dst(info, current_ptr, path_below);
652
// else if (this == info->dst_type)
654
// // Record the most public access path that got us here
655
// if (info->path_dynamic_ptr_to_dst_ptr != public_path)
656
// info->path_dynamic_ptr_to_dst_ptr = path_below;
657
// bool does_dst_type_point_to_our_static_type = false;
658
// for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
660
// p->search_above_dst(info, current_ptr, current_ptr, public_path);
661
// if (info->found_our_static_ptr)
662
// does_dst_type_point_to_our_static_type = true;
663
// // break out early here if you can detect it doesn't matter if you do
665
// if (!does_dst_type_point_to_our_static_type)
667
// // We found a dst_type that doesn't point to (static_ptr, static_type)
668
// // So record the address of this dst_ptr and increment the
669
// // count of the number of such dst_types found in the tree.
670
// info->dst_ptr_not_leading_to_static_ptr = current_ptr;
671
// info->number_to_dst_ptr += 1;
676
// // This is not a static_type and not a dst_type.
677
// for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
679
// p->search_below_dst(info, current_ptr, public_path);
680
// // break out early here if you can detect it doesn't matter if you do
685
__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
686
const void* current_ptr,
688
bool use_strcmp) const
690
typedef const __base_class_type_info* Iter;
691
if (is_equal(this, info->static_type, use_strcmp))
692
process_static_type_below_dst(info, current_ptr, path_below);
693
else if (is_equal(this, info->dst_type, use_strcmp))
695
// We've been here before if we've recorded current_ptr in one of these
697
if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
698
current_ptr == info->dst_ptr_not_leading_to_static_ptr)
700
// We've seen this node before, and therefore have already searched
701
// its base classes above.
702
// Update path to here that is "most public".
703
if (path_below == public_path)
704
info->path_dynamic_ptr_to_dst_ptr = public_path;
706
else // We have haven't been here before
708
// Record the access path that got us here
709
// If there is more than one dst_type this path doesn't matter.
710
info->path_dynamic_ptr_to_dst_ptr = path_below;
711
// Only search above here if dst_type derives from static_type, or
712
// if it is unknown if dst_type derives from static_type.
713
if (info->is_dst_type_derived_from_static_type != no)
715
// Set up flags to record results from all base classes
716
bool is_dst_type_derived_from_static_type = false;
717
bool does_dst_type_point_to_our_static_type = false;
718
// We've found a dst_type with a potentially public path to here.
719
// We have to assume the path is public because it may become
720
// public later (if we get back to here with a public path).
721
// We can stop looking above if:
722
// 1. We've found a public path to (static_ptr, static_type).
723
// 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
724
// This is detected at the (static_ptr, static_type).
725
// 3. We can prove that there is no public path to (static_ptr, static_type)
727
const Iter e = __base_info + __base_count;
728
for (Iter p = __base_info; p < e; ++p)
730
// Zero out found flags
731
info->found_our_static_ptr = false;
732
info->found_any_static_type = false;
733
p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
734
if (info->search_done)
736
if (info->found_any_static_type)
738
is_dst_type_derived_from_static_type = true;
739
if (info->found_our_static_ptr)
741
does_dst_type_point_to_our_static_type = true;
742
// If we found what we're looking for, stop looking above.
743
if (info->path_dst_ptr_to_static_ptr == public_path)
745
// We found a private path to (static_ptr, static_type)
746
// If there is no diamond then there is only one path
747
// to (static_ptr, static_type) and we just found it.
748
if (!(__flags & __diamond_shaped_mask))
753
// If we found a static_type that isn't the one we're looking
754
// for, and if there are no repeated types above here,
755
// then stop looking.
756
if (!(__flags & __non_diamond_repeat_mask))
761
if (!does_dst_type_point_to_our_static_type)
763
// We found a dst_type that doesn't point to (static_ptr, static_type)
764
// So record the address of this dst_ptr and increment the
765
// count of the number of such dst_types found in the tree.
766
info->dst_ptr_not_leading_to_static_ptr = current_ptr;
767
info->number_to_dst_ptr += 1;
768
// If there exists another dst with a private path to
769
// (static_ptr, static_type), then the cast from
770
// (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
772
if (info->number_to_static_ptr == 1 &&
773
info->path_dst_ptr_to_static_ptr == not_public_path)
774
info->search_done = true;
776
// If we found no static_type,s then dst_type doesn't derive
777
// from static_type, else it does. Record this result so that
778
// next time we hit a dst_type we will know not to search above
779
// it if it doesn't derive from static_type.
780
if (is_dst_type_derived_from_static_type)
781
info->is_dst_type_derived_from_static_type = yes;
783
info->is_dst_type_derived_from_static_type = no;
789
// This is not a static_type and not a dst_type.
790
const Iter e = __base_info + __base_count;
791
Iter p = __base_info;
792
p->search_below_dst(info, current_ptr, path_below, use_strcmp);
795
if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
797
// If there are multiple paths to a base above from here, or if
798
// a dst_type pointing to (static_ptr, static_type) has been found,
799
// then there is no way to break out of this loop early unless
800
// something below detects the search is done.
803
if (info->search_done)
805
p->search_below_dst(info, current_ptr, path_below, use_strcmp);
808
else if (__flags & __non_diamond_repeat_mask)
810
// There are not multiple paths to any base class from here and a
811
// dst_type pointing to (static_ptr, static_type) has not yet been
815
if (info->search_done)
817
// If we just found a dst_type with a public path to (static_ptr, static_type),
818
// then the only reason to continue the search is to make sure
819
// no other dst_type points to (static_ptr, static_type).
820
// If !diamond, then we don't need to search here.
821
if (info->number_to_static_ptr == 1 &&
822
info->path_dst_ptr_to_static_ptr == public_path)
824
p->search_below_dst(info, current_ptr, path_below, use_strcmp);
829
// There are no repeated types above this node.
830
// There are no nodes with multiple parents above this node.
831
// no dst_type has been found to (static_ptr, static_type)
834
if (info->search_done)
836
// If we just found a dst_type with a public path to (static_ptr, static_type),
837
// then the only reason to continue the search is to make sure sure
838
// no other dst_type points to (static_ptr, static_type).
839
// If !diamond, then we don't need to search here.
840
// if we just found a dst_type with a private path to (static_ptr, static_type),
841
// then we're only looking for a public path to (static_ptr, static_type)
842
// and to check for other dst_types.
843
// If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
844
// and not a dst_type under here.
845
if (info->number_to_static_ptr == 1)
847
p->search_below_dst(info, current_ptr, path_below, use_strcmp);
854
// This is the same algorithm as __vmi_class_type_info::search_below_dst but
855
// simplified to the case that there is only a single base class.
857
__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
858
const void* current_ptr,
860
bool use_strcmp) const
862
if (is_equal(this, info->static_type, use_strcmp))
863
process_static_type_below_dst(info, current_ptr, path_below);
864
else if (is_equal(this, info->dst_type, use_strcmp))
866
// We've been here before if we've recorded current_ptr in one of these
868
if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
869
current_ptr == info->dst_ptr_not_leading_to_static_ptr)
871
// We've seen this node before, and therefore have already searched
872
// its base classes above.
873
// Update path to here that is "most public".
874
if (path_below == public_path)
875
info->path_dynamic_ptr_to_dst_ptr = public_path;
877
else // We have haven't been here before
879
// Record the access path that got us here
880
// If there is more than one dst_type this path doesn't matter.
881
info->path_dynamic_ptr_to_dst_ptr = path_below;
882
// Only search above here if dst_type derives from static_type, or
883
// if it is unknown if dst_type derives from static_type.
884
if (info->is_dst_type_derived_from_static_type != no)
886
// Set up flags to record results from all base classes
887
bool is_dst_type_derived_from_static_type = false;
888
bool does_dst_type_point_to_our_static_type = false;
889
// Zero out found flags
890
info->found_our_static_ptr = false;
891
info->found_any_static_type = false;
892
__base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
893
if (info->found_any_static_type)
895
is_dst_type_derived_from_static_type = true;
896
if (info->found_our_static_ptr)
897
does_dst_type_point_to_our_static_type = true;
899
if (!does_dst_type_point_to_our_static_type)
901
// We found a dst_type that doesn't point to (static_ptr, static_type)
902
// So record the address of this dst_ptr and increment the
903
// count of the number of such dst_types found in the tree.
904
info->dst_ptr_not_leading_to_static_ptr = current_ptr;
905
info->number_to_dst_ptr += 1;
906
// If there exists another dst with a private path to
907
// (static_ptr, static_type), then the cast from
908
// (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
909
if (info->number_to_static_ptr == 1 &&
910
info->path_dst_ptr_to_static_ptr == not_public_path)
911
info->search_done = true;
913
// If we found no static_type,s then dst_type doesn't derive
914
// from static_type, else it does. Record this result so that
915
// next time we hit a dst_type we will know not to search above
916
// it if it doesn't derive from static_type.
917
if (is_dst_type_derived_from_static_type)
918
info->is_dst_type_derived_from_static_type = yes;
920
info->is_dst_type_derived_from_static_type = no;
926
// This is not a static_type and not a dst_type
927
__base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
931
// This is the same algorithm as __vmi_class_type_info::search_below_dst but
932
// simplified to the case that there is no base class.
934
__class_type_info::search_below_dst(__dynamic_cast_info* info,
935
const void* current_ptr,
937
bool use_strcmp) const
939
typedef const __base_class_type_info* Iter;
940
if (is_equal(this, info->static_type, use_strcmp))
941
process_static_type_below_dst(info, current_ptr, path_below);
942
else if (is_equal(this, info->dst_type, use_strcmp))
944
// We've been here before if we've recorded current_ptr in one of these
946
if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
947
current_ptr == info->dst_ptr_not_leading_to_static_ptr)
949
// We've seen this node before, and therefore have already searched
950
// its base classes above.
951
// Update path to here that is "most public".
952
if (path_below == public_path)
953
info->path_dynamic_ptr_to_dst_ptr = public_path;
955
else // We have haven't been here before
957
// Record the access path that got us here
958
// If there is more than one dst_type this path doesn't matter.
959
info->path_dynamic_ptr_to_dst_ptr = path_below;
960
// We found a dst_type that doesn't point to (static_ptr, static_type)
961
// So record the address of this dst_ptr and increment the
962
// count of the number of such dst_types found in the tree.
963
info->dst_ptr_not_leading_to_static_ptr = current_ptr;
964
info->number_to_dst_ptr += 1;
965
// If there exists another dst with a private path to
966
// (static_ptr, static_type), then the cast from
967
// (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
968
if (info->number_to_static_ptr == 1 &&
969
info->path_dst_ptr_to_static_ptr == not_public_path)
970
info->search_done = true;
971
// We found that dst_type does not derive from static_type
972
info->is_dst_type_derived_from_static_type = no;
977
// Call this function when searching above a dst_type node. This function searches
978
// for a public path to (static_ptr, static_type).
979
// This function is guaranteed not to find a node of type dst_type.
980
// Theoretically this is a very simple function which just stops if it finds a
981
// static_type node: All the hoopla surrounding the search code is doing
982
// nothing but looking for excuses to stop the search prematurely (break out of
983
// the for-loop). That is, the algorithm below is simply an optimization of this:
985
// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
986
// const void* dst_ptr,
987
// const void* current_ptr,
988
// int path_below) const
990
// if (this == info->static_type)
991
// process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
994
// typedef const __base_class_type_info* Iter;
995
// // This is not a static_type and not a dst_type
996
// for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
998
// p->search_above_dst(info, dst_ptr, current_ptr, public_path);
999
// // break out early here if you can detect it doesn't matter if you do
1004
__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1005
const void* dst_ptr,
1006
const void* current_ptr,
1008
bool use_strcmp) const
1010
if (is_equal(this, info->static_type, use_strcmp))
1011
process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1014
typedef const __base_class_type_info* Iter;
1015
// This is not a static_type and not a dst_type
1016
// Save flags so they can be restored when returning to nodes below.
1017
bool found_our_static_ptr = info->found_our_static_ptr;
1018
bool found_any_static_type = info->found_any_static_type;
1019
// We've found a dst_type below with a path to here. If the path
1020
// to here is not public, there may be another path to here that
1021
// is public. So we have to assume that the path to here is public.
1022
// We can stop looking above if:
1023
// 1. We've found a public path to (static_ptr, static_type).
1024
// 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
1025
// This is detected at the (static_ptr, static_type).
1026
// 3. We can prove that there is no public path to (static_ptr, static_type)
1028
const Iter e = __base_info + __base_count;
1029
Iter p = __base_info;
1030
// Zero out found flags
1031
info->found_our_static_ptr = false;
1032
info->found_any_static_type = false;
1033
p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1038
if (info->search_done)
1040
if (info->found_our_static_ptr)
1042
// If we found what we're looking for, stop looking above.
1043
if (info->path_dst_ptr_to_static_ptr == public_path)
1045
// We found a private path to (static_ptr, static_type)
1046
// If there is no diamond then there is only one path
1047
// to (static_ptr, static_type) from here and we just found it.
1048
if (!(__flags & __diamond_shaped_mask))
1051
else if (info->found_any_static_type)
1053
// If we found a static_type that isn't the one we're looking
1054
// for, and if there are no repeated types above here,
1055
// then stop looking.
1056
if (!(__flags & __non_diamond_repeat_mask))
1059
// Zero out found flags
1060
info->found_our_static_ptr = false;
1061
info->found_any_static_type = false;
1062
p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1066
info->found_our_static_ptr = found_our_static_ptr;
1067
info->found_any_static_type = found_any_static_type;
1071
// This is the same algorithm as __vmi_class_type_info::search_above_dst but
1072
// simplified to the case that there is only a single base class.
1074
__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
1075
const void* dst_ptr,
1076
const void* current_ptr,
1078
bool use_strcmp) const
1080
if (is_equal(this, info->static_type, use_strcmp))
1081
process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1083
__base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1086
// This is the same algorithm as __vmi_class_type_info::search_above_dst but
1087
// simplified to the case that there is no base class.
1089
__class_type_info::search_above_dst(__dynamic_cast_info* info,
1090
const void* dst_ptr,
1091
const void* current_ptr,
1093
bool use_strcmp) const
1095
if (is_equal(this, info->static_type, use_strcmp))
1096
process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1099
// The search functions for __base_class_type_info are simply convenience
1100
// functions for adjusting the current_ptr and path_below as the search is
1101
// passed up to the base class node.
1104
__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
1105
const void* dst_ptr,
1106
const void* current_ptr,
1108
bool use_strcmp) const
1110
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
1111
if (__offset_flags & __virtual_mask)
1113
const char* vtable = *static_cast<const char*const*>(current_ptr);
1114
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1116
__base_type->search_above_dst(info, dst_ptr,
1117
static_cast<const char*>(current_ptr) + offset_to_base,
1118
(__offset_flags & __public_mask) ?
1125
__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
1126
const void* current_ptr,
1128
bool use_strcmp) const
1130
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
1131
if (__offset_flags & __virtual_mask)
1133
const char* vtable = *static_cast<const char*const*>(current_ptr);
1134
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1136
__base_type->search_below_dst(info,
1137
static_cast<const char*>(current_ptr) + offset_to_base,
1138
(__offset_flags & __public_mask) ?
1144
#pragma GCC visibility pop