~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to system/lib/libcxxabi/src/private_typeinfo.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===----------------------- private_typeinfo.cpp -------------------------===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is dual licensed under the MIT and the University of Illinois Open
 
6
// Source Licenses. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
 
 
10
#include "private_typeinfo.h"
 
11
 
 
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.
 
15
// 
 
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.
 
20
// 
 
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.
 
26
// 
 
27
// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a
 
28
// printf-like function called syslog:
 
29
// 
 
30
//     void syslog(const char* format, ...);
 
31
// 
 
32
// If you want this functionality but your platform doesn't have syslog,
 
33
// just implement it in terms of fprintf(stderr, ...).
 
34
// 
 
35
// _LIBCXX_DYNAMIC_FALLBACK is currently off by default.
 
36
 
 
37
#if _LIBCXX_DYNAMIC_FALLBACK
 
38
#include "abort_message.h"
 
39
#include <string.h>
 
40
#include <sys/syslog.h>
 
41
#endif
 
42
 
 
43
namespace __cxxabiv1
 
44
{
 
45
 
 
46
#pragma GCC visibility push(hidden)
 
47
 
 
48
#if _LIBCXX_DYNAMIC_FALLBACK
 
49
 
 
50
inline
 
51
bool
 
52
is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
 
53
{
 
54
    if (!use_strcmp)
 
55
        return x == y;
 
56
    return strcmp(x->name(), y->name()) == 0;
 
57
}
 
58
 
 
59
#else  // !_LIBCXX_DYNAMIC_FALLBACK
 
60
 
 
61
inline
 
62
bool
 
63
is_equal(const std::type_info* x, const std::type_info* y, bool)
 
64
{
 
65
    return x == y;
 
66
}
 
67
 
 
68
#endif  // _LIBCXX_DYNAMIC_FALLBACK
 
69
 
 
70
// __shim_type_info
 
71
 
 
72
__shim_type_info::~__shim_type_info()
 
73
{
 
74
}
 
75
 
 
76
void __shim_type_info::noop1() const {}
 
77
void __shim_type_info::noop2() const {}
 
78
 
 
79
// __fundamental_type_info
 
80
 
 
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()
 
86
{
 
87
}
 
88
 
 
89
// __array_type_info
 
90
 
 
91
__array_type_info::~__array_type_info()
 
92
{
 
93
}
 
94
 
 
95
// __function_type_info
 
96
 
 
97
__function_type_info::~__function_type_info()
 
98
{
 
99
}
 
100
 
 
101
// __enum_type_info
 
102
 
 
103
__enum_type_info::~__enum_type_info()
 
104
{
 
105
}
 
106
 
 
107
// __class_type_info
 
108
 
 
109
__class_type_info::~__class_type_info()
 
110
{
 
111
}
 
112
 
 
113
// __si_class_type_info
 
114
 
 
115
__si_class_type_info::~__si_class_type_info()
 
116
{
 
117
}
 
118
 
 
119
// __vmi_class_type_info
 
120
 
 
121
__vmi_class_type_info::~__vmi_class_type_info()
 
122
{
 
123
}
 
124
 
 
125
// __pbase_type_info
 
126
 
 
127
__pbase_type_info::~__pbase_type_info()
 
128
{
 
129
}
 
130
 
 
131
// __pointer_type_info
 
132
 
 
133
__pointer_type_info::~__pointer_type_info()
 
134
{
 
135
}
 
136
 
 
137
// __pointer_to_member_type_info
 
138
 
 
139
__pointer_to_member_type_info::~__pointer_to_member_type_info()
 
140
{
 
141
}
 
142
 
 
143
// can_catch
 
144
 
 
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
 
156
//      std::nullptr_t.
 
157
 
 
158
// adjustedPtr:
 
159
// 
 
160
// catch (A& a) : adjustedPtr == &a
 
161
// catch (A* a) : adjustedPtr == a
 
162
// catch (A** a) : adjustedPtr == a
 
163
// 
 
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
 
167
// 
 
168
// catch (...) : adjustedPtr == & of the exception
 
169
 
 
170
// Handles bullet 1
 
171
bool
 
172
__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
 
173
                                   void*&) const
 
174
{
 
175
    return is_equal(this, thrown_type, false);
 
176
}
 
177
 
 
178
bool
 
179
__array_type_info::can_catch(const __shim_type_info*, void*&) const
 
180
{
 
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.
 
185
    return false;
 
186
}
 
187
 
 
188
bool
 
189
__function_type_info::can_catch(const __shim_type_info*, void*&) const
 
