private_typeinfo.cpp revision 552b14000a3063cfa561fd3f9fd3c26259e7ca31
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#if __APPLE__
13#include <sys/syslog.h>
14#endif
15
16namespace __cxxabiv1
17{
18
19#pragma GCC visibility push(hidden)
20
21// __shim_type_info
22
23__shim_type_info::~__shim_type_info()
24{
25}
26
27void __shim_type_info::noop1() const {}
28void __shim_type_info::noop2() const {}
29
30// __fundamental_type_info
31
32// This miraculously (compiler magic) emits the type_info's for:
33//   1. all of the fundamental types
34//   2. pointers to all of the fundamental types
35//   3. pointers to all of the const fundamental types
36__fundamental_type_info::~__fundamental_type_info()
37{
38}
39
40// __array_type_info
41
42__array_type_info::~__array_type_info()
43{
44}
45
46// __function_type_info
47
48__function_type_info::~__function_type_info()
49{
50}
51
52// __enum_type_info
53
54__enum_type_info::~__enum_type_info()
55{
56}
57
58// __class_type_info
59
60__class_type_info::~__class_type_info()
61{
62}
63
64// __si_class_type_info
65
66__si_class_type_info::~__si_class_type_info()
67{
68}
69
70// __vmi_class_type_info
71
72__vmi_class_type_info::~__vmi_class_type_info()
73{
74}
75
76// __pbase_type_info
77
78__pbase_type_info::~__pbase_type_info()
79{
80}
81
82// __pointer_type_info
83
84__pointer_type_info::~__pointer_type_info()
85{
86}
87
88// __pointer_to_member_type_info
89
90__pointer_to_member_type_info::~__pointer_to_member_type_info()
91{
92}
93
94// can_catch
95
96// A handler is a match for an exception object of type E if
97//   1. The handler is of type cv T or cv T& and E and T are the same type
98//      (ignoring the top-level cv-qualifiers), or
99//   2. the handler is of type cv T or cv T& and T is an unambiguous public
100//       base class of E, or
101//   3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
102//      converted to the type of the handler by either or both of
103//      A. a standard pointer conversion (4.10) not involving conversions to
104//         pointers to private or protected or ambiguous classes
105//      B. a qualification conversion
106//   4. the handler is a pointer or pointer to member type and E is
107//      std::nullptr_t.
108
109// adjustedPtr:
110//
111// catch (A& a) : adjustedPtr == &a
112// catch (A* a) : adjustedPtr == a
113// catch (A** a) : adjustedPtr == a
114//
115// catch (D2& d2) : adjustedPtr == &d2  (d2 is base class of thrown object)
116// catch (D2* d2) : adjustedPtr == d2
117// catch (D2*& d2) : adjustedPtr == d2
118//
119// catch (...) : adjustedPtr == & of the exception
120
121// Handles bullet 1
122bool
123__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
124                                   void*&) const
125{
126    return this == thrown_type;
127}
128
129bool
130__array_type_info::can_catch(const __shim_type_info*, void*&) const
131{
132    // We can get here if someone tries to catch an array by reference.
133    //   However if someone tries to throw an array, it immediately gets
134    //   converted to a pointer, which will not convert back to an array
135    //   at the catch clause.  So this can never catch anything.
136    return false;
137}
138
139bool
140__function_type_info::can_catch(const __shim_type_info*, void*&) const
141{
142    // We can get here if someone tries to catch a function by reference.
143    //   However if someone tries to throw a function, it immediately gets
144    //   converted to a pointer, which will not convert back to a function
145    //   at the catch clause.  So this can never catch anything.
146    return false;
147}
148
149// Handles bullet 1
150bool
151__enum_type_info::can_catch(const __shim_type_info* thrown_type,
152                            void*&) const
153{
154    return this == thrown_type;
155}
156
157#pragma clang diagnostic push
158#pragma clang diagnostic ignored "-Wmissing-field-initializers"
159
160// Handles bullets 1 and 2
161bool
162__class_type_info::can_catch(const __shim_type_info* thrown_type,
163                             void*& adjustedPtr) const
164{
165    // bullet 1
166    if (this == thrown_type)
167        return true;
168    const __class_type_info* thrown_class_type =
169        dynamic_cast<const __class_type_info*>(thrown_type);
170    if (thrown_class_type == 0)
171        return false;
172    // bullet 2
173    __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0};
174    info.number_of_dst_type = 1;
175    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
176    if (info.path_dst_ptr_to_static_ptr == public_path)
177    {
178        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
179        return true;
180    }
181    return false;
182}
183
184#pragma clang diagnostic pop
185
186void
187__class_type_info::process_found_base_class(__dynamic_cast_info* info,
188                                               void* adjustedPtr,
189                                               int path_below) const
190{
191    if (info->dst_ptr_leading_to_static_ptr == 0)
192    {
193        // First time here
194        info->dst_ptr_leading_to_static_ptr = adjustedPtr;
195        info->path_dst_ptr_to_static_ptr = path_below;
196        info->number_to_static_ptr = 1;
197    }
198    else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
199    {
200        // We've been here before.  Update path to "most public"
201        if (info->path_dst_ptr_to_static_ptr == not_public_path)
202            info->path_dst_ptr_to_static_ptr = path_below;
203    }
204    else
205    {
206        // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
207        //   to a static_type
208        info->number_to_static_ptr += 1;
209        info->path_dst_ptr_to_static_ptr = not_public_path;
210        info->search_done = true;
211    }
212}
213
214void
215__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
216                                               void* adjustedPtr,
217                                               int path_below) const
218{
219    if (this == info->static_type)
220        process_found_base_class(info, adjustedPtr, path_below);
221}
222
223void
224__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
225                                                  void* adjustedPtr,
226                                                  int path_below) const
227{
228    if (this == info->static_type)
229        process_found_base_class(info, adjustedPtr, path_below);
230    else
231        __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
232}
233
234void
235__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
236                                                    void* adjustedPtr,
237                                                    int path_below) const
238{
239    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
240    if (__offset_flags & __virtual_mask)
241    {
242        const char* vtable = *static_cast<const char*const*>(adjustedPtr);
243        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
244    }
245    __base_type->has_unambiguous_public_base(info,
246                                             static_cast<char*>(adjustedPtr) + offset_to_base,
247                                             (__offset_flags & __public_mask) ?
248                                                 path_below :
249                                                 not_public_path);
250}
251
252void
253__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
254                                                   void* adjustedPtr,
255                                                   int path_below) const
256{
257    if (this == info->static_type)
258        process_found_base_class(info, adjustedPtr, path_below);
259    else
260    {
261        typedef const __base_class_type_info* Iter;
262        const Iter e = __base_info + __base_count;
263        Iter p = __base_info;
264        p->has_unambiguous_public_base(info, adjustedPtr, path_below);
265        if (++p < e)
266        {
267            do
268            {
269                p->has_unambiguous_public_base(info, adjustedPtr, path_below);
270                if (info->search_done)
271                    break;
272            } while (++p < e);
273        }
274    }
275}
276
277// Handles bullets 1 and 4 for both pointers and member pointers
278bool
279__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
280                             void*&) const
281{
282    if (this == thrown_type)
283        return true;
284    return thrown_type == &typeid(std::nullptr_t);
285}
286
287#pragma clang diagnostic push
288#pragma clang diagnostic ignored "-Wmissing-field-initializers"
289
290// Handles bullets 1, 3 and 4
291bool
292__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
293                               void*& adjustedPtr) const
294{
295    // Do the dereference adjustment
296    adjustedPtr = *static_cast<void**>(adjustedPtr);
297    // bullets 1 and 4
298    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
299        return true;
300    // bullet 3
301    const __pointer_type_info* thrown_pointer_type =
302        dynamic_cast<const __pointer_type_info*>(thrown_type);
303    if (thrown_pointer_type == 0)
304        return false;
305    // bullet 3B
306    if (thrown_pointer_type->__flags & ~__flags)
307        return false;
308    if (__pointee == thrown_pointer_type->__pointee)
309        return true;
310    // bullet 3A
311    if (__pointee == &typeid(void))
312        return true;
313    const __class_type_info* catch_class_type =
314        dynamic_cast<const __class_type_info*>(__pointee);
315    if (catch_class_type == 0)
316        return false;
317    const __class_type_info* thrown_class_type =
318        dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
319    if (thrown_class_type == 0)
320        return false;
321    __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0};
322    info.number_of_dst_type = 1;
323    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
324    if (info.path_dst_ptr_to_static_ptr == public_path)
325    {
326        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
327        return true;
328    }
329    return false;
330}
331
332#pragma clang diagnostic pop
333
334#pragma GCC visibility pop
335#pragma GCC visibility push(default)
336
337#pragma clang diagnostic push
338#pragma clang diagnostic ignored "-Wmissing-field-initializers"
339
340// __dynamic_cast
341
342// static_ptr: pointer to an object of type static_type; nonnull, and since the
343//   object is polymorphic, *(void**)static_ptr is a virtual table pointer.
344//   static_ptr is &v in the expression dynamic_cast<T>(v).
345// static_type: static type of the object pointed to by static_ptr.
346// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
347// src2dst_offset: a static hint about the location of the
348//                 source subobject with respect to the complete object;
349//                 special negative values are:
350//                     -1: no hint
351//                     -2: static_type is not a public base of dst_type
352//                     -3: static_type is a multiple public base type but never a
353//                         virtual base type
354//                 otherwise, the static_type type is a unique public nonvirtual
355//                 base type of dst_type at offset src2dst_offset from the
356//                 origin of dst_type.
357//
358// (dynamic_ptr, dynamic_type) are the run time type of the complete object
359// referred to by static_ptr and a pointer to it.  These can be found from
360// static_ptr for polymorphic types.
361// static_type is guaranteed to be a polymorphic type.
362//
363// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward.  Each
364// node of the tree represents a base class/object of its parent (or parents) below.
365// Each node is uniquely represented by a pointer to the object, and a pointer
366// to a type_info - its type.  Different nodes may have the same pointer and
367// different nodes may have the same type.  But only one node has a specific
368// (pointer-value, type) pair.  In C++ two objects of the same type can not
369// share the same address.
370//
371// There are two flavors of nodes which have the type dst_type:
372//    1.  Those that are derived from (below) (static_ptr, static_type).
373//    2.  Those that are not derived from (below) (static_ptr, static_type).
374//
375// Invariants of the DAG:
376//
377// There is at least one path from the root (dynamic_ptr, dynamic_type) to
378// the node (static_ptr, static_type).  This path may or may not be public.
379// There may be more than one such path (some public some not).  Such a path may
380// or may not go through a node having type dst_type.
381//
382// No node of type T appears above a node of the same type.  That means that
383// there is only one node with dynamic_type.  And if dynamic_type == dst_type,
384// then there is only one dst_type in the DAG.
385//
386// No node of type dst_type appears above a node of type static_type.  Such
387// DAG's are possible in C++, but the compiler computes those dynamic_casts at
388// compile time, and only calls __dynamic_cast when dst_type lies below
389// static_type in the DAG.
390//
391// dst_type != static_type:  The compiler computes the dynamic_cast in this case too.
392// dynamic_type != static_type:  The compiler computes the dynamic_cast in this case too.
393//
394// Returns:
395//
396// If there is exactly one dst_type of flavor 1, and
397//    If there is a public path from that dst_type to (static_ptr, static_type), or
398//    If there are 0 dst_types of flavor 2, and there is a public path from
399//        (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
400//        path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
401//        a pointer to that dst_type.
402// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
403//    if there is a public path from (dynamic_ptr, dynamic_type) to
404//    (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
405//    to the one dst_type, then return a pointer to that one dst_type.
406// Else return nullptr.
407//
408// If dynamic_type == dst_type, then the above algorithm collapses to the
409// following cheaper algorithm:
410//
411// If there is a public path from (dynamic_ptr, dynamic_type) to
412//    (static_ptr, static_type), then return dynamic_ptr.
413// Else return nullptr.
414extern "C"
415void*
416__dynamic_cast(const void* static_ptr,
417               const __class_type_info* static_type,
418               const __class_type_info* dst_type,
419               std::ptrdiff_t src2dst_offset)
420{
421    // Possible future optimization:  Take advantage of src2dst_offset
422    // Currently clang always sets src2dst_offset to -1 (no hint).
423
424    // Get (dynamic_ptr, dynamic_type) from static_ptr
425    void** vtable = *(void***)static_ptr;
426    ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
427    const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
428    const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
429
430    // Initialize answer to nullptr.  This will be changed from the search
431    //    results if a non-null answer is found.  Regardless, this is what will
432    //    be returned.
433    const void* dst_ptr = 0;
434    // Initialize info struct for this search.
435    __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
436
437    // Find out if we can use a giant short cut in the search
438    if (dynamic_type == dst_type)
439    {
440        // Using giant short cut.  Add that information to info.
441        info.number_of_dst_type = 1;
442        // Do the  search
443        dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path);
444#if __APPLE__
445        // The following if should always be false because we should definitely
446        //   find (static_ptr, static_type), either on a public or private path
447        if (info.path_dst_ptr_to_static_ptr == unknown)
448        {
449            // We get here only if there is some kind of visibility problem
450            //   in client code.
451            syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
452                    "should have public visibility.  At least of of them is hidden. %s"
453                    ", %s.\n", static_type->name(), dynamic_type->name());
454            info.path_dst_ptr_to_static_ptr = public_path;
455        }
456#endif  // __APPLE__
457        // Query the search.
458        if (info.path_dst_ptr_to_static_ptr == public_path)
459            dst_ptr = dynamic_ptr;
460    }
461    else
462    {
463        // Not using giant short cut.  Do the search
464        dynamic_type->search_below_dst(&info, dynamic_ptr, public_path);
465 #if __APPLE__
466        // The following if should always be false because we should definitely
467        //   find (static_ptr, static_type), either on a public or private path
468       if (info.path_dst_ptr_to_static_ptr == unknown &&
469            info.path_dynamic_ptr_to_static_ptr == unknown)
470        {
471            syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
472                            " has hidden visibility.  They should all have public visibility.  "
473                            " %s, %s, %s.\n", static_type->name(), dynamic_type->name(),
474                    dst_type->name());
475        }
476#endif  // __APPLE__
477        // Query the search.
478        switch (info.number_to_static_ptr)
479        {
480        case 0:
481            if (info.number_to_dst_ptr == 1 &&
482                    info.path_dynamic_ptr_to_static_ptr == public_path &&
483                    info.path_dynamic_ptr_to_dst_ptr == public_path)
484                dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
485            break;
486        case 1:
487            if (info.path_dst_ptr_to_static_ptr == public_path ||
488                   (
489                       info.number_to_dst_ptr == 0 &&
490                       info.path_dynamic_ptr_to_static_ptr == public_path &&
491                       info.path_dynamic_ptr_to_dst_ptr == public_path
492                   )
493               )
494                dst_ptr = info.dst_ptr_leading_to_static_ptr;
495            break;
496        }
497    }
498    return const_cast<void*>(dst_ptr);
499}
500
501#pragma clang diagnostic pop
502
503#pragma GCC visibility pop
504#pragma GCC visibility push(hidden)
505
506// Call this function when you hit a static_type which is a base (above) a dst_type.
507// Let caller know you hit a static_type.  But only start recording details if
508// this is (static_ptr, static_type) -- the node we are casting from.
509// If this is (static_ptr, static_type)
510//   Record the path (public or not) from the dst_type to here.  There may be
511//   multiple paths from the same dst_type to here, record the "most public" one.
512//   Record the dst_ptr as pointing to (static_ptr, static_type).
513//   If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
514//   then mark this dyanmic_cast as ambiguous and stop the search.
515void
516__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
517                                                 const void* dst_ptr,
518                                                 const void* current_ptr,
519                                                 int path_below) const
520{
521    // Record that we found a static_type
522    info->found_any_static_type = true;
523    if (current_ptr == info->static_ptr)
524    {
525        // Record that we found (static_ptr, static_type)
526        info->found_our_static_ptr = true;
527        if (info->dst_ptr_leading_to_static_ptr == 0)
528        {
529            // First time here
530            info->dst_ptr_leading_to_static_ptr = dst_ptr;
531            info->path_dst_ptr_to_static_ptr = path_below;
532            info->number_to_static_ptr = 1;
533            // If there is only one dst_type in the entire tree and the path from
534            //    there to here is public then we are done!
535            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
536                info->search_done = true;
537        }
538        else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
539        {
540            // We've been here before.  Update path to "most public"
541            if (info->path_dst_ptr_to_static_ptr == not_public_path)
542                info->path_dst_ptr_to_static_ptr = path_below;
543            // If there is only one dst_type in the entire tree and the path from
544            //    there to here is public then we are done!
545            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
546                info->search_done = true;
547        }
548        else
549        {
550            // We've detected an ambiguous cast from (static_ptr, static_type)
551            //   to a dst_type
552            info->number_to_static_ptr += 1;
553            info->search_done = true;
554        }
555    }
556}
557
558// Call this function when you hit a static_type which is not a base (above) a dst_type.
559// If this is (static_ptr, static_type)
560//   Record the path (public or not) from (dynamic_ptr, dynamic_type) to here.  There may be
561//   multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
562void
563__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
564                                                 const void* current_ptr,
565                                                 int path_below) const
566{
567    if (current_ptr == info->static_ptr)
568    {
569        // Record the most public path from (dynamic_ptr, dynamic_type) to
570        //                                  (static_ptr, static_type)
571        if (info->path_dynamic_ptr_to_static_ptr != public_path)
572            info->path_dynamic_ptr_to_static_ptr = path_below;
573    }
574}
575
576// Call this function when searching below a dst_type node.  This function searches
577// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
578// If it finds a static_type node, there is no need to further search base classes
579// above.
580// If it finds a dst_type node it should search base classes using search_above_dst
581// to find out if this dst_type points to (static_ptr, static_type) or not.
582// Either way, the dst_type is recorded as one of two "flavors":  one that does
583// or does not point to (static_ptr, static_type).
584// If this is neither a static_type nor a dst_type node, continue searching
585// base classes above.
586// All the hoopla surrounding the search code is doing nothing but looking for
587// excuses to stop the search prematurely (break out of the for-loop).  That is,
588// the algorithm below is simply an optimization of this:
589// void
590// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
591//                                         const void* current_ptr,
592//                                         int path_below) const
593// {
594//     typedef const __base_class_type_info* Iter;
595//     if (this == info->static_type)
596//         process_static_type_below_dst(info, current_ptr, path_below);
597//     else if (this == info->dst_type)
598//     {
599//         // Record the most public access path that got us here
600//         if (info->path_dynamic_ptr_to_dst_ptr != public_path)
601//             info->path_dynamic_ptr_to_dst_ptr = path_below;
602//         bool does_dst_type_point_to_our_static_type = false;
603//         for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
604//         {
605//             p->search_above_dst(info, current_ptr, current_ptr, public_path);
606//             if (info->found_our_static_ptr)
607//                 does_dst_type_point_to_our_static_type = true;
608//             // break out early here if you can detect it doesn't matter if you do
609//         }
610//         if (!does_dst_type_point_to_our_static_type)
611//         {
612//             // We found a dst_type that doesn't point to (static_ptr, static_type)
613//             // So record the address of this dst_ptr and increment the
614//             // count of the number of such dst_types found in the tree.
615//             info->dst_ptr_not_leading_to_static_ptr = current_ptr;
616//             info->number_to_dst_ptr += 1;
617//         }
618//     }
619//     else
620//     {
621//         // This is not a static_type and not a dst_type.
622//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
623//         {
624//             p->search_below_dst(info, current_ptr, public_path);
625//             // break out early here if you can detect it doesn't matter if you do
626//         }
627//     }
628// }
629void
630__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
631                                        const void* current_ptr,
632                                        int path_below) const
633{
634    typedef const __base_class_type_info* Iter;
635    if (this == info->static_type)
636        process_static_type_below_dst(info, current_ptr, path_below);
637    else if (this == info->dst_type)
638    {
639        // We've been here before if we've recorded current_ptr in one of these
640        //   two places:
641        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
642            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
643        {
644            // We've seen this node before, and therefore have already searched
645            // its base classes above.
646            //  Update path to here that is "most public".
647            if (path_below == public_path)
648                info->path_dynamic_ptr_to_dst_ptr = public_path;
649        }
650        else  // We have haven't been here before
651        {
652            // Record the access path that got us here
653            //   If there is more than one dst_type this path doesn't matter.
654            info->path_dynamic_ptr_to_dst_ptr = path_below;
655            // Only search above here if dst_type derives from static_type, or
656            //    if it is unknown if dst_type derives from static_type.
657            if (info->is_dst_type_derived_from_static_type != no)
658            {
659                // Set up flags to record results from all base classes
660                bool is_dst_type_derived_from_static_type = false;
661                bool does_dst_type_point_to_our_static_type = false;
662                // We've found a dst_type with a potentially public path to here.
663                // We have to assume the path is public because it may become
664                //   public later (if we get back to here with a public path).
665                // We can stop looking above if:
666                //    1.  We've found a public path to (static_ptr, static_type).
667                //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
668                //        This is detected at the (static_ptr, static_type).
669                //    3.  We can prove that there is no public path to (static_ptr, static_type)
670                //        above here.
671                const Iter e = __base_info + __base_count;
672                for (Iter p = __base_info; p < e; ++p)
673                {
674                    // Zero out found flags
675                    info->found_our_static_ptr = false;
676                    info->found_any_static_type = false;
677                    p->search_above_dst(info, current_ptr, current_ptr, public_path);
678                    if (info->search_done)
679                        break;
680                    if (info->found_any_static_type)
681                    {
682                        is_dst_type_derived_from_static_type = true;
683                        if (info->found_our_static_ptr)
684                        {
685                            does_dst_type_point_to_our_static_type = true;
686                            // If we found what we're looking for, stop looking above.
687                            if (info->path_dst_ptr_to_static_ptr == public_path)
688                                break;
689                            // We found a private path to (static_ptr, static_type)
690                            //   If there is no diamond then there is only one path
691                            //   to (static_ptr, static_type) and we just found it.
692                            if (!(__flags & __diamond_shaped_mask))
693                                break;
694                        }
695                        else
696                        {
697                            // If we found a static_type that isn't the one we're looking
698                            //    for, and if there are no repeated types above here,
699                            //    then stop looking.
700                            if (!(__flags & __non_diamond_repeat_mask))
701                                break;
702                        }
703                    }
704                }
705                if (!does_dst_type_point_to_our_static_type)
706                {
707                    // We found a dst_type that doesn't point to (static_ptr, static_type)
708                    // So record the address of this dst_ptr and increment the
709                    // count of the number of such dst_types found in the tree.
710                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
711                    info->number_to_dst_ptr += 1;
712                    // If there exists another dst with a private path to
713                    //    (static_ptr, static_type), then the cast from
714                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
715                    //      so stop search.
716                    if (info->number_to_static_ptr == 1 &&
717                            info->path_dst_ptr_to_static_ptr == not_public_path)
718                        info->search_done = true;
719                }
720                // If we found no static_type,s then dst_type doesn't derive
721                //   from static_type, else it does.  Record this result so that
722                //   next time we hit a dst_type we will know not to search above
723                //   it if it doesn't derive from static_type.
724                if (is_dst_type_derived_from_static_type)
725                    info->is_dst_type_derived_from_static_type = yes;
726                else
727                    info->is_dst_type_derived_from_static_type = no;
728            }
729        }
730    }
731    else
732    {
733        // This is not a static_type and not a dst_type.
734        const Iter e = __base_info + __base_count;
735        Iter p = __base_info;
736        p->search_below_dst(info, current_ptr, path_below);
737        if (++p < e)
738        {
739            if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
740            {
741                // If there are multiple paths to a base above from here, or if
742                //    a dst_type pointing to (static_ptr, static_type) has been found,
743                //    then there is no way to break out of this loop early unless
744                //    something below detects the search is done.
745                do
746                {
747                    if (info->search_done)
748                        break;
749                    p->search_below_dst(info, current_ptr, path_below);
750                } while (++p < e);
751            }
752            else if (__flags & __non_diamond_repeat_mask)
753            {
754                // There are not multiple paths to any base class from here and a
755                //   dst_type pointing to (static_ptr, static_type) has not yet been
756                //   found.
757                do
758                {
759                    if (info->search_done)
760                        break;
761                    // If we just found a dst_type with a public path to (static_ptr, static_type),
762                    //    then the only reason to continue the search is to make sure
763                    //    no other dst_type points to (static_ptr, static_type).
764                    //    If !diamond, then we don't need to search here.
765                    if (info->number_to_static_ptr == 1 &&
766                              info->path_dst_ptr_to_static_ptr == public_path)
767                        break;
768                    p->search_below_dst(info, current_ptr, path_below);
769                } while (++p < e);
770            }
771            else
772            {
773                // There are no repeated types above this node.
774                // There are no nodes with multiple parents above this node.
775                // no dst_type has been found to (static_ptr, static_type)
776                do
777                {
778                    if (info->search_done)
779                        break;
780                    // If we just found a dst_type with a public path to (static_ptr, static_type),
781                    //    then the only reason to continue the search is to make sure sure
782                    //    no other dst_type points to (static_ptr, static_type).
783                    //    If !diamond, then we don't need to search here.
784                    // if we just found a dst_type with a private path to (static_ptr, static_type),
785                    //    then we're only looking for a public path to (static_ptr, static_type)
786                    //    and to check for other dst_types.
787                    //    If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
788                    //    and not a dst_type under here.
789                    if (info->number_to_static_ptr == 1)
790                        break;
791                    p->search_below_dst(info, current_ptr, path_below);
792                } while (++p < e);
793            }
794        }
795    }
796}
797
798// This is the same algorithm as __vmi_class_type_info::search_below_dst but
799//   simplified to the case that there is only a single base class.
800void
801__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
802                                       const void* current_ptr,
803                                       int path_below) const
804{
805    if (this == info->static_type)
806        process_static_type_below_dst(info, current_ptr, path_below);
807    else if (this == info->dst_type)
808    {
809        // We've been here before if we've recorded current_ptr in one of these
810        //   two places:
811        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
812            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
813        {
814            // We've seen this node before, and therefore have already searched
815            // its base classes above.
816            //  Update path to here that is "most public".
817            if (path_below == public_path)
818                info->path_dynamic_ptr_to_dst_ptr = public_path;
819        }
820        else  // We have haven't been here before
821        {
822            // Record the access path that got us here
823            //   If there is more than one dst_type this path doesn't matter.
824            info->path_dynamic_ptr_to_dst_ptr = path_below;
825            // Only search above here if dst_type derives from static_type, or
826            //    if it is unknown if dst_type derives from static_type.
827            if (info->is_dst_type_derived_from_static_type != no)
828            {
829                // Set up flags to record results from all base classes
830                bool is_dst_type_derived_from_static_type = false;
831                bool does_dst_type_point_to_our_static_type = false;
832                // Zero out found flags
833                info->found_our_static_ptr = false;
834                info->found_any_static_type = false;
835                __base_type->search_above_dst(info, current_ptr, current_ptr, public_path);
836                if (info->found_any_static_type)
837                {
838                    is_dst_type_derived_from_static_type = true;
839                    if (info->found_our_static_ptr)
840                        does_dst_type_point_to_our_static_type = true;
841                }
842                if (!does_dst_type_point_to_our_static_type)
843                {
844                    // We found a dst_type that doesn't point to (static_ptr, static_type)
845                    // So record the address of this dst_ptr and increment the
846                    // count of the number of such dst_types found in the tree.
847                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
848                    info->number_to_dst_ptr += 1;
849                    // If there exists another dst with a private path to
850                    //    (static_ptr, static_type), then the cast from
851                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
852                    if (info->number_to_static_ptr == 1 &&
853                            info->path_dst_ptr_to_static_ptr == not_public_path)
854                        info->search_done = true;
855                }
856                // If we found no static_type,s then dst_type doesn't derive
857                //   from static_type, else it does.  Record this result so that
858                //   next time we hit a dst_type we will know not to search above
859                //   it if it doesn't derive from static_type.
860                if (is_dst_type_derived_from_static_type)
861                    info->is_dst_type_derived_from_static_type = yes;
862                else
863                    info->is_dst_type_derived_from_static_type = no;
864            }
865        }
866    }
867    else
868    {
869        // This is not a static_type and not a dst_type
870        __base_type->search_below_dst(info, current_ptr, path_below);
871    }
872}
873
874// This is the same algorithm as __vmi_class_type_info::search_below_dst but
875//   simplified to the case that there is no base class.
876void
877__class_type_info::search_below_dst(__dynamic_cast_info* info,
878                                    const void* current_ptr,
879                                    int path_below) const
880{
881    typedef const __base_class_type_info* Iter;
882    if (this == info->static_type)
883        process_static_type_below_dst(info, current_ptr, path_below);
884    else if (this == info->dst_type)
885    {
886        // We've been here before if we've recorded current_ptr in one of these
887        //   two places:
888        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
889            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
890        {
891            // We've seen this node before, and therefore have already searched
892            // its base classes above.
893            //  Update path to here that is "most public".
894            if (path_below == public_path)
895                info->path_dynamic_ptr_to_dst_ptr = public_path;
896        }
897        else  // We have haven't been here before
898        {
899            // Record the access path that got us here
900            //   If there is more than one dst_type this path doesn't matter.
901            info->path_dynamic_ptr_to_dst_ptr = path_below;
902            // We found a dst_type that doesn't point to (static_ptr, static_type)
903            // So record the address of this dst_ptr and increment the
904            // count of the number of such dst_types found in the tree.
905            info->dst_ptr_not_leading_to_static_ptr = current_ptr;
906            info->number_to_dst_ptr += 1;
907            // If there exists another dst with a private path to
908            //    (static_ptr, static_type), then the cast from
909            //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
910            if (info->number_to_static_ptr == 1 &&
911                    info->path_dst_ptr_to_static_ptr == not_public_path)
912                info->search_done = true;
913            // We found that dst_type does not derive from static_type
914            info->is_dst_type_derived_from_static_type = no;
915        }
916    }
917}
918
919// Call this function when searching above a dst_type node.  This function searches
920// for a public path to (static_ptr, static_type).
921// This function is guaranteed not to find a node of type dst_type.
922// Theoretically this is a very simple function which just stops if it finds a
923// static_type node:  All the hoopla surrounding the search code is doing
924// nothing but looking for excuses to stop the search prematurely (break out of
925// the for-loop).  That is, the algorithm below is simply an optimization of this:
926// void
927// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
928//                                         const void* dst_ptr,
929//                                         const void* current_ptr,
930//                                         int path_below) const
931// {
932//     if (this == info->static_type)
933//         process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
934//     else
935//     {
936//         typedef const __base_class_type_info* Iter;
937//         // This is not a static_type and not a dst_type
938//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
939//         {
940//             p->search_above_dst(info, dst_ptr, current_ptr, public_path);
941//             // break out early here if you can detect it doesn't matter if you do
942//         }
943//     }
944// }
945void
946__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
947                                        const void* dst_ptr,
948                                        const void* current_ptr,
949                                        int path_below) const
950{
951    if (this == info->static_type)
952        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
953    else
954    {
955        typedef const __base_class_type_info* Iter;
956        // This is not a static_type and not a dst_type
957        // Save flags so they can be restored when returning to nodes below.
958        bool found_our_static_ptr = info->found_our_static_ptr;
959        bool found_any_static_type = info->found_any_static_type;
960        // We've found a dst_type below with a path to here.  If the path
961        //    to here is not public, there may be another path to here that
962        //    is public.  So we have to assume that the path to here is public.
963        //  We can stop looking above if:
964        //    1.  We've found a public path to (static_ptr, static_type).
965        //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
966        //        This is detected at the (static_ptr, static_type).
967        //    3.  We can prove that there is no public path to (static_ptr, static_type)
968        //        above here.
969        const Iter e = __base_info + __base_count;
970        Iter p = __base_info;
971        // Zero out found flags
972        info->found_our_static_ptr = false;
973        info->found_any_static_type = false;
974        p->search_above_dst(info, dst_ptr, current_ptr, path_below);
975        if (++p < e)
976        {
977            do
978            {
979                if (info->search_done)
980                    break;
981                if (info->found_our_static_ptr)
982                {
983                    // If we found what we're looking for, stop looking above.
984                    if (info->path_dst_ptr_to_static_ptr == public_path)
985                        break;
986                    // We found a private path to (static_ptr, static_type)
987                    //   If there is no diamond then there is only one path
988                    //   to (static_ptr, static_type) from here and we just found it.
989                    if (!(__flags & __diamond_shaped_mask))
990                        break;
991                }
992                else if (info->found_any_static_type)
993                {
994                    // If we found a static_type that isn't the one we're looking
995                    //    for, and if there are no repeated types above here,
996                    //    then stop looking.
997                    if (!(__flags & __non_diamond_repeat_mask))
998                        break;
999                }
1000                // Zero out found flags
1001                info->found_our_static_ptr = false;
1002                info->found_any_static_type = false;
1003                p->search_above_dst(info, dst_ptr, current_ptr, path_below);
1004            } while (++p < e);
1005        }
1006        // Restore flags
1007        info->found_our_static_ptr = found_our_static_ptr;
1008        info->found_any_static_type = found_any_static_type;
1009    }
1010}
1011
1012// This is the same algorithm as __vmi_class_type_info::search_above_dst but
1013//   simplified to the case that there is only a single base class.
1014void
1015__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
1016                                       const void* dst_ptr,
1017                                       const void* current_ptr,
1018                                       int path_below) const
1019{
1020    if (this == info->static_type)
1021        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1022    else
1023        __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below);
1024}
1025
1026// This is the same algorithm as __vmi_class_type_info::search_above_dst but
1027//   simplified to the case that there is no base class.
1028void
1029__class_type_info::search_above_dst(__dynamic_cast_info* info,
1030                                    const void* dst_ptr,
1031                                    const void* current_ptr,
1032                                    int path_below) const
1033{
1034    if (this == info->static_type)
1035        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1036}
1037
1038// The search functions for __base_class_type_info are simply convenience
1039//   functions for adjusting the current_ptr and path_below as the search is
1040//   passed up to the base class node.
1041
1042void
1043__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
1044                                         const void* dst_ptr,
1045                                         const void* current_ptr,
1046                                         int path_below) const
1047{
1048    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
1049    if (__offset_flags & __virtual_mask)
1050    {
1051        const char* vtable = *static_cast<const char*const*>(current_ptr);
1052        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1053    }
1054    __base_type->search_above_dst(info, dst_ptr,
1055                                  static_cast<const char*>(current_ptr) + offset_to_base,
1056                                  (__offset_flags & __public_mask) ?
1057                                      path_below :
1058                                      not_public_path);
1059}
1060
1061void
1062__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
1063                                         const void* current_ptr,
1064                                         int path_below) const
1065{
1066    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
1067    if (__offset_flags & __virtual_mask)
1068    {
1069        const char* vtable = *static_cast<const char*const*>(current_ptr);
1070        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1071    }
1072    __base_type->search_below_dst(info,
1073                                  static_cast<const char*>(current_ptr) + offset_to_base,
1074                                  (__offset_flags & __public_mask) ?
1075                                      path_below :
1076                                      not_public_path);
1077}
1078
1079#pragma GCC visibility pop
1080
1081}  // __cxxabiv1
1082