blob: ef9466ef610bbb1478141a620dca479862dea4cd [file] [log] [blame]
Howard Hinnant152beb72012-01-09 17:10:00 +00001//===----------------------- private_typeinfo.cpp -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "private_typeinfo.h"
11
Howard Hinnant326aca32012-09-28 22:43:50 +000012// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more
13// forgiving when type_info's mistakenly have hidden visibility and thus
14// multiple type_infos can exist for a single type.
15//
16// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where
17// there is a detected inconsistency in the type_info hierarchy during a
18// dynamic_cast, then the equality operation will fall back to using strcmp
Howard Hinnant6d00fef2013-02-15 15:48:49 +000019// on type_info names to determine type_info equality.
Howard Hinnant326aca32012-09-28 22:43:50 +000020//
21// This change happens *only* under dynamic_cast, and only when
22// dynamic_cast is faced with the choice: abort, or possibly give back the
23// wrong answer. If when the dynamic_cast is done with this fallback
24// algorithm and an inconsistency is still detected, dynamic_cast will call
Howard Hinnant6d00fef2013-02-15 15:48:49 +000025// abort with an appropriate message.
Howard Hinnant326aca32012-09-28 22:43:50 +000026//
27// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a
28// printf-like function called syslog:
29//
Yaron Keren36fd93f2013-11-22 12:11:40 +000030// void syslog(int facility_priority, const char* format, ...);
Howard Hinnant326aca32012-09-28 22:43:50 +000031//
32// If you want this functionality but your platform doesn't have syslog,
33// just implement it in terms of fprintf(stderr, ...).
34//
35// _LIBCXX_DYNAMIC_FALLBACK is currently off by default.
36
Eric Fiselier91fc04d2016-01-19 23:42:10 +000037
38#include <string.h>
39
40
Dan Alberta1fce462015-02-05 01:33:15 +000041#ifdef _LIBCXX_DYNAMIC_FALLBACK
Howard Hinnant326aca32012-09-28 22:43:50 +000042#include "abort_message.h"
Howard Hinnant1a0d1bc2012-09-28 00:05:34 +000043#include <sys/syslog.h>
44#endif
45
Yaron Kerend9eb5fc2013-11-22 21:43:23 +000046// On Windows, typeids are different between DLLs and EXEs, so comparing
47// type_info* will work for typeids from the same compiled file but fail
48// for typeids from a DLL and an executable. Among other things, exceptions
49// are not caught by handlers since can_catch() returns false.
50//
51// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls
52// is_equal() with use_strcmp=false so the string names are not compared.
53
54#ifdef _WIN32
55#include <string.h>
56#endif
57
Shoaib Meenai54227ae2017-03-01 03:55:57 +000058static inline
Howard Hinnant326aca32012-09-28 22:43:50 +000059bool
60is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
61{
Eric Fiselier91fc04d2016-01-19 23:42:10 +000062#ifndef _WIN32
Howard Hinnant326aca32012-09-28 22:43:50 +000063 if (!use_strcmp)
64 return x == y;
65 return strcmp(x->name(), y->name()) == 0;
Eric Fiselier7dbbe8a2016-01-19 23:40:49 +000066#else
67 return (x == y) || (strcmp(x->name(), y->name()) == 0);
Eric Fiselier91fc04d2016-01-19 23:42:10 +000068#endif
Eric Fiselier7dbbe8a2016-01-19 23:40:49 +000069}
70
Shoaib Meenai54227ae2017-03-01 03:55:57 +000071namespace __cxxabiv1
72{
Howard Hinnant326aca32012-09-28 22:43:50 +000073
Howard Hinnantfacfc462012-01-22 01:23:02 +000074// __shim_type_info
75
76__shim_type_info::~__shim_type_info()
77{
78}
79
Howard Hinnant8f286282012-02-23 21:09:29 +000080void __shim_type_info::noop1() const {}
81void __shim_type_info::noop2() const {}
82
Howard Hinnant152beb72012-01-09 17:10:00 +000083// __fundamental_type_info
84
Howard Hinnant16650b52012-01-11 00:11:17 +000085// This miraculously (compiler magic) emits the type_info's for:
86// 1. all of the fundamental types
87// 2. pointers to all of the fundamental types
88// 3. pointers to all of the const fundamental types
Howard Hinnant152beb72012-01-09 17:10:00 +000089__fundamental_type_info::~__fundamental_type_info()
90{
91}
92
93// __array_type_info
94
95__array_type_info::~__array_type_info()
96{
97}
98
99// __function_type_info
100
101__function_type_info::~__function_type_info()
102{
103}
104
105// __enum_type_info
106
107__enum_type_info::~__enum_type_info()
108{
109}
110
111// __class_type_info
112
113__class_type_info::~__class_type_info()
114{
115}
116
117// __si_class_type_info
118
119__si_class_type_info::~__si_class_type_info()
120{
121}
122
Howard Hinnant35b2c2a2012-01-24 21:35:18 +0000123// __vmi_class_type_info
124
125__vmi_class_type_info::~__vmi_class_type_info()
126{
127}
128
129// __pbase_type_info
130
131__pbase_type_info::~__pbase_type_info()
132{
133}
134
135// __pointer_type_info
136
137__pointer_type_info::~__pointer_type_info()
138{
139}
140
141// __pointer_to_member_type_info
142
143__pointer_to_member_type_info::~__pointer_to_member_type_info()
144{
145}
146
Howard Hinnantc30bfdc2012-01-22 21:47:40 +0000147// can_catch
148
149// A handler is a match for an exception object of type E if
Howard Hinnanta1919d22012-01-23 18:39:47 +0000150// 1. The handler is of type cv T or cv T& and E and T are the same type
151// (ignoring the top-level cv-qualifiers), or
152// 2. the handler is of type cv T or cv T& and T is an unambiguous public
153// base class of E, or
154// 3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
155// converted to the type of the handler by either or both of
156// A. a standard pointer conversion (4.10) not involving conversions to
157// pointers to private or protected or ambiguous classes
158// B. a qualification conversion
159// 4. the handler is a pointer or pointer to member type and E is
160// std::nullptr_t.
Howard Hinnantc30bfdc2012-01-22 21:47:40 +0000161
162// adjustedPtr:
163//
164// catch (A& a) : adjustedPtr == &a
165// catch (A* a) : adjustedPtr == a
166// catch (A** a) : adjustedPtr == a
167//
168// catch (D2& d2) : adjustedPtr == &d2 (d2 is base class of thrown object)
169// catch (D2* d2) : adjustedPtr == d2
170// catch (D2*& d2) : adjustedPtr == d2
Richard Smith081ea862016-07-19 20:19:37 +0000171//
Howard Hinnantc30bfdc2012-01-22 21:47:40 +0000172// catch (...) : adjustedPtr == & of the exception
Richard Smith081ea862016-07-19 20:19:37 +0000173//
174// If the thrown type is nullptr_t and the caught type is a pointer to
175// member type, adjustedPtr points to a statically-allocated null pointer
176// representation of that type.
Howard Hinnantc30bfdc2012-01-22 21:47:40 +0000177
Howard Hinnanta1919d22012-01-23 18:39:47 +0000178// Handles bullet 1
Howard Hinnanta1919d22012-01-23 18:39:47 +0000179bool
180__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
181 void*&) const
182{
Howard Hinnant06bbbdd2012-11-15 18:00:42 +0000183 return is_equal(this, thrown_type, false);
Howard Hinnanta1919d22012-01-23 18:39:47 +0000184}
185
186bool
Howard Hinnant96f01712012-03-09 18:01:37 +0000187__array_type_info::can_catch(const __shim_type_info*, void*&) const
Howard Hinnanta1919d22012-01-23 18:39:47 +0000188{
Howard Hinnantaafd08a2012-02-01 19:21:28 +0000189 // We can get here if someone tries to catch an array by reference.
190 // However if someone tries to throw an array, it immediately gets
191 // converted to a pointer, which will not convert back to an array
192 // at the catch clause. So this can never catch anything.
Howard Hinnanta1919d22012-01-23 18:39:47 +0000193 return false;
194}
195
196bool
Howard Hinnant96f01712012-03-09 18:01:37 +0000197__function_type_info::can_catch(const __shim_type_info*, void*&) const
Howard Hinnanta1919d22012-01-23 18:39:47 +0000198{
Howard Hinnant4b3cb1c2012-02-01 19:42:45 +0000199 // We can get here if someone tries to catch a function by reference.
200 // However if someone tries to throw a function, it immediately gets
201 // converted to a pointer, which will not convert back to a function
202 // at the catch clause. So this can never catch anything.
Howard Hinnanta1919d22012-01-23 18:39:47 +0000203 return false;
204}
205
206// Handles bullet 1
Howard Hinnanta1919d22012-01-23 18:39:47 +0000207bool
208__enum_type_info::can_catch(const __shim_type_info* thrown_type,
209 void*&) const
210{
Howard Hinnant06bbbdd2012-11-15 18:00:42 +0000211 return is_equal(this, thrown_type, false);
Howard Hinnanta1919d22012-01-23 18:39:47 +0000212}
213
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000214#ifdef __clang__
Howard Hinnant91f198a2012-03-08 20:32:50 +0000215#pragma clang diagnostic push
216#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000217#endif
Howard Hinnant91f198a2012-03-08 20:32:50 +0000218
Howard Hinnanta1919d22012-01-23 18:39:47 +0000219// Handles bullets 1 and 2
220bool
221__class_type_info::can_catch(const __shim_type_info* thrown_type,
222 void*& adjustedPtr) const
223{
224 // bullet 1
Howard Hinnant06bbbdd2012-11-15 18:00:42 +0000225 if (is_equal(this, thrown_type, false))
Howard Hinnanta1919d22012-01-23 18:39:47 +0000226 return true;
227 const __class_type_info* thrown_class_type =
228 dynamic_cast<const __class_type_info*>(thrown_type);
229 if (thrown_class_type == 0)
230 return false;
231 // bullet 2
Saleem Abdulrasoolec60ec42017-06-11 22:57:26 +0000232 __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
Howard Hinnanta1919d22012-01-23 18:39:47 +0000233 info.number_of_dst_type = 1;
234 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
235 if (info.path_dst_ptr_to_static_ptr == public_path)
236 {
237 adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
238 return true;
239 }
240 return false;
241}
242
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000243#ifdef __clang__
Howard Hinnant91f198a2012-03-08 20:32:50 +0000244#pragma clang diagnostic pop
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000245#endif
Howard Hinnant91f198a2012-03-08 20:32:50 +0000246
Howard Hinnanta1919d22012-01-23 18:39:47 +0000247void
248__class_type_info::process_found_base_class(__dynamic_cast_info* info,
249 void* adjustedPtr,
250 int path_below) const
251{
252 if (info->dst_ptr_leading_to_static_ptr == 0)
253 {
254 // First time here
255 info->dst_ptr_leading_to_static_ptr = adjustedPtr;
256 info->path_dst_ptr_to_static_ptr = path_below;
257 info->number_to_static_ptr = 1;
258 }
259 else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
260 {
261 // We've been here before. Update path to "most public"
262 if (info->path_dst_ptr_to_static_ptr == not_public_path)
263 info->path_dst_ptr_to_static_ptr = path_below;
264 }
265 else
266 {
267 // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
268 // to a static_type
269 info->number_to_static_ptr += 1;
270 info->path_dst_ptr_to_static_ptr = not_public_path;
271 info->search_done = true;
272 }
273}
274
275void
276__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
277 void* adjustedPtr,
278 int path_below) const
279{
Howard Hinnant06bbbdd2012-11-15 18:00:42 +0000280 if (is_equal(this, info->static_type, false))
Howard Hinnanta1919d22012-01-23 18:39:47 +0000281 process_found_base_class(info, adjustedPtr, path_below);
282}
283
284void
285__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
286 void* adjustedPtr,
287 int path_below) const
288{
Howard Hinnant06bbbdd2012-11-15 18:00:42 +0000289 if (is_equal(this, info->static_type, false))
Howard Hinnanta1919d22012-01-23 18:39:47 +0000290 process_found_base_class(info, adjustedPtr, path_below);
291 else
292 __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
293}
294
295void
296__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
297 void* adjustedPtr,
298 int path_below) const
299{
Marshall Clow98bbf282014-02-06 04:47:02 +0000300 ptrdiff_t offset_to_base = 0;
301 if (adjustedPtr != nullptr)
Howard Hinnanta1919d22012-01-23 18:39:47 +0000302 {
Marshall Clow98bbf282014-02-06 04:47:02 +0000303 offset_to_base = __offset_flags >> __offset_shift;
304 if (__offset_flags & __virtual_mask)
305 {
306 const char* vtable = *static_cast<const char*const*>(adjustedPtr);
307 offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
308 }
Howard Hinnanta1919d22012-01-23 18:39:47 +0000309 }
Marshall Clow98bbf282014-02-06 04:47:02 +0000310 __base_type->has_unambiguous_public_base(
311 info,
312 static_cast<char*>(adjustedPtr) + offset_to_base,
313 (__offset_flags & __public_mask) ? path_below : not_public_path);
Howard Hinnanta1919d22012-01-23 18:39:47 +0000314}
315
316void
317__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
318 void* adjustedPtr,
319 int path_below) const
320{
Howard Hinnant06bbbdd2012-11-15 18:00:42 +0000321 if (is_equal(this, info->static_type, false))
Howard Hinnanta1919d22012-01-23 18:39:47 +0000322 process_found_base_class(info, adjustedPtr, path_below);
323 else
324 {
325 typedef const __base_class_type_info* Iter;
326 const Iter e = __base_info + __base_count;
327 Iter p = __base_info;
328 p->has_unambiguous_public_base(info, adjustedPtr, path_below);
329 if (++p < e)
330 {
331 do
332 {
333 p->has_unambiguous_public_base(info, adjustedPtr, path_below);
334 if (info->search_done)
335 break;
336 } while (++p < e);
337 }
338 }
339}
340
Richard Smith081ea862016-07-19 20:19:37 +0000341// Handles bullet 1 for both pointers and member pointers
Howard Hinnanta1919d22012-01-23 18:39:47 +0000342bool
343__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
344 void*&) const
345{
Eric Fiselier91fc04d2016-01-19 23:42:10 +0000346 bool use_strcmp = this->__flags & (__incomplete_class_mask |
347 __incomplete_mask);
348 if (!use_strcmp) {
349 const __pbase_type_info* thrown_pbase = dynamic_cast<const __pbase_type_info*>(
350 thrown_type);
351 if (!thrown_pbase) return false;
352 use_strcmp = thrown_pbase->__flags & (__incomplete_class_mask |
353 __incomplete_mask);
354 }
355 return is_equal(this, thrown_type, use_strcmp);
Howard Hinnanta1919d22012-01-23 18:39:47 +0000356}
357
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000358#ifdef __clang__
Howard Hinnant91f198a2012-03-08 20:32:50 +0000359#pragma clang diagnostic push
360#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000361#endif
Howard Hinnant91f198a2012-03-08 20:32:50 +0000362
Howard Hinnanta1919d22012-01-23 18:39:47 +0000363// Handles bullets 1, 3 and 4
Eric Fiselier1b4ddb12014-11-24 18:46:37 +0000364// NOTE: It might not be safe to adjust the pointer if it is not not a pointer
365// type. Only adjust the pointer after we know it is safe to do so.
Howard Hinnanta1919d22012-01-23 18:39:47 +0000366bool
367__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
368 void*& adjustedPtr) const
369{
Richard Smith081ea862016-07-19 20:19:37 +0000370 // bullet 4
371 if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) {
372 adjustedPtr = nullptr;
373 return true;
374 }
375
376 // bullet 1
Eric Fiselier1b4ddb12014-11-24 18:46:37 +0000377 if (__pbase_type_info::can_catch(thrown_type, adjustedPtr)) {
378 if (adjustedPtr != NULL)
379 adjustedPtr = *static_cast<void**>(adjustedPtr);
Howard Hinnanta1919d22012-01-23 18:39:47 +0000380 return true;
Eric Fiselier1b4ddb12014-11-24 18:46:37 +0000381 }
Howard Hinnanta1919d22012-01-23 18:39:47 +0000382 // bullet 3
383 const __pointer_type_info* thrown_pointer_type =
384 dynamic_cast<const __pointer_type_info*>(thrown_type);
385 if (thrown_pointer_type == 0)
386 return false;
Eric Fiselier1b4ddb12014-11-24 18:46:37 +0000387 // Do the dereference adjustment
388 if (adjustedPtr != NULL)
389 adjustedPtr = *static_cast<void**>(adjustedPtr);
Richard Smithf1636202016-12-02 02:06:53 +0000390 // bullet 3B and 3C
391 if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask)
392 return false;
393 if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask)
Howard Hinnanta1919d22012-01-23 18:39:47 +0000394 return false;
Howard Hinnant06bbbdd2012-11-15 18:00:42 +0000395 if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
Howard Hinnanta1919d22012-01-23 18:39:47 +0000396 return true;
397 // bullet 3A
Eric Fiselierb979db12015-05-01 01:49:37 +0000398 if (is_equal(__pointee, &typeid(void), false)) {
399 // pointers to functions cannot be converted to void*.
400 // pointers to member functions are not handled here.
401 const __function_type_info* thrown_function =
402 dynamic_cast<const __function_type_info*>(thrown_pointer_type->__pointee);
403 return (thrown_function == nullptr);
404 }
Eric Fiselier0cb62d12015-04-02 23:26:37 +0000405 // Handle pointer to pointer
406 const __pointer_type_info* nested_pointer_type =
407 dynamic_cast<const __pointer_type_info*>(__pointee);
408 if (nested_pointer_type) {
409 if (~__flags & __const_mask) return false;
410 return nested_pointer_type->can_catch_nested(thrown_pointer_type->__pointee);
411 }
412
413 // Handle pointer to pointer to member
414 const __pointer_to_member_type_info* member_ptr_type =
415 dynamic_cast<const __pointer_to_member_type_info*>(__pointee);
416 if (member_ptr_type) {
417 if (~__flags & __const_mask) return false;
418 return member_ptr_type->can_catch_nested(thrown_pointer_type->__pointee);
419 }
420
421 // Handle pointer to class type
Howard Hinnanta1919d22012-01-23 18:39:47 +0000422 const __class_type_info* catch_class_type =
423 dynamic_cast<const __class_type_info*>(__pointee);
424 if (catch_class_type == 0)
425 return false;
426 const __class_type_info* thrown_class_type =
427 dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
428 if (thrown_class_type == 0)
429 return false;
Saleem Abdulrasoolec60ec42017-06-11 22:57:26 +0000430 __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
Howard Hinnanta1919d22012-01-23 18:39:47 +0000431 info.number_of_dst_type = 1;
432 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
433 if (info.path_dst_ptr_to_static_ptr == public_path)
434 {
Marshall Clow288859d2014-02-05 18:19:57 +0000435 if (adjustedPtr != NULL)
436 adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
Howard Hinnanta1919d22012-01-23 18:39:47 +0000437 return true;
438 }
439 return false;
440}
Howard Hinnantc30bfdc2012-01-22 21:47:40 +0000441
Eric Fiselier0cb62d12015-04-02 23:26:37 +0000442bool __pointer_type_info::can_catch_nested(
443 const __shim_type_info* thrown_type) const
444{
445 const __pointer_type_info* thrown_pointer_type =
446 dynamic_cast<const __pointer_type_info*>(thrown_type);
447 if (thrown_pointer_type == 0)
448 return false;
449 // bullet 3B
450 if (thrown_pointer_type->__flags & ~__flags)
451 return false;
452 if (is_equal(__pointee, thrown_pointer_type->__pointee, false))
453 return true;
454 // If the pointed to types differ then the catch type must be const
455 // qualified.
456 if (~__flags & __const_mask)
457 return false;
458
459 // Handle pointer to pointer
460 const __pointer_type_info* nested_pointer_type =
461 dynamic_cast<const __pointer_type_info*>(__pointee);
462 if (nested_pointer_type) {
463 return nested_pointer_type->can_catch_nested(
464 thrown_pointer_type->__pointee);
465 }
466
467 // Handle pointer to pointer to member
468 const __pointer_to_member_type_info* member_ptr_type =
469 dynamic_cast<const __pointer_to_member_type_info*>(__pointee);
470 if (member_ptr_type) {
471 return member_ptr_type->can_catch_nested(thrown_pointer_type->__pointee);
472 }
473
474 return false;
475}
476
477bool __pointer_to_member_type_info::can_catch(
478 const __shim_type_info* thrown_type, void*& adjustedPtr) const {
Richard Smith081ea862016-07-19 20:19:37 +0000479 // bullet 4
480 if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) {
481 // We assume that the pointer to member representation is the same for
482 // all pointers to data members and for all pointers to member functions.
483 struct X {};
484 if (dynamic_cast<const __function_type_info*>(__pointee)) {
485 static int (X::*const null_ptr_rep)() = nullptr;
486 adjustedPtr = const_cast<int (X::**)()>(&null_ptr_rep);
487 } else {
488 static int X::*const null_ptr_rep = nullptr;
489 adjustedPtr = const_cast<int X::**>(&null_ptr_rep);
490 }
491 return true;
492 }
493
494 // bullet 1
Eric Fiselier0cb62d12015-04-02 23:26:37 +0000495 if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
496 return true;
497
498 const __pointer_to_member_type_info* thrown_pointer_type =
499 dynamic_cast<const __pointer_to_member_type_info*>(thrown_type);
500 if (thrown_pointer_type == 0)
501 return false;
Richard Smithf1636202016-12-02 02:06:53 +0000502 if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask)
Eric Fiselier0cb62d12015-04-02 23:26:37 +0000503 return false;
Richard Smithf1636202016-12-02 02:06:53 +0000504 if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask)
505 return false;
506 if (!is_equal(__pointee, thrown_pointer_type->__pointee, false))
Eric Fiselier0cb62d12015-04-02 23:26:37 +0000507 return false;
508 if (is_equal(__context, thrown_pointer_type->__context, false))
509 return true;
510
Eric Fiselier554d59a2015-04-06 23:03:01 +0000511 // [except.handle] does not allow the pointer-to-member conversions mentioned
512 // in [mem.conv] to take place. For this reason we don't check Derived->Base
513 // for Derived->Base conversions.
Eric Fiselier0cb62d12015-04-02 23:26:37 +0000514
515 return false;
516}
517
518bool __pointer_to_member_type_info::can_catch_nested(
519 const __shim_type_info* thrown_type) const
520{
521 const __pointer_to_member_type_info* thrown_member_ptr_type =
522 dynamic_cast<const __pointer_to_member_type_info*>(thrown_type);
523 if (thrown_member_ptr_type == 0)
524 return false;
525 if (~__flags & thrown_member_ptr_type->__flags)
526 return false;
527 if (!is_equal(__pointee, thrown_member_ptr_type->__pointee, false))
528 return false;
529 if (!is_equal(__context, thrown_member_ptr_type->__context, false))
530 return false;
531 return true;
532}
533
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000534#ifdef __clang__
Howard Hinnant91f198a2012-03-08 20:32:50 +0000535#pragma clang diagnostic pop
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000536#endif
Howard Hinnant91f198a2012-03-08 20:32:50 +0000537
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000538#ifdef __clang__
Howard Hinnant91f198a2012-03-08 20:32:50 +0000539#pragma clang diagnostic push
540#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000541#endif
Howard Hinnant91f198a2012-03-08 20:32:50 +0000542
Howard Hinnant16650b52012-01-11 00:11:17 +0000543// __dynamic_cast
544
Howard Hinnantcc614df2012-01-16 17:06:51 +0000545// static_ptr: pointer to an object of type static_type; nonnull, and since the
546// object is polymorphic, *(void**)static_ptr is a virtual table pointer.
547// static_ptr is &v in the expression dynamic_cast<T>(v).
548// static_type: static type of the object pointed to by static_ptr.
549// dst_type: destination type of the cast (the "T" in "dynamic_cast<T>(v)").
Howard Hinnant16650b52012-01-11 00:11:17 +0000550// src2dst_offset: a static hint about the location of the
551// source subobject with respect to the complete object;
552// special negative values are:
553// -1: no hint
554// -2: static_type is not a public base of dst_type
555// -3: static_type is a multiple public base type but never a
556// virtual base type
557// otherwise, the static_type type is a unique public nonvirtual
558// base type of dst_type at offset src2dst_offset from the
559// origin of dst_type.
Howard Hinnant13093662012-01-16 00:13:46 +0000560//
Howard Hinnantcc614df2012-01-16 17:06:51 +0000561// (dynamic_ptr, dynamic_type) are the run time type of the complete object
562// referred to by static_ptr and a pointer to it. These can be found from
563// static_ptr for polymorphic types.
Howard Hinnant13093662012-01-16 00:13:46 +0000564// static_type is guaranteed to be a polymorphic type.
565//
Howard Hinnantcc614df2012-01-16 17:06:51 +0000566// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward. Each
567// node of the tree represents a base class/object of its parent (or parents) below.
568// Each node is uniquely represented by a pointer to the object, and a pointer
569// to a type_info - its type. Different nodes may have the same pointer and
570// different nodes may have the same type. But only one node has a specific
571// (pointer-value, type) pair. In C++ two objects of the same type can not
572// share the same address.
573//
574// There are two flavors of nodes which have the type dst_type:
575// 1. Those that are derived from (below) (static_ptr, static_type).
576// 2. Those that are not derived from (below) (static_ptr, static_type).
577//
578// Invariants of the DAG:
579//
580// There is at least one path from the root (dynamic_ptr, dynamic_type) to
581// the node (static_ptr, static_type). This path may or may not be public.
582// There may be more than one such path (some public some not). Such a path may
583// or may not go through a node having type dst_type.
584//
585// No node of type T appears above a node of the same type. That means that
586// there is only one node with dynamic_type. And if dynamic_type == dst_type,
587// then there is only one dst_type in the DAG.
588//
589// No node of type dst_type appears above a node of type static_type. Such
590// DAG's are possible in C++, but the compiler computes those dynamic_casts at
591// compile time, and only calls __dynamic_cast when dst_type lies below
592// static_type in the DAG.
593//
594// dst_type != static_type: The compiler computes the dynamic_cast in this case too.
Howard Hinnantfacfc462012-01-22 01:23:02 +0000595// dynamic_type != static_type: The compiler computes the dynamic_cast in this case too.
Howard Hinnantcc614df2012-01-16 17:06:51 +0000596//
597// Returns:
598//
599// If there is exactly one dst_type of flavor 1, and
Howard Hinnant13093662012-01-16 00:13:46 +0000600// If there is a public path from that dst_type to (static_ptr, static_type), or
Howard Hinnantcc614df2012-01-16 17:06:51 +0000601// If there are 0 dst_types of flavor 2, and there is a public path from
Howard Hinnant13093662012-01-16 00:13:46 +0000602// (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public
603// path from (dynamic_ptr, dynamic_type) to the one dst_type, then return
604// a pointer to that dst_type.
Howard Hinnantcc614df2012-01-16 17:06:51 +0000605// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and
Howard Hinnantfacfc462012-01-22 01:23:02 +0000606// if there is a public path from (dynamic_ptr, dynamic_type) to
Howard Hinnant13093662012-01-16 00:13:46 +0000607// (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type)
608// to the one dst_type, then return a pointer to that one dst_type.
609// Else return nullptr.
610//
611// If dynamic_type == dst_type, then the above algorithm collapses to the
612// following cheaper algorithm:
613//
614// If there is a public path from (dynamic_ptr, dynamic_type) to
615// (static_ptr, static_type), then return dynamic_ptr.
616// Else return nullptr.
Saleem Abdulrasool46eb39a2016-09-23 21:36:24 +0000617
618extern "C" _LIBCXXABI_FUNC_VIS void *
619__dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
620 const __class_type_info *dst_type,
621 std::ptrdiff_t src2dst_offset) {
Howard Hinnant0550d572012-02-01 21:12:07 +0000622 // Possible future optimization: Take advantage of src2dst_offset
623 // Currently clang always sets src2dst_offset to -1 (no hint).
Howard Hinnantcc614df2012-01-16 17:06:51 +0000624
625 // Get (dynamic_ptr, dynamic_type) from static_ptr
Saleem Abdulrasool0f111c22015-04-27 02:21:55 +0000626 void **vtable = *static_cast<void ** const *>(static_ptr);
Howard Hinnantcc614df2012-01-16 17:06:51 +0000627 ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
628 const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
629 const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
630
631 // Initialize answer to nullptr. This will be changed from the search
632 // results if a non-null answer is found. Regardless, this is what will
633 // be returned.
Howard Hinnantf877d212012-01-11 23:49:18 +0000634 const void* dst_ptr = 0;
Howard Hinnantcc614df2012-01-16 17:06:51 +0000635 // Initialize info struct for this search.
Saleem Abdulrasoolec60ec42017-06-11 22:57:26 +0000636 __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
Howard Hinnantcc614df2012-01-16 17:06:51 +0000637
638 // Find out if we can use a giant short cut in the search
Howard Hinnant06bbbdd2012-11-15 18:00:42 +0000639 if (is_equal(dynamic_type, dst_type, false))
Howard Hinnantf877d212012-01-11 23:49:18 +0000640 {
Howard Hinnantcc614df2012-01-16 17:06:51 +0000641 // Using giant short cut. Add that information to info.
Howard Hinnant13093662012-01-16 00:13:46 +0000642 info.number_of_dst_type = 1;
Howard Hinnantcc614df2012-01-16 17:06:51 +0000643 // Do the search
Howard Hinnant326aca32012-09-28 22:43:50 +0000644 dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
Dan Alberta1fce462015-02-05 01:33:15 +0000645#ifdef _LIBCXX_DYNAMIC_FALLBACK
Howard Hinnant1a0d1bc2012-09-28 00:05:34 +0000646 // The following if should always be false because we should definitely
647 // find (static_ptr, static_type), either on a public or private path
648 if (info.path_dst_ptr_to_static_ptr == unknown)
649 {
650 // We get here only if there is some kind of visibility problem
651 // in client code.
Howard Hinnant552b1402012-09-28 17:58:48 +0000652 syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
Howard Hinnant6c33e762013-06-17 18:10:34 +0000653 "should have public visibility. At least one of them is hidden. %s"
Howard Hinnant552b1402012-09-28 17:58:48 +0000654 ", %s.\n", static_type->name(), dynamic_type->name());
Howard Hinnant326aca32012-09-28 22:43:50 +0000655 // Redo the search comparing type_info's using strcmp
656 info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
657 info.number_of_dst_type = 1;
658 dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
Howard Hinnant1a0d1bc2012-09-28 00:05:34 +0000659 }
Howard Hinnant326aca32012-09-28 22:43:50 +0000660#endif // _LIBCXX_DYNAMIC_FALLBACK
Howard Hinnantcc614df2012-01-16 17:06:51 +0000661 // Query the search.
Howard Hinnant13093662012-01-16 00:13:46 +0000662 if (info.path_dst_ptr_to_static_ptr == public_path)
Howard Hinnantf877d212012-01-11 23:49:18 +0000663 dst_ptr = dynamic_ptr;
664 }
665 else
666 {
Howard Hinnantcc614df2012-01-16 17:06:51 +0000667 // Not using giant short cut. Do the search
Howard Hinnant326aca32012-09-28 22:43:50 +0000668 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
Dan Alberta1fce462015-02-05 01:33:15 +0000669 #ifdef _LIBCXX_DYNAMIC_FALLBACK
Howard Hinnant1a0d1bc2012-09-28 00:05:34 +0000670 // The following if should always be false because we should definitely
671 // find (static_ptr, static_type), either on a public or private path
Howard Hinnant326aca32012-09-28 22:43:50 +0000672 if (info.path_dst_ptr_to_static_ptr == unknown &&
Howard Hinnant1a0d1bc2012-09-28 00:05:34 +0000673 info.path_dynamic_ptr_to_static_ptr == unknown)
674 {
Howard Hinnant552b1402012-09-28 17:58:48 +0000675 syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
Stephan Bergmann66224e12017-11-13 15:40:31 +0000676 "has hidden visibility. They should all have public visibility. "
677 "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
Howard Hinnant1a0d1bc2012-09-28 00:05:34 +0000678 dst_type->name());
Howard Hinnant326aca32012-09-28 22:43:50 +0000679 // Redo the search comparing type_info's using strcmp
680 info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
681 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
Howard Hinnant1a0d1bc2012-09-28 00:05:34 +0000682 }
Howard Hinnant326aca32012-09-28 22:43:50 +0000683#endif // _LIBCXX_DYNAMIC_FALLBACK
Howard Hinnantcc614df2012-01-16 17:06:51 +0000684 // Query the search.
Howard Hinnantf877d212012-01-11 23:49:18 +0000685 switch (info.number_to_static_ptr)
686 {
687 case 0:
688 if (info.number_to_dst_ptr == 1 &&
689 info.path_dynamic_ptr_to_static_ptr == public_path &&
690 info.path_dynamic_ptr_to_dst_ptr == public_path)
691 dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
692 break;
693 case 1:
Howard Hinnant185dc7d2012-01-12 19:48:14 +0000694 if (info.path_dst_ptr_to_static_ptr == public_path ||
695 (
696 info.number_to_dst_ptr == 0 &&
697 info.path_dynamic_ptr_to_static_ptr == public_path &&
698 info.path_dynamic_ptr_to_dst_ptr == public_path
699 )
700 )
Howard Hinnantf877d212012-01-11 23:49:18 +0000701 dst_ptr = info.dst_ptr_leading_to_static_ptr;
702 break;
703 }
704 }
705 return const_cast<void*>(dst_ptr);
Howard Hinnant16650b52012-01-11 00:11:17 +0000706}
707
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000708#ifdef __clang__
Howard Hinnant91f198a2012-03-08 20:32:50 +0000709#pragma clang diagnostic pop
Nick Lewyckyfaf34fb2015-03-05 02:56:05 +0000710#endif
Howard Hinnant91f198a2012-03-08 20:32:50 +0000711
Howard Hinnant13093662012-01-16 00:13:46 +0000712// Call this function when you hit a static_type which is a base (above) a dst_type.
713// Let caller know you hit a static_type. But only start recording details if
714// this is (static_ptr, static_type) -- the node we are casting from.
715// If this is (static_ptr, static_type)
716// Record the path (public or not) from the dst_type to here. There may be
717// multiple paths from the same dst_type to here, record the "most public" one.
718// Record the dst_ptr as pointing to (static_ptr, static_type).
719// If more than one (dst_ptr, dst_type) points to (static_ptr, static_type),
720// then mark this dyanmic_cast as ambiguous and stop the search.
721void
722__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info,
723 const void* dst_ptr,
724 const void* current_ptr,
725 int path_below) const
726{
727 // Record that we found a static_type
728 info->found_any_static_type = true;
729 if (current_ptr == info->static_ptr)
730 {
731 // Record that we found (static_ptr, static_type)
732 info->found_our_static_ptr = true;
733 if (info->dst_ptr_leading_to_static_ptr == 0)
734 {
735 // First time here
736 info->dst_ptr_leading_to_static_ptr = dst_ptr;
737 info->path_dst_ptr_to_static_ptr = path_below;
738 info->number_to_static_ptr = 1;
739 // If there is only one dst_type in the entire tree and the path from
740 // there to here is public then we are done!
741 if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
742 info->search_done = true;
743 }
744 else if (info->dst_ptr_leading_to_static_ptr == dst_ptr)
745 {
746 // We've been here before. Update path to "most public"
747 if (info->path_dst_ptr_to_static_ptr == not_public_path)
748 info->path_dst_ptr_to_static_ptr = path_below;
749 // If there is only one dst_type in the entire tree and the path from
750 // there to here is public then we are done!
751 if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path)
752 info->search_done = true;
753 }
754 else
755 {
756 // We've detected an ambiguous cast from (static_ptr, static_type)
757 // to a dst_type
758 info->number_to_static_ptr += 1;
759 info->search_done = true;
760 }
761 }
762}
763
764// Call this function when you hit a static_type which is not a base (above) a dst_type.
Howard Hinnant13093662012-01-16 00:13:46 +0000765// If this is (static_ptr, static_type)
766// Record the path (public or not) from (dynamic_ptr, dynamic_type) to here. There may be
767// multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one.
768void
769__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info,
770 const void* current_ptr,
771 int path_below) const
772{
Howard Hinnant13093662012-01-16 00:13:46 +0000773 if (current_ptr == info->static_ptr)
774 {
Howard Hinnant13093662012-01-16 00:13:46 +0000775 // Record the most public path from (dynamic_ptr, dynamic_type) to
776 // (static_ptr, static_type)
777 if (info->path_dynamic_ptr_to_static_ptr != public_path)
778 info->path_dynamic_ptr_to_static_ptr = path_below;
779 }
780}
781
782// Call this function when searching below a dst_type node. This function searches
783// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes.
784// If it finds a static_type node, there is no need to further search base classes
785// above.
786// If it finds a dst_type node it should search base classes using search_above_dst
787// to find out if this dst_type points to (static_ptr, static_type) or not.
Howard Hinnantcc614df2012-01-16 17:06:51 +0000788// Either way, the dst_type is recorded as one of two "flavors": one that does
Howard Hinnant13093662012-01-16 00:13:46 +0000789// or does not point to (static_ptr, static_type).
790// If this is neither a static_type nor a dst_type node, continue searching
791// base classes above.
792// All the hoopla surrounding the search code is doing nothing but looking for
Howard Hinnantfacfc462012-01-22 01:23:02 +0000793// excuses to stop the search prematurely (break out of the for-loop). That is,
794// the algorithm below is simply an optimization of this:
795// void
796// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
797// const void* current_ptr,
798// int path_below) const
799// {
800// typedef const __base_class_type_info* Iter;
801// if (this == info->static_type)
802// process_static_type_below_dst(info, current_ptr, path_below);
803// else if (this == info->dst_type)
804// {
805// // Record the most public access path that got us here
806// if (info->path_dynamic_ptr_to_dst_ptr != public_path)
807// info->path_dynamic_ptr_to_dst_ptr = path_below;
808// bool does_dst_type_point_to_our_static_type = false;
809// for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p)
810// {
811// p->search_above_dst(info, current_ptr, current_ptr, public_path);
812// if (info->found_our_static_ptr)
813// does_dst_type_point_to_our_static_type = true;
814// // break out early here if you can detect it doesn't matter if you do
815// }
816// if (!does_dst_type_point_to_our_static_type)
817// {
818// // We found a dst_type that doesn't point to (static_ptr, static_type)
819// // So record the address of this dst_ptr and increment the
820// // count of the number of such dst_types found in the tree.
821// info->dst_ptr_not_leading_to_static_ptr = current_ptr;
822// info->number_to_dst_ptr += 1;
823// }
824// }
825// else
826// {
827// // This is not a static_type and not a dst_type.
828// for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
829// {
830// p->search_below_dst(info, current_ptr, public_path);
831// // break out early here if you can detect it doesn't matter if you do
832// }
833// }
834// }
Howard Hinnant13093662012-01-16 00:13:46 +0000835void
836__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
837 const void* current_ptr,
Howard Hinnant326aca32012-09-28 22:43:50 +0000838 int path_below,
839 bool use_strcmp) const
Howard Hinnant13093662012-01-16 00:13:46 +0000840{
841 typedef const __base_class_type_info* Iter;
Howard Hinnant326aca32012-09-28 22:43:50 +0000842 if (is_equal(this, info->static_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +0000843 process_static_type_below_dst(info, current_ptr, path_below);
Howard Hinnant326aca32012-09-28 22:43:50 +0000844 else if (is_equal(this, info->dst_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +0000845 {
846 // We've been here before if we've recorded current_ptr in one of these
847 // two places:
848 if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
849 current_ptr == info->dst_ptr_not_leading_to_static_ptr)
850 {
851 // We've seen this node before, and therefore have already searched
852 // its base classes above.
853 // Update path to here that is "most public".
854 if (path_below == public_path)
855 info->path_dynamic_ptr_to_dst_ptr = public_path;
856 }
857 else // We have haven't been here before
858 {
859 // Record the access path that got us here
860 // If there is more than one dst_type this path doesn't matter.
861 info->path_dynamic_ptr_to_dst_ptr = path_below;
862 // Only search above here if dst_type derives from static_type, or
863 // if it is unknown if dst_type derives from static_type.
864 if (info->is_dst_type_derived_from_static_type != no)
865 {
866 // Set up flags to record results from all base classes
867 bool is_dst_type_derived_from_static_type = false;
868 bool does_dst_type_point_to_our_static_type = false;
869 // We've found a dst_type with a potentially public path to here.
870 // We have to assume the path is public because it may become
871 // public later (if we get back to here with a public path).
872 // We can stop looking above if:
873 // 1. We've found a public path to (static_ptr, static_type).
874 // 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
875 // This is detected at the (static_ptr, static_type).
876 // 3. We can prove that there is no public path to (static_ptr, static_type)
877 // above here.
878 const Iter e = __base_info + __base_count;
879 for (Iter p = __base_info; p < e; ++p)
880 {
881 // Zero out found flags
882 info->found_our_static_ptr = false;
883 info->found_any_static_type = false;
Howard Hinnant326aca32012-09-28 22:43:50 +0000884 p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
Howard Hinnantcc614df2012-01-16 17:06:51 +0000885 if (info->search_done)
Howard Hinnant13093662012-01-16 00:13:46 +0000886 break;
887 if (info->found_any_static_type)
888 {
889 is_dst_type_derived_from_static_type = true;
890 if (info->found_our_static_ptr)
891 {
892 does_dst_type_point_to_our_static_type = true;
893 // If we found what we're looking for, stop looking above.
894 if (info->path_dst_ptr_to_static_ptr == public_path)
895 break;
896 // We found a private path to (static_ptr, static_type)
897 // If there is no diamond then there is only one path
898 // to (static_ptr, static_type) and we just found it.
899 if (!(__flags & __diamond_shaped_mask))
900 break;
901 }
902 else
903 {
904 // If we found a static_type that isn't the one we're looking
905 // for, and if there are no repeated types above here,
906 // then stop looking.
907 if (!(__flags & __non_diamond_repeat_mask))
908 break;
909 }
910 }
911 }
912 if (!does_dst_type_point_to_our_static_type)
913 {
914 // We found a dst_type that doesn't point to (static_ptr, static_type)
915 // So record the address of this dst_ptr and increment the
916 // count of the number of such dst_types found in the tree.
917 info->dst_ptr_not_leading_to_static_ptr = current_ptr;
918 info->number_to_dst_ptr += 1;
919 // If there exists another dst with a private path to
920 // (static_ptr, static_type), then the cast from
921 // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous,
922 // so stop search.
923 if (info->number_to_static_ptr == 1 &&
924 info->path_dst_ptr_to_static_ptr == not_public_path)
925 info->search_done = true;
926 }
927 // If we found no static_type,s then dst_type doesn't derive
928 // from static_type, else it does. Record this result so that
929 // next time we hit a dst_type we will know not to search above
930 // it if it doesn't derive from static_type.
931 if (is_dst_type_derived_from_static_type)
932 info->is_dst_type_derived_from_static_type = yes;
933 else
934 info->is_dst_type_derived_from_static_type = no;
935 }
936 }
937 }
938 else
939 {
940 // This is not a static_type and not a dst_type.
941 const Iter e = __base_info + __base_count;
Howard Hinnant65255632012-01-16 18:21:05 +0000942 Iter p = __base_info;
Howard Hinnant326aca32012-09-28 22:43:50 +0000943 p->search_below_dst(info, current_ptr, path_below, use_strcmp);
Howard Hinnant65255632012-01-16 18:21:05 +0000944 if (++p < e)
Howard Hinnant13093662012-01-16 00:13:46 +0000945 {
Howard Hinnant65255632012-01-16 18:21:05 +0000946 if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1)
Howard Hinnant13093662012-01-16 00:13:46 +0000947 {
Howard Hinnant65255632012-01-16 18:21:05 +0000948 // If there are multiple paths to a base above from here, or if
949 // a dst_type pointing to (static_ptr, static_type) has been found,
950 // then there is no way to break out of this loop early unless
951 // something below detects the search is done.
952 do
953 {
954 if (info->search_done)
955 break;
Howard Hinnant326aca32012-09-28 22:43:50 +0000956 p->search_below_dst(info, current_ptr, path_below, use_strcmp);
Howard Hinnant65255632012-01-16 18:21:05 +0000957 } while (++p < e);
Howard Hinnant13093662012-01-16 00:13:46 +0000958 }
Howard Hinnant65255632012-01-16 18:21:05 +0000959 else if (__flags & __non_diamond_repeat_mask)
Howard Hinnant13093662012-01-16 00:13:46 +0000960 {
Howard Hinnant65255632012-01-16 18:21:05 +0000961 // There are not multiple paths to any base class from here and a
962 // dst_type pointing to (static_ptr, static_type) has not yet been
963 // found.
964 do
965 {
966 if (info->search_done)
967 break;
968 // If we just found a dst_type with a public path to (static_ptr, static_type),
969 // then the only reason to continue the search is to make sure
970 // no other dst_type points to (static_ptr, static_type).
971 // If !diamond, then we don't need to search here.
972 if (info->number_to_static_ptr == 1 &&
973 info->path_dst_ptr_to_static_ptr == public_path)
974 break;
Howard Hinnant326aca32012-09-28 22:43:50 +0000975 p->search_below_dst(info, current_ptr, path_below, use_strcmp);
Howard Hinnant65255632012-01-16 18:21:05 +0000976 } while (++p < e);
Howard Hinnant13093662012-01-16 00:13:46 +0000977 }
Howard Hinnant65255632012-01-16 18:21:05 +0000978 else
Howard Hinnant13093662012-01-16 00:13:46 +0000979 {
Howard Hinnant65255632012-01-16 18:21:05 +0000980 // There are no repeated types above this node.
981 // There are no nodes with multiple parents above this node.
982 // no dst_type has been found to (static_ptr, static_type)
983 do
984 {
985 if (info->search_done)
986 break;
987 // If we just found a dst_type with a public path to (static_ptr, static_type),
988 // then the only reason to continue the search is to make sure sure
989 // no other dst_type points to (static_ptr, static_type).
990 // If !diamond, then we don't need to search here.
991 // if we just found a dst_type with a private path to (static_ptr, static_type),
992 // then we're only looking for a public path to (static_ptr, static_type)
993 // and to check for other dst_types.
994 // If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type)
995 // and not a dst_type under here.
996 if (info->number_to_static_ptr == 1)
997 break;
Howard Hinnant326aca32012-09-28 22:43:50 +0000998 p->search_below_dst(info, current_ptr, path_below, use_strcmp);
Howard Hinnant65255632012-01-16 18:21:05 +0000999 } while (++p < e);
Howard Hinnant13093662012-01-16 00:13:46 +00001000 }
1001 }
1002 }
1003}
1004
1005// This is the same algorithm as __vmi_class_type_info::search_below_dst but
1006// simplified to the case that there is only a single base class.
1007void
1008__si_class_type_info::search_below_dst(__dynamic_cast_info* info,
1009 const void* current_ptr,
Howard Hinnant326aca32012-09-28 22:43:50 +00001010 int path_below,
1011 bool use_strcmp) const
Howard Hinnant13093662012-01-16 00:13:46 +00001012{
Howard Hinnant326aca32012-09-28 22:43:50 +00001013 if (is_equal(this, info->static_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +00001014 process_static_type_below_dst(info, current_ptr, path_below);
Howard Hinnant326aca32012-09-28 22:43:50 +00001015 else if (is_equal(this, info->dst_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +00001016 {
1017 // We've been here before if we've recorded current_ptr in one of these
1018 // two places:
1019 if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
1020 current_ptr == info->dst_ptr_not_leading_to_static_ptr)
1021 {
1022 // We've seen this node before, and therefore have already searched
1023 // its base classes above.
1024 // Update path to here that is "most public".
1025 if (path_below == public_path)
1026 info->path_dynamic_ptr_to_dst_ptr = public_path;
1027 }
1028 else // We have haven't been here before
1029 {
1030 // Record the access path that got us here
1031 // If there is more than one dst_type this path doesn't matter.
1032 info->path_dynamic_ptr_to_dst_ptr = path_below;
1033 // Only search above here if dst_type derives from static_type, or
1034 // if it is unknown if dst_type derives from static_type.
1035 if (info->is_dst_type_derived_from_static_type != no)
1036 {
1037 // Set up flags to record results from all base classes
1038 bool is_dst_type_derived_from_static_type = false;
1039 bool does_dst_type_point_to_our_static_type = false;
1040 // Zero out found flags
1041 info->found_our_static_ptr = false;
1042 info->found_any_static_type = false;
Howard Hinnant326aca32012-09-28 22:43:50 +00001043 __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp);
Howard Hinnant13093662012-01-16 00:13:46 +00001044 if (info->found_any_static_type)
1045 {
1046 is_dst_type_derived_from_static_type = true;
1047 if (info->found_our_static_ptr)
1048 does_dst_type_point_to_our_static_type = true;
1049 }
1050 if (!does_dst_type_point_to_our_static_type)
1051 {
1052 // We found a dst_type that doesn't point to (static_ptr, static_type)
1053 // So record the address of this dst_ptr and increment the
1054 // count of the number of such dst_types found in the tree.
1055 info->dst_ptr_not_leading_to_static_ptr = current_ptr;
1056 info->number_to_dst_ptr += 1;
1057 // If there exists another dst with a private path to
1058 // (static_ptr, static_type), then the cast from
1059 // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
1060 if (info->number_to_static_ptr == 1 &&
1061 info->path_dst_ptr_to_static_ptr == not_public_path)
1062 info->search_done = true;
1063 }
1064 // If we found no static_type,s then dst_type doesn't derive
1065 // from static_type, else it does. Record this result so that
1066 // next time we hit a dst_type we will know not to search above
1067 // it if it doesn't derive from static_type.
1068 if (is_dst_type_derived_from_static_type)
1069 info->is_dst_type_derived_from_static_type = yes;
1070 else
1071 info->is_dst_type_derived_from_static_type = no;
1072 }
1073 }
1074 }
1075 else
1076 {
1077 // This is not a static_type and not a dst_type
Howard Hinnant326aca32012-09-28 22:43:50 +00001078 __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp);
Howard Hinnant13093662012-01-16 00:13:46 +00001079 }
1080}
1081
1082// This is the same algorithm as __vmi_class_type_info::search_below_dst but
1083// simplified to the case that there is no base class.
1084void
1085__class_type_info::search_below_dst(__dynamic_cast_info* info,
1086 const void* current_ptr,
Howard Hinnant326aca32012-09-28 22:43:50 +00001087 int path_below,
1088 bool use_strcmp) const
Howard Hinnant13093662012-01-16 00:13:46 +00001089{
Howard Hinnant326aca32012-09-28 22:43:50 +00001090 if (is_equal(this, info->static_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +00001091 process_static_type_below_dst(info, current_ptr, path_below);
Howard Hinnant326aca32012-09-28 22:43:50 +00001092 else if (is_equal(this, info->dst_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +00001093 {
1094 // We've been here before if we've recorded current_ptr in one of these
1095 // two places:
1096 if (current_ptr == info->dst_ptr_leading_to_static_ptr ||
1097 current_ptr == info->dst_ptr_not_leading_to_static_ptr)
1098 {
1099 // We've seen this node before, and therefore have already searched
1100 // its base classes above.
1101 // Update path to here that is "most public".
1102 if (path_below == public_path)
1103 info->path_dynamic_ptr_to_dst_ptr = public_path;
1104 }
1105 else // We have haven't been here before
1106 {
1107 // Record the access path that got us here
1108 // If there is more than one dst_type this path doesn't matter.
1109 info->path_dynamic_ptr_to_dst_ptr = path_below;
1110 // We found a dst_type that doesn't point to (static_ptr, static_type)
1111 // So record the address of this dst_ptr and increment the
1112 // count of the number of such dst_types found in the tree.
1113 info->dst_ptr_not_leading_to_static_ptr = current_ptr;
1114 info->number_to_dst_ptr += 1;
1115 // If there exists another dst with a private path to
1116 // (static_ptr, static_type), then the cast from
1117 // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous.
1118 if (info->number_to_static_ptr == 1 &&
1119 info->path_dst_ptr_to_static_ptr == not_public_path)
1120 info->search_done = true;
1121 // We found that dst_type does not derive from static_type
1122 info->is_dst_type_derived_from_static_type = no;
1123 }
1124 }
1125}
1126
1127// Call this function when searching above a dst_type node. This function searches
1128// for a public path to (static_ptr, static_type).
1129// This function is guaranteed not to find a node of type dst_type.
1130// Theoretically this is a very simple function which just stops if it finds a
Howard Hinnantfacfc462012-01-22 01:23:02 +00001131// static_type node: All the hoopla surrounding the search code is doing
1132// nothing but looking for excuses to stop the search prematurely (break out of
1133// the for-loop). That is, the algorithm below is simply an optimization of this:
1134// void
1135// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1136// const void* dst_ptr,
1137// const void* current_ptr,
1138// int path_below) const
1139// {
1140// if (this == info->static_type)
1141// process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1142// else
1143// {
1144// typedef const __base_class_type_info* Iter;
1145// // This is not a static_type and not a dst_type
1146// for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p)
1147// {
1148// p->search_above_dst(info, dst_ptr, current_ptr, public_path);
1149// // break out early here if you can detect it doesn't matter if you do
1150// }
1151// }
1152// }
Howard Hinnant13093662012-01-16 00:13:46 +00001153void
1154__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info,
1155 const void* dst_ptr,
1156 const void* current_ptr,
Howard Hinnant326aca32012-09-28 22:43:50 +00001157 int path_below,
1158 bool use_strcmp) const
Howard Hinnant13093662012-01-16 00:13:46 +00001159{
Howard Hinnant326aca32012-09-28 22:43:50 +00001160 if (is_equal(this, info->static_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +00001161 process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1162 else
1163 {
1164 typedef const __base_class_type_info* Iter;
1165 // This is not a static_type and not a dst_type
1166 // Save flags so they can be restored when returning to nodes below.
1167 bool found_our_static_ptr = info->found_our_static_ptr;
1168 bool found_any_static_type = info->found_any_static_type;
1169 // We've found a dst_type below with a path to here. If the path
1170 // to here is not public, there may be another path to here that
1171 // is public. So we have to assume that the path to here is public.
1172 // We can stop looking above if:
1173 // 1. We've found a public path to (static_ptr, static_type).
1174 // 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type.
1175 // This is detected at the (static_ptr, static_type).
1176 // 3. We can prove that there is no public path to (static_ptr, static_type)
1177 // above here.
1178 const Iter e = __base_info + __base_count;
Howard Hinnant65255632012-01-16 18:21:05 +00001179 Iter p = __base_info;
1180 // Zero out found flags
1181 info->found_our_static_ptr = false;
1182 info->found_any_static_type = false;
Howard Hinnant326aca32012-09-28 22:43:50 +00001183 p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
Howard Hinnant65255632012-01-16 18:21:05 +00001184 if (++p < e)
Howard Hinnant13093662012-01-16 00:13:46 +00001185 {
Howard Hinnant65255632012-01-16 18:21:05 +00001186 do
Howard Hinnant13093662012-01-16 00:13:46 +00001187 {
Howard Hinnant65255632012-01-16 18:21:05 +00001188 if (info->search_done)
Howard Hinnant13093662012-01-16 00:13:46 +00001189 break;
Howard Hinnant65255632012-01-16 18:21:05 +00001190 if (info->found_our_static_ptr)
1191 {
1192 // If we found what we're looking for, stop looking above.
1193 if (info->path_dst_ptr_to_static_ptr == public_path)
1194 break;
1195 // We found a private path to (static_ptr, static_type)
1196 // If there is no diamond then there is only one path
1197 // to (static_ptr, static_type) from here and we just found it.
1198 if (!(__flags & __diamond_shaped_mask))
1199 break;
1200 }
1201 else if (info->found_any_static_type)
1202 {
1203 // If we found a static_type that isn't the one we're looking
1204 // for, and if there are no repeated types above here,
1205 // then stop looking.
1206 if (!(__flags & __non_diamond_repeat_mask))
1207 break;
1208 }
1209 // Zero out found flags
1210 info->found_our_static_ptr = false;
1211 info->found_any_static_type = false;
Howard Hinnant326aca32012-09-28 22:43:50 +00001212 p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
Howard Hinnant65255632012-01-16 18:21:05 +00001213 } while (++p < e);
Howard Hinnant13093662012-01-16 00:13:46 +00001214 }
1215 // Restore flags
1216 info->found_our_static_ptr = found_our_static_ptr;
1217 info->found_any_static_type = found_any_static_type;
1218 }
1219}
1220
1221// This is the same algorithm as __vmi_class_type_info::search_above_dst but
1222// simplified to the case that there is only a single base class.
1223void
1224__si_class_type_info::search_above_dst(__dynamic_cast_info* info,
1225 const void* dst_ptr,
1226 const void* current_ptr,
Howard Hinnant326aca32012-09-28 22:43:50 +00001227 int path_below,
1228 bool use_strcmp) const
Howard Hinnant13093662012-01-16 00:13:46 +00001229{
Howard Hinnant326aca32012-09-28 22:43:50 +00001230 if (is_equal(this, info->static_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +00001231 process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1232 else
Howard Hinnant326aca32012-09-28 22:43:50 +00001233 __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp);
Howard Hinnant13093662012-01-16 00:13:46 +00001234}
1235
1236// This is the same algorithm as __vmi_class_type_info::search_above_dst but
1237// simplified to the case that there is no base class.
1238void
1239__class_type_info::search_above_dst(__dynamic_cast_info* info,
1240 const void* dst_ptr,
1241 const void* current_ptr,
Howard Hinnant326aca32012-09-28 22:43:50 +00001242 int path_below,
1243 bool use_strcmp) const
Howard Hinnant13093662012-01-16 00:13:46 +00001244{
Howard Hinnant326aca32012-09-28 22:43:50 +00001245 if (is_equal(this, info->static_type, use_strcmp))
Howard Hinnant13093662012-01-16 00:13:46 +00001246 process_static_type_above_dst(info, dst_ptr, current_ptr, path_below);
1247}
1248
1249// The search functions for __base_class_type_info are simply convenience
1250// functions for adjusting the current_ptr and path_below as the search is
1251// passed up to the base class node.
1252
1253void
1254__base_class_type_info::search_above_dst(__dynamic_cast_info* info,
1255 const void* dst_ptr,
1256 const void* current_ptr,
Howard Hinnant326aca32012-09-28 22:43:50 +00001257 int path_below,
1258 bool use_strcmp) const
Howard Hinnant13093662012-01-16 00:13:46 +00001259{
1260 ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
1261 if (__offset_flags & __virtual_mask)
1262 {
Howard Hinnantcc614df2012-01-16 17:06:51 +00001263 const char* vtable = *static_cast<const char*const*>(current_ptr);
1264 offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
Howard Hinnant13093662012-01-16 00:13:46 +00001265 }
1266 __base_type->search_above_dst(info, dst_ptr,
Howard Hinnantcc614df2012-01-16 17:06:51 +00001267 static_cast<const char*>(current_ptr) + offset_to_base,
Howard Hinnant13093662012-01-16 00:13:46 +00001268 (__offset_flags & __public_mask) ?
1269 path_below :
Howard Hinnant326aca32012-09-28 22:43:50 +00001270 not_public_path,
1271 use_strcmp);
Howard Hinnant13093662012-01-16 00:13:46 +00001272}
1273
1274void
1275__base_class_type_info::search_below_dst(__dynamic_cast_info* info,
1276 const void* current_ptr,
Howard Hinnant326aca32012-09-28 22:43:50 +00001277 int path_below,
1278 bool use_strcmp) const
Howard Hinnant13093662012-01-16 00:13:46 +00001279{
1280 ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
1281 if (__offset_flags & __virtual_mask)
1282 {
Howard Hinnantcc614df2012-01-16 17:06:51 +00001283 const char* vtable = *static_cast<const char*const*>(current_ptr);
1284 offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
Howard Hinnant13093662012-01-16 00:13:46 +00001285 }
1286 __base_type->search_below_dst(info,
Howard Hinnantcc614df2012-01-16 17:06:51 +00001287 static_cast<const char*>(current_ptr) + offset_to_base,
Howard Hinnant13093662012-01-16 00:13:46 +00001288 (__offset_flags & __public_mask) ?
1289 path_below :
Howard Hinnant326aca32012-09-28 22:43:50 +00001290 not_public_path,
1291 use_strcmp);
Howard Hinnant13093662012-01-16 00:13:46 +00001292}
1293
Howard Hinnant152beb72012-01-09 17:10:00 +00001294} // __cxxabiv1