190
{
 
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.
 
195
    return false;
 
196
}
 
197
 
 
198
// Handles bullet 1
 
199
bool
 
200
__enum_type_info::can_catch(const __shim_type_info* thrown_type,
 
201
                            void*&) const
 
202
{
 
203
    return is_equal(this, thrown_type, false);
 
204
}
 
205
 
 
206
#pragma clang diagnostic push
 
207
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
 
208
 
 
209
// Handles bullets 1 and 2
 
210
bool
 
211
__class_type_info::can_catch(const __shim_type_info* thrown_type,
 
212
                             void*& adjustedPtr) const
 
213
{
 
214
    // bullet 1
 
215
    if (is_equal(this, thrown_type, false))
 
216
        return true;
 
217
    const __class_type_info* thrown_class_type =
 
218
        dynamic_cast<const __class_type_info*>(thrown_type);
 
219
    if (thrown_class_type == 0)
 
220
        return false;
 
221
    // bullet 2
 
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)
 
226
    {
 
227
        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
 
228
        return true;
 
229
    }
 
230
    return false;
 
231
}
 
232
 
 
233
#pragma clang diagnostic pop
 
234
 
 
235
void
 
236
__class_type_info::process_found_base_class(__dynamic_cast_info* info,
 
237
                                               void* adjustedPtr,
 
238
                                               int path_below) const
 
239
{
 
240
    if (info->dst_ptr_leading_to_static_ptr == 0)
 
241
    {
 
242
        // First time here
 
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;
 
246
    }
 
247
    else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
 
248
    {
 
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;
 
252
    }
 
253
    else
 
254
    {
 
255
        // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
 
256
        //   to a static_type
 
257
        info->number_to_static_ptr += 1;
 
258
        info->path_dst_ptr_to_static_ptr = not_public_path;
 
259
        info->search_done = true;
 
260
    }
 
261
}
 
262
 
 
263
void
 
264
__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
 
265
                                               void* adjustedPtr,
 
266
                                               int path_below) const
 
267
{
 
268
    if (is_equal(this, info->static_type, false))
 
269
        process_found_base_class(info, adjustedPtr, path_below);
 
270
}
 
271
 
 
272
void
 
273
__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
 
274
                                                  void* adjustedPtr,
 
275
                                                  int path_below) const
 
276
{
 
277
    if (is_equal(this, info->static_type, false))
 
278
        process_found_base_class(info, adjustedPtr, path_below);
 
279
    else
 
280
        __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
 
281
}
 
282
 
 
283
void
 
284
__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
 
285
                                                    void* adjustedPtr,
 
286
                                                    int path_below) const
 
287
{
 
288
    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
 
289
    if (__offset_flags & __virtual_mask)
 
290
    {
 
291
        const char* vtable = *static_cast<const char*const*>(adjustedPtr);
 
292
        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
 
293
    }
 
294
    __base_type->has_unambiguous_public_base(info,
 
295
                                             static_cast<char*>(adjustedPtr) + offset_to_base,
 
296
                                             (__offset_flags & __public_mask) ?
 
297
                                                 path_below :
 
298
                                                 not_public_path);
 
299
}
 
300
 
 
301
void
 
302
__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
 
303
                                                   void* adjustedPtr,
 
304
                                                   int path_below) const
 
305
{
 
306
    if (is_equal(this, info->static_type, false))
 
307
        process_found_base_class(info, adjustedPtr, path_below);
 
308
    else
 
309
    {
 
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);
 
314
        if (++p < e)
 
315
        {
 
316
            do
 
317
            {
 
318
                p->has_unambiguous_public_base(info, adjustedPtr, path_below);
 
319
                if (info->search_done)
 
320
                    break;
 
321
            } while (++p < e);
 
322
        }
 
323
    }
 
324
}
 
325
 
 
326
// Handles bullets 1 and 4 for both pointers and member pointers
 
327
bool
 
328
__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
 
329
                             void*&) const
 
330
{
 
331
    if (is_equal(this, thrown_type, false))
 
332
        return true;
 
333
    return is_equal(thrown_type, &typeid(std::nullptr_t), false);
 
334
}
 
335
 
 
336
#pragma clang diagnostic push
 
337
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
 
338
 
 
339
// Handles bullets 1, 3 and 4
 
340
bool
 
341
__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
 
342
                               void*& adjustedPtr) const
 
