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//
3036fd93fd039ef14005d6ab51c2e9f2816d2b7063Yaron Keren//     void syslog(int facility_priority, 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
43d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// On Windows, typeids are different between DLLs and EXEs, so comparing
44d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// type_info* will work for typeids from the same compiled file but fail
45d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// for typeids from a DLL and an executable. Among other things, exceptions
46d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// are not caught by handlers since can_catch() returns false.
47d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren//
48d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls
49d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// is_equal() with use_strcmp=false so the string names are not compared.
50d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren
51d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#ifdef _WIN32
52d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#include <string.h>
53d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#endif
54d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren
55152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnantnamespace __cxxabiv1
56152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
57152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
580240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility push(hidden)
59facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
60326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#if _LIBCXX_DYNAMIC_FALLBACK
61326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
62326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
63326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
64326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
65326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
66326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (!use_strcmp)
67326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        return x == y;
68326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return strcmp(x->name(), y->name()) == 0;
69326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
70326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
71326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#else  // !_LIBCXX_DYNAMIC_FALLBACK
72326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
73326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
74326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
75326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool)
76326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
77d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#ifndef _WIN32
78326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return x == y;
79d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#else
80d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren    return (x == y) || (strcmp(x->name(), y->name()) == 0);
81d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#endif
82326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
83326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
84326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
85326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
86facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __shim_type_info
87facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
88facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant__shim_type_info::~__shim_type_info()
89facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
90facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
91facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
928f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop1() const {}
938f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop2() const {}
948f28628704f966409e860c74c46041e04c082720Howard Hinnant
95152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// __fundamental_type_info
96152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
9716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant// This miraculously (compiler magic) emits the type_info's for:
9816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   1. all of the fundamental types
9916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   2. pointers to all of the fundamental types
10016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   3. pointers to all of the const fundamental types
101152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant__fundamental_type_info::~__fundamental_type_info()
102152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
103152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
104152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __array_type_info
10635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
10735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__array_type_info::~__array_type_info()
108facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
109facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
110facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
11135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __function_type_info
112152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__function_type_info::~__function_type_info()
114152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
115152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
116152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __enum_type_info
11835b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
11935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__enum_type_info::~__enum_type_info()
120facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
121facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
122facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
12335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __class_type_info
124152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__class_type_info::~__class_type_info()
126152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
127152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
128152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __si_class_type_info
13035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
13135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__si_class_type_info::~__si_class_type_info()
132facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
133facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
134facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
13535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __vmi_class_type_info
136152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
13735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__vmi_class_type_info::~__vmi_class_type_info()
138152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
139152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
140152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
14135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pbase_type_info
14235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
14335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pbase_type_info::~__pbase_type_info()
144facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
145facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
146facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
14735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_type_info
148152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
14935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_type_info::~__pointer_type_info()
15035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant{
15135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant}
15235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
15335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_to_member_type_info
15435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
15535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_to_member_type_info::~__pointer_to_member_type_info()
156152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
157152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
158152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
159c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// can_catch
160c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
161c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// A handler is a match for an exception object of type E if
162a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   1. The handler is of type cv T or cv T& and E and T are the same type
163a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      (ignoring the top-level cv-qualifiers), or
164a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   2. the handler is of type cv T or cv T& and T is an unambiguous public
165a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//       base class of E, or
166a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
167a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      converted to the type of the handler by either or both of
168a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      A. a standard pointer conversion (4.10) not involving conversions to
169a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//         pointers to private or protected or ambiguous classes
170a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      B. a qualification conversion
171a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   4. the handler is a pointer or pointer to member type and E is
172a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      std::nullptr_t.
173c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
174c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// adjustedPtr:
175c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
176c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A& a) : adjustedPtr == &a
177c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A* a) : adjustedPtr == a
178c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A** a) : adjustedPtr == a
179c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
180c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2& d2) : adjustedPtr == &d2  (d2 is base class of thrown object)
181c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2* d2) : adjustedPtr == d2
182c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2*& d2) : adjustedPtr == d2
183c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
184c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (...) : adjustedPtr == & of the exception
185c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
186a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
187a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
188a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
189a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                   void*&) const
190a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
19106bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
192a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
193a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
194a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
19596f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__array_type_info::can_catch(const __shim_type_info*, void*&) const
196a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
197aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    // We can get here if someone tries to catch an array by reference.
198aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   However if someone tries to throw an array, it immediately gets
199aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   converted to a pointer, which will not convert back to an array
200aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   at the catch clause.  So this can never catch anything.
201a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
202a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
203a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
204a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
20596f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__function_type_info::can_catch(const __shim_type_info*, void*&) const
206a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
2074b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    // We can get here if someone tries to catch a function by reference.
2084b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   However if someone tries to throw a function, it immediately gets
2094b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   converted to a pointer, which will not convert back to a function
2104b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   at the catch clause.  So this can never catch anything.
211a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
212a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
213a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
214a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
215a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
216a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__enum_type_info::can_catch(const __shim_type_info* thrown_type,
217a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                            void*&) const
218a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
21906bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
220a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
221a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
22291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
22391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
22491f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
225a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1 and 2
226a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
227a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::can_catch(const __shim_type_info* thrown_type,
228a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*& adjustedPtr) const
229a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
230a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 1
23106bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, thrown_type, false))
232a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
233a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
234a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_type);
235a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
236a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
237a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 2
238a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0};
239a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
240a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
241a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
242a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
243a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
244a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
245a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
246a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
247a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
248a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
24991f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
25091f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
251a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
252a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::process_found_base_class(__dynamic_cast_info* info,
253a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
254a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
255a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
256a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info->dst_ptr_leading_to_static_ptr == 0)
257a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
258a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // First time here
259a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->dst_ptr_leading_to_static_ptr = adjustedPtr;
260a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = path_below;
261a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr = 1;
262a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
263a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
264a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
265a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've been here before.  Update path to "most public"
266a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (info->path_dst_ptr_to_static_ptr == not_public_path)
267a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
268a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
269a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
270a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
271a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
272a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        //   to a static_type
273a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr += 1;
274a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = not_public_path;
275a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->search_done = true;
276a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
277a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
278a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
279a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
280a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
281a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
282a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
283a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
28406bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
285a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
286a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
287a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
288a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
289a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
290a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  void* adjustedPtr,
291a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  int path_below) const
292a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
29306bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
294a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
295a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
296a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
297a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
298a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
299a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
300a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
301a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    void* adjustedPtr,
302a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    int path_below) const
303a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
30498bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    ptrdiff_t offset_to_base = 0;
30598bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    if (adjustedPtr != nullptr)
306a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
30798bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        offset_to_base = __offset_flags >> __offset_shift;
30898bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        if (__offset_flags & __virtual_mask)
30998bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        {
31098bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            const char* vtable = *static_cast<const char*const*>(adjustedPtr);
31198bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
31298bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        }
313a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
31498bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    __base_type->has_unambiguous_public_base(
31598bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            info,
31698bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            static_cast<char*>(adjustedPtr) + offset_to_base,
31798bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            (__offset_flags & __public_mask) ? path_below : not_public_path);
318a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
319a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
320a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
321a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
322a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   void* adjustedPtr,
323a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   int path_below) const
324a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
32506bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
326a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
327a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
328a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
329a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        typedef const __base_class_type_info* Iter;
330a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        const Iter e = __base_info + __base_count;
331a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        Iter p = __base_info;
332a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        p->has_unambiguous_public_base(info, adjustedPtr, path_below);
333a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (++p < e)
334a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        {
335a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            do
336a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            {
337a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                p->has_unambiguous_public_base(info, adjustedPtr, path_below);
338a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                if (info->search_done)
339a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                    break;
340a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            } while (++p < e);
341a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        }
342a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
343a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
344a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
345c649bdea9d3f67756d97fa1c9a837f53a762dbccHoward Hinnant// Handles bullets 1 and 4 for both pointers and member pointers
346a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
347a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
348a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*&) const
349a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
35006bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, thrown_type, false))
351a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
35206bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(thrown_type, &typeid(std::nullptr_t), false);
353a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
354a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
35591f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
35691f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
35791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
358a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1, 3 and 4
359a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
360a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
361a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                               void*& adjustedPtr) const
362a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
363a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // Do the dereference adjustment
36498bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    if (adjustedPtr != NULL)
36598bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        adjustedPtr = *static_cast<void**>(adjustedPtr);
366a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullets 1 and 4
367a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
368a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
369a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3
370a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __pointer_type_info* thrown_pointer_type =
371a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __pointer_type_info*>(thrown_type);
372a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type == 0)
373a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
374a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3B
375a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type->__flags & ~__flags)
376a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
37706bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
378a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
379a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3A
38006bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, &typeid(void), false))
381a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
382a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* catch_class_type =
383a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(__pointee);
384a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (catch_class_type == 0)
385a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
386a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
387a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
388a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
389a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
390a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0};
391a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
392a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
393a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
394a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
395288859d0a1684e0899702f50353ccdbc1bdab8b7Marshall Clow        if (adjustedPtr != NULL)
396288859d0a1684e0899702f50353ccdbc1bdab8b7Marshall Clow            adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
397a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
398a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
399a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
400a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
401c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
40291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
40391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
4040240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility pop
405facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(default)
406facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
40791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
40891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
40991f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
4101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// __dynamic_cast
4111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
412cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr: pointer to an object of type static_type; nonnull, and since the
413cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   object is polymorphic, *(void**)static_ptr is a virtual table pointer.
414cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   static_ptr is &v in the expression dynamic_cast<T>(v).
415cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type: static type of the object pointed to by static_ptr.
416cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
4171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// src2dst_offset: a static hint about the location of the
4181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 source subobject with respect to the complete object;
4191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 special negative values are:
4201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -1: no hint
4211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -2: static_type is not a public base of dst_type
4221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -3: static_type is a multiple public base type but never a
4231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                         virtual base type
4241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 otherwise, the static_type type is a unique public nonvirtual
4251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 base type of dst_type at offset src2dst_offset from the
4261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 origin of dst_type.
4271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
428cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) are the run time type of the complete object
429cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// referred to by static_ptr and a pointer to it.  These can be found from
430cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr for polymorphic types.
4311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// static_type is guaranteed to be a polymorphic type.
4321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
433cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward.  Each
434cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// node of the tree represents a base class/object of its parent (or parents) below.
435cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Each node is uniquely represented by a pointer to the object, and a pointer
436cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// to a type_info - its type.  Different nodes may have the same pointer and
437cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// different nodes may have the same type.  But only one node has a specific
438cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (pointer-value, type) pair.  In C++ two objects of the same type can not
439cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// share the same address.
440cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
441cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There are two flavors of nodes which have the type dst_type:
442cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    1.  Those that are derived from (below) (static_ptr, static_type).
443cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    2.  Those that are not derived from (below) (static_ptr, static_type).
444cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
445cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Invariants of the DAG:
446cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
447cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There is at least one path from the root (dynamic_ptr, dynamic_type) to
448cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// the node (static_ptr, static_type).  This path may or may not be public.
449cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There may be more than one such path (some public some not).  Such a path may
450cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// or may not go through a node having type dst_type.
451cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
452cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type T appears above a node of the same type.  That means that
453cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// there is only one node with dynamic_type.  And if dynamic_type == dst_type,
454cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// then there is only one dst_type in the DAG.
455cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
456cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type dst_type appears above a node of type static_type.  Such
457cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// DAG's are possible in C++, but the compiler computes those dynamic_casts at
458cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// compile time, and only calls __dynamic_cast when dst_type lies below
459cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type in the DAG.
460cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
461cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type != static_type:  The compiler computes the dynamic_cast in this case too.
462facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// dynamic_type != static_type:  The compiler computes the dynamic_cast in this case too.
463cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
464cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Returns:
465cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
466cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// If there is exactly one dst_type of flavor 1, and
4671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    If there is a public path from that dst_type to (static_ptr, static_type), or
468cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    If there are 0 dst_types of flavor 2, and there is a public path from
4691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
4701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
4711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        a pointer to that dst_type.
472cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
473facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//    if there is a public path from (dynamic_ptr, dynamic_type) to
4741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
4751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    to the one dst_type, then return a pointer to that one dst_type.
4761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
4771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
4781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If dynamic_type == dst_type, then the above algorithm collapses to the
4791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// following cheaper algorithm:
4801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
4811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If there is a public path from (dynamic_ptr, dynamic_type) to
4821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type), then return dynamic_ptr.
4831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
4841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantextern "C"
4851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid*
4861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__dynamic_cast(const void* static_ptr,
4870240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               const __class_type_info* static_type,
4880240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               const __class_type_info* dst_type,
4890240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               std::ptrdiff_t src2dst_offset)
4901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
4910550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Possible future optimization:  Take advantage of src2dst_offset
4920550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Currently clang always sets src2dst_offset to -1 (no hint).
493cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
494cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Get (dynamic_ptr, dynamic_type) from static_ptr
4951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    void** vtable = *(void***)static_ptr;
496cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
497cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
498cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
499cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
500cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize answer to nullptr.  This will be changed from the search
501cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    results if a non-null answer is found.  Regardless, this is what will
502cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    be returned.
5031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    const void* dst_ptr = 0;
504cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize info struct for this search.
5051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
506cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
507cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Find out if we can use a giant short cut in the search
50806bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(dynamic_type, dst_type, false))
509f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
510cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Using giant short cut.  Add that information to info.
5111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info.number_of_dst_type = 1;
512cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Do the  search
513326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
514326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#if _LIBCXX_DYNAMIC_FALLBACK
5151a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
5161a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
5171a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown)
5181a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
5191a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            // We get here only if there is some kind of visibility problem
5201a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            //   in client code.
521552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
5226c33e768c1b37af3e5d5f9f0e2a72fcf1dc51382Howard Hinnant                    "should have public visibility.  At least one of them is hidden. %s"
523552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                    ", %s.\n", static_type->name(), dynamic_type->name());
524326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
525326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
526326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info.number_of_dst_type = 1;
527326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
5281a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
529326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
530cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
5311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info.path_dst_ptr_to_static_ptr == public_path)
5321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            dst_ptr = dynamic_ptr;
5331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
5341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
5351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
536cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Not using giant short cut.  Do the search
537326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
538326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant #if _LIBCXX_DYNAMIC_FALLBACK
5391a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
5401a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
541326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown &&
5421a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            info.path_dynamic_ptr_to_static_ptr == unknown)
5431a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
544552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
545552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " has hidden visibility.  They should all have public visibility.  "
546552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " %s, %s, %s.\n", static_type->name(), dynamic_type->name(),
5471a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant                    dst_type->name());
548326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
549326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
550326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
5511a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
552326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
553cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
5541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        switch (info.number_to_static_ptr)
555f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
5561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 0:
5571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.number_to_dst_ptr == 1 &&
5581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_static_ptr == public_path &&
5591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_dst_ptr == public_path)
5601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
5611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
5621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 1:
5631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.path_dst_ptr_to_static_ptr == public_path ||
5641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   (
5651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.number_to_dst_ptr == 0 &&
5661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_static_ptr == public_path &&
5671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_dst_ptr == public_path
5681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   )
5691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant               )
5701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_leading_to_static_ptr;
5711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
572f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
573f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
5741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    return const_cast<void*>(dst_ptr);
575f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
576f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
57791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
57891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
579facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
580facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(hidden)
581facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
5821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is a base (above) a dst_type.
5831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Let caller know you hit a static_type.  But only start recording details if
5841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// this is (static_ptr, static_type) -- the node we are casting from.
5851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
5861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from the dst_type to here.  There may be
5871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from the same dst_type to here, record the "most public" one.
5881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the dst_ptr as pointing to (static_ptr, static_type).
5891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
5901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   then mark this dyanmic_cast as ambiguous and stop the search.
5911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
5921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
5931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* dst_ptr,
5941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
5951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
596f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
5971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    // Record that we found a static_type
5981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    info->found_any_static_type = true;
5991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
600271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
6011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record that we found (static_ptr, static_type)
6021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = true;
6031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->dst_ptr_leading_to_static_ptr == 0)
604271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
6051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // First time here
6061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_leading_to_static_ptr = dst_ptr;
6071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
6081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr = 1;
6091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
6101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
6111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
6121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
613271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
6141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
615f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
6161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've been here before.  Update path to "most public"
6171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->path_dst_ptr_to_static_ptr == not_public_path)
6181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dst_ptr_to_static_ptr = path_below;
6191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
6201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
6211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
6221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
623f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
624f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        else
625f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
6261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've detected an ambiguous cast from (static_ptr, static_type)
6271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   to a dst_type
6281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr += 1;
6291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->search_done = true;
630f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
631f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
632f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
633f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
6341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is not a base (above) a dst_type.
6351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
6361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from (dynamic_ptr, dynamic_type) to here.  There may be
6371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
63816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
6391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
6401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
6411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
642152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
6431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
6441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
6451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record the most public path from (dynamic_ptr, dynamic_type) to
6461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //                                  (static_ptr, static_type)
6471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->path_dynamic_ptr_to_static_ptr != public_path)
6481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_static_ptr = path_below;
6491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
650152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
651152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
6521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching below a dst_type node.  This function searches
6531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
6541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a static_type node, there is no need to further search base classes
6551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// above.
6561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a dst_type node it should search base classes using search_above_dst
6571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// to find out if this dst_type points to (static_ptr, static_type) or not.
658cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Either way, the dst_type is recorded as one of two "flavors":  one that does
6591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// or does not point to (static_ptr, static_type).
6601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is neither a static_type nor a dst_type node, continue searching
6611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// base classes above.
6621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// All the hoopla surrounding the search code is doing nothing but looking for
663facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// excuses to stop the search prematurely (break out of the for-loop).  That is,
664facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the algorithm below is simply an optimization of this:
665facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
666facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
667facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
668facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
669facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
670facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     typedef const __base_class_type_info* Iter;
671facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
672facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_below_dst(info, current_ptr, path_below);
673facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else if (this == info->dst_type)
674facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
675facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // Record the most public access path that got us here
676facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (info->path_dynamic_ptr_to_dst_ptr != public_path)
677facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->path_dynamic_ptr_to_dst_ptr = path_below;
678facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         bool does_dst_type_point_to_our_static_type = false;
679facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
680facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
681facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, current_ptr, current_ptr, public_path);
682facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             if (info->found_our_static_ptr)
683facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                 does_dst_type_point_to_our_static_type = true;
684facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
685facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
686facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (!does_dst_type_point_to_our_static_type)
687facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
688facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // We found a dst_type that doesn't point to (static_ptr, static_type)
689facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // So record the address of this dst_ptr and increment the
690facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // count of the number of such dst_types found in the tree.
691facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->dst_ptr_not_leading_to_static_ptr = current_ptr;
692facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->number_to_dst_ptr += 1;
693facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
694facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
695facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
696facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
697facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type.
698facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
699facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
700facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_below_dst(info, current_ptr, public_path);
701facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
702facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
703facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
704facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
7051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
7061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
7071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
708326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
709326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
710f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
711f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    typedef const __base_class_type_info* Iter;
712326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
7131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
714326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
715f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
7161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
7171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
7181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
7191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
720f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
7211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
7221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
7231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
7241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
7251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
7261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
7271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
7281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
7291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
7301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
7311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
7321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
7331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
7341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
7351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
7361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
7371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
7381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
7391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We've found a dst_type with a potentially public path to here.
7401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We have to assume the path is public because it may become
7411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   public later (if we get back to here with a public path).
7421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We can stop looking above if:
7431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    1.  We've found a public path to (static_ptr, static_type).
7441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
7451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        This is detected at the (static_ptr, static_type).
7461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    3.  We can prove that there is no public path to (static_ptr, static_type)
7471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        above here.
7481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                const Iter e = __base_info + __base_count;
7491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                for (Iter p = __base_info; p < e; ++p)
7501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
7511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // Zero out found flags
7521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_our_static_ptr = false;
7531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_any_static_type = false;
754326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
755cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                    if (info->search_done)
7561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        break;
7571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_any_static_type)
7581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    {
7591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        is_dst_type_derived_from_static_type = true;
7601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        if (info->found_our_static_ptr)
7611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
7621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            does_dst_type_point_to_our_static_type = true;
7631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found what we're looking for, stop looking above.
7641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (info->path_dst_ptr_to_static_ptr == public_path)
7651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // We found a private path to (static_ptr, static_type)
7671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   If there is no diamond then there is only one path
7681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   to (static_ptr, static_type) and we just found it.
7691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __diamond_shaped_mask))
7701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
7721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        else
7731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
7741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found a static_type that isn't the one we're looking
7751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    for, and if there are no repeated types above here,
7761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    then stop looking.
7771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __non_diamond_repeat_mask))
7781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
7801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    }
7811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
7821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
7831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
7841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
7851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
7861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
7871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
7881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->number_to_dst_ptr += 1;
7891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // If there exists another dst with a private path to
7901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //    (static_ptr, static_type), then the cast from
7911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
7921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //      so stop search.
7931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
7941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
7951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
7961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
7971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
7981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
7991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
8001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
8011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
8021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
8031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
8041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
8051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
806f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
807f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
8081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
809271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
8101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type.
8111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
81265255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
813326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_below_dst(info, current_ptr, path_below, use_strcmp);
81465255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
8151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
81665255631de793131622f701df9075dfd78abfc50Howard Hinnant            if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
8171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
81865255631de793131622f701df9075dfd78abfc50Howard Hinnant                // If there are multiple paths to a base above from here, or if
81965255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    a dst_type pointing to (static_ptr, static_type) has been found,
82065255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    then there is no way to break out of this loop early unless
82165255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    something below detects the search is done.
82265255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
82365255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
82465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
82565255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
826326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
82765255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
8281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
82965255631de793131622f701df9075dfd78abfc50Howard Hinnant            else if (__flags & __non_diamond_repeat_mask)
830271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
83165255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are not multiple paths to any base class from here and a
83265255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   dst_type pointing to (static_ptr, static_type) has not yet been
83365255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   found.
83465255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
83565255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
83665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
83765255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
83865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
83965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure
84065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
84165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
84265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1 &&
84365255631de793131622f701df9075dfd78abfc50Howard Hinnant                              info->path_dst_ptr_to_static_ptr == public_path)
84465255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
845326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
84665255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
847271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
84865255631de793131622f701df9075dfd78abfc50Howard Hinnant            else
849271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
85065255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no repeated types above this node.
85165255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no nodes with multiple parents above this node.
85265255631de793131622f701df9075dfd78abfc50Howard Hinnant                // no dst_type has been found to (static_ptr, static_type)
85365255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
85465255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
85565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
85665255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
85765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
85865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure sure
85965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
86065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
86165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // if we just found a dst_type with a private path to (static_ptr, static_type),
86265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then we're only looking for a public path to (static_ptr, static_type)
86365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and to check for other dst_types.
86465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
86565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and not a dst_type under here.
86665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1)
86765255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
868326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
86965255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
870271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
871271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
872271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
8731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
8741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
8751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
8761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
8771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
8781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
8791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
880326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
881326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
8821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
883326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
8841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
885326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
886f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
8871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
8881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
8891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
8901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
891f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
8921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
8931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
8941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
895f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            if (path_below == public_path)
896f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
897f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
898271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        else  // We have haven't been here before
899f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
900271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            // Record the access path that got us here
9011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
902f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
9031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
9041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
9051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
906f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            {
9071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
9081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
9091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
9101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Zero out found flags
9111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_our_static_ptr = false;
9121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_any_static_type = false;
913326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
9141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (info->found_any_static_type)
915f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
9161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    is_dst_type_derived_from_static_type = true;
9171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_our_static_ptr)
9181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        does_dst_type_point_to_our_static_type = true;
919f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
9201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
921f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
9221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
9231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
9241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
9251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
926f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                    info->number_to_dst_ptr += 1;
927271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    // If there exists another dst with a private path to
928271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //    (static_ptr, static_type), then the cast from
929271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
930271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
9311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
9321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
933f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
9341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
9351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
9361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
9371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
9381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
9391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
9401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
9411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
942f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            }
943f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
944f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
946f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
9471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
948326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
949f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
9511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
9521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
9531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
9541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
9551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_below_dst(__dynamic_cast_info* info,
9561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
957326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
958326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
9591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
9601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    typedef const __base_class_type_info* Iter;
961326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
9621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
963326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
964f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
9651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
9661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
9671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
9681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
9691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
9701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
9711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
9721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
9731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
9741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
9751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
9761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
977271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
9781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
9791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
9801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
9811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found a dst_type that doesn't point to (static_ptr, static_type)
9821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // So record the address of this dst_ptr and increment the
9831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // count of the number of such dst_types found in the tree.
9841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_not_leading_to_static_ptr = current_ptr;
9851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_dst_ptr += 1;
9861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there exists another dst with a private path to
9871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    (static_ptr, static_type), then the cast from
9881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
989271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            if (info->number_to_static_ptr == 1 &&
9901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->path_dst_ptr_to_static_ptr == not_public_path)
9911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
9921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found that dst_type does not derive from static_type
9931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->is_dst_type_derived_from_static_type = no;
994271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
995271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
9961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
9971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
9981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching above a dst_type node.  This function searches
9991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a public path to (static_ptr, static_type).
10001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This function is guaranteed not to find a node of type dst_type.
10011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Theoretically this is a very simple function which just stops if it finds a
1002facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// static_type node:  All the hoopla surrounding the search code is doing
1003facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// nothing but looking for excuses to stop the search prematurely (break out of
1004facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the for-loop).  That is, the algorithm below is simply an optimization of this:
1005facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
1006facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1007facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* dst_ptr,
1008facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
1009facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
1010facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
1011facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
1012facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1013facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
1014facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
1015facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         typedef const __base_class_type_info* Iter;
1016facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type
1017facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
1018facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
1019facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, dst_ptr, current_ptr, public_path);
1020facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
1021facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
1022facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
1023facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
10241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
10261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* dst_ptr,
10271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
1028326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
1029326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
10301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
1031326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
10321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1033271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    else
1034271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
10351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        typedef const __base_class_type_info* Iter;
10361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
10371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Save flags so they can be restored when returning to nodes below.
10381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_our_static_ptr = info->found_our_static_ptr;
10391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_any_static_type = info->found_any_static_type;
10401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've found a dst_type below with a path to here.  If the path
10411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    to here is not public, there may be another path to here that
10421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    is public.  So we have to assume that the path to here is public.
10431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //  We can stop looking above if:
10441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    1.  We've found a public path to (static_ptr, static_type).
10451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
10461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        This is detected at the (static_ptr, static_type).
10471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    3.  We can prove that there is no public path to (static_ptr, static_type)
10481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        above here.
10491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
105065255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
105165255631de793131622f701df9075dfd78abfc50Howard Hinnant        // Zero out found flags
105265255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_our_static_ptr = false;
105365255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_any_static_type = false;
1054326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
105565255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
1056271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
105765255631de793131622f701df9075dfd78abfc50Howard Hinnant            do
10581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
105965255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->search_done)
10601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    break;
106165255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->found_our_static_ptr)
106265255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
106365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found what we're looking for, stop looking above.
106465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->path_dst_ptr_to_static_ptr == public_path)
106565255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
106665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // We found a private path to (static_ptr, static_type)
106765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   If there is no diamond then there is only one path
106865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   to (static_ptr, static_type) from here and we just found it.
106965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __diamond_shaped_mask))
107065255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
107165255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
107265255631de793131622f701df9075dfd78abfc50Howard Hinnant                else if (info->found_any_static_type)
107365255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
107465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found a static_type that isn't the one we're looking
107565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    for, and if there are no repeated types above here,
107665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then stop looking.
107765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __non_diamond_repeat_mask))
107865255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
107965255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
108065255631de793131622f701df9075dfd78abfc50Howard Hinnant                // Zero out found flags
108165255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_our_static_ptr = false;
108265255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_any_static_type = false;
1083326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
108465255631de793131622f701df9075dfd78abfc50Howard Hinnant            } while (++p < e);
1085271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
10861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Restore flags
10871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = found_our_static_ptr;
10881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_any_static_type = found_any_static_type;
1089f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
1090185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant}
1091185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant
10921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
10931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
10941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
10961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* dst_ptr,
10971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
1098326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
1099326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
1100f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
1101326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
11021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
11031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
1104326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1105f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
1106f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
11071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
11081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
110916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
11101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_above_dst(__dynamic_cast_info* info,
11111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* dst_ptr,
11121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
1113326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
1114326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
111516650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
1116326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
11171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
111816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
111916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
11201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// The search functions for __base_class_type_info are simply convenience
11211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   functions for adjusting the current_ptr and path_below as the search is
11221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   passed up to the base class node.
11231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
112416650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
11251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
11261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* dst_ptr,
11271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1128326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1129326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
113016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
113116650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
113216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    if (__offset_flags & __virtual_mask)
113316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    {
1134cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1135cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
113616650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    }
11371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_above_dst(info, dst_ptr,
1138cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
11391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
11401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1141326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1142326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
1143152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
1144152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
11461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
11471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1148326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1149326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
115016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
11511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
11521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (__offset_flags & __virtual_mask)
1153f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
1154cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1155cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1156f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
11571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_below_dst(info,
1158cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
11591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
11601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1161326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1162326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
116316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
116416650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
1165facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
1166facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
1167152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}  // __cxxabiv1
1168