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
370a1ce9cae10bf7e2e6640e2a8f1efe7062c47292Dan Albert#ifdef _LIBCXX_DYNAMIC_FALLBACK
38326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#include "abort_message.h"
39326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#include <string.h>
401a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant#include <sys/syslog.h>
411a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant#endif
421a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant
43d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// On Windows, typeids are different between DLLs and EXEs, so comparing
44d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// type_info* will work for typeids from the same compiled file but fail
45d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// for typeids from a DLL and an executable. Among other things, exceptions
46d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// are not caught by handlers since can_catch() returns false.
47d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren//
48d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls
49d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// is_equal() with use_strcmp=false so the string names are not compared.
50d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren
51d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#ifdef _WIN32
52d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#include <string.h>
53d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#endif
54d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren
55152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnantnamespace __cxxabiv1
56152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
57152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
580240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility push(hidden)
59facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
600a1ce9cae10bf7e2e6640e2a8f1efe7062c47292Dan Albert#ifdef _LIBCXX_DYNAMIC_FALLBACK
61326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
62326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
63326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
64326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
65326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
66326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (!use_strcmp)
67326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        return x == y;
68326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return strcmp(x->name(), y->name()) == 0;
69326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
70326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
71326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#else  // !_LIBCXX_DYNAMIC_FALLBACK
72326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
73326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
74326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
75326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool)
76326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
77d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#ifndef _WIN32
78326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return x == y;
79d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#else
80d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren    return (x == y) || (strcmp(x->name(), y->name()) == 0);
81d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#endif
82326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
83326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
84326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
85326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
86facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __shim_type_info
87facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
88facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant__shim_type_info::~__shim_type_info()
89facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
90facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
91facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
928f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop1() const {}
938f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop2() const {}
948f28628704f966409e860c74c46041e04c082720Howard Hinnant
95152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// __fundamental_type_info
96152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
9716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant// This miraculously (compiler magic) emits the type_info's for:
9816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   1. all of the fundamental types
9916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   2. pointers to all of the fundamental types
10016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   3. pointers to all of the const fundamental types
101152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant__fundamental_type_info::~__fundamental_type_info()
102152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
103152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
104152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __array_type_info
10635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
10735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__array_type_info::~__array_type_info()
108facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
109facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
110facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
11135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __function_type_info
112152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__function_type_info::~__function_type_info()
114152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
115152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
116152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __enum_type_info
11835b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
11935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__enum_type_info::~__enum_type_info()
120facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
121facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
122facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
12335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __class_type_info
124152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__class_type_info::~__class_type_info()
126152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
127152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
128152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __si_class_type_info
13035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
13135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__si_class_type_info::~__si_class_type_info()
132facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
133facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
134facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
13535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __vmi_class_type_info
136152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
13735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__vmi_class_type_info::~__vmi_class_type_info()
138152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
139152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
140152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
14135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pbase_type_info
14235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
14335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pbase_type_info::~__pbase_type_info()
144facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
145facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
146facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
14735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_type_info
148152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
14935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_type_info::~__pointer_type_info()
15035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant{
15135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant}
15235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
15335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_to_member_type_info
15435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
15535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_to_member_type_info::~__pointer_to_member_type_info()
156152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
157152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
158152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
159c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// can_catch
160c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
161c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// A handler is a match for an exception object of type E if
162a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   1. The handler is of type cv T or cv T& and E and T are the same type
163a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      (ignoring the top-level cv-qualifiers), or
164a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   2. the handler is of type cv T or cv T& and T is an unambiguous public
165a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//       base class of E, or
166a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
167a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      converted to the type of the handler by either or both of
168a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      A. a standard pointer conversion (4.10) not involving conversions to
169a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//         pointers to private or protected or ambiguous classes
170a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      B. a qualification conversion
171a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   4. the handler is a pointer or pointer to member type and E is
172a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      std::nullptr_t.
173c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
174c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// adjustedPtr:
175c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
176c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A& a) : adjustedPtr == &a
177c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A* a) : adjustedPtr == a
178c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A** a) : adjustedPtr == a
179c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
180c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2& d2) : adjustedPtr == &d2  (d2 is base class of thrown object)
181c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2* d2) : adjustedPtr == d2
182c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2*& d2) : adjustedPtr == d2
183c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
184c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (...) : adjustedPtr == & of the exception
185c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
186a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
187a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
188a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
189a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                   void*&) const
190a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
19106bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
192a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
193a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
194a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
19596f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__array_type_info::can_catch(const __shim_type_info*, void*&) const
196a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
197aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    // We can get here if someone tries to catch an array by reference.
198aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   However if someone tries to throw an array, it immediately gets
199aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   converted to a pointer, which will not convert back to an array
200aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   at the catch clause.  So this can never catch anything.
201a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
202a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
203a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
204a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
20596f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__function_type_info::can_catch(const __shim_type_info*, void*&) const
206a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
2074b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    // We can get here if someone tries to catch a function by reference.
2084b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   However if someone tries to throw a function, it immediately gets
2094b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   converted to a pointer, which will not convert back to a function
2104b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   at the catch clause.  So this can never catch anything.
211a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
212a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
213a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
214a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
215a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
216a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__enum_type_info::can_catch(const __shim_type_info* thrown_type,
217a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                            void*&) const
218a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
21906bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
220a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
221a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
22291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
22391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
22491f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
225a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1 and 2
226a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
227a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::can_catch(const __shim_type_info* thrown_type,
228a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*& adjustedPtr) const
229a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
230a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 1
23106bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, thrown_type, false))
232a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
233a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
234a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_type);
235a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
236a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
237a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 2
238a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0};
239a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
240a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
241a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
242a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
243a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
244a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
245a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
246a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
247a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
248a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
24991f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
25091f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
251a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
252a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::process_found_base_class(__dynamic_cast_info* info,
253a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
254a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
255a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
256a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info->dst_ptr_leading_to_static_ptr == 0)
257a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
258a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // First time here
259a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->dst_ptr_leading_to_static_ptr = adjustedPtr;
260a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = path_below;
261a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr = 1;
262a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
263a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
264a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
265a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've been here before.  Update path to "most public"
266a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (info->path_dst_ptr_to_static_ptr == not_public_path)
267a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
268a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
269a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
270a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
271a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
272a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        //   to a static_type
273a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr += 1;
274a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = not_public_path;
275a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->search_done = true;
276a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
277a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
278a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
279a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
280a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
281a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
282a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
283a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
28406bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
285a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
286a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
287a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
288a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
289a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
290a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  void* adjustedPtr,
291a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  int path_below) const
292a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
29306bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
294a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
295a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
296a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
297a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
298a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
299a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
300a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
301a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    void* adjustedPtr,
302a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    int path_below) const
303a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
30498bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    ptrdiff_t offset_to_base = 0;
30598bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    if (adjustedPtr != nullptr)
306a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
30798bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        offset_to_base = __offset_flags >> __offset_shift;
30898bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        if (__offset_flags & __virtual_mask)
30998bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        {
31098bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            const char* vtable = *static_cast<const char*const*>(adjustedPtr);
31198bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
31298bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow        }
313a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
31498bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow    __base_type->has_unambiguous_public_base(
31598bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            info,
31698bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            static_cast<char*>(adjustedPtr) + offset_to_base,
31798bbf28c5eac8ed3356909563e4d80529507995fMarshall Clow            (__offset_flags & __public_mask) ? path_below : not_public_path);
318a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
319a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
320a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
321a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
322a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   void* adjustedPtr,
323a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   int path_below) const
324a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
32506bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
326a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
327a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
328a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
329a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        typedef const __base_class_type_info* Iter;
330a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        const Iter e = __base_info + __base_count;
331a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        Iter p = __base_info;
332a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        p->has_unambiguous_public_base(info, adjustedPtr, path_below);
333a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (++p < e)
334a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        {
335a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            do
336a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            {
337a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                p->has_unambiguous_public_base(info, adjustedPtr, path_below);
338a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                if (info->search_done)
339a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                    break;
340a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            } while (++p < e);
341a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        }
342a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
343a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
344a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
345c649bdea9d3f67756d97fa1c9a837f53a762dbccHoward Hinnant// Handles bullets 1 and 4 for both pointers and member pointers
346a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
347a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
348a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*&) const
349a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
350e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert    return is_equal(this, thrown_type, false) ||
351e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert           is_equal(thrown_type, &typeid(std::nullptr_t), false);
352a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
353a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
35491f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
35591f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
35691f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
357a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1, 3 and 4
358e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert// NOTE: It might not be safe to adjust the pointer if it is not not a pointer
359e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert// type. Only adjust the pointer after we know it is safe to do so.
360a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
361a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
362a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                               void*& adjustedPtr) const
363a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
364a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullets 1 and 4
365e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr)) {
366e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert        if (adjustedPtr != NULL)
367e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert            adjustedPtr = *static_cast<void**>(adjustedPtr);
368a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
369e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert    }
370a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3
371a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __pointer_type_info* thrown_pointer_type =
372a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __pointer_type_info*>(thrown_type);
373a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type == 0)
374a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
375e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert    // Do the dereference adjustment
376e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert    if (adjustedPtr != NULL)
377e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert        adjustedPtr = *static_cast<void**>(adjustedPtr);
378a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3B
379a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type->__flags & ~__flags)
380a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
38106bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
382a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
383a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3A
38406bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, &typeid(void), false))
385a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
386a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* catch_class_type =
387a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(__pointee);
388a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (catch_class_type == 0)
389a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
390a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
391a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
392a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
393a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
394a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0};
395a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
396a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
397a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
398a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
399288859d0a1684e0899702f50353ccdbc1bdab8b7Marshall Clow        if (adjustedPtr != NULL)
400288859d0a1684e0899702f50353ccdbc1bdab8b7Marshall Clow            adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
401a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
402a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
403a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
404a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
405c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
40691f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
40791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
4080240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility pop
409facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(default)
410facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
41191f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
41291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
41391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
4141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// __dynamic_cast
4151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
416cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr: pointer to an object of type static_type; nonnull, and since the
417cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   object is polymorphic, *(void**)static_ptr is a virtual table pointer.
418cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   static_ptr is &v in the expression dynamic_cast<T>(v).
419cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type: static type of the object pointed to by static_ptr.
420cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
4211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// src2dst_offset: a static hint about the location of the
4221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 source subobject with respect to the complete object;
4231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 special negative values are:
4241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -1: no hint
4251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -2: static_type is not a public base of dst_type
4261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -3: static_type is a multiple public base type but never a
4271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                         virtual base type
4281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 otherwise, the static_type type is a unique public nonvirtual
4291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 base type of dst_type at offset src2dst_offset from the
4301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 origin of dst_type.
4311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
432cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) are the run time type of the complete object
433cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// referred to by static_ptr and a pointer to it.  These can be found from
434cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr for polymorphic types.
4351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// static_type is guaranteed to be a polymorphic type.
4361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
437cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward.  Each
438cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// node of the tree represents a base class/object of its parent (or parents) below.
439cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Each node is uniquely represented by a pointer to the object, and a pointer
440cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// to a type_info - its type.  Different nodes may have the same pointer and
441cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// different nodes may have the same type.  But only one node has a specific
442cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (pointer-value, type) pair.  In C++ two objects of the same type can not
443cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// share the same address.
444cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
445cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There are two flavors of nodes which have the type dst_type:
446cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    1.  Those that are derived from (below) (static_ptr, static_type).
447cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    2.  Those that are not derived from (below) (static_ptr, static_type).
448cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
449cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Invariants of the DAG:
450cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
451cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There is at least one path from the root (dynamic_ptr, dynamic_type) to
452cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// the node (static_ptr, static_type).  This path may or may not be public.
453cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There may be more than one such path (some public some not).  Such a path may
454cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// or may not go through a node having type dst_type.
455cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
456cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type T appears above a node of the same type.  That means that
457cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// there is only one node with dynamic_type.  And if dynamic_type == dst_type,
458cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// then there is only one dst_type in the DAG.
459cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
460cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type dst_type appears above a node of type static_type.  Such
461cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// DAG's are possible in C++, but the compiler computes those dynamic_casts at
462cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// compile time, and only calls __dynamic_cast when dst_type lies below
463cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type in the DAG.
464cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
465cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type != static_type:  The compiler computes the dynamic_cast in this case too.
466facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// dynamic_type != static_type:  The compiler computes the dynamic_cast in this case too.
467cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
468cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Returns:
469cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
470cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// If there is exactly one dst_type of flavor 1, and
4711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    If there is a public path from that dst_type to (static_ptr, static_type), or
472cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    If there are 0 dst_types of flavor 2, and there is a public path from
4731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
4741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
4751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        a pointer to that dst_type.
476cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
477facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//    if there is a public path from (dynamic_ptr, dynamic_type) to
4781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
4791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    to the one dst_type, then return a pointer to that one dst_type.
4801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
4811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
4821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If dynamic_type == dst_type, then the above algorithm collapses to the
4831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// following cheaper algorithm:
4841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
4851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If there is a public path from (dynamic_ptr, dynamic_type) to
4861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type), then return dynamic_ptr.
4871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
4881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantextern "C"
4891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid*
4901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__dynamic_cast(const void* static_ptr,
4910240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               const __class_type_info* static_type,
4920240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               const __class_type_info* dst_type,
4930240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               std::ptrdiff_t src2dst_offset)
4941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
4950550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Possible future optimization:  Take advantage of src2dst_offset
4960550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Currently clang always sets src2dst_offset to -1 (no hint).
497cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
498cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Get (dynamic_ptr, dynamic_type) from static_ptr
4991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    void** vtable = *(void***)static_ptr;
500cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
501cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
502cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
503cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
504cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize answer to nullptr.  This will be changed from the search
505cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    results if a non-null answer is found.  Regardless, this is what will
506cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    be returned.
5071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    const void* dst_ptr = 0;
508cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize info struct for this search.
5091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
510cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
511cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Find out if we can use a giant short cut in the search
51206bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(dynamic_type, dst_type, false))
513f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
514cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Using giant short cut.  Add that information to info.
5151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info.number_of_dst_type = 1;
516cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Do the  search
517326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
5180a1ce9cae10bf7e2e6640e2a8f1efe7062c47292Dan Albert#ifdef _LIBCXX_DYNAMIC_FALLBACK
5191a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
5201a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
5211a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown)
5221a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
5231a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            // We get here only if there is some kind of visibility problem
5241a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            //   in client code.
525552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
5266c33e768c1b37af3e5d5f9f0e2a72fcf1dc51382Howard Hinnant                    "should have public visibility.  At least one of them is hidden. %s"
527552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                    ", %s.\n", static_type->name(), dynamic_type->name());
528326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
529326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
530326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info.number_of_dst_type = 1;
531326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
5321a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
533326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
534cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
5351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info.path_dst_ptr_to_static_ptr == public_path)
5361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            dst_ptr = dynamic_ptr;
5371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
5381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
5391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
540cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Not using giant short cut.  Do the search
541326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
5420a1ce9cae10bf7e2e6640e2a8f1efe7062c47292Dan Albert #ifdef _LIBCXX_DYNAMIC_FALLBACK
5431a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
5441a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
545326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown &&
5461a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            info.path_dynamic_ptr_to_static_ptr == unknown)
5471a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
548552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
549552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " has hidden visibility.  They should all have public visibility.  "
550552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " %s, %s, %s.\n", static_type->name(), dynamic_type->name(),
5511a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant                    dst_type->name());
552326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
553326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
554326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
5551a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
556326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
557cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
5581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        switch (info.number_to_static_ptr)
559f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
5601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 0:
5611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.number_to_dst_ptr == 1 &&
5621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_static_ptr == public_path &&
5631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_dst_ptr == public_path)
5641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
5651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
5661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 1:
5671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.path_dst_ptr_to_static_ptr == public_path ||
5681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   (
5691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.number_to_dst_ptr == 0 &&
5701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_static_ptr == public_path &&
5711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_dst_ptr == public_path
5721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   )
5731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant               )
5741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_leading_to_static_ptr;
5751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
576f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
577f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
5781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    return const_cast<void*>(dst_ptr);
579f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
580f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
58191f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
58291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
583facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
584facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(hidden)
585facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
5861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is a base (above) a dst_type.
5871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Let caller know you hit a static_type.  But only start recording details if
5881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// this is (static_ptr, static_type) -- the node we are casting from.
5891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
5901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from the dst_type to here.  There may be
5911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from the same dst_type to here, record the "most public" one.
5921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the dst_ptr as pointing to (static_ptr, static_type).
5931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
5941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   then mark this dyanmic_cast as ambiguous and stop the search.
5951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
5961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
5971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* dst_ptr,
5981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
5991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
600f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
6011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    // Record that we found a static_type
6021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    info->found_any_static_type = true;
6031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
604271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
6051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record that we found (static_ptr, static_type)
6061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = true;
6071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->dst_ptr_leading_to_static_ptr == 0)
608271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
6091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // First time here
6101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_leading_to_static_ptr = dst_ptr;
6111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
6121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr = 1;
6131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
6141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
6151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
6161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
617271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
6181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
619f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
6201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've been here before.  Update path to "most public"
6211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->path_dst_ptr_to_static_ptr == not_public_path)
6221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dst_ptr_to_static_ptr = path_below;
6231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
6241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
6251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
6261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
627f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
628f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        else
629f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
6301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've detected an ambiguous cast from (static_ptr, static_type)
6311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   to a dst_type
6321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr += 1;
6331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->search_done = true;
634f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
635f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
636f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
637f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
6381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is not a base (above) a dst_type.
6391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
6401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from (dynamic_ptr, dynamic_type) to here.  There may be
6411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
64216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
6431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
6441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
6451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
646152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
6471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
6481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
6491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record the most public path from (dynamic_ptr, dynamic_type) to
6501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //                                  (static_ptr, static_type)
6511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->path_dynamic_ptr_to_static_ptr != public_path)
6521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_static_ptr = path_below;
6531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
654152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
655152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
6561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching below a dst_type node.  This function searches
6571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
6581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a static_type node, there is no need to further search base classes
6591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// above.
6601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a dst_type node it should search base classes using search_above_dst
6611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// to find out if this dst_type points to (static_ptr, static_type) or not.
662cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Either way, the dst_type is recorded as one of two "flavors":  one that does
6631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// or does not point to (static_ptr, static_type).
6641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is neither a static_type nor a dst_type node, continue searching
6651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// base classes above.
6661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// All the hoopla surrounding the search code is doing nothing but looking for
667facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// excuses to stop the search prematurely (break out of the for-loop).  That is,
668facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the algorithm below is simply an optimization of this:
669facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
670facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
671facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
672facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
673facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
674facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     typedef const __base_class_type_info* Iter;
675facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
676facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_below_dst(info, current_ptr, path_below);
677facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else if (this == info->dst_type)
678facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
679facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // Record the most public access path that got us here
680facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (info->path_dynamic_ptr_to_dst_ptr != public_path)
681facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->path_dynamic_ptr_to_dst_ptr = path_below;
682facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         bool does_dst_type_point_to_our_static_type = false;
683facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
684facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
685facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, current_ptr, current_ptr, public_path);
686facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             if (info->found_our_static_ptr)
687facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                 does_dst_type_point_to_our_static_type = true;
688facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
689facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
690facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (!does_dst_type_point_to_our_static_type)
691facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
692facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // We found a dst_type that doesn't point to (static_ptr, static_type)
693facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // So record the address of this dst_ptr and increment the
694facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // count of the number of such dst_types found in the tree.
695facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->dst_ptr_not_leading_to_static_ptr = current_ptr;
696facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->number_to_dst_ptr += 1;
697facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
698facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
699facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
700facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
701facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type.
702facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
703facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
704facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_below_dst(info, current_ptr, public_path);
705facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
706facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
707facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
708facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
7091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
7101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
7111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
712326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
713326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
714f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
715f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    typedef const __base_class_type_info* Iter;
716326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
7171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
718326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
719f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
7201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
7211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
7221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
7231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
724f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
7251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
7261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
7271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
7281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
7291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
7301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
7311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
7321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
7331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
7341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
7351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
7361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
7371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
7381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
7391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
7401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
7411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
7421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
7431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We've found a dst_type with a potentially public path to here.
7441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We have to assume the path is public because it may become
7451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   public later (if we get back to here with a public path).
7461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We can stop looking above if:
7471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    1.  We've found a public path to (static_ptr, static_type).
7481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
7491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        This is detected at the (static_ptr, static_type).
7501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    3.  We can prove that there is no public path to (static_ptr, static_type)
7511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        above here.
7521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                const Iter e = __base_info + __base_count;
7531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                for (Iter p = __base_info; p < e; ++p)
7541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
7551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // Zero out found flags
7561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_our_static_ptr = false;
7571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_any_static_type = false;
758326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
759cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                    if (info->search_done)
7601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        break;
7611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_any_static_type)
7621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    {
7631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        is_dst_type_derived_from_static_type = true;
7641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        if (info->found_our_static_ptr)
7651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
7661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            does_dst_type_point_to_our_static_type = true;
7671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found what we're looking for, stop looking above.
7681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (info->path_dst_ptr_to_static_ptr == public_path)
7691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // We found a private path to (static_ptr, static_type)
7711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   If there is no diamond then there is only one path
7721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   to (static_ptr, static_type) and we just found it.
7731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __diamond_shaped_mask))
7741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
7761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        else
7771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
7781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found a static_type that isn't the one we're looking
7791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    for, and if there are no repeated types above here,
7801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    then stop looking.
7811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __non_diamond_repeat_mask))
7821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
7841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    }
7851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
7861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
7871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
7881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
7891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
7901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
7911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
7921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->number_to_dst_ptr += 1;
7931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // If there exists another dst with a private path to
7941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //    (static_ptr, static_type), then the cast from
7951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
7961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //      so stop search.
7971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
7981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
7991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
8001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
8011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
8021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
8031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
8041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
8051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
8061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
8071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
8081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
8091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
810f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
811f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
8121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
813271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
8141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type.
8151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
81665255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
817326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_below_dst(info, current_ptr, path_below, use_strcmp);
81865255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
8191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
82065255631de793131622f701df9075dfd78abfc50Howard Hinnant            if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
8211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
82265255631de793131622f701df9075dfd78abfc50Howard Hinnant                // If there are multiple paths to a base above from here, or if
82365255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    a dst_type pointing to (static_ptr, static_type) has been found,
82465255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    then there is no way to break out of this loop early unless
82565255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    something below detects the search is done.
82665255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
82765255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
82865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
82965255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
830326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
83165255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
8321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
83365255631de793131622f701df9075dfd78abfc50Howard Hinnant            else if (__flags & __non_diamond_repeat_mask)
834271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
83565255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are not multiple paths to any base class from here and a
83665255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   dst_type pointing to (static_ptr, static_type) has not yet been
83765255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   found.
83865255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
83965255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
84065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
84165255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
84265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
84365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure
84465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
84565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
84665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1 &&
84765255631de793131622f701df9075dfd78abfc50Howard Hinnant                              info->path_dst_ptr_to_static_ptr == public_path)
84865255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
849326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
85065255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
851271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
85265255631de793131622f701df9075dfd78abfc50Howard Hinnant            else
853271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
85465255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no repeated types above this node.
85565255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no nodes with multiple parents above this node.
85665255631de793131622f701df9075dfd78abfc50Howard Hinnant                // no dst_type has been found to (static_ptr, static_type)
85765255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
85865255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
85965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
86065255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
86165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
86265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure sure
86365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
86465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
86565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // if we just found a dst_type with a private path to (static_ptr, static_type),
86665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then we're only looking for a public path to (static_ptr, static_type)
86765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and to check for other dst_types.
86865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
86965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and not a dst_type under here.
87065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1)
87165255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
872326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
87365255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
874271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
875271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
876271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
8771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
8781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
8791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
8801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
8811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
8821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
8831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
884326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
885326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
8861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
887326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
8881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
889326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
890f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
8911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
8921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
8931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
8941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
895f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
8961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
8971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
8981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
899f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            if (path_below == public_path)
900f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
901f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
902271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        else  // We have haven't been here before
903f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
904271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            // Record the access path that got us here
9051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
906f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
9071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
9081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
9091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
910f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            {
9111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
9121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
9131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
9141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Zero out found flags
9151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_our_static_ptr = false;
9161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_any_static_type = false;
917326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
9181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (info->found_any_static_type)
919f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
9201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    is_dst_type_derived_from_static_type = true;
9211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_our_static_ptr)
9221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        does_dst_type_point_to_our_static_type = true;
923f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
9241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
925f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
9261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
9271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
9281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
9291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
930f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                    info->number_to_dst_ptr += 1;
931271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    // If there exists another dst with a private path to
932271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //    (static_ptr, static_type), then the cast from
933271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
934271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
9351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
9361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
937f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
9381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
9391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
9401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
9411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
9421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
9431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
9441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
9451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
946f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            }
947f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
948f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
950f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
9511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
952326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
953f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
9551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
9561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
9571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
9581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
9591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_below_dst(__dynamic_cast_info* info,
9601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
961326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
962326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
9631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
964326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
9651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
966326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
967f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
9681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
9691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
9701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
9711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
9721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
9731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
9741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
9751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
9761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
9771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
9781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
9791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
980271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
9811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
9821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
9831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
9841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found a dst_type that doesn't point to (static_ptr, static_type)
9851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // So record the address of this dst_ptr and increment the
9861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // count of the number of such dst_types found in the tree.
9871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_not_leading_to_static_ptr = current_ptr;
9881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_dst_ptr += 1;
9891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there exists another dst with a private path to
9901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    (static_ptr, static_type), then the cast from
9911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
992271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            if (info->number_to_static_ptr == 1 &&
9931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->path_dst_ptr_to_static_ptr == not_public_path)
9941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
9951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found that dst_type does not derive from static_type
9961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->is_dst_type_derived_from_static_type = no;
997271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
998271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
9991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
10001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
10011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching above a dst_type node.  This function searches
10021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a public path to (static_ptr, static_type).
10031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This function is guaranteed not to find a node of type dst_type.
10041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Theoretically this is a very simple function which just stops if it finds a
1005facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// static_type node:  All the hoopla surrounding the search code is doing
1006facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// nothing but looking for excuses to stop the search prematurely (break out of
1007facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the for-loop).  That is, the algorithm below is simply an optimization of this:
1008facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
1009facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1010facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* dst_ptr,
1011facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
1012facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
1013facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
1014facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
1015facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1016facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
1017facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
1018facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         typedef const __base_class_type_info* Iter;
1019facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type
1020facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
1021facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
1022facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, dst_ptr, current_ptr, public_path);
1023facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
1024facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
1025facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
1026facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
10271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
10291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* dst_ptr,
10301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
1031326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
1032326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
10331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
1034326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
10351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1036271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    else
1037271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
10381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        typedef const __base_class_type_info* Iter;
10391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
10401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Save flags so they can be restored when returning to nodes below.
10411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_our_static_ptr = info->found_our_static_ptr;
10421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_any_static_type = info->found_any_static_type;
10431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've found a dst_type below with a path to here.  If the path
10441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    to here is not public, there may be another path to here that
10451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    is public.  So we have to assume that the path to here is public.
10461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //  We can stop looking above if:
10471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    1.  We've found a public path to (static_ptr, static_type).
10481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
10491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        This is detected at the (static_ptr, static_type).
10501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    3.  We can prove that there is no public path to (static_ptr, static_type)
10511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        above here.
10521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
105365255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
105465255631de793131622f701df9075dfd78abfc50Howard Hinnant        // Zero out found flags
105565255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_our_static_ptr = false;
105665255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_any_static_type = false;
1057326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
105865255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
1059271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
106065255631de793131622f701df9075dfd78abfc50Howard Hinnant            do
10611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
106265255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->search_done)
10631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    break;
106465255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->found_our_static_ptr)
106565255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
106665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found what we're looking for, stop looking above.
106765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->path_dst_ptr_to_static_ptr == public_path)
106865255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
106965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // We found a private path to (static_ptr, static_type)
107065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   If there is no diamond then there is only one path
107165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   to (static_ptr, static_type) from here and we just found it.
107265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __diamond_shaped_mask))
107365255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
107465255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
107565255631de793131622f701df9075dfd78abfc50Howard Hinnant                else if (info->found_any_static_type)
107665255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
107765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found a static_type that isn't the one we're looking
107865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    for, and if there are no repeated types above here,
107965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then stop looking.
108065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __non_diamond_repeat_mask))
108165255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
108265255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
108365255631de793131622f701df9075dfd78abfc50Howard Hinnant                // Zero out found flags
108465255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_our_static_ptr = false;
108565255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_any_static_type = false;
1086326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
108765255631de793131622f701df9075dfd78abfc50Howard Hinnant            } while (++p < e);
1088271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
10891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Restore flags
10901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = found_our_static_ptr;
10911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_any_static_type = found_any_static_type;
1092f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
1093185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant}
1094185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant
10951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
10961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
10971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
10991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* dst_ptr,
11001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
1101326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
1102326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
1103f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
1104326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
11051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
11061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
1107326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1108f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
1109f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
11101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
11111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
111216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
11131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_above_dst(__dynamic_cast_info* info,
11141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* dst_ptr,
11151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
1116326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
1117326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
111816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
1119326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
11201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
112116650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
112216650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
11231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// The search functions for __base_class_type_info are simply convenience
11241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   functions for adjusting the current_ptr and path_below as the search is
11251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   passed up to the base class node.
11261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
112716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
11281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
11291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* dst_ptr,
11301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1131326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1132326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
113316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
113416650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
113516650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    if (__offset_flags & __virtual_mask)
113616650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    {
1137cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1138cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
113916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    }
11401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_above_dst(info, dst_ptr,
1141cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
11421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
11431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1144326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1145326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
1146152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
1147152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
11491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
11501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1151326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1152326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
115316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
11541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
11551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (__offset_flags & __virtual_mask)
1156f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
1157cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1158cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1159f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
11601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_below_dst(info,
1161cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
11621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
11631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1164326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1165326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
116616650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
116716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
1168facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
1169facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
1170152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}  // __cxxabiv1
1171