343
{
 
344
    // Do the dereference adjustment
 
345
    adjustedPtr = *static_cast<void**>(adjustedPtr);
 
346
    // bullets 1 and 4
 
347
    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
 
348
        return true;
 
349
    // bullet 3
 
350
    const __pointer_type_info* thrown_pointer_type =
 
351
        dynamic_cast<const __pointer_type_info*>(thrown_type);
 
352
    if (thrown_pointer_type == 0)
 
353
        return false;
 
354
    // bullet 3B
 
355
    if (thrown_pointer_type->__flags & ~__flags)
 
356
        return false;
 
357
    if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
 
358
        return true;
 
359
    // bullet 3A
 
360
    if (is_equal(__pointee, &typeid(void), false))
 
361
        return true;
 
362
    const __class_type_info* catch_class_type =
 
363
        dynamic_cast<const __class_type_info*>(__pointee);
 
364
    if (catch_class_type == 0)
 
365
        return false;
 
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)
 
369
        return false;
 
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)
 
374
    {
 
375
        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
 
376
        return true;
 
377
    }
 
378
    return false;
 
379
}
 
380
 
 
381
#pragma clang diagnostic pop
 
382
 
 
383
#pragma GCC visibility pop
 
384
#pragma GCC visibility push(default)
 
385
 
 
386
#pragma clang diagnostic push
 
387
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
 
388
 
 
389
// __dynamic_cast
 
390
 
 
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:
 
399
//                     -1: no hint
 
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
 
402
//                         virtual base type
 
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.
 
406
//
 
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.
 
411
//
 
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.
 
419
//
 
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).
 
423
//
 
424
// Invariants of the DAG:
 
425
//
 
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.
 
430
//
 
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.
 
434
//
 
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.
 
439
//
 
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.
 
442
//
 
443
// Returns:
 
444
//
 
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.
 
456
//
 
457
// If dynamic_type == dst_type, then the above algorithm collapses to the
 
458
// following cheaper algorithm:
 
459
//
 
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.
 
463
extern "C"
 
464
void*
 
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)
 
469
{
 
470
    // Possible future optimization:  Take advantage of src2dst_offset
 
471
    // Currently clang always sets src2dst_offset to -1 (no hint).
 
472
 
 
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]);
 
478
 
 
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
 
481
    //    be returned.
 
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};
 
485
 
 
486
    // Find out if we can use a giant short cut in the search
 
487
    if (is_equal(dynamic_type, dst_type, false))
 
488
    {
 
489
        // Using giant short cut.  Add that information to info.
 
490
        info.number_of_dst_type = 1;
 
491
        // Do the  search
 
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)
 
497
        {
 
498
            // We get here only if there is some kind of visibility problem
 
499
            //   in client code.
 
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);
 
507
        }
 
508
#endif  // _LIBCXX_DYNAMIC_FALLBACK
 
509
        // Query the search.
 
510
        if (info.path_dst_ptr_to_static_ptr == public_path)
 
511
            dst_ptr = dynamic_ptr;
 
512
    }
 
513
    else
 
514
    {
 
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)
 
522
        {
 
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(),
 
526
                    dst_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);
 
530
        }
 
531
#endif  // _LIBCXX_DYNAMIC_FALLBACK
 
532
        // Query the search.
 
533
        switch (info.number_to_static_ptr)
 
534
        {
 
535
        case 0:
 
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;
 
540
            break;
 
541
        case 1:
 
542
            if (info.path_dst_ptr_to_static_ptr == public_path ||
 
543
                   (
 
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
 
547
                   )
 
548
               )
 
549
                dst_ptr = info.dst_ptr_leading_to_static_ptr;
 
550
            break;
 
551
        }
 
552
    }
 
553
    return const_cast<void*>(dst_ptr);
 
554
}
 
555
 
 
556
#pragma clang diagnostic pop
 
557
 
 
558
#pragma GCC visibility pop
 
559
#pragma GCC visibility push(hidden)
 
560
 
 
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.
 
570
void
 
571
__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
 
572
                                                 const void* dst_ptr,
 
573
                                                 const void* current_ptr,
 
574
                                                 int path_below) const
 
575
{
 
576
    // Record that we found a static_type
 
577
    info->found_any_static_type = true;
 
578
    if (current_ptr == info->static_ptr)
 
579
    {
 
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)
 
583
        {
 
584
            // First time here
 
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;
 
592
        }
 
593
        else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
 
594
        {
 
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;
 
602
        }
 
603
        else
 
604
        {
 
605
            // We've detected an ambiguous cast from (static_ptr, static_type)
 
606
            //   to a dst_type
 
607
            info->number_to_static_ptr += 1;
 
608
            info->search_done = true;
 
609
        }
 
610
    }
 
