private_typeinfo.cpp revision d9eb5fc4502578e2d2a4df8c60c46970c36c4046
1152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//===----------------------- private_typeinfo.cpp -------------------------===//
2152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//
3152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//                     The LLVM Compiler Infrastructure
4152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//
5152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
6152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// Source Licenses. See LICENSE.TXT for details.
7152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//
8152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant//===----------------------------------------------------------------------===//
9152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant#include "private_typeinfo.h"
11152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more
13326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// forgiving when type_info's mistakenly have hidden visibility and thus
14326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// multiple type_infos can exist for a single type.
15326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
16326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where
17326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// there is a detected inconsistency in the type_info hierarchy during a
18326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// dynamic_cast, then the equality operation will fall back to using strcmp
196d00feffc82d4f8c0201242291a0e93b492e1dd4Howard Hinnant// on type_info names to determine type_info equality.
20326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
21326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// This change happens *only* under dynamic_cast, and only when
22326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// dynamic_cast is faced with the choice:  abort, or possibly give back the
23326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// wrong answer.  If when the dynamic_cast is done with this fallback
24326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// algorithm and an inconsistency is still detected, dynamic_cast will call
256d00feffc82d4f8c0201242291a0e93b492e1dd4Howard Hinnant// abort with an appropriate message.
26326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
27326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a
28326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// printf-like function called syslog:
29326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
3036fd93fd039ef14005d6ab51c2e9f2816d2b7063Yaron Keren//     void syslog(int facility_priority, const char* format, ...);
31326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
32326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// If you want this functionality but your platform doesn't have syslog,
33326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// just implement it in terms of fprintf(stderr, ...).
34326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant//
35326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant// _LIBCXX_DYNAMIC_FALLBACK is currently off by default.
36326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
37326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#if _LIBCXX_DYNAMIC_FALLBACK
38326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#include "abort_message.h"
39326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#include <string.h>
401a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant#include <sys/syslog.h>
411a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant#endif
421a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant
43d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// On Windows, typeids are different between DLLs and EXEs, so comparing
44d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// type_info* will work for typeids from the same compiled file but fail
45d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// for typeids from a DLL and an executable. Among other things, exceptions
46d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// are not caught by handlers since can_catch() returns false.
47d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren//
48d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls
49d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren// is_equal() with use_strcmp=false so the string names are not compared.
50d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren
51d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#ifdef _WIN32
52d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#include <string.h>
53d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#endif
54d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren
55152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnantnamespace __cxxabiv1
56152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
57152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
580240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility push(hidden)
59facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
60326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#if _LIBCXX_DYNAMIC_FALLBACK
61326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
62326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
63326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
64326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
65326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
66326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (!use_strcmp)
67326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        return x == y;
68326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return strcmp(x->name(), y->name()) == 0;
69326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
70326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
71326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#else  // !_LIBCXX_DYNAMIC_FALLBACK
72326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
73326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantinline
74326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantbool
75326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnantis_equal(const std::type_info* x, const std::type_info* y, bool)
76326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant{
77d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#ifndef _WIN32
78326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    return x == y;
79d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#else
80d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren    return (x == y) || (strcmp(x->name(), y->name()) == 0);
81d9eb5fc4502578e2d2a4df8c60c46970c36c4046Yaron Keren#endif
82326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant}
83326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
84326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
85326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant
86facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __shim_type_info
87facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
88facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant__shim_type_info::~__shim_type_info()
89facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
90facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
91facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
928f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop1() const {}
938f28628704f966409e860c74c46041e04c082720Howard Hinnantvoid __shim_type_info::noop2() const {}
948f28628704f966409e860c74c46041e04c082720Howard Hinnant
95152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant// __fundamental_type_info
96152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
9716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant// This miraculously (compiler magic) emits the type_info's for:
9816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   1. all of the fundamental types
9916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   2. pointers to all of the fundamental types
10016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant//   3. pointers to all of the const fundamental types
101152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant__fundamental_type_info::~__fundamental_type_info()
102152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
103152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
104152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
10535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __array_type_info
10635b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
10735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__array_type_info::~__array_type_info()
108facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
109facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
110facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
11135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __function_type_info
112152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__function_type_info::~__function_type_info()
114152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
115152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
116152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __enum_type_info
11835b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
11935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__enum_type_info::~__enum_type_info()
120facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
121facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
122facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
12335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __class_type_info
124152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__class_type_info::~__class_type_info()
126152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
127152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
128152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
12935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __si_class_type_info
13035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
13135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__si_class_type_info::~__si_class_type_info()
132facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
133facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
134facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
13535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __vmi_class_type_info
136152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
13735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__vmi_class_type_info::~__vmi_class_type_info()
138152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
139152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
140152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
14135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pbase_type_info
14235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
14335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pbase_type_info::~__pbase_type_info()
144facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant{
145facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant}
146facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
14735b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_type_info
148152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
14935b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_type_info::~__pointer_type_info()
15035b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant{
15135b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant}
15235b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
15335b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant// __pointer_to_member_type_info
15435b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant
15535b2c2af6b2720a3f624ad556b1a3c75394350d7Howard Hinnant__pointer_to_member_type_info::~__pointer_to_member_type_info()
156152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
157152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
158152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
159c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// can_catch
160c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
161c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// A handler is a match for an exception object of type E if
162a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   1. The handler is of type cv T or cv T& and E and T are the same type
163a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      (ignoring the top-level cv-qualifiers), or
164a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   2. the handler is of type cv T or cv T& and T is an unambiguous public
165a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//       base class of E, or
166a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
167a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      converted to the type of the handler by either or both of
168a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      A. a standard pointer conversion (4.10) not involving conversions to
169a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//         pointers to private or protected or ambiguous classes
170a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      B. a qualification conversion
171a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//   4. the handler is a pointer or pointer to member type and E is
172a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant//      std::nullptr_t.
173c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
174c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// adjustedPtr:
175c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
176c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A& a) : adjustedPtr == &a
177c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A* a) : adjustedPtr == a
178c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (A** a) : adjustedPtr == a
179c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
180c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2& d2) : adjustedPtr == &d2  (d2 is base class of thrown object)
181c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2* d2) : adjustedPtr == d2
182c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (D2*& d2) : adjustedPtr == d2
183c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant//
184c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant// catch (...) : adjustedPtr == & of the exception
185c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
186a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
187a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
188a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
189a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                   void*&) const
190a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
19106bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
192a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
193a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
194a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
19596f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__array_type_info::can_catch(const __shim_type_info*, void*&) const
196a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
197aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    // We can get here if someone tries to catch an array by reference.
198aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   However if someone tries to throw an array, it immediately gets
199aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   converted to a pointer, which will not convert back to an array
200aafd08aa288da66805f97231e8c64020bc9d50c6Howard Hinnant    //   at the catch clause.  So this can never catch anything.
201a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
202a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
203a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
204a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
20596f01710bc5b9c37765f60b9a2e12327d2463d65Howard Hinnant__function_type_info::can_catch(const __shim_type_info*, void*&) const
206a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
2074b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    // We can get here if someone tries to catch a function by reference.
2084b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   However if someone tries to throw a function, it immediately gets
2094b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   converted to a pointer, which will not convert back to a function
2104b3cb1cb82c0479bc9c675b79a2250ea4c85aae8Howard Hinnant    //   at the catch clause.  So this can never catch anything.
211a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
212a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
213a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
214a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullet 1
215a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
216a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__enum_type_info::can_catch(const __shim_type_info* thrown_type,
217a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                            void*&) const
218a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
21906bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(this, thrown_type, false);
220a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
221a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
22291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
22391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
22491f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
225a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1 and 2
226a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
227a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::can_catch(const __shim_type_info* thrown_type,
228a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*& adjustedPtr) const
229a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
230a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 1
23106bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, thrown_type, false))
232a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
233a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
234a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_type);
235a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
236a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
237a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 2
238a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0};
239a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
240a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
241a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
242a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
243a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
244a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
245a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
246a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
247a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
248a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
24991f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
25091f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
251a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
252a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::process_found_base_class(__dynamic_cast_info* info,
253a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
254a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
255a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
256a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info->dst_ptr_leading_to_static_ptr == 0)
257a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
258a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // First time here
259a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->dst_ptr_leading_to_static_ptr = adjustedPtr;
260a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = path_below;
261a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr = 1;
262a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
263a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
264a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
265a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've been here before.  Update path to "most public"
266a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (info->path_dst_ptr_to_static_ptr == not_public_path)
267a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
268a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
269a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
270a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
271a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
272a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        //   to a static_type
273a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->number_to_static_ptr += 1;
274a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->path_dst_ptr_to_static_ptr = not_public_path;
275a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        info->search_done = true;
276a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
277a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
278a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
279a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
280a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
281a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               void* adjustedPtr,
282a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                               int path_below) const
283a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
28406bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
285a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
286a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
287a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
288a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
289a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
290a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  void* adjustedPtr,
291a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                  int path_below) const
292a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
29306bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
294a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
295a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
296a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
297a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
298a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
299a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
300a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
301a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    void* adjustedPtr,
302a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                    int path_below) const
303a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
304a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
305a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (__offset_flags & __virtual_mask)
306a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
307a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        const char* vtable = *static_cast<const char*const*>(adjustedPtr);
308a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
309a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
310a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __base_type->has_unambiguous_public_base(info,
311a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                             static_cast<char*>(adjustedPtr) + offset_to_base,
312a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                             (__offset_flags & __public_mask) ?
313a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                 path_below :
314a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                 not_public_path);
315a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
316a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
317a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantvoid
318a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
319a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   void* adjustedPtr,
320a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                                                   int path_below) const
321a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
32206bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, info->static_type, false))
323a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        process_found_base_class(info, adjustedPtr, path_below);
324a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    else
325a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
326a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        typedef const __base_class_type_info* Iter;
327a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        const Iter e = __base_info + __base_count;
328a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        Iter p = __base_info;
329a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        p->has_unambiguous_public_base(info, adjustedPtr, path_below);
330a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        if (++p < e)
331a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        {
332a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            do
333a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            {
334a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                p->has_unambiguous_public_base(info, adjustedPtr, path_below);
335a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                if (info->search_done)
336a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                    break;
337a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant            } while (++p < e);
338a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        }
339a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
340a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
341a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
342c649bdea9d3f67756d97fa1c9a837f53a762dbccHoward Hinnant// Handles bullets 1 and 4 for both pointers and member pointers
343a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
344a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
345a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                             void*&) const
346a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
34706bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(this, thrown_type, false))
348a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
34906bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    return is_equal(thrown_type, &typeid(std::nullptr_t), false);
350a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
351a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant
35291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
35391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
35491f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
355a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant// Handles bullets 1, 3 and 4
356a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnantbool
357a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
358a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant                               void*& adjustedPtr) const
359a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant{
360a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // Do the dereference adjustment
361a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    adjustedPtr = *static_cast<void**>(adjustedPtr);
362a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullets 1 and 4
363a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
364a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
365a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3
366a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __pointer_type_info* thrown_pointer_type =
367a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __pointer_type_info*>(thrown_type);
368a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type == 0)
369a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
370a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3B
371a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_pointer_type->__flags & ~__flags)
372a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
37306bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
374a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
375a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    // bullet 3A
37606bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(__pointee, &typeid(void), false))
377a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
378a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* catch_class_type =
379a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(__pointee);
380a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (catch_class_type == 0)
381a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
382a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    const __class_type_info* thrown_class_type =
383a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
384a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (thrown_class_type == 0)
385a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return false;
386a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0};
387a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    info.number_of_dst_type = 1;
388a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
389a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    if (info.path_dst_ptr_to_static_ptr == public_path)
390a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    {
391a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
392a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant        return true;
393a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    }
394a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant    return false;
395a1919d2ee24b06c833493cf06335afa307028bf7Howard Hinnant}
396c30bfdc7ff4f0ab46e614fb8891be0785ae9a753Howard Hinnant
39791f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
39891f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
3990240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant#pragma GCC visibility pop
400facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(default)
401facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
40291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic push
40391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic ignored "-Wmissing-field-initializers"
40491f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
4051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// __dynamic_cast
4061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
407cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr: pointer to an object of type static_type; nonnull, and since the
408cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   object is polymorphic, *(void**)static_ptr is a virtual table pointer.
409cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//   static_ptr is &v in the expression dynamic_cast<T>(v).
410cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type: static type of the object pointed to by static_ptr.
411cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
4121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// src2dst_offset: a static hint about the location of the
4131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 source subobject with respect to the complete object;
4141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 special negative values are:
4151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -1: no hint
4161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -2: static_type is not a public base of dst_type
4171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                     -3: static_type is a multiple public base type but never a
4181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                         virtual base type
4191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 otherwise, the static_type type is a unique public nonvirtual
4201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 base type of dst_type at offset src2dst_offset from the
4211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//                 origin of dst_type.
4221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
423cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) are the run time type of the complete object
424cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// referred to by static_ptr and a pointer to it.  These can be found from
425cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_ptr for polymorphic types.
4261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// static_type is guaranteed to be a polymorphic type.
4271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
428cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward.  Each
429cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// node of the tree represents a base class/object of its parent (or parents) below.
430cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Each node is uniquely represented by a pointer to the object, and a pointer
431cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// to a type_info - its type.  Different nodes may have the same pointer and
432cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// different nodes may have the same type.  But only one node has a specific
433cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// (pointer-value, type) pair.  In C++ two objects of the same type can not
434cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// share the same address.
435cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
436cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There are two flavors of nodes which have the type dst_type:
437cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    1.  Those that are derived from (below) (static_ptr, static_type).
438cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    2.  Those that are not derived from (below) (static_ptr, static_type).
439cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
440cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Invariants of the DAG:
441cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
442cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There is at least one path from the root (dynamic_ptr, dynamic_type) to
443cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// the node (static_ptr, static_type).  This path may or may not be public.
444cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// There may be more than one such path (some public some not).  Such a path may
445cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// or may not go through a node having type dst_type.
446cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
447cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type T appears above a node of the same type.  That means that
448cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// there is only one node with dynamic_type.  And if dynamic_type == dst_type,
449cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// then there is only one dst_type in the DAG.
450cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
451cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// No node of type dst_type appears above a node of type static_type.  Such
452cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// DAG's are possible in C++, but the compiler computes those dynamic_casts at
453cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// compile time, and only calls __dynamic_cast when dst_type lies below
454cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// static_type in the DAG.
455cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
456cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// dst_type != static_type:  The compiler computes the dynamic_cast in this case too.
457facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// dynamic_type != static_type:  The compiler computes the dynamic_cast in this case too.
458cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
459cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Returns:
460cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//
461cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// If there is exactly one dst_type of flavor 1, and
4621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    If there is a public path from that dst_type to (static_ptr, static_type), or
463cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant//    If there are 0 dst_types of flavor 2, and there is a public path from
4641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
4651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
4661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//        a pointer to that dst_type.
467cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
468facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//    if there is a public path from (dynamic_ptr, dynamic_type) to
4691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
4701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    to the one dst_type, then return a pointer to that one dst_type.
4711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
4721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
4731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If dynamic_type == dst_type, then the above algorithm collapses to the
4741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// following cheaper algorithm:
4751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//
4761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If there is a public path from (dynamic_ptr, dynamic_type) to
4771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//    (static_ptr, static_type), then return dynamic_ptr.
4781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Else return nullptr.
4791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantextern "C"
4801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid*
4811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__dynamic_cast(const void* static_ptr,
4820240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               const __class_type_info* static_type,
4830240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               const __class_type_info* dst_type,
4840240685ed6756ee0eed7c76e37eb2abdc01dcf82Howard Hinnant               std::ptrdiff_t src2dst_offset)
4851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
4860550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Possible future optimization:  Take advantage of src2dst_offset
4870550d57ec1c783ff5f56ff15f933e01d81574105Howard Hinnant    // Currently clang always sets src2dst_offset to -1 (no hint).
488cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
489cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Get (dynamic_ptr, dynamic_type) from static_ptr
4901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    void** vtable = *(void***)static_ptr;
491cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
492cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
493cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
494cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
495cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize answer to nullptr.  This will be changed from the search
496cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    results if a non-null answer is found.  Regardless, this is what will
497cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    //    be returned.
4981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    const void* dst_ptr = 0;
499cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Initialize info struct for this search.
5001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
501cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant
502cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant    // Find out if we can use a giant short cut in the search
50306bbbdde3c601994cd92206c6afe26fbc67812baHoward Hinnant    if (is_equal(dynamic_type, dst_type, false))
504f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
505cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Using giant short cut.  Add that information to info.
5061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info.number_of_dst_type = 1;
507cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Do the  search
508326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
509326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#if _LIBCXX_DYNAMIC_FALLBACK
5101a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
5111a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
5121a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown)
5131a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
5141a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            // We get here only if there is some kind of visibility problem
5151a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            //   in client code.
516552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
5176c33e768c1b37af3e5d5f9f0e2a72fcf1dc51382Howard Hinnant                    "should have public visibility.  At least one of them is hidden. %s"
518552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                    ", %s.\n", static_type->name(), dynamic_type->name());
519326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
520326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
521326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info.number_of_dst_type = 1;
522326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
5231a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
524326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
525cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
5261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info.path_dst_ptr_to_static_ptr == public_path)
5271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            dst_ptr = dynamic_ptr;
5281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
5291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
5301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
531cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Not using giant short cut.  Do the search
532326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
533326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant #if _LIBCXX_DYNAMIC_FALLBACK
5341a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        // The following if should always be false because we should definitely
5351a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        //   find (static_ptr, static_type), either on a public or private path
536326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        if (info.path_dst_ptr_to_static_ptr == unknown &&
5371a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant            info.path_dynamic_ptr_to_static_ptr == unknown)
5381a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        {
539552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant            syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
540552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " has hidden visibility.  They should all have public visibility.  "
541552b14000a3063cfa561fd3f9fd3c26259e7ca31Howard Hinnant                            " %s, %s, %s.\n", static_type->name(), dynamic_type->name(),
5421a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant                    dst_type->name());
543326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            // Redo the search comparing type_info's using strcmp
544326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
545326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant            dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
5461a0d1bc64fa339249c28511fdd6a9780152c9980Howard Hinnant        }
547326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant#endif  // _LIBCXX_DYNAMIC_FALLBACK
548cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        // Query the search.
5491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        switch (info.number_to_static_ptr)
550f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
5511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 0:
5521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.number_to_dst_ptr == 1 &&
5531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_static_ptr == public_path &&
5541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info.path_dynamic_ptr_to_dst_ptr == public_path)
5551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
5561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
5571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        case 1:
5581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info.path_dst_ptr_to_static_ptr == public_path ||
5591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   (
5601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.number_to_dst_ptr == 0 &&
5611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_static_ptr == public_path &&
5621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                       info.path_dynamic_ptr_to_dst_ptr == public_path
5631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                   )
5641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant               )
5651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                dst_ptr = info.dst_ptr_leading_to_static_ptr;
5661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            break;
567f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
568f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
5691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    return const_cast<void*>(dst_ptr);
570f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
571f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
57291f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant#pragma clang diagnostic pop
57391f198a4c8f43b40f23e8c51641e62fe5e13115aHoward Hinnant
574facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
575facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility push(hidden)
576facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
5771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is a base (above) a dst_type.
5781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Let caller know you hit a static_type.  But only start recording details if
5791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// this is (static_ptr, static_type) -- the node we are casting from.
5801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
5811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from the dst_type to here.  There may be
5821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from the same dst_type to here, record the "most public" one.
5831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the dst_ptr as pointing to (static_ptr, static_type).
5841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
5851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   then mark this dyanmic_cast as ambiguous and stop the search.
5861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
5871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
5881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* dst_ptr,
5891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
5901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
591f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
5921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    // Record that we found a static_type
5931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    info->found_any_static_type = true;
5941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
595271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
5961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record that we found (static_ptr, static_type)
5971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = true;
5981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->dst_ptr_leading_to_static_ptr == 0)
599271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
6001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // First time here
6011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_leading_to_static_ptr = dst_ptr;
6021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dst_ptr_to_static_ptr = path_below;
6031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr = 1;
6041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
6051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
6061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
6071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
608271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
6091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
610f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
6111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've been here before.  Update path to "most public"
6121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->path_dst_ptr_to_static_ptr == not_public_path)
6131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dst_ptr_to_static_ptr = path_below;
6141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there is only one dst_type in the entire tree and the path from
6151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    there to here is public then we are done!
6161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
6171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
618f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
619f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        else
620f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
6211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've detected an ambiguous cast from (static_ptr, static_type)
6221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   to a dst_type
6231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_static_ptr += 1;
6241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->search_done = true;
625f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
626f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
627f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
628f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
6291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when you hit a static_type which is not a base (above) a dst_type.
6301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is (static_ptr, static_type)
6311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   Record the path (public or not) from (dynamic_ptr, dynamic_type) to here.  There may be
6321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
63316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
6341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
6351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 const void* current_ptr,
6361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                                 int path_below) const
637152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant{
6381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (current_ptr == info->static_ptr)
6391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    {
6401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Record the most public path from (dynamic_ptr, dynamic_type) to
6411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //                                  (static_ptr, static_type)
6421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (info->path_dynamic_ptr_to_static_ptr != public_path)
6431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_static_ptr = path_below;
6441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    }
645152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
646152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
6471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching below a dst_type node.  This function searches
6481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
6491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a static_type node, there is no need to further search base classes
6501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// above.
6511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If it finds a dst_type node it should search base classes using search_above_dst
6521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// to find out if this dst_type points to (static_ptr, static_type) or not.
653cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant// Either way, the dst_type is recorded as one of two "flavors":  one that does
6541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// or does not point to (static_ptr, static_type).
6551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// If this is neither a static_type nor a dst_type node, continue searching
6561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// base classes above.
6571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// All the hoopla surrounding the search code is doing nothing but looking for
658facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// excuses to stop the search prematurely (break out of the for-loop).  That is,
659facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the algorithm below is simply an optimization of this:
660facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
661facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
662facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
663facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
664facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
665facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     typedef const __base_class_type_info* Iter;
666facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
667facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_below_dst(info, current_ptr, path_below);
668facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else if (this == info->dst_type)
669facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
670facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // Record the most public access path that got us here
671facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (info->path_dynamic_ptr_to_dst_ptr != public_path)
672facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->path_dynamic_ptr_to_dst_ptr = path_below;
673facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         bool does_dst_type_point_to_our_static_type = false;
674facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
675facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
676facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, current_ptr, current_ptr, public_path);
677facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             if (info->found_our_static_ptr)
678facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                 does_dst_type_point_to_our_static_type = true;
679facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
680facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
681facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         if (!does_dst_type_point_to_our_static_type)
682facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
683facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // We found a dst_type that doesn't point to (static_ptr, static_type)
684facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // So record the address of this dst_ptr and increment the
685facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // count of the number of such dst_types found in the tree.
686facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->dst_ptr_not_leading_to_static_ptr = current_ptr;
687facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             info->number_to_dst_ptr += 1;
688facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
689facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
690facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
691facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
692facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type.
693facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
694facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
695facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_below_dst(info, current_ptr, public_path);
696facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
697facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
698facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
699facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
7001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
7011309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
7021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
703326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
704326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
705f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
706f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    typedef const __base_class_type_info* Iter;
707326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
7081309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
709326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
710f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
7111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
7121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
7131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
7141309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
715f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
7161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
7171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
7181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
7191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
7201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
7211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
7221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
7231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
7241309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
7251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
7261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
7271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
7281309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
7291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
7301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
7311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
7321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
7331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
7341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We've found a dst_type with a potentially public path to here.
7351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We have to assume the path is public because it may become
7361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   public later (if we get back to here with a public path).
7371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // We can stop looking above if:
7381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    1.  We've found a public path to (static_ptr, static_type).
7391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
7401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        This is detected at the (static_ptr, static_type).
7411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //    3.  We can prove that there is no public path to (static_ptr, static_type)
7421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //        above here.
7431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                const Iter e = __base_info + __base_count;
7441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                for (Iter p = __base_info; p < e; ++p)
7451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
7461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // Zero out found flags
7471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_our_static_ptr = false;
7481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->found_any_static_type = false;
749326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
750cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                    if (info->search_done)
7511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        break;
7521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_any_static_type)
7531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    {
7541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        is_dst_type_derived_from_static_type = true;
7551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        if (info->found_our_static_ptr)
7561309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
7571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            does_dst_type_point_to_our_static_type = true;
7581309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found what we're looking for, stop looking above.
7591309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (info->path_dst_ptr_to_static_ptr == public_path)
7601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // We found a private path to (static_ptr, static_type)
7621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   If there is no diamond then there is only one path
7631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //   to (static_ptr, static_type) and we just found it.
7641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __diamond_shaped_mask))
7651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
7671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        else
7681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        {
7691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            // If we found a static_type that isn't the one we're looking
7701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    for, and if there are no repeated types above here,
7711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            //    then stop looking.
7721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            if (!(__flags & __non_diamond_repeat_mask))
7731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                break;
7741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        }
7751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    }
7761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
7771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
7781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                {
7791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
7801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
7811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
7821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
7831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->number_to_dst_ptr += 1;
7841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // If there exists another dst with a private path to
7851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //    (static_ptr, static_type), then the cast from
7861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
7871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    //      so stop search.
7881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
7891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
7901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
7911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                }
7921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
7931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
7941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
7951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
7961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
7971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
7981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
7991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
8001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
801f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
802f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
8031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
804271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
8051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type.
8061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
80765255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
808326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_below_dst(info, current_ptr, path_below, use_strcmp);
80965255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
8101309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
81165255631de793131622f701df9075dfd78abfc50Howard Hinnant            if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
8121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
81365255631de793131622f701df9075dfd78abfc50Howard Hinnant                // If there are multiple paths to a base above from here, or if
81465255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    a dst_type pointing to (static_ptr, static_type) has been found,
81565255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    then there is no way to break out of this loop early unless
81665255631de793131622f701df9075dfd78abfc50Howard Hinnant                //    something below detects the search is done.
81765255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
81865255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
81965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
82065255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
821326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
82265255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
8231309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            }
82465255631de793131622f701df9075dfd78abfc50Howard Hinnant            else if (__flags & __non_diamond_repeat_mask)
825271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
82665255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are not multiple paths to any base class from here and a
82765255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   dst_type pointing to (static_ptr, static_type) has not yet been
82865255631de793131622f701df9075dfd78abfc50Howard Hinnant                //   found.
82965255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
83065255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
83165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
83265255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
83365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
83465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure
83565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
83665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
83765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1 &&
83865255631de793131622f701df9075dfd78abfc50Howard Hinnant                              info->path_dst_ptr_to_static_ptr == public_path)
83965255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
840326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
84165255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
842271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
84365255631de793131622f701df9075dfd78abfc50Howard Hinnant            else
844271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            {
84565255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no repeated types above this node.
84665255631de793131622f701df9075dfd78abfc50Howard Hinnant                // There are no nodes with multiple parents above this node.
84765255631de793131622f701df9075dfd78abfc50Howard Hinnant                // no dst_type has been found to (static_ptr, static_type)
84865255631de793131622f701df9075dfd78abfc50Howard Hinnant                do
84965255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
85065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->search_done)
85165255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
85265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we just found a dst_type with a public path to (static_ptr, static_type),
85365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then the only reason to continue the search is to make sure sure
85465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    no other dst_type points to (static_ptr, static_type).
85565255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond, then we don't need to search here.
85665255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // if we just found a dst_type with a private path to (static_ptr, static_type),
85765255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then we're only looking for a public path to (static_ptr, static_type)
85865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and to check for other dst_types.
85965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
86065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    and not a dst_type under here.
86165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->number_to_static_ptr == 1)
86265255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
863326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                    p->search_below_dst(info, current_ptr, path_below, use_strcmp);
86465255631de793131622f701df9075dfd78abfc50Howard Hinnant                } while (++p < e);
865271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            }
866271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
867271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
8681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
8691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
8701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
8711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
8721309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
8731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
8741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
875326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
876326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
8771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
878326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
8791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
880326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
881f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
8821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
8831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
8841309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
8851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
886f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
8871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
8881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
8891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
890f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            if (path_below == public_path)
891f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
892f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
893271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        else  // We have haven't been here before
894f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        {
895271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            // Record the access path that got us here
8961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
897f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
8981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Only search above here if dst_type derives from static_type, or
8991309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    if it is unknown if dst_type derives from static_type.
9001309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (info->is_dst_type_derived_from_static_type != no)
901f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            {
9021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Set up flags to record results from all base classes
9031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool is_dst_type_derived_from_static_type = false;
9041309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                bool does_dst_type_point_to_our_static_type = false;
9051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // Zero out found flags
9061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_our_static_ptr = false;
9071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->found_any_static_type = false;
908326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
9091309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (info->found_any_static_type)
910f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
9111309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    is_dst_type_derived_from_static_type = true;
9121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    if (info->found_our_static_ptr)
9131309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        does_dst_type_point_to_our_static_type = true;
914f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
9151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (!does_dst_type_point_to_our_static_type)
916f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                {
9171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // We found a dst_type that doesn't point to (static_ptr, static_type)
9181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // So record the address of this dst_ptr and increment the
9191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    // count of the number of such dst_types found in the tree.
9201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->dst_ptr_not_leading_to_static_ptr = current_ptr;
921f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                    info->number_to_dst_ptr += 1;
922271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    // If there exists another dst with a private path to
923271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //    (static_ptr, static_type), then the cast from
924271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
925271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant                    if (info->number_to_static_ptr == 1 &&
9261309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                            info->path_dst_ptr_to_static_ptr == not_public_path)
9271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                        info->search_done = true;
928f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant                }
9291309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                // If we found no static_type,s then dst_type doesn't derive
9301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   from static_type, else it does.  Record this result so that
9311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   next time we hit a dst_type we will know not to search above
9321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                //   it if it doesn't derive from static_type.
9331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                if (is_dst_type_derived_from_static_type)
9341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = yes;
9351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                else
9361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->is_dst_type_derived_from_static_type = no;
937f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant            }
938f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant        }
939f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
941f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
9421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
943326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
944f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
9451309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
9461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
9471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_below_dst but
9481309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
9491309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
9501309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_below_dst(__dynamic_cast_info* info,
9511309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
952326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
953326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
9541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
9551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    typedef const __base_class_type_info* Iter;
956326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
9571309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_below_dst(info, current_ptr, path_below);
958326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    else if (is_equal(this, info->dst_type, use_strcmp))
959f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
9601309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've been here before if we've recorded current_ptr in one of these
9611309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //   two places:
9621309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
9631309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            current_ptr == info->dst_ptr_not_leading_to_static_ptr)
9641309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        {
9651309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We've seen this node before, and therefore have already searched
9661309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // its base classes above.
9671309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //  Update path to here that is "most public".
9681309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            if (path_below == public_path)
9691309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->path_dynamic_ptr_to_dst_ptr = public_path;
9701309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        }
9711309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        else  // We have haven't been here before
972271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
9731309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // Record the access path that got us here
9741309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //   If there is more than one dst_type this path doesn't matter.
9751309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->path_dynamic_ptr_to_dst_ptr = path_below;
9761309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found a dst_type that doesn't point to (static_ptr, static_type)
9771309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // So record the address of this dst_ptr and increment the
9781309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // count of the number of such dst_types found in the tree.
9791309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->dst_ptr_not_leading_to_static_ptr = current_ptr;
9801309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->number_to_dst_ptr += 1;
9811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // If there exists another dst with a private path to
9821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //    (static_ptr, static_type), then the cast from
9831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            //     (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
984271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant            if (info->number_to_static_ptr == 1 &&
9851309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    info->path_dst_ptr_to_static_ptr == not_public_path)
9861309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                info->search_done = true;
9871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            // We found that dst_type does not derive from static_type
9881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            info->is_dst_type_derived_from_static_type = no;
989271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
990271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    }
9911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant}
9921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
9931309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Call this function when searching above a dst_type node.  This function searches
9941309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// for a public path to (static_ptr, static_type).
9951309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This function is guaranteed not to find a node of type dst_type.
9961309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// Theoretically this is a very simple function which just stops if it finds a
997facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// static_type node:  All the hoopla surrounding the search code is doing
998facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// nothing but looking for excuses to stop the search prematurely (break out of
999facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// the for-loop).  That is, the algorithm below is simply an optimization of this:
1000facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// void
1001facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1002facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* dst_ptr,
1003facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         const void* current_ptr,
1004facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//                                         int path_below) const
1005facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// {
1006facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     if (this == info->static_type)
1007facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1008facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     else
1009facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     {
1010facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         typedef const __base_class_type_info* Iter;
1011facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         // This is not a static_type and not a dst_type
1012facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
1013facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         {
1014facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             p->search_above_dst(info, dst_ptr, current_ptr, public_path);
1015facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//             // break out early here if you can detect it doesn't matter if you do
1016facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//         }
1017facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant//     }
1018facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant// }
10191309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
10211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* dst_ptr,
10221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                        const void* current_ptr,
1023326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        int path_below,
1024326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                        bool use_strcmp) const
10251309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant{
1026326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
10271309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1028271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    else
1029271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant    {
10301309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        typedef const __base_class_type_info* Iter;
10311309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // This is not a static_type and not a dst_type
10321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Save flags so they can be restored when returning to nodes below.
10331309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_our_static_ptr = info->found_our_static_ptr;
10341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        bool found_any_static_type = info->found_any_static_type;
10351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // We've found a dst_type below with a path to here.  If the path
10361309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    to here is not public, there may be another path to here that
10371309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    is public.  So we have to assume that the path to here is public.
10381309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //  We can stop looking above if:
10391309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    1.  We've found a public path to (static_ptr, static_type).
10401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    2.  We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
10411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        This is detected at the (static_ptr, static_type).
10421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //    3.  We can prove that there is no public path to (static_ptr, static_type)
10431309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        //        above here.
10441309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        const Iter e = __base_info + __base_count;
104565255631de793131622f701df9075dfd78abfc50Howard Hinnant        Iter p = __base_info;
104665255631de793131622f701df9075dfd78abfc50Howard Hinnant        // Zero out found flags
104765255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_our_static_ptr = false;
104865255631de793131622f701df9075dfd78abfc50Howard Hinnant        info->found_any_static_type = false;
1049326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
105065255631de793131622f701df9075dfd78abfc50Howard Hinnant        if (++p < e)
1051271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        {
105265255631de793131622f701df9075dfd78abfc50Howard Hinnant            do
10531309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant            {
105465255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->search_done)
10551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                    break;
105665255631de793131622f701df9075dfd78abfc50Howard Hinnant                if (info->found_our_static_ptr)
105765255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
105865255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found what we're looking for, stop looking above.
105965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (info->path_dst_ptr_to_static_ptr == public_path)
106065255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
106165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // We found a private path to (static_ptr, static_type)
106265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   If there is no diamond then there is only one path
106365255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //   to (static_ptr, static_type) from here and we just found it.
106465255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __diamond_shaped_mask))
106565255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
106665255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
106765255631de793131622f701df9075dfd78abfc50Howard Hinnant                else if (info->found_any_static_type)
106865255631de793131622f701df9075dfd78abfc50Howard Hinnant                {
106965255631de793131622f701df9075dfd78abfc50Howard Hinnant                    // If we found a static_type that isn't the one we're looking
107065255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    for, and if there are no repeated types above here,
107165255631de793131622f701df9075dfd78abfc50Howard Hinnant                    //    then stop looking.
107265255631de793131622f701df9075dfd78abfc50Howard Hinnant                    if (!(__flags & __non_diamond_repeat_mask))
107365255631de793131622f701df9075dfd78abfc50Howard Hinnant                        break;
107465255631de793131622f701df9075dfd78abfc50Howard Hinnant                }
107565255631de793131622f701df9075dfd78abfc50Howard Hinnant                // Zero out found flags
107665255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_our_static_ptr = false;
107765255631de793131622f701df9075dfd78abfc50Howard Hinnant                info->found_any_static_type = false;
1078326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
107965255631de793131622f701df9075dfd78abfc50Howard Hinnant            } while (++p < e);
1080271f1ac649aac4c80df7534270b19f3fbdce9c5dHoward Hinnant        }
10811309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        // Restore flags
10821309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_our_static_ptr = found_our_static_ptr;
10831309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        info->found_any_static_type = found_any_static_type;
1084f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
1085185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant}
1086185dc7d61ff4e58909f043f3a0c0d7d1d87ba7daHoward Hinnant
10871309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
10881309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is only a single base class.
10891309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
10901309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
10911309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* dst_ptr,
10921309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                       const void* current_ptr,
1093326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       int path_below,
1094326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                       bool use_strcmp) const
1095f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant{
1096326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
10971309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
10981309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    else
1099326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant        __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
1100f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant}
1101f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant
11021309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// This is the same algorithm as __vmi_class_type_info::search_above_dst but
11031309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   simplified to the case that there is no base class.
110416650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
11051309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__class_type_info::search_above_dst(__dynamic_cast_info* info,
11061309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* dst_ptr,
11071309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                    const void* current_ptr,
1108326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    int path_below,
1109326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                    bool use_strcmp) const
111016650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
1111326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant    if (is_equal(this, info->static_type, use_strcmp))
11121309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant        process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
111316650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
111416650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
11151309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant// The search functions for __base_class_type_info are simply convenience
11161309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   functions for adjusting the current_ptr and path_below as the search is
11171309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant//   passed up to the base class node.
11181309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant
111916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnantvoid
11201309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
11211309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* dst_ptr,
11221309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1123326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1124326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
112516650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
112616650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
112716650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    if (__offset_flags & __virtual_mask)
112816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    {
1129cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1130cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
113116650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant    }
11321309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_above_dst(info, dst_ptr,
1133cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
11341309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
11351309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1136326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1137326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
1138152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}
1139152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant
11401309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnantvoid
11411309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
11421309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                         const void* current_ptr,
1143326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         int path_below,
1144326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                         bool use_strcmp) const
114516650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant{
11461309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
11471309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    if (__offset_flags & __virtual_mask)
1148f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    {
1149cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        const char* vtable = *static_cast<const char*const*>(current_ptr);
1150cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1151f877d21f16d5ecb32570a89148e614ff68d632beHoward Hinnant    }
11521309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant    __base_type->search_below_dst(info,
1153cc614df38c199d9781a6dea123e714970e82711fHoward Hinnant                                  static_cast<const char*>(current_ptr) + offset_to_base,
11541309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                  (__offset_flags & __public_mask) ?
11551309366d3676ca5a34bea0388ad2d2dd5701dc9bHoward Hinnant                                      path_below :
1156326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                      not_public_path,
1157326aca3713db53b9fb0dbfedc17d2e72aaca8a74Howard Hinnant                                  use_strcmp);
115816650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant}
115916650b58dfc7d1a2632b052843dc4e21ae949b07Howard Hinnant
1160facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant#pragma GCC visibility pop
1161facfc46ef3ecde55e675fa19d93d9a25b169c49fHoward Hinnant
1162152beb7a421a05155ae339434c2b48e2151111cdHoward Hinnant}  // __cxxabiv1
1163