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
3791fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier
3891fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier#include <string.h>
3991fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier
4091fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier
41a1fce46063c99e307594236c55004b4e5b62243fDan Albert#ifdef _LIBCXX_DYNAMIC_FALLBACK
42326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#include "abort_message.h"
431a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant#include <sys/syslog.h>
441a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant#endif
451a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant
46d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// On Windows, typeids are different between DLLs and EXEs, so comparing
47d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// type_info* will work for typeids from the same compiled file but fail
48d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// for typeids from a DLL and an executable. Among other things, exceptions
49d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// are not caught by handlers since can_catch() returns false.
50d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren//
51d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls
52d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// is_equal() with use_strcmp=false so the string names are not compared.
53d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren
54d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#ifdef _WIN32
55d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#include <string.h>
56d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#endif
57d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren
58152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnantnamespace __cxxabiv1
59152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
60152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
610240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility push(hidden)
62facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
63326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
64326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
65326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
66326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
6791fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier#ifndef _WIN32
68326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (!use_strcmp)
69326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        return x == y;
70326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return strcmp(x->name(), y->name()) == 0;
71d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#else
72d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren    return (x == y) || (strcmp(x->name(), y->name()) == 0);
7391fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier#endif
74326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
75326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
76326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
77facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __shim_type_info
78facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
79facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant__shim_type_info::~__shim_type_info()
80facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
81facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
82facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
838f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop1() const {}
848f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop2() const {}
858f28628704f966409e860c74c46041e04c082720Howard Hinnant
86152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// __fundamental_type_info
87152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
8816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant// This miraculously (compiler magic) emits the type_info's for:
8916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   1. all of the fundamental types
9016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   2. pointers to all of the fundamental types
9116650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   3. pointers to all of the const fundamental types
92152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant__fundamental_type_info::~__fundamental_type_info()
93152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
94152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
95152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
9635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __array_type_info
9735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
9835b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__array_type_info::~__array_type_info()
99facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
100facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
101facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
10235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __function_type_info
103152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__function_type_info::~__function_type_info()
105152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
106152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
107152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10835b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __enum_type_info
10935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
11035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__enum_type_info::~__enum_type_info()
111facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
112facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
113facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
11435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __class_type_info
115152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__class_type_info::~__class_type_info()
117152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
118152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
119152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __si_class_type_info
12135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
12235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__si_class_type_info::~__si_class_type_info()
123facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
124facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
125facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
12635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __vmi_class_type_info
127152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12835b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__vmi_class_type_info::~__vmi_class_type_info()
129152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
130152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
131152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
13235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pbase_type_info
13335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
13435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pbase_type_info::~__pbase_type_info()
135facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
136facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
137facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
13835b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_type_info
139152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
14035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_type_info::~__pointer_type_info()
14135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant{
14235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant}
14335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
14435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_to_member_type_info
14535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
14635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_to_member_type_info::~__pointer_to_member_type_info()
147152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
148152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
149152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
150c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// can_catch
151c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
152c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// A handler is a match for an exception object of type E if
153a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   1. The handler is of type cv T or cv T& and E and T are the same type
154a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      (ignoring the top-level cv-qualifiers), or
155a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   2. the handler is of type cv T or cv T& and T is an unambiguous public
156a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//       base class of E, or
157a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
158a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      converted to the type of the handler by either or both of
159a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      A. a standard pointer conversion (4.10) not involving conversions to
160a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//         pointers to private or protected or ambiguous classes
161a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      B. a qualification conversion
162a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   4. the handler is a pointer or pointer to member type and E is
163a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      std::nullptr_t.
164c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
165c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// adjustedPtr:
166c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
167c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A& a) : adjustedPtr == &a
168c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A* a) : adjustedPtr == a
169c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A** a) : adjustedPtr == a
170c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
171c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2& d2) : adjustedPtr == &d2  (d2 is base class of thrown object)
172c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2* d2) : adjustedPtr == d2
173c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2*& d2) : adjustedPtr == d2
174081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith//
175c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (...) : adjustedPtr == & of the exception
176081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith//
177081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith// If the thrown type is nullptr_t and the caught type is a pointer to
178081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith// member type, adjustedPtr points to a statically-allocated null pointer
179081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith// representation of that type.
180c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
181a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
182a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
183a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
184a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                   void*&) const
185a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
18606bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
187a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
188a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
189a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
19096f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__array_type_info::can_catch(const __shim_type_info*, void*&) const
191a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
192aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    // We can get here if someone tries to catch an array by reference.
193aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   However if someone tries to throw an array, it immediately gets
194aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   converted to a pointer, which will not convert back to an array
195aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   at the catch clause.  So this can never catch anything.
196a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
197a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
198a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
199a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
20096f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__function_type_info::can_catch(const __shim_type_info*, void*&) const
201a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
2024b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    // We can get here if someone tries to catch a function by reference.
2034b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   However if someone tries to throw a function, it immediately gets
2044b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   converted to a pointer, which will not convert back to a function
2054b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   at the catch clause.  So this can never catch anything.
206a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
207a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
208a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
209a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
210a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
211a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__enum_type_info::can_catch(const __shim_type_info* thrown_type,
212a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                            void*&) const
213a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
21406bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
215a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
216a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
217faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#ifdef __clang__
21891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
21991f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
220faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#endif
22191f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
222a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1 and 2
223a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
224a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::can_catch(const __shim_type_info* thrown_type,
225a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*& adjustedPtr) const
226a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
227a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 1
22806bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, thrown_type, false))
229a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
230a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
231a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_type);
232a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
233a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
234a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 2
235a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0};
236a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
237a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
238a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
239a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
240a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
241a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
242a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
243a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
244a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
245a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
246faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#ifdef __clang__
24791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
248faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#endif
24991f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
250a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
251a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::process_found_base_class(__dynamic_cast_info* info,
252a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
253a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
254a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
255a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info->dst_ptr_leading_to_static_ptr == 0)
256a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
257a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // First time here
258a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->dst_ptr_leading_to_static_ptr = adjustedPtr;
259a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = path_below;
260a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr = 1;
261a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
262a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
263a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
264a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've been here before.  Update path to "most public"
265a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (info->path_dst_ptr_to_static_ptr == not_public_path)
266a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
267a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
268a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
269a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
270a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
271a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        //   to a static_type
272a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr += 1;
273a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = not_public_path;
274a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->search_done = true;
275a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
276a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
277a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
278a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
279a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
280a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
281a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
282a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
28306bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
284a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
285a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
286a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
287a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
288a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
289a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  void* adjustedPtr,
290a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  int path_below) const
291a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
29206bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
293a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
294a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
295a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
296a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
297a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
298a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
299a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
300a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    void* adjustedPtr,
301a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    int path_below) const
302a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
30398bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    ptrdiff_t offset_to_base = 0;
30498bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    if (adjustedPtr != nullptr)
305a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
30698bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        offset_to_base = __offset_flags >> __offset_shift;
30798bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        if (__offset_flags & __virtual_mask)
30898bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        {
30998bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            const char* vtable = *static_cast<const char*const*>(adjustedPtr);
31098bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
31198bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        }
312a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
31398bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    __base_type->has_unambiguous_public_base(
31498bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            info,
31598bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            static_cast<char*>(adjustedPtr) + offset_to_base,
31698bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            (__offset_flags & __public_mask) ? path_below : not_public_path);
317a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
318a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
319a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
320a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
321a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   void* adjustedPtr,
322a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   int path_below) const
323a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
32406bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
325a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
326a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
327a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
328a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        typedef const __base_class_type_info* Iter;
329a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        const Iter e = __base_info + __base_count;
330a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        Iter p = __base_info;
331a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        p->has_unambiguous_public_base(info, adjustedPtr, path_below);
332a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (++p < e)
333a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        {
334a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            do
335a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            {
336a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                p->has_unambiguous_public_base(info, adjustedPtr, path_below);
337a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                if (info->search_done)
338a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                    break;
339a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            } while (++p < e);
340a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        }
341a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
342a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
343a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
344081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith// Handles bullet 1 for both pointers and member pointers
345a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
346a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
347a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*&) const
348a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
34991fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier    bool use_strcmp = this->__flags & (__incomplete_class_mask |
35091fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier                                       __incomplete_mask);
35191fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier    if (!use_strcmp) {
35291fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier        const __pbase_type_info* thrown_pbase = dynamic_cast<const __pbase_type_info*>(
35391fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier                thrown_type);
35491fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier        if (!thrown_pbase) return false;
35591fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier        use_strcmp = thrown_pbase->__flags & (__incomplete_class_mask |
35691fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier                                              __incomplete_mask);
35791fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier    }
35891fc04d667ef064c0750133aa75bd58886030f15Eric Fiselier    return is_equal(this, thrown_type, use_strcmp);
359a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
360a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
361faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#ifdef __clang__
36291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
36391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
364faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#endif
36591f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
366a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1, 3 and 4
3671b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier// NOTE: It might not be safe to adjust the pointer if it is not not a pointer
3681b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier// type. Only adjust the pointer after we know it is safe to do so.
369a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
370a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
371a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                               void*& adjustedPtr) const
372a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
373081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith    // bullet 4
374081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith    if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) {
375081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      adjustedPtr = nullptr;
376081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      return true;
377081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith    }
378081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith
379081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith    // bullet 1
3801b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr)) {
3811b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier        if (adjustedPtr != NULL)
3821b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier            adjustedPtr = *static_cast<void**>(adjustedPtr);
383a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
3841b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier    }
385a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3
386a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __pointer_type_info* thrown_pointer_type =
387a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __pointer_type_info*>(thrown_type);
388a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type == 0)
389a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
3901b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier    // Do the dereference adjustment
3911b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier    if (adjustedPtr != NULL)
3921b4ddb114e91d196cf3a652124e70560edf3816cEric Fiselier        adjustedPtr = *static_cast<void**>(adjustedPtr);
393f1636207ad8e142a11f80860ea27ea92fcc8c776Richard Smith    // bullet 3B and 3C
394f1636207ad8e142a11f80860ea27ea92fcc8c776Richard Smith    if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask)
395f1636207ad8e142a11f80860ea27ea92fcc8c776Richard Smith        return false;
396f1636207ad8e142a11f80860ea27ea92fcc8c776Richard Smith    if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask)
397a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
39806bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
399a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
400a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3A
401b979db159a515fe12b54f793690618313e017259Eric Fiselier    if (is_equal(__pointee, &typeid(void), false)) {
402b979db159a515fe12b54f793690618313e017259Eric Fiselier        // pointers to functions cannot be converted to void*.
403b979db159a515fe12b54f793690618313e017259Eric Fiselier        // pointers to member functions are not handled here.
404b979db159a515fe12b54f793690618313e017259Eric Fiselier        const __function_type_info* thrown_function =
405b979db159a515fe12b54f793690618313e017259Eric Fiselier            dynamic_cast<const __function_type_info*>(thrown_pointer_type->__pointee);
406b979db159a515fe12b54f793690618313e017259Eric Fiselier        return (thrown_function == nullptr);
407b979db159a515fe12b54f793690618313e017259Eric Fiselier    }
4080cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    // Handle pointer to pointer
4090cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __pointer_type_info* nested_pointer_type =
4100cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        dynamic_cast<const __pointer_type_info*>(__pointee);
4110cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (nested_pointer_type) {
4120cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        if (~__flags & __const_mask) return false;
4130cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return nested_pointer_type->can_catch_nested(thrown_pointer_type->__pointee);
4140cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    }
4150cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
4160cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    // Handle pointer to pointer to member
4170cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __pointer_to_member_type_info* member_ptr_type =
4180cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        dynamic_cast<const __pointer_to_member_type_info*>(__pointee);
4190cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (member_ptr_type) {
4200cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        if (~__flags & __const_mask) return false;
4210cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return member_ptr_type->can_catch_nested(thrown_pointer_type->__pointee);
4220cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    }
4230cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
4240cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    // Handle pointer to class type
425a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* catch_class_type =
426a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(__pointee);
427a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (catch_class_type == 0)
428a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
429a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
430a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
431a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
432a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
433a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0};
434a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
435a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
436a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
437a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
438288859d0a1684e0899702f50353ccdbc1bdab8b7Marshall Clow        if (adjustedPtr != NULL)
439288859d0a1684e0899702f50353ccdbc1bdab8b7Marshall Clow            adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
440a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
441a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
442a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
443a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
444c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
4450cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselierbool __pointer_type_info::can_catch_nested(
4460cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __shim_type_info* thrown_type) const
4470cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier{
4480cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier  const __pointer_type_info* thrown_pointer_type =
4490cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        dynamic_cast<const __pointer_type_info*>(thrown_type);
4500cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (thrown_pointer_type == 0)
4510cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
4520cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    // bullet 3B
4530cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (thrown_pointer_type->__flags & ~__flags)
4540cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
4550cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
4560cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return true;
4570cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    // If the pointed to types differ then the catch type must be const
4580cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    // qualified.
4590cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (~__flags & __const_mask)
4600cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
4610cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
4620cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    // Handle pointer to pointer
4630cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __pointer_type_info* nested_pointer_type =
4640cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        dynamic_cast<const __pointer_type_info*>(__pointee);
4650cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (nested_pointer_type) {
4660cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return nested_pointer_type->can_catch_nested(
4670cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier            thrown_pointer_type->__pointee);
4680cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    }
4690cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
4700cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    // Handle pointer to pointer to member
4710cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __pointer_to_member_type_info* member_ptr_type =
4720cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        dynamic_cast<const __pointer_to_member_type_info*>(__pointee);
4730cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (member_ptr_type) {
4740cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return member_ptr_type->can_catch_nested(thrown_pointer_type->__pointee);
4750cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    }
4760cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
4770cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    return false;
4780cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier}
4790cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
4800cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselierbool __pointer_to_member_type_info::can_catch(
4810cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __shim_type_info* thrown_type, void*& adjustedPtr) const {
482081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith    // bullet 4
483081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith    if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) {
484081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      // We assume that the pointer to member representation is the same for
485081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      // all pointers to data members and for all pointers to member functions.
486081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      struct X {};
487081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      if (dynamic_cast<const __function_type_info*>(__pointee)) {
488081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith        static int (X::*const null_ptr_rep)() = nullptr;
489081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith        adjustedPtr = const_cast<int (X::**)()>(&null_ptr_rep);
490081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      } else {
491081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith        static int X::*const null_ptr_rep = nullptr;
492081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith        adjustedPtr = const_cast<int X::**>(&null_ptr_rep);
493081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      }
494081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith      return true;
495081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith    }
496081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith
497081ea86d80df60bcbb5517868ec5f1afab6bf973Richard Smith    // bullet 1
4980cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
4990cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return true;
5000cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
5010cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __pointer_to_member_type_info* thrown_pointer_type =
5020cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        dynamic_cast<const __pointer_to_member_type_info*>(thrown_type);
5030cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (thrown_pointer_type == 0)
5040cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
505f1636207ad8e142a11f80860ea27ea92fcc8c776Richard Smith    if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask)
506f1636207ad8e142a11f80860ea27ea92fcc8c776Richard Smith        return false;
507f1636207ad8e142a11f80860ea27ea92fcc8c776Richard Smith    if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask)
5080cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
509f1636207ad8e142a11f80860ea27ea92fcc8c776Richard Smith    if (!is_equal(__pointee, thrown_pointer_type->__pointee, false))
5100cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
5110cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (is_equal(__context, thrown_pointer_type->__context, false))
5120cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return true;
5130cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
514554d59ab0b989830273c9183f7bdfd12108cad7aEric Fiselier    // [except.handle] does not allow the pointer-to-member conversions mentioned
515554d59ab0b989830273c9183f7bdfd12108cad7aEric Fiselier    // in [mem.conv] to take place. For this reason we don't check Derived->Base
516554d59ab0b989830273c9183f7bdfd12108cad7aEric Fiselier    // for Derived->Base conversions.
5170cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
5180cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    return false;
5190cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier}
5200cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
5210cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselierbool __pointer_to_member_type_info::can_catch_nested(
5220cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __shim_type_info* thrown_type) const
5230cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier{
5240cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    const __pointer_to_member_type_info* thrown_member_ptr_type =
5250cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        dynamic_cast<const __pointer_to_member_type_info*>(thrown_type);
5260cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (thrown_member_ptr_type == 0)
5270cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
5280cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (~__flags & thrown_member_ptr_type->__flags)
5290cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
5300cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (!is_equal(__pointee, thrown_member_ptr_type->__pointee, false))
5310cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
5320cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    if (!is_equal(__context, thrown_member_ptr_type->__context, false))
5330cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier        return false;
5340cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier    return true;
5350cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier}
5360cb62d1b51f3d9ab65e0ba7b6541dda0663fe50dEric Fiselier
537faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#ifdef __clang__
53891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
539faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#endif
54091f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
5410240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility pop
542facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(default)
543facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
544faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#ifdef __clang__
54591f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
54691f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
547faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#endif
54891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
5491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// __dynamic_cast
5501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
551cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr: pointer to an object of type static_type; nonnull, and since the
552cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   object is polymorphic, *(void**)static_ptr is a virtual table pointer.
553cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   static_ptr is &v in the expression dynamic_cast<T>(v).
554cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type: static type of the object pointed to by static_ptr.
555cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
5561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// src2dst_offset: a static hint about the location of the
5571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 source subobject with respect to the complete object;
5581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 special negative values are:
5591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -1: no hint
5601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -2: static_type is not a public base of dst_type
5611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -3: static_type is a multiple public base type but never a
5621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                         virtual base type
5631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 otherwise, the static_type type is a unique public nonvirtual
5641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 base type of dst_type at offset src2dst_offset from the
5651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 origin of dst_type.
5661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
567cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) are the run time type of the complete object
568cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// referred to by static_ptr and a pointer to it.  These can be found from
569cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr for polymorphic types.
5701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// static_type is guaranteed to be a polymorphic type.
5711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
572cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward.  Each
573cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// node of the tree represents a base class/object of its parent (or parents) below.
574cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Each node is uniquely represented by a pointer to the object, and a pointer
575cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// to a type_info - its type.  Different nodes may have the same pointer and
576cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// different nodes may have the same type.  But only one node has a specific
577cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (pointer-value, type) pair.  In C++ two objects of the same type can not
578cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// share the same address.
579cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
580cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There are two flavors of nodes which have the type dst_type:
581cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    1.  Those that are derived from (below) (static_ptr, static_type).
582cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    2.  Those that are not derived from (below) (static_ptr, static_type).
583cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
584cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Invariants of the DAG:
585cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
586cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There is at least one path from the root (dynamic_ptr, dynamic_type) to
587cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// the node (static_ptr, static_type).  This path may or may not be public.
588cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There may be more than one such path (some public some not).  Such a path may
589cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// or may not go through a node having type dst_type.
590cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
591cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type T appears above a node of the same type.  That means that
592cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// there is only one node with dynamic_type.  And if dynamic_type == dst_type,
593cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// then there is only one dst_type in the DAG.
594cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
595cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type dst_type appears above a node of type static_type.  Such
596cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// DAG's are possible in C++, but the compiler computes those dynamic_casts at
597cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// compile time, and only calls __dynamic_cast when dst_type lies below
598cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type in the DAG.
599cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
600cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type != static_type:  The compiler computes the dynamic_cast in this case too.
601facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// dynamic_type != static_type:  The compiler computes the dynamic_cast in this case too.
602cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
603cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Returns:
604cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
605cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// If there is exactly one dst_type of flavor 1, and
6061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    If there is a public path from that dst_type to (static_ptr, static_type), or
607cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    If there are 0 dst_types of flavor 2, and there is a public path from
6081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
6091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
6101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        a pointer to that dst_type.
611cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
612facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//    if there is a public path from (dynamic_ptr, dynamic_type) to
6131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
6141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    to the one dst_type, then return a pointer to that one dst_type.
6151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
6161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
6171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If dynamic_type == dst_type, then the above algorithm collapses to the
6181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// following cheaper algorithm:
6191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
6201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If there is a public path from (dynamic_ptr, dynamic_type) to
6211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type), then return dynamic_ptr.
6221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
62346eb39a561ce4e4952abcb05378e38f01fd3fac6Saleem Abdulrasool
62446eb39a561ce4e4952abcb05378e38f01fd3fac6Saleem Abdulrasoolextern "C" _LIBCXXABI_FUNC_VIS void *
62546eb39a561ce4e4952abcb05378e38f01fd3fac6Saleem Abdulrasool__dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
62646eb39a561ce4e4952abcb05378e38f01fd3fac6Saleem Abdulrasool               const __class_type_info *dst_type,
62746eb39a561ce4e4952abcb05378e38f01fd3fac6Saleem Abdulrasool               std::ptrdiff_t src2dst_offset) {
6280550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Possible future optimization:  Take advantage of src2dst_offset
6290550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Currently clang always sets src2dst_offset to -1 (no hint).
630cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
631cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Get (dynamic_ptr, dynamic_type) from static_ptr
6320f111c296c143eb179af0313d5d4108f346b3fbaSaleem Abdulrasool    void **vtable = *static_cast<void ** const *>(static_ptr);
633cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
634cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
635cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
636cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
637cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize answer to nullptr.  This will be changed from the search
638cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    results if a non-null answer is found.  Regardless, this is what will
639cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    be returned.
6401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    const void* dst_ptr = 0;
641cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize info struct for this search.
6421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
643cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
644cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Find out if we can use a giant short cut in the search
64506bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(dynamic_type, dst_type, false))
646f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
647cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Using giant short cut.  Add that information to info.
6481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info.number_of_dst_type = 1;
649cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Do the  search
650326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
651a1fce46063c99e307594236c55004b4e5b62243fDan Albert#ifdef _LIBCXX_DYNAMIC_FALLBACK
6521a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
6531a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
6541a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown)
6551a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
6561a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            // We get here only if there is some kind of visibility problem
6571a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            //   in client code.
658552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
6596c33e768c1b37af3e5d5f9f0e2a72fcf1dc51382Howard Hinnant                    "should have public visibility.  At least one of them is hidden. %s"
660552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                    ", %s.\n", static_type->name(), dynamic_type->name());
661326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
662326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
663326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info.number_of_dst_type = 1;
664326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
6651a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
666326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
667cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
6681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info.path_dst_ptr_to_static_ptr == public_path)
6691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            dst_ptr = dynamic_ptr;
6701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
6711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
6721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
673cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Not using giant short cut.  Do the search
674326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
675a1fce46063c99e307594236c55004b4e5b62243fDan Albert #ifdef _LIBCXX_DYNAMIC_FALLBACK
6761a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
6771a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
678326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown &&
6791a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            info.path_dynamic_ptr_to_static_ptr == unknown)
6801a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
681552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
682552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " has hidden visibility.  They should all have public visibility.  "
683552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " %s, %s, %s.\n", static_type->name(), dynamic_type->name(),
6841a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant                    dst_type->name());
685326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
686326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
687326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
6881a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
689326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
690cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
6911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        switch (info.number_to_static_ptr)
692f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
6931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 0:
6941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.number_to_dst_ptr == 1 &&
6951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_static_ptr == public_path &&
6961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_dst_ptr == public_path)
6971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
6981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
6991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 1:
7001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.path_dst_ptr_to_static_ptr == public_path ||
7011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   (
7021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.number_to_dst_ptr == 0 &&
7031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_static_ptr == public_path &&
7041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_dst_ptr == public_path
7051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   )
7061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant               )
7071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_leading_to_static_ptr;
7081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
709f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
710f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
7111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    return const_cast<void*>(dst_ptr);
712f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
713f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
714faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#ifdef __clang__
71591f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
716faf34fbbbbb5956d6da2661a00f5c6b5aefcfe55Nick Lewycky#endif
71791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
718facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
719facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(hidden)
720facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
7211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is a base (above) a dst_type.
7221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Let caller know you hit a static_type.  But only start recording details if
7231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// this is (static_ptr, static_type) -- the node we are casting from.
7241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
7251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from the dst_type to here.  There may be
7261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from the same dst_type to here, record the "most public" one.
7271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the dst_ptr as pointing to (static_ptr, static_type).
7281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
7291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   then mark this dyanmic_cast as ambiguous and stop the search.
7301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
7311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
7321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* dst_ptr,
7331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
7341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
735f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
7361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    // Record that we found a static_type
7371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    info->found_any_static_type = true;
7381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
739271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
7401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record that we found (static_ptr, static_type)
7411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = true;
7421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->dst_ptr_leading_to_static_ptr == 0)
743271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
7441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // First time here
7451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_leading_to_static_ptr = dst_ptr;
7461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
7471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr = 1;
7481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
7491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
7501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
7511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
752271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
7531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
754f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
7551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've been here before.  Update path to "most public"
7561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->path_dst_ptr_to_static_ptr == not_public_path)
7571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dst_ptr_to_static_ptr = path_below;
7581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
7591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
7601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
7611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
762f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
763f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        else
764f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
7651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've detected an ambiguous cast from (static_ptr, static_type)
7661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   to a dst_type
7671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr += 1;
7681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->search_done = true;
769f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
770f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
771f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
772f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
7731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is not a base (above) a dst_type.
7741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
7751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from (dynamic_ptr, dynamic_type) to here.  There may be
7761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
77716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
7781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
7791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
7801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
781152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
7821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
7831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
7841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record the most public path from (dynamic_ptr, dynamic_type) to
7851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //                                  (static_ptr, static_type)
7861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->path_dynamic_ptr_to_static_ptr != public_path)
7871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_static_ptr = path_below;
7881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
789152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
790152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
7911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching below a dst_type node.  This function searches
7921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
7931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a static_type node, there is no need to further search base classes
7941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// above.
7951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a dst_type node it should search base classes using search_above_dst
7961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// to find out if this dst_type points to (static_ptr, static_type) or not.
797cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Either way, the dst_type is recorded as one of two "flavors":  one that does
7981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// or does not point to (static_ptr, static_type).
7991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is neither a static_type nor a dst_type node, continue searching
8001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// base classes above.
8011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// All the hoopla surrounding the search code is doing nothing but looking for
802facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// excuses to stop the search prematurely (break out of the for-loop).  That is,
803facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the algorithm below is simply an optimization of this:
804facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
805facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
806facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
807facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
808facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
809facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     typedef const __base_class_type_info* Iter;
810facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
811facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_below_dst(info, current_ptr, path_below);
812facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else if (this == info->dst_type)
813facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
814facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // Record the most public access path that got us here
815facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (info->path_dynamic_ptr_to_dst_ptr != public_path)
816facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->path_dynamic_ptr_to_dst_ptr = path_below;
817facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         bool does_dst_type_point_to_our_static_type = false;
818facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
819facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
820facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, current_ptr, current_ptr, public_path);
821facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             if (info->found_our_static_ptr)
822facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                 does_dst_type_point_to_our_static_type = true;
823facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
824facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
825facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (!does_dst_type_point_to_our_static_type)
826facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
827facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // We found a dst_type that doesn't point to (static_ptr, static_type)
828facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // So record the address of this dst_ptr and increment the
829facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // count of the number of such dst_types found in the tree.
830facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->dst_ptr_not_leading_to_static_ptr = current_ptr;
831facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->number_to_dst_ptr += 1;
832facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
833facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
834facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
835facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
836facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type.
837facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
838facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
839facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_below_dst(info, current_ptr, public_path);
840facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
841facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
842facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
843facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
8441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
8451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
8461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
847326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
848326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
849f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
850f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    typedef const __base_class_type_info* Iter;
851326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
8521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
853326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
854f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
8551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
8561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
8571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
8581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
859f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
8601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
8611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
8621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
8631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
8641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
8651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
8661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
8671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
8681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
8691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
8701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
8711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
8721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
8731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
8741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
8751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
8761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
8771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
8781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We've found a dst_type with a potentially public path to here.
8791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We have to assume the path is public because it may become
8801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   public later (if we get back to here with a public path).
8811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We can stop looking above if:
8821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    1.  We've found a public path to (static_ptr, static_type).
8831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
8841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        This is detected at the (static_ptr, static_type).
8851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    3.  We can prove that there is no public path to (static_ptr, static_type)
8861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        above here.
8871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                const Iter e = __base_info + __base_count;
8881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                for (Iter p = __base_info; p < e; ++p)
8891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
8901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // Zero out found flags
8911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_our_static_ptr = false;
8921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_any_static_type = false;
893326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
894cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                    if (info->search_done)
8951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        break;
8961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_any_static_type)
8971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    {
8981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        is_dst_type_derived_from_static_type = true;
8991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        if (info->found_our_static_ptr)
9001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
9011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            does_dst_type_point_to_our_static_type = true;
9021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found what we're looking for, stop looking above.
9031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (info->path_dst_ptr_to_static_ptr == public_path)
9041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
9051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // We found a private path to (static_ptr, static_type)
9061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   If there is no diamond then there is only one path
9071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   to (static_ptr, static_type) and we just found it.
9081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __diamond_shaped_mask))
9091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
9101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
9111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        else
9121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
9131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found a static_type that isn't the one we're looking
9141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    for, and if there are no repeated types above here,
9151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    then stop looking.
9161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __non_diamond_repeat_mask))
9171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
9181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
9191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    }
9201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
9211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
9221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
9231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
9241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
9251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
9261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
9271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->number_to_dst_ptr += 1;
9281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // If there exists another dst with a private path to
9291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //    (static_ptr, static_type), then the cast from
9301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
9311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //      so stop search.
9321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
9331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
9341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
9351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
9361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
9371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
9381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
9391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
9401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
9411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
9421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
9431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
9441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
945f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
946f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
948271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
9491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type.
9501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
95165255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
952326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_below_dst(info, current_ptr, path_below, use_strcmp);
95365255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
9541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
95565255631de793131622f701df9075dfd78abfc50Howard Hinnant            if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
9561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
95765255631de793131622f701df9075dfd78abfc50Howard Hinnant                // If there are multiple paths to a base above from here, or if
95865255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    a dst_type pointing to (static_ptr, static_type) has been found,
95965255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    then there is no way to break out of this loop early unless
96065255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    something below detects the search is done.
96165255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
96265255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
96365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
96465255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
965326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
96665255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
9671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
96865255631de793131622f701df9075dfd78abfc50Howard Hinnant            else if (__flags & __non_diamond_repeat_mask)
969271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
97065255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are not multiple paths to any base class from here and a
97165255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   dst_type pointing to (static_ptr, static_type) has not yet been
97265255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   found.
97365255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
97465255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
97565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
97665255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
97765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
97865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure
97965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
98065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
98165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1 &&
98265255631de793131622f701df9075dfd78abfc50Howard Hinnant                              info->path_dst_ptr_to_static_ptr == public_path)
98365255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
984326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
98565255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
986271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
98765255631de793131622f701df9075dfd78abfc50Howard Hinnant            else
988271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
98965255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no repeated types above this node.
99065255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no nodes with multiple parents above this node.
99165255631de793131622f701df9075dfd78abfc50Howard Hinnant                // no dst_type has been found to (static_ptr, static_type)
99265255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
99365255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
99465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
99565255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
99665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
99765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure sure
99865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
99965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
100065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // if we just found a dst_type with a private path to (static_ptr, static_type),
100165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then we're only looking for a public path to (static_ptr, static_type)
100265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and to check for other dst_types.
100365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
100465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and not a dst_type under here.
100565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1)
100665255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
1007326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
100865255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
1009271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
1010271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
1011271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
10121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
10131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
10141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
10151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
10161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
10181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
1019326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
1020326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
10211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
1022326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
10231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
1024326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
1025f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
10261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
10271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
10281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
10291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
1030f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
10311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
10321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
10331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
1034f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            if (path_below == public_path)
1035f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
1036f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
1037271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        else  // We have haven't been here before
1038f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
1039271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            // Record the access path that got us here
10401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
1041f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
10421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
10431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
10441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
1045f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            {
10461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
10471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
10481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
10491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Zero out found flags
10501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_our_static_ptr = false;
10511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_any_static_type = false;
1052326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
10531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (info->found_any_static_type)
1054f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
10551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    is_dst_type_derived_from_static_type = true;
10561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_our_static_ptr)
10571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        does_dst_type_point_to_our_static_type = true;
1058f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
10591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
1060f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
10611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
10621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
10631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
10641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
1065f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                    info->number_to_dst_ptr += 1;
1066271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    // If there exists another dst with a private path to
1067271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //    (static_ptr, static_type), then the cast from
1068271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
1069271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
10701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
10711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
1072f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
10731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
10741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
10751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
10761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
10771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
10781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
10791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
10801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
1081f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            }
1082f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
1083f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
10841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
1085f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
10861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
1087326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
1088f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
10891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
10901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
10911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
10921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
10931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_below_dst(__dynamic_cast_info* info,
10951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
1096326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
1097326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
10981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
1099326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
11001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
1101326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
1102f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
11031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
11041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
11051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
11061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
11071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
11081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
11091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
11101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
11111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
11121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
11131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
11141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
1115271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
11161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
11171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
11181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
11191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found a dst_type that doesn't point to (static_ptr, static_type)
11201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // So record the address of this dst_ptr and increment the
11211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // count of the number of such dst_types found in the tree.
11221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_not_leading_to_static_ptr = current_ptr;
11231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_dst_ptr += 1;
11241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there exists another dst with a private path to
11251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    (static_ptr, static_type), then the cast from
11261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
1127271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            if (info->number_to_static_ptr == 1 &&
11281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->path_dst_ptr_to_static_ptr == not_public_path)
11291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
11301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found that dst_type does not derive from static_type
11311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->is_dst_type_derived_from_static_type = no;
1132271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
1133271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
11341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
11351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
11361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching above a dst_type node.  This function searches
11371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a public path to (static_ptr, static_type).
11381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This function is guaranteed not to find a node of type dst_type.
11391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Theoretically this is a very simple function which just stops if it finds a
1140facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// static_type node:  All the hoopla surrounding the search code is doing
1141facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// nothing but looking for excuses to stop the search prematurely (break out of
1142facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the for-loop).  That is, the algorithm below is simply an optimization of this:
1143facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
1144facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1145facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* dst_ptr,
1146facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
1147facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
1148facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
1149facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
1150facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1151facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
1152facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
1153facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         typedef const __base_class_type_info* Iter;
1154facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type
1155facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
1156facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
1157facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, dst_ptr, current_ptr, public_path);
1158facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
1159facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
1160facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
1161facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
11621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
11631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
11641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* dst_ptr,
11651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
1166326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
1167326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
11681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
1169326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
11701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1171271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    else
1172271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
11731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        typedef const __base_class_type_info* Iter;
11741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
11751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Save flags so they can be restored when returning to nodes below.
11761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_our_static_ptr = info->found_our_static_ptr;
11771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_any_static_type = info->found_any_static_type;
11781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've found a dst_type below with a path to here.  If the path
11791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    to here is not public, there may be another path to here that
11801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    is public.  So we have to assume that the path to here is public.
11811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //  We can stop looking above if:
11821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    1.  We've found a public path to (static_ptr, static_type).
11831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
11841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        This is detected at the (static_ptr, static_type).
11851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    3.  We can prove that there is no public path to (static_ptr, static_type)
11861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        above here.
11871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
118865255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
118965255631de793131622f701df9075dfd78abfc50Howard Hinnant        // Zero out found flags
119065255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_our_static_ptr = false;
119165255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_any_static_type = false;
1192326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
119365255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
1194271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
119565255631de793131622f701df9075dfd78abfc50Howard Hinnant            do
11961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
119765255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->search_done)
11981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    break;
119965255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->found_our_static_ptr)
120065255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
120165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found what we're looking for, stop looking above.
120265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->path_dst_ptr_to_static_ptr == public_path)
120365255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
120465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // We found a private path to (static_ptr, static_type)
120565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   If there is no diamond then there is only one path
120665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   to (static_ptr, static_type) from here and we just found it.
120765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __diamond_shaped_mask))
120865255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
120965255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
121065255631de793131622f701df9075dfd78abfc50Howard Hinnant                else if (info->found_any_static_type)
121165255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
121265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found a static_type that isn't the one we're looking
121365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    for, and if there are no repeated types above here,
121465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then stop looking.
121565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __non_diamond_repeat_mask))
121665255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
121765255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
121865255631de793131622f701df9075dfd78abfc50Howard Hinnant                // Zero out found flags
121965255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_our_static_ptr = false;
122065255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_any_static_type = false;
1221326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
122265255631de793131622f701df9075dfd78abfc50Howard Hinnant            } while (++p < e);
1223271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
12241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Restore flags
12251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = found_our_static_ptr;
12261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_any_static_type = found_any_static_type;
1227f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
1228185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant}
1229185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant
12301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
12311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
12321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
12331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
12341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* dst_ptr,
12351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
1236326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
1237326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
1238f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
1239326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
12401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
12411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
1242326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1243f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
1244f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
12451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
12461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
124716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
12481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_above_dst(__dynamic_cast_info* info,
12491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* dst_ptr,
12501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
1251326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
1252326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
125316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
1254326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
12551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
125616650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
125716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
12581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// The search functions for __base_class_type_info are simply convenience
12591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   functions for adjusting the current_ptr and path_below as the search is
12601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   passed up to the base class node.
12611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
126216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
12631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
12641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* dst_ptr,
12651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1266326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1267326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
126816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
126916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
127016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    if (__offset_flags & __virtual_mask)
127116650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    {
1272cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1273cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
127416650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    }
12751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_above_dst(info, dst_ptr,
1276cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
12771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
12781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1279326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1280326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
1281152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
1282152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
12841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
12851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1286326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1287326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
128816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
12891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
12901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (__offset_flags & __virtual_mask)
1291f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
1292cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1293cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1294f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
12951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_below_dst(info,
1296cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
12971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
12981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1299326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1300326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
130116650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
130216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
1303facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
1304facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
1305152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}  // __cxxabiv1
1306