611
}
 
612
 
 
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.
 
617
void
 
618
__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
 
619
                                                 const void* current_ptr,
 
620
                                                 int path_below) const
 
621
{
 
622
    if (current_ptr == info->static_ptr)
 
623
    {
 
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;
 
628
    }
 
629
}
 
630
 
 
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
 
634
// above.
 
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:
 
644
// void
 
645
// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
 
646
//                                         const void* current_ptr,
 
647
//                                         int path_below) const
 
648
// {
 
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)
 
653
//     {
 
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)
 
659
//         {
 
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
 
664
//         }
 
665
//         if (!does_dst_type_point_to_our_static_type)
 
666
//         {
 
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;
 
672
//         }
 
673
//     }
 
674
//     else
 
675
//     {
 
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)
 
678
//         {
 
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
 
681
//         }
 
682
//     }
 
683
// }
 
684
void
 
685
__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
 
686
                                        const void* current_ptr,
 
687
                                        int path_below,
 
688
                                        bool use_strcmp) const
 
689
{
 
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))
 
694
    {
 
695
        // We've been here before if we've recorded current_ptr in one of these
 
696
        //   two places:
 
697
        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
 
698
            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
 
699
        {
 
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;
 
705
        }
 
706
        else  // We have haven't been here before
 
707
        {
 
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)
 
714
            {
 
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)
 
726
                //        above here.
 
727
                const Iter e = __base_info + __base_count;
 
728
                for (Iter p = __base_info; p < e; ++p)
 
729
                {
 
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)
 
735
                        break;
 
736
                    if (info->found_any_static_type)
 
737
                    {
 
738
                        is_dst_type_derived_from_static_type = true;
 
739
                        if (info->found_our_static_ptr)
 
740
                        {
 
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)
 
744
                                break;
 
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))
 
749
                                break;
 
750
                        }
 
751
                        else
 
752
                        {
 
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))
 
757
                                break;
 
758
                        }
 
759
                    }
 
760
                }
 
761
                if (!does_dst_type_point_to_our_static_type)
 
762
                {
 
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,
 
771
                    //      so stop search.
 
772
                    if (info->number_to_static_ptr == 1 &&
 
773
                            info->path_dst_ptr_to_static_ptr == not_public_path)
 
774
                        info->search_done = true;
 
775
                }
 
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;
 
782
                else
 
783
                    info->is_dst_type_derived_from_static_type = no;
 
784
            }
 
785
        }
 
786
    }
 
787
    else
 
788
    {
 
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);
 
793
        if (++p < e)
 
794
        {
 
795
            if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
 
796
            {
 
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.
 
801
                do
 
802
                {
 
803
                    if (info->search_done)
 
804
                        break;
 
805
                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
 
806
                } while (++p < e);
 
807
            }
 
808
            else if (__flags & __non_diamond_repeat_mask)
 
809
            {
 
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
 
812
                //   found.
 
813
                do
 
814
                {
 
815
                    if (info->search_done)
 
816
                        break;
 
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)
 
823
                        break;
 
824
                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
 
825
                } while (++p < e);
 
826
            }
 
827
            else
 
828
            {
 
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)
 
832
                do
 
833
                {
 
834
                    if (info->search_done)
 
835
                        break;
 
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)
 
846
                        break;
 
847
                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
 
848
                } while (++p < e);
 
849
            }
 
850
        }
 
851
    }
 
852
}
 
853
 
 
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.
 
856
void
 
857
__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
 
858
                                       const void* current_ptr,
 
859
                                       int path_below,
 
860
                                       bool use_strcmp) const
 
861
{
 
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))
 
865
    {
 
866
        // We've been here before if we've recorded current_ptr in one of these
 
867
        //   two places:
 
868
        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
 
869
            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
 
870
        {
 
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;
 
876
        }
 
877
        else  // We have haven't been here before
 
878
        {
 
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)
 
885
            {
 
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)
 
894
                {
 
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;
 
898
                }
 
899
                if (!does_dst_type_point_to_our_static_type)
 
900
                {
 
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;
 
912
                }
 
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;
 
919
                else
 
920
                    info->is_dst_type_derived_from_static_type = no;
 
921
            }
 
922
        }
 
923
    }
 
924
    else
 
925
    {
 
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);
 
928
    }
 
929
}
 
930
 
 
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.
 
933
void
 
934
__class_type_info::search_below_dst(__dynamic_cast_info* info,
 
935
                                    const void* current_ptr,
 
936
                                    int path_below,
 
937
                                    bool use_strcmp) const
 
