private_typeinfo.cpp revision 6d00feffc82d4f8c0201242291a0e93b492e1dd4
1152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//===----------------------- private_typeinfo.cpp -------------------------===//
2152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//
3152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//                     The LLVM Compiler Infrastructure
4152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//
5152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
6152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// Source Licenses. See LICENSE.TXT for details.
7152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//
8152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//===----------------------------------------------------------------------===//
9152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant#include "private_typeinfo.h"
11152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more
13326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// forgiving when type_info's mistakenly have hidden visibility and thus
14326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// multiple type_infos can exist for a single type.
15326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
16326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where
17326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// there is a detected inconsistency in the type_info hierarchy during a
18326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// dynamic_cast, then the equality operation will fall back to using strcmp
196d00feffc82d4f8c0201242291a0e93b492e1dd4Howard Hinnant// on type_info names to determine type_info equality.
20326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
21326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// This change happens *only* under dynamic_cast, and only when
22326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// dynamic_cast is faced with the choice:  abort, or possibly give back the
23326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// wrong answer.  If when the dynamic_cast is done with this fallback
24326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// algorithm and an inconsistency is still detected, dynamic_cast will call
256d00feffc82d4f8c0201242291a0e93b492e1dd4Howard Hinnant// abort with an appropriate message.
26326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
27326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a
28326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// printf-like function called syslog:
29326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
30326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//     void syslog(const char* format, ...);
31326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
32326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// If you want this functionality but your platform doesn't have syslog,
33326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// just implement it in terms of fprintf(stderr, ...).
34326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
35326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// _LIBCXX_DYNAMIC_FALLBACK is currently off by default.
36326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
37326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#if _LIBCXX_DYNAMIC_FALLBACK
38326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#include "abort_message.h"
39326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#include <string.h>
401a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant#include <sys/syslog.h>
411a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant#endif
421a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant
43152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnantnamespace __cxxabiv1
44152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
45152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
460240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility push(hidden)
47facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
48326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#if _LIBCXX_DYNAMIC_FALLBACK
49326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
50326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
51326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
52326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
53326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
54326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (!use_strcmp)
55326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        return x == y;
56326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return strcmp(x->name(), y->name()) == 0;
57326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
58326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
59326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#else  // !_LIBCXX_DYNAMIC_FALLBACK
60326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
61326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
62326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
63326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool)
64326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
65326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return x == y;
66326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
67326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
68326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
69326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
70facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __shim_type_info
71facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
72facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant__shim_type_info::~__shim_type_info()
73facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
74facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
75facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
768f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop1() const {}
778f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop2() const {}
788f28628704f966409e860c74c46041e04c082720Howard Hinnant
79152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// __fundamental_type_info
80152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
8116650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant// This miraculously (compiler magic) emits the type_info's for:
8216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   1. all of the fundamental types
8316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   2. pointers to all of the fundamental types
8416650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   3. pointers to all of the const fundamental types
85152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant__fundamental_type_info::~__fundamental_type_info()
86152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
87152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
88152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
8935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __array_type_info
9035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
9135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__array_type_info::~__array_type_info()
92facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
93facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
94facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
9535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __function_type_info
96152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
9735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__function_type_info::~__function_type_info()
98152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
99152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
100152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __enum_type_info
10235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
10335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__enum_type_info::~__enum_type_info()
104facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
105facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
106facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
10735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __class_type_info
108152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__class_type_info::~__class_type_info()
110152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
111152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
112152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __si_class_type_info
11435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
11535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__si_class_type_info::~__si_class_type_info()
116facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
117facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
118facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
11935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __vmi_class_type_info
120152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__vmi_class_type_info::~__vmi_class_type_info()
122152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
123152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
124152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pbase_type_info
12635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
12735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pbase_type_info::~__pbase_type_info()
128facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
129facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
130facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
13135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_type_info
132152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
13335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_type_info::~__pointer_type_info()
13435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant{
13535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant}
13635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
13735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_to_member_type_info
13835b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
13935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_to_member_type_info::~__pointer_to_member_type_info()
140152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
141152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
142152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
143c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// can_catch
144c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
145c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// A handler is a match for an exception object of type E if
146a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   1. The handler is of type cv T or cv T& and E and T are the same type
147a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      (ignoring the top-level cv-qualifiers), or
148a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   2. the handler is of type cv T or cv T& and T is an unambiguous public
149a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//       base class of E, or
150a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
151a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      converted to the type of the handler by either or both of
152a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      A. a standard pointer conversion (4.10) not involving conversions to
153a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//         pointers to private or protected or ambiguous classes
154a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      B. a qualification conversion
155a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   4. the handler is a pointer or pointer to member type and E is
156a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      std::nullptr_t.
157c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
158c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// adjustedPtr:
159c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
160c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A& a) : adjustedPtr == &a
161c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A* a) : adjustedPtr == a
162c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A** a) : adjustedPtr == a
163c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
164c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2& d2) : adjustedPtr == &d2  (d2 is base class of thrown object)
165c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2* d2) : adjustedPtr == d2
166c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2*& d2) : adjustedPtr == d2
167c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
168c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (...) : adjustedPtr == & of the exception
169c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
170a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
171a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
172a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
173a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                   void*&) const
174a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
17506bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
176a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
177a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
178a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
17996f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__array_type_info::can_catch(const __shim_type_info*, void*&) const
180a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
181aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    // We can get here if someone tries to catch an array by reference.
182aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   However if someone tries to throw an array, it immediately gets
183aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   converted to a pointer, which will not convert back to an array
184aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   at the catch clause.  So this can never catch anything.
185a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
186a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
187a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
188a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
18996f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__function_type_info::can_catch(const __shim_type_info*, void*&) const
190a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
1914b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    // We can get here if someone tries to catch a function by reference.
1924b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   However if someone tries to throw a function, it immediately gets
1934b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   converted to a pointer, which will not convert back to a function
1944b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   at the catch clause.  So this can never catch anything.
195a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
196a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
197a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
198a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
199a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
200a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__enum_type_info::can_catch(const __shim_type_info* thrown_type,
201a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                            void*&) const
202a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
20306bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
204a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
205a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
20691f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
20791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
20891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
209a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1 and 2
210a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
211a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::can_catch(const __shim_type_info* thrown_type,
212a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*& adjustedPtr) const
213a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
214a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 1
21506bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, thrown_type, false))
216a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
217a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
218a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_type);
219a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
220a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
221a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 2
222a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0};
223a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
224a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
225a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
226a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
227a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
228a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
229a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
230a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
231a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
232a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
23391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
23491f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
235a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
236a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::process_found_base_class(__dynamic_cast_info* info,
237a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
238a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
239a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
240a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info->dst_ptr_leading_to_static_ptr == 0)
241a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
242a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // First time here
243a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->dst_ptr_leading_to_static_ptr = adjustedPtr;
244a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = path_below;
245a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr = 1;
246a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
247a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
248a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
249a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've been here before.  Update path to "most public"
250a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (info->path_dst_ptr_to_static_ptr == not_public_path)
251a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
252a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
253a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
254a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
255a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
256a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        //   to a static_type
257a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr += 1;
258a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = not_public_path;
259a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->search_done = true;
260a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
261a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
262a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
263a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
264a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
265a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
266a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
267a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
26806bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
269a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
270a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
271a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
272a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
273a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
274a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  void* adjustedPtr,
275a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  int path_below) const
276a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
27706bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
278a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
279a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
280a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
281a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
282a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
283a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
284a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
285a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    void* adjustedPtr,
286a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    int path_below) const
287a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
288a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
289a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (__offset_flags & __virtual_mask)
290a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
291a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        const char* vtable = *static_cast<const char*const*>(adjustedPtr);
292a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
293a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
294a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __base_type->has_unambiguous_public_base(info,
295a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                             static_cast<char*>(adjustedPtr) + offset_to_base,
296a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                             (__offset_flags & __public_mask) ?
297a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                 path_below :
298a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                 not_public_path);
299a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
300a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
301a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
302a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
303a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   void* adjustedPtr,
304a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   int path_below) const
305a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
30606bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
307a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
308a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
309a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
310a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        typedef const __base_class_type_info* Iter;
311a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        const Iter e = __base_info + __base_count;
312a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        Iter p = __base_info;
313a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        p->has_unambiguous_public_base(info, adjustedPtr, path_below);
314a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (++p < e)
315a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        {
316a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            do
317a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            {
318a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                p->has_unambiguous_public_base(info, adjustedPtr, path_below);
319a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                if (info->search_done)
320a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                    break;
321a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            } while (++p < e);
322a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        }
323a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
324a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
325a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
326c649bdea9d3f67756d97fa1c9a837f53a762dbccHoward Hinnant// Handles bullets 1 and 4 for both pointers and member pointers
327a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
328a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
329a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*&) const
330a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
33106bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, thrown_type, false))
332a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
33306bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(thrown_type, &typeid(std::nullptr_t), false);
334a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
335a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
33691f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
33791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
33891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
339a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1, 3 and 4
340a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
341a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
342a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                               void*& adjustedPtr) const
343a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
344a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // Do the dereference adjustment
345a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    adjustedPtr = *static_cast<void**>(adjustedPtr);
346a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullets 1 and 4
347a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
348a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
349a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3
350a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __pointer_type_info* thrown_pointer_type =
351a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __pointer_type_info*>(thrown_type);
352a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type == 0)
353a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
354a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3B
355a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type->__flags & ~__flags)
356a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
35706bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
358a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
359a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3A
36006bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, &typeid(void), false))
361a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
362a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* catch_class_type =
363a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(__pointee);
364a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (catch_class_type == 0)
365a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
366a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
367a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
368a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
369a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
370a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0};
371a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
372a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
373a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
374a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
375a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
376a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
377a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
378a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
379a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
380c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
38191f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
38291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
3830240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility pop
384facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(default)
385facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
38691f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
38791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
38891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
3891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// __dynamic_cast
3901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
391cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr: pointer to an object of type static_type; nonnull, and since the
392cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   object is polymorphic, *(void**)static_ptr is a virtual table pointer.
393cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   static_ptr is &v in the expression dynamic_cast<T>(v).
394cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type: static type of the object pointed to by static_ptr.
395cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
3961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// src2dst_offset: a static hint about the location of the
3971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 source subobject with respect to the complete object;
3981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 special negative values are:
3991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -1: no hint
4001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -2: static_type is not a public base of dst_type
4011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -3: static_type is a multiple public base type but never a
4021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                         virtual base type
4031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 otherwise, the static_type type is a unique public nonvirtual
4041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 base type of dst_type at offset src2dst_offset from the
4051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 origin of dst_type.
4061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
407cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) are the run time type of the complete object
408cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// referred to by static_ptr and a pointer to it.  These can be found from
409cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr for polymorphic types.
4101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// static_type is guaranteed to be a polymorphic type.
4111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
412cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward.  Each
413cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// node of the tree represents a base class/object of its parent (or parents) below.
414cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Each node is uniquely represented by a pointer to the object, and a pointer
415cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// to a type_info - its type.  Different nodes may have the same pointer and
416cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// different nodes may have the same type.  But only one node has a specific
417cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (pointer-value, type) pair.  In C++ two objects of the same type can not
418cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// share the same address.
419cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
420cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There are two flavors of nodes which have the type dst_type:
421cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    1.  Those that are derived from (below) (static_ptr, static_type).
422cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    2.  Those that are not derived from (below) (static_ptr, static_type).
423cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
424cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Invariants of the DAG:
425cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
426cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There is at least one path from the root (dynamic_ptr, dynamic_type) to
427cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// the node (static_ptr, static_type).  This path may or may not be public.
428cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There may be more than one such path (some public some not).  Such a path may
429cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// or may not go through a node having type dst_type.
430cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
431cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type T appears above a node of the same type.  That means that
432cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// there is only one node with dynamic_type.  And if dynamic_type == dst_type,
433cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// then there is only one dst_type in the DAG.
434cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
435cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type dst_type appears above a node of type static_type.  Such
436cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// DAG's are possible in C++, but the compiler computes those dynamic_casts at
437cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// compile time, and only calls __dynamic_cast when dst_type lies below
438cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type in the DAG.
439cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
440cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type != static_type:  The compiler computes the dynamic_cast in this case too.
441facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// dynamic_type != static_type:  The compiler computes the dynamic_cast in this case too.
442cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
443cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Returns:
444cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
445cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// If there is exactly one dst_type of flavor 1, and
4461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    If there is a public path from that dst_type to (static_ptr, static_type), or
447cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    If there are 0 dst_types of flavor 2, and there is a public path from
4481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
4491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
4501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        a pointer to that dst_type.
451cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
452facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//    if there is a public path from (dynamic_ptr, dynamic_type) to
4531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
4541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    to the one dst_type, then return a pointer to that one dst_type.
4551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
4561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
4571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If dynamic_type == dst_type, then the above algorithm collapses to the
4581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// following cheaper algorithm:
4591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
4601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If there is a public path from (dynamic_ptr, dynamic_type) to
4611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type), then return dynamic_ptr.
4621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
4631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantextern "C"
4641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid*
4651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__dynamic_cast(const void* static_ptr,
4660240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               const __class_type_info* static_type,
4670240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               const __class_type_info* dst_type,
4680240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               std::ptrdiff_t src2dst_offset)
4691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
4700550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Possible future optimization:  Take advantage of src2dst_offset
4710550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Currently clang always sets src2dst_offset to -1 (no hint).
472cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
473cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Get (dynamic_ptr, dynamic_type) from static_ptr
4741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    void** vtable = *(void***)static_ptr;
475cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
476cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
477cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
478cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
479cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize answer to nullptr.  This will be changed from the search
480cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    results if a non-null answer is found.  Regardless, this is what will
481cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    be returned.
4821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    const void* dst_ptr = 0;
483cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize info struct for this search.
4841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
485cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
486cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Find out if we can use a giant short cut in the search
48706bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(dynamic_type, dst_type, false))
488f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
489cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Using giant short cut.  Add that information to info.
4901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info.number_of_dst_type = 1;
491cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Do the  search
492326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
493326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#if _LIBCXX_DYNAMIC_FALLBACK
4941a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
4951a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
4961a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown)
4971a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
4981a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            // We get here only if there is some kind of visibility problem
4991a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            //   in client code.
500552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
501552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                    "should have public visibility.  At least of of them is hidden. %s"
502552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                    ", %s.\n", static_type->name(), dynamic_type->name());
503326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
504326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
505326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info.number_of_dst_type = 1;
506326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
5071a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
508326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
509cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
5101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info.path_dst_ptr_to_static_ptr == public_path)
5111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            dst_ptr = dynamic_ptr;
5121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
5131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
5141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
515cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Not using giant short cut.  Do the search
516326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
517326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant #if _LIBCXX_DYNAMIC_FALLBACK
5181a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
5191a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
520326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown &&
5211a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            info.path_dynamic_ptr_to_static_ptr == unknown)
5221a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
523552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
524552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " has hidden visibility.  They should all have public visibility.  "
525552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " %s, %s, %s.\n", static_type->name(), dynamic_type->name(),
5261a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant                    dst_type->name());
527326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
528326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
529326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
5301a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
531326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
532cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
5331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        switch (info.number_to_static_ptr)
534f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
5351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 0:
5361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.number_to_dst_ptr == 1 &&
5371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_static_ptr == public_path &&
5381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_dst_ptr == public_path)
5391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
5401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
5411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 1:
5421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.path_dst_ptr_to_static_ptr == public_path ||
5431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   (
5441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.number_to_dst_ptr == 0 &&
5451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_static_ptr == public_path &&
5461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_dst_ptr == public_path
5471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   )
5481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant               )
5491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_leading_to_static_ptr;
5501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
551f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
552f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
5531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    return const_cast<void*>(dst_ptr);
554f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
555f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
55691f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
55791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
558facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
559facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(hidden)
560facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
5611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is a base (above) a dst_type.
5621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Let caller know you hit a static_type.  But only start recording details if
5631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// this is (static_ptr, static_type) -- the node we are casting from.
5641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
5651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from the dst_type to here.  There may be
5661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from the same dst_type to here, record the "most public" one.
5671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the dst_ptr as pointing to (static_ptr, static_type).
5681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
5691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   then mark this dyanmic_cast as ambiguous and stop the search.
5701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
5711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
5721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* dst_ptr,
5731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
5741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
575f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
5761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    // Record that we found a static_type
5771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    info->found_any_static_type = true;
5781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
579271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
5801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record that we found (static_ptr, static_type)
5811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = true;
5821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->dst_ptr_leading_to_static_ptr == 0)
583271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
5841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // First time here
5851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_leading_to_static_ptr = dst_ptr;
5861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
5871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr = 1;
5881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
5891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
5901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
5911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
592271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
5931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
594f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
5951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've been here before.  Update path to "most public"
5961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->path_dst_ptr_to_static_ptr == not_public_path)
5971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dst_ptr_to_static_ptr = path_below;
5981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
5991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
6001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
6011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
602f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
603f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        else
604f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
6051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've detected an ambiguous cast from (static_ptr, static_type)
6061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   to a dst_type
6071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr += 1;
6081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->search_done = true;
609f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
610f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
611f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
612f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
6131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is not a base (above) a dst_type.
6141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
6151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from (dynamic_ptr, dynamic_type) to here.  There may be
6161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
61716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
6181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
6191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
6201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
621152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
6221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
6231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
6241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record the most public path from (dynamic_ptr, dynamic_type) to
6251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //                                  (static_ptr, static_type)
6261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->path_dynamic_ptr_to_static_ptr != public_path)
6271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_static_ptr = path_below;
6281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
629152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
630152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
6311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching below a dst_type node.  This function searches
6321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
6331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a static_type node, there is no need to further search base classes
6341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// above.
6351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a dst_type node it should search base classes using search_above_dst
6361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// to find out if this dst_type points to (static_ptr, static_type) or not.
637cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Either way, the dst_type is recorded as one of two "flavors":  one that does
6381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// or does not point to (static_ptr, static_type).
6391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is neither a static_type nor a dst_type node, continue searching
6401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// base classes above.
6411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// All the hoopla surrounding the search code is doing nothing but looking for
642facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// excuses to stop the search prematurely (break out of the for-loop).  That is,
643facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the algorithm below is simply an optimization of this:
644facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
645facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
646facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
647facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
648facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
649facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     typedef const __base_class_type_info* Iter;
650facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
651facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_below_dst(info, current_ptr, path_below);
652facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else if (this == info->dst_type)
653facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
654facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // Record the most public access path that got us here
655facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (info->path_dynamic_ptr_to_dst_ptr != public_path)
656facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->path_dynamic_ptr_to_dst_ptr = path_below;
657facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         bool does_dst_type_point_to_our_static_type = false;
658facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
659facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
660facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, current_ptr, current_ptr, public_path);
661facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             if (info->found_our_static_ptr)
662facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                 does_dst_type_point_to_our_static_type = true;
663facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
664facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
665facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (!does_dst_type_point_to_our_static_type)
666facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
667facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // We found a dst_type that doesn't point to (static_ptr, static_type)
668facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // So record the address of this dst_ptr and increment the
669facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // count of the number of such dst_types found in the tree.
670facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->dst_ptr_not_leading_to_static_ptr = current_ptr;
671facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->number_to_dst_ptr += 1;
672facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
673facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
674facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
675facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
676facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type.
677facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
678facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
679facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_below_dst(info, current_ptr, public_path);
680facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
681facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
682facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
683facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
6841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
6851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
6861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
687326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
688326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
689f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
690f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    typedef const __base_class_type_info* Iter;
691326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
6921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
693326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
694f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
6951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
6961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
6971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
6981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
699f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
7001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
7011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
7021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
7031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
7041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
7051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
7061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
7071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
7081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
7091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
7101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
7111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
7121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
7131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
7141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
7151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
7161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
7171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
7181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We've found a dst_type with a potentially public path to here.
7191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We have to assume the path is public because it may become
7201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   public later (if we get back to here with a public path).
7211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We can stop looking above if:
7221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    1.  We've found a public path to (static_ptr, static_type).
7231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
7241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        This is detected at the (static_ptr, static_type).
7251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    3.  We can prove that there is no public path to (static_ptr, static_type)
7261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        above here.
7271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                const Iter e = __base_info + __base_count;
7281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                for (Iter p = __base_info; p < e; ++p)
7291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
7301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // Zero out found flags
7311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_our_static_ptr = false;
7321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_any_static_type = false;
733326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
734cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                    if (info->search_done)
7351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        break;
7361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_any_static_type)
7371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    {
7381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        is_dst_type_derived_from_static_type = true;
7391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        if (info->found_our_static_ptr)
7401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
7411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            does_dst_type_point_to_our_static_type = true;
7421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found what we're looking for, stop looking above.
7431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (info->path_dst_ptr_to_static_ptr == public_path)
7441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // We found a private path to (static_ptr, static_type)
7461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   If there is no diamond then there is only one path
7471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   to (static_ptr, static_type) and we just found it.
7481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __diamond_shaped_mask))
7491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
7511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        else
7521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
7531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found a static_type that isn't the one we're looking
7541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    for, and if there are no repeated types above here,
7551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    then stop looking.
7561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __non_diamond_repeat_mask))
7571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
7591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    }
7601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
7611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
7621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
7631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
7641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
7651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
7661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
7671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->number_to_dst_ptr += 1;
7681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // If there exists another dst with a private path to
7691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //    (static_ptr, static_type), then the cast from
7701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
7711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //      so stop search.
7721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
7731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
7741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
7751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
7761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
7771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
7781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
7791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
7801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
7811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
7821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
7831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
7841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
785f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
786f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
7871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
788271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
7891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type.
7901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
79165255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
792326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_below_dst(info, current_ptr, path_below, use_strcmp);
79365255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
7941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
79565255631de793131622f701df9075dfd78abfc50Howard Hinnant            if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
7961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
79765255631de793131622f701df9075dfd78abfc50Howard Hinnant                // If there are multiple paths to a base above from here, or if
79865255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    a dst_type pointing to (static_ptr, static_type) has been found,
79965255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    then there is no way to break out of this loop early unless
80065255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    something below detects the search is done.
80165255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
80265255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
80365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
80465255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
805326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
80665255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
8071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
80865255631de793131622f701df9075dfd78abfc50Howard Hinnant            else if (__flags & __non_diamond_repeat_mask)
809271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
81065255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are not multiple paths to any base class from here and a
81165255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   dst_type pointing to (static_ptr, static_type) has not yet been
81265255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   found.
81365255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
81465255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
81565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
81665255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
81765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
81865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure
81965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
82065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
82165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1 &&
82265255631de793131622f701df9075dfd78abfc50Howard Hinnant                              info->path_dst_ptr_to_static_ptr == public_path)
82365255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
824326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
82565255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
826271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
82765255631de793131622f701df9075dfd78abfc50Howard Hinnant            else
828271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
82965255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no repeated types above this node.
83065255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no nodes with multiple parents above this node.
83165255631de793131622f701df9075dfd78abfc50Howard Hinnant                // no dst_type has been found to (static_ptr, static_type)
83265255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
83365255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
83465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
83565255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
83665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
83765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure sure
83865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
83965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
84065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // if we just found a dst_type with a private path to (static_ptr, static_type),
84165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then we're only looking for a public path to (static_ptr, static_type)
84265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and to check for other dst_types.
84365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
84465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and not a dst_type under here.
84565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1)
84665255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
847326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
84865255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
849271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
850271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
851271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
8521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
8531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
8541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
8551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
8561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
8571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
8581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
859326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
860326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
8611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
862326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
8631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
864326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
865f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
8661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
8671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
8681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
8691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
870f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
8711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
8721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
8731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
874f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            if (path_below == public_path)
875f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
876f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
877271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        else  // We have haven't been here before
878f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
879271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            // Record the access path that got us here
8801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
881f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
8821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
8831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
8841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
885f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            {
8861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
8871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
8881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
8891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Zero out found flags
8901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_our_static_ptr = false;
8911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_any_static_type = false;
892326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
8931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (info->found_any_static_type)
894f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
8951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    is_dst_type_derived_from_static_type = true;
8961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_our_static_ptr)
8971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        does_dst_type_point_to_our_static_type = true;
898f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
8991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
900f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
9011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
9021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
9031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
9041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
905f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                    info->number_to_dst_ptr += 1;
906271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    // If there exists another dst with a private path to
907271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //    (static_ptr, static_type), then the cast from
908271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
909271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
9101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
9111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
912f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
9131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
9141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
9151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
9161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
9171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
9181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
9191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
9201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
921f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            }
922f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
923f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
925f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
9261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
927326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
928f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
9301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
9311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
9321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
9331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
9341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_below_dst(__dynamic_cast_info* info,
9351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
936326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
937326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
9381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
9391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    typedef const __base_class_type_info* Iter;
940326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
9411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
942326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
943f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
9441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
9451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
9461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
9471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
9481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
9491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
9501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
9511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
9521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
9531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
9541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
9551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
956271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
9571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
9581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
9591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
9601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found a dst_type that doesn't point to (static_ptr, static_type)
9611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // So record the address of this dst_ptr and increment the
9621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // count of the number of such dst_types found in the tree.
9631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_not_leading_to_static_ptr = current_ptr;
9641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_dst_ptr += 1;
9651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there exists another dst with a private path to
9661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    (static_ptr, static_type), then the cast from
9671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
968271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            if (info->number_to_static_ptr == 1 &&
9691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->path_dst_ptr_to_static_ptr == not_public_path)
9701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
9711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found that dst_type does not derive from static_type
9721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->is_dst_type_derived_from_static_type = no;
973271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
974271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
9751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
9761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
9771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching above a dst_type node.  This function searches
9781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a public path to (static_ptr, static_type).
9791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This function is guaranteed not to find a node of type dst_type.
9801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Theoretically this is a very simple function which just stops if it finds a
981facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// static_type node:  All the hoopla surrounding the search code is doing
982facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// nothing but looking for excuses to stop the search prematurely (break out of
983facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the for-loop).  That is, the algorithm below is simply an optimization of this:
984facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
985facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
986facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* dst_ptr,
987facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
988facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
989facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
990facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
991facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
992facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
993facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
994facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         typedef const __base_class_type_info* Iter;
995facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type
996facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
997facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
998facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, dst_ptr, current_ptr, public_path);
999facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
1000facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
1001facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
1002facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
10031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
10051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* dst_ptr,
10061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
1007326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
1008326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
10091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
1010326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
10111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1012271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    else
1013271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
10141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        typedef const __base_class_type_info* Iter;
10151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
10161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Save flags so they can be restored when returning to nodes below.
10171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_our_static_ptr = info->found_our_static_ptr;
10181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_any_static_type = info->found_any_static_type;
10191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've found a dst_type below with a path to here.  If the path
10201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    to here is not public, there may be another path to here that
10211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    is public.  So we have to assume that the path to here is public.
10221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //  We can stop looking above if:
10231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    1.  We've found a public path to (static_ptr, static_type).
10241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
10251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        This is detected at the (static_ptr, static_type).
10261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    3.  We can prove that there is no public path to (static_ptr, static_type)
10271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        above here.
10281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
102965255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
103065255631de793131622f701df9075dfd78abfc50Howard Hinnant        // Zero out found flags
103165255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_our_static_ptr = false;
103265255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_any_static_type = false;
1033326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
103465255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
1035271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
103665255631de793131622f701df9075dfd78abfc50Howard Hinnant            do
10371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
103865255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->search_done)
10391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    break;
104065255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->found_our_static_ptr)
104165255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
104265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found what we're looking for, stop looking above.
104365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->path_dst_ptr_to_static_ptr == public_path)
104465255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
104565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // We found a private path to (static_ptr, static_type)
104665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   If there is no diamond then there is only one path
104765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   to (static_ptr, static_type) from here and we just found it.
104865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __diamond_shaped_mask))
104965255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
105065255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
105165255631de793131622f701df9075dfd78abfc50Howard Hinnant                else if (info->found_any_static_type)
105265255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
105365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found a static_type that isn't the one we're looking
105465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    for, and if there are no repeated types above here,
105565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then stop looking.
105665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __non_diamond_repeat_mask))
105765255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
105865255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
105965255631de793131622f701df9075dfd78abfc50Howard Hinnant                // Zero out found flags
106065255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_our_static_ptr = false;
106165255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_any_static_type = false;
1062326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
106365255631de793131622f701df9075dfd78abfc50Howard Hinnant            } while (++p < e);
1064271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
10651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Restore flags
10661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = found_our_static_ptr;
10671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_any_static_type = found_any_static_type;
1068f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
1069185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant}
1070185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant
10711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
10721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
10731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
10751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* dst_ptr,
10761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
1077326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
1078326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
1079f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
1080326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
10811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
10821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
1083326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1084f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
1085f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
10861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
10871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
108816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
10891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_above_dst(__dynamic_cast_info* info,
10901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* dst_ptr,
10911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
1092326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
1093326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
109416650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
1095326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
10961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
109716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
109816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
10991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// The search functions for __base_class_type_info are simply convenience
11001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   functions for adjusting the current_ptr and path_below as the search is
11011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   passed up to the base class node.
11021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
110316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
11041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
11051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* dst_ptr,
11061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1107326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1108326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
110916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
111016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
111116650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    if (__offset_flags & __virtual_mask)
111216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    {
1113cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1114cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
111516650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    }
11161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_above_dst(info, dst_ptr,
1117cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
11181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
11191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1120326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1121326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
1122152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
1123152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
11251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
11261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1127326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1128326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
112916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
11301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
11311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (__offset_flags & __virtual_mask)
1132f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
1133cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1134cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1135f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
11361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_below_dst(info,
1137cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
11381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
11391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1140326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1141326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
114216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
114316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
1144facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
1145facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
1146152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}  // __cxxabiv1
1147