938
{
 
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))
 
943
    {
 
944
        // We've been here before if we've recorded current_ptr in one of these
 
945
        //   two places:
 
946
        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
 
947
            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
 
948
        {
 
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;
 
954
        }
 
955
        else  // We have haven't been here before
 
956
        {
 
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;
 
973
        }
 
974
    }
 
975
}
 
976
 
 
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:
 
984
// void
 
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
 
989
// {
 
990
//     if (this == info->static_type)
 
991
//         process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
 
992
//     else
 
993
//     {
 
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)
 
997
//         {
 
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
 
1000
//         }
 
1001
//     }
 
1002
// }
 
1003
void
 
1004
__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
 
1005
                                        const void* dst_ptr,
 
1006
                                        const void* current_ptr,
 
1007
                                        int path_below,
 
1008
                                        bool use_strcmp) const
 
1009
{
 
1010
    if (is_equal(this, info->static_type, use_strcmp))
 
1011
        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
 
1012
    else
 
1013
    {
 
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)
 
1027
        //        above here.
 
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);
 
1034
        if (++p < e)
 
1035
        {
 
1036
            do
 
1037
            {
 
1038
                if (info->search_done)
 
1039
                    break;
 
1040
                if (info->found_our_static_ptr)
 
1041
                {
 
1042
                    // If we found what we're looking for, stop looking above.
 
1043
                    if (info->path_dst_ptr_to_static_ptr == public_path)
 
1044
                        break;
 
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))
 
1049
                        break;
 
1050
                }
 
1051
                else if (info->found_any_static_type)
 
1052
                {
 
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))
 
1057
                        break;
 
1058
                }
 
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);
 
1063
            } while (++p < e);
 
1064
        }
 
1065
        // Restore flags
 
1066
        info->found_our_static_ptr = found_our_static_ptr;
 
1067
        info->found_any_static_type = found_any_static_type;
 
1068
    }
 
1069
}
 
1070
 
 
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.
 
1073
void
 
1074
__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
 
1075
                                       const void* dst_ptr,
 
1076
                                       const void* current_ptr,
 
1077
                                       int path_below,
 
1078
                                       bool use_strcmp) const
 
1079
{
 
1080
    if (is_equal(this, info->static_type, use_strcmp))
 
1081
        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
 
1082
    else
 
1083
        __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
 
1084
}
 
1085
 
 
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.
 
1088
void
 
1089
__class_type_info::search_above_dst(__dynamic_cast_info* info,
 
1090
                                    const void* dst_ptr,
 
1091
                                    const void* current_ptr,
 
1092
                                    int path_below,
 
1093
                                    bool use_strcmp) const
 
1094
{
 
1095
    if (is_equal(this, info->static_type, use_strcmp))
 
1096
        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
 
1097
}
 
1098
 
 
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.
 
1102
 
 
1103
void
 
1104
__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
 
1105
                                         const void* dst_ptr,
 
1106
                                         const void* current_ptr,
 
1107
                                         int path_below,
 
1108
                                         bool use_strcmp) const
 
1109
{
 
1110
    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
 
1111
    if (__offset_flags & __virtual_mask)
 
1112
    {
 
1113
        const char* vtable = *static_cast<const char*const*>(current_ptr);
 
1114
        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
 
1115
    }
 
1116
    __base_type->search_above_dst(info, dst_ptr,
 
1117
                                  static_cast<const char*>(current_ptr) + offset_to_base,
 
1118
                                  (__offset_flags & __public_mask) ?
 
1119
                                      path_below :
 
1120
                                      not_public_path,
 
1121
                                  use_strcmp);
 
1122
}
 
1123
 
 
1124
void
 
1125
__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
 
1126
                                         const void* current_ptr,
 
1127
                                         int path_below,
 
1128
                                         bool use_strcmp) const
 
1129
{
 
1130
    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
 
1131
    if (__offset_flags & __virtual_mask)
 
1132
    {
 
1133
        const char* vtable = *static_cast<const char*const*>(current_ptr);
 
1134
        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
 
1135
    }
 
1136
    __base_type->search_below_dst(info,
 
1137
                                  static_cast<const char*>(current_ptr) + offset_to_base,
 
1138
                                  (__offset_flags & __public_mask) ?
 
1139
                                      path_below :
 
1140
                                      not_public_path,
 
1141
                                  use_strcmp);
 
1142
}
 
1143
 
 
1144
#pragma GCC visibility pop
 
1145
 
 
1146
}  // __cxxabiv1