-: 0:Source:/workspaces/llvm-project/libcxxabi/src/private_typeinfo.cpp -: 0:Graph:./libcxxabi/src/CMakeFiles/cxxabi_shared_objects.dir/private_typeinfo.cpp.gcno -: 0:Data:./libcxxabi/src/CMakeFiles/cxxabi_shared_objects.dir/private_typeinfo.cpp.gcda -: 0:Runs:1 -: 0:Programs:1 -: 1://===----------------------------------------------------------------------===// -: 2:// -: 3:// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -: 4:// See https://llvm.org/LICENSE.txt for license information. -: 5:// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -: 6:// -: 7://===----------------------------------------------------------------------===// -: 8: -: 9:#include "private_typeinfo.h" -: 10: -: 11:// The flag _LIBCXXABI_FORGIVING_DYNAMIC_CAST is used to make dynamic_cast -: 12:// more forgiving when type_info's mistakenly have hidden visibility and -: 13:// thus multiple type_infos can exist for a single type. -: 14:// -: 15:// When _LIBCXXABI_FORGIVING_DYNAMIC_CAST is defined, and only in the case where -: 16:// there is a detected inconsistency in the type_info hierarchy during a -: 17:// dynamic_cast, then the equality operation will fall back to using strcmp -: 18:// on type_info names to determine type_info equality. -: 19:// -: 20:// This change happens *only* under dynamic_cast, and only when -: 21:// dynamic_cast is faced with the choice: abort, or possibly give back the -: 22:// wrong answer. If when the dynamic_cast is done with this fallback -: 23:// algorithm and an inconsistency is still detected, dynamic_cast will call -: 24:// abort with an appropriate message. -: 25:// -: 26:// The current implementation of _LIBCXXABI_FORGIVING_DYNAMIC_CAST requires a -: 27:// printf-like function called syslog: -: 28:// -: 29:// void syslog(int facility_priority, const char* format, ...); -: 30:// -: 31:// If you want this functionality but your platform doesn't have syslog, -: 32:// just implement it in terms of fprintf(stderr, ...). -: 33:// -: 34:// _LIBCXXABI_FORGIVING_DYNAMIC_CAST is currently off by default. -: 35: -: 36:// On Windows, typeids are different between DLLs and EXEs, so comparing -: 37:// type_info* will work for typeids from the same compiled file but fail -: 38:// for typeids from a DLL and an executable. Among other things, exceptions -: 39:// are not caught by handlers since can_catch() returns false. -: 40:// -: 41:// Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST does not help since can_catch() calls -: 42:// is_equal() with use_strcmp=false so the string names are not compared. -: 43: -: 44:#include -: 45:#include -: 46: -: 47:#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST -: 48:#include "abort_message.h" -: 49:#include -: 50:#include -: 51:#endif -: 52: -: 53:static inline -: 54:bool 225847: 55:is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp) -: 56:{ -: 57: // Use std::type_info's default comparison unless we've explicitly asked -: 58: // for strcmp. 225847: 59: if (!use_strcmp) 225828: 60: return *x == *y; -: 61: // Still allow pointer equality to short circut. 19: 62: return x == y || strcmp(x->name(), y->name()) == 0; 225847: 63:} -: 64: 4439: 65:static inline ptrdiff_t update_offset_to_base(const char* vtable, -: 66: ptrdiff_t offset_to_base) { -: 67:#if __has_feature(cxx_abi_relative_vtable) -: 68: // VTable components are 32 bits in the relative vtables ABI. -: 69: return *reinterpret_cast(vtable + offset_to_base); -: 70:#else 4439: 71: return *reinterpret_cast(vtable + offset_to_base); -: 72:#endif -: 73:} -: 74: -: 75:namespace __cxxabiv1 -: 76:{ -: 77: -: 78:namespace { -: 79: -: 80:struct derived_object_info { -: 81: const void* dynamic_ptr; -: 82: const __class_type_info* dynamic_type; -: 83: std::ptrdiff_t offset_to_derived; -: 84:}; -: 85: -: 86:/// A helper function that gets (dynamic_ptr, dynamic_type, offset_to_derived) from static_ptr. 66156: 87:void dyn_cast_get_derived_info(derived_object_info* info, const void* static_ptr) -: 88:{ -: 89:#if __has_feature(cxx_abi_relative_vtable) -: 90: // The vtable address will point to the first virtual function, which is 8 -: 91: // bytes after the start of the vtable (4 for the offset from top + 4 for -: 92: // the typeinfo component). -: 93: const int32_t* vtable = -: 94: *reinterpret_cast(static_ptr); -: 95: info->offset_to_derived = static_cast(vtable[-2]); -: 96: info->dynamic_ptr = static_cast(static_ptr) + info->offset_to_derived; -: 97: -: 98: // The typeinfo component is now a relative offset to a proxy. -: 99: int32_t offset_to_ti_proxy = vtable[-1]; -: 100: const uint8_t* ptr_to_ti_proxy = -: 101: reinterpret_cast(vtable) + offset_to_ti_proxy; -: 102: info->dynamic_type = *(reinterpret_cast(ptr_to_ti_proxy)); -: 103:#else 66156: 104: void **vtable = *static_cast(static_ptr); 66156: 105: info->offset_to_derived = reinterpret_cast(vtable[-2]); 66156: 106: info->dynamic_ptr = static_cast(static_ptr) + info->offset_to_derived; 66156: 107: info->dynamic_type = static_cast(vtable[-1]); -: 108:#endif 66156: 109:} -: 110: -: 111:/// A helper function for __dynamic_cast that casts a base sub-object pointer -: 112:/// to the object's dynamic type. -: 113:/// -: 114:/// This function returns the casting result directly. No further processing -: 115:/// required. -: 116:/// -: 117:/// Specifically, this function can only be called if the following pre- -: 118:/// condition holds: -: 119:/// * The dynamic type of the object pointed to by `static_ptr` is exactly -: 120:/// the same as `dst_type`. -: 121: 41328: 122:const void* dyn_cast_to_derived(const void* static_ptr, -: 123: const void* dynamic_ptr, -: 124: const __class_type_info* static_type, -: 125: const __class_type_info* dst_type, -: 126: std::ptrdiff_t offset_to_derived, -: 127: std::ptrdiff_t src2dst_offset) -: 128:{ -: 129: // We're downcasting from src_type to the complete object's dynamic type. -: 130: // This is a really hot path that can be further optimized with the -: 131: // `src2dst_offset` hint. -: 132: // In such a case, dynamic_ptr already gives the casting result if the -: 133: // casting ever succeeds. All we have to do now is to check static_ptr -: 134: // points to a public base sub-object of dynamic_ptr. -: 135: 41328: 136: if (src2dst_offset >= 0) -: 137: { -: 138: // The static type is a unique public non-virtual base type of -: 139: // dst_type at offset `src2dst_offset` from the origin of dst. -: 140: // Note that there might be other non-public static_type bases. The -: 141: // hint only guarantees that the public base is non-virtual and -: 142: // unique. So we have to check whether static_ptr points to that -: 143: // unique public base sub-object. 41044: 144: if (offset_to_derived != -src2dst_offset) 10: 145: return nullptr; 41034: 146: return dynamic_ptr; -: 147: } -: 148: 284: 149: if (src2dst_offset == -2) -: 150: { -: 151: // static_type is not a public base of dst_type. 61: 152: return nullptr; -: 153: } -: 154: -: 155: // If src2dst_offset == -3, then: -: 156: // src_type is a multiple public base type but never a virtual -: 157: // base type. We can't conclude that static_ptr points to those -: 158: // public base sub-objects because there might be other non- -: 159: // public static_type bases. The search is inevitable. -: 160: -: 161: // Fallback to the slow path to check that static_type is a public -: 162: // base type of dynamic_type. -: 163: // Using giant short cut. Add that information to info. 1115: 164: __dynamic_cast_info info = { 223: 165: dst_type, 223: 166: static_ptr, 223: 167: static_type, 223: 168: src2dst_offset, -: 169: 0, 0, 0, 0, 0, 0, 0, 0, -: 170: 1, // number_of_dst_type -: 171: false, false, false -: 172: }; -: 173: // Do the search 223: 174: dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false); -: 175:#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST -: 176: // The following if should always be false because we should -: 177: // definitely find (static_ptr, static_type), either on a public -: 178: // or private path -: 179: if (info.path_dst_ptr_to_static_ptr == unknown) -: 180: { -: 181: // We get here only if there is some kind of visibility problem -: 182: // in client code. -: 183: static_assert(std::atomic::is_always_lock_free, ""); -: 184: static std::atomic error_count(0); -: 185: size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); -: 186: if ((error_count_snapshot & (error_count_snapshot-1)) == 0) -: 187: syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's " -: 188: "should have public visibility. At least one of them is hidden. %s" -: 189: ", %s.\n", static_type->name(), dynamic_type->name()); -: 190: // Redo the search comparing type_info's using strcmp -: 191: info = {dst_type, static_ptr, static_type, src2dst_offset, 0}; -: 192: info.number_of_dst_type = 1; -: 193: dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true); -: 194: } -: 195:#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST -: 196: // Query the search. 223: 197: if (info.path_dst_ptr_to_static_ptr != public_path) 6: 198: return nullptr; -: 199: 217: 200: return dynamic_ptr; 41328: 201:} -: 202: -: 203:/// A helper function for __dynamic_cast that tries to perform a downcast -: 204:/// before giving up and falling back to the slow path. -: 205: 24828: 206:const void* dyn_cast_try_downcast(const void* static_ptr, -: 207: const void* dynamic_ptr, -: 208: const __class_type_info* dst_type, -: 209: const __class_type_info* dynamic_type, -: 210: std::ptrdiff_t src2dst_offset) -: 211:{ 24828: 212: if (src2dst_offset < 0) -: 213: { -: 214: // We can only optimize the case if the static type is a unique public -: 215: // base of dst_type. Give up. 1068: 216: return nullptr; -: 217: } -: 218: -: 219: // Pretend there is a dst_type object that leads to static_ptr. Later we -: 220: // will check whether this imagined dst_type object exists. If it exists -: 221: // then it will be the casting result. 23760: 222: const void* dst_ptr_to_static = reinterpret_cast(static_ptr) - src2dst_offset; -: 223: 23760: 224: if (reinterpret_cast(dst_ptr_to_static) < reinterpret_cast(dynamic_ptr)) -: 225: { -: 226: // The imagined dst_type object does not exist. Bail-out quickly. 37: 227: return nullptr; -: 228: } -: 229: -: 230: // Try to search a path from dynamic_type to dst_type. 118615: 231: __dynamic_cast_info dynamic_to_dst_info = { 23723: 232: dynamic_type, 23723: 233: dst_ptr_to_static, 23723: 234: dst_type, 23723: 235: src2dst_offset, -: 236: 0, 0, 0, 0, 0, 0, 0, 0, -: 237: 1, // number_of_dst_type -: 238: false, false, false -: 239: }; 23723: 240: dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false); 23723: 241: if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) { -: 242: // We have found at least one path from dynamic_ptr to dst_ptr. The -: 243: // downcast can succeed. 20825: 244: return dst_ptr_to_static; -: 245: } -: 246: 2898: 247: return nullptr; 24828: 248:} -: 249: 4003: 250:const void* dyn_cast_slow(const void* static_ptr, -: 251: const void* dynamic_ptr, -: 252: const __class_type_info* static_type, -: 253: const __class_type_info* dst_type, -: 254: const __class_type_info* dynamic_type, -: 255: std::ptrdiff_t src2dst_offset) -: 256:{ -: 257: // Not using giant short cut. Do the search -: 258: -: 259: // Initialize info struct for this search. 20015: 260: __dynamic_cast_info info = { 4003: 261: dst_type, 4003: 262: static_ptr, 4003: 263: static_type, 4003: 264: src2dst_offset, -: 265: 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false -: 266: }; -: 267: 4003: 268: dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false); -: 269:#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST -: 270: // The following if should always be false because we should -: 271: // definitely find (static_ptr, static_type), either on a public -: 272: // or private path -: 273: if (info.path_dst_ptr_to_static_ptr == unknown && -: 274: info.path_dynamic_ptr_to_static_ptr == unknown) -: 275: { -: 276: static_assert(std::atomic::is_always_lock_free, ""); -: 277: static std::atomic error_count(0); -: 278: size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); -: 279: if ((error_count_snapshot & (error_count_snapshot-1)) == 0) -: 280: syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's " -: 281: "has hidden visibility or is defined in more than one translation " -: 282: "unit. They should all have public visibility. " -: 283: "%s, %s, %s.\n", static_type->name(), dynamic_type->name(), -: 284: dst_type->name()); -: 285: // Redo the search comparing type_info's using strcmp -: 286: info = {dst_type, static_ptr, static_type, src2dst_offset, 0}; -: 287: dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true); -: 288: } -: 289:#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST -: 290: // Query the search. 4003: 291: switch (info.number_to_static_ptr) -: 292: { -: 293: case 0: 4011: 294: if (info.number_to_dst_ptr == 1 && 469: 295: info.path_dynamic_ptr_to_static_ptr == public_path && 426: 296: info.path_dynamic_ptr_to_dst_ptr == public_path) 413: 297: return info.dst_ptr_not_leading_to_static_ptr; 3172: 298: break; -: 299: case 1: 430: 300: if (info.path_dst_ptr_to_static_ptr == public_path || -: 301: ( 60: 302: info.number_to_dst_ptr == 0 && 59: 303: info.path_dynamic_ptr_to_static_ptr == public_path && 15: 304: info.path_dynamic_ptr_to_dst_ptr == public_path -: 305: ) -: 306: ) 369: 307: return info.dst_ptr_leading_to_static_ptr; 46: 308: break; -: 309: } -: 310: 3221: 311: return nullptr; 4003: 312:} -: 313: -: 314:} // namespace -: 315: -: 316:// __shim_type_info -: 317: #####: 318:__shim_type_info::~__shim_type_info() #####: 319:{ #####: 320:} -: 321: #####: 322:void __shim_type_info::noop1() const {} #####: 323:void __shim_type_info::noop2() const {} -: 324: -: 325:// __fundamental_type_info -: 326: -: 327:// This miraculously (compiler magic) emits the type_info's for: -: 328:// 1. all of the fundamental types -: 329:// 2. pointers to all of the fundamental types -: 330:// 3. pointers to all of the const fundamental types #####: 331:__fundamental_type_info::~__fundamental_type_info() #####: 332:{ #####: 333:} -: 334: -: 335:// __array_type_info -: 336: #####: 337:__array_type_info::~__array_type_info() #####: 338:{ #####: 339:} -: 340: -: 341:// __function_type_info -: 342: #####: 343:__function_type_info::~__function_type_info() #####: 344:{ #####: 345:} -: 346: -: 347:// __enum_type_info -: 348: #####: 349:__enum_type_info::~__enum_type_info() #####: 350:{ #####: 351:} -: 352: -: 353:// __class_type_info -: 354: #####: 355:__class_type_info::~__class_type_info() #####: 356:{ #####: 357:} -: 358: -: 359:// __si_class_type_info -: 360: #####: 361:__si_class_type_info::~__si_class_type_info() #####: 362:{ #####: 363:} -: 364: -: 365:// __vmi_class_type_info -: 366: #####: 367:__vmi_class_type_info::~__vmi_class_type_info() #####: 368:{ #####: 369:} -: 370: -: 371:// __pbase_type_info -: 372: #####: 373:__pbase_type_info::~__pbase_type_info() #####: 374:{ #####: 375:} -: 376: -: 377:// __pointer_type_info -: 378: #####: 379:__pointer_type_info::~__pointer_type_info() #####: 380:{ #####: 381:} -: 382: -: 383:// __pointer_to_member_type_info -: 384: #####: 385:__pointer_to_member_type_info::~__pointer_to_member_type_info() #####: 386:{ #####: 387:} -: 388: -: 389:// can_catch -: 390: -: 391:// A handler is a match for an exception object of type E if -: 392:// 1. The handler is of type cv T or cv T& and E and T are the same type -: 393:// (ignoring the top-level cv-qualifiers), or -: 394:// 2. the handler is of type cv T or cv T& and T is an unambiguous public -: 395:// base class of E, or -: 396:// 3. the handler is of type cv1 T* cv2 and E is a pointer type that can be -: 397:// converted to the type of the handler by either or both of -: 398:// A. a standard pointer conversion (4.10) not involving conversions to -: 399:// pointers to private or protected or ambiguous classes -: 400:// B. a qualification conversion -: 401:// 4. the handler is a pointer or pointer to member type and E is -: 402:// std::nullptr_t. -: 403: -: 404:// adjustedPtr: -: 405:// -: 406:// catch (A& a) : adjustedPtr == &a -: 407:// catch (A* a) : adjustedPtr == a -: 408:// catch (A** a) : adjustedPtr == a -: 409:// -: 410:// catch (D2& d2) : adjustedPtr == &d2 (d2 is base class of thrown object) -: 411:// catch (D2* d2) : adjustedPtr == d2 -: 412:// catch (D2*& d2) : adjustedPtr == d2 -: 413:// -: 414:// catch (...) : adjustedPtr == & of the exception -: 415:// -: 416:// If the thrown type is nullptr_t and the caught type is a pointer to -: 417:// member type, adjustedPtr points to a statically-allocated null pointer -: 418:// representation of that type. -: 419: -: 420:// Handles bullet 1 -: 421:bool 21: 422:__fundamental_type_info::can_catch(const __shim_type_info* thrown_type, -: 423: void*&) const -: 424:{ 21: 425: return is_equal(this, thrown_type, false); -: 426:} -: 427: -: 428:bool 1: 429:__array_type_info::can_catch(const __shim_type_info*, void*&) const -: 430:{ -: 431: // We can get here if someone tries to catch an array by reference. -: 432: // However if someone tries to throw an array, it immediately gets -: 433: // converted to a pointer, which will not convert back to an array -: 434: // at the catch clause. So this can never catch anything. 1: 435: return false; -: 436:} -: 437: -: 438:bool 1: 439:__function_type_info::can_catch(const __shim_type_info*, void*&) const -: 440:{ -: 441: // We can get here if someone tries to catch a function by reference. -: 442: // However if someone tries to throw a function, it immediately gets -: 443: // converted to a pointer, which will not convert back to a function -: 444: // at the catch clause. So this can never catch anything. 1: 445: return false; -: 446:} -: 447: -: 448:// Handles bullet 1 -: 449:bool #####: 450:__enum_type_info::can_catch(const __shim_type_info* thrown_type, -: 451: void*&) const -: 452:{ #####: 453: return is_equal(this, thrown_type, false); -: 454:} -: 455: -: 456:#ifdef __clang__ -: 457:#pragma clang diagnostic push -: 458:#pragma clang diagnostic ignored "-Wmissing-field-initializers" -: 459:#endif -: 460: -: 461:// Handles bullets 1 and 2 -: 462:bool 40: 463:__class_type_info::can_catch(const __shim_type_info* thrown_type, -: 464: void*& adjustedPtr) const -: 465:{ -: 466: // bullet 1 40: 467: if (is_equal(this, thrown_type, false)) 28: 468: return true; 12: 469: const __class_type_info* thrown_class_type = 12: 470: dynamic_cast(thrown_type); 12: 471: if (thrown_class_type == 0) #####: 472: return false; -: 473: // bullet 2 12: 474: __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; 12: 475: info.number_of_dst_type = 1; 12: 476: thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path); 12: 477: if (info.path_dst_ptr_to_static_ptr == public_path) -: 478: { 8: 479: adjustedPtr = const_cast(info.dst_ptr_leading_to_static_ptr); 8: 480: return true; -: 481: } 4: 482: return false; 40: 483:} -: 484: -: 485:#ifdef __clang__ -: 486:#pragma clang diagnostic pop -: 487:#endif -: 488: -: 489:void 158: 490:__class_type_info::process_found_base_class(__dynamic_cast_info* info, -: 491: void* adjustedPtr, -: 492: int path_below) const -: 493:{ 158: 494: if (info->dst_ptr_leading_to_static_ptr == 0) -: 495: { -: 496: // First time here 138: 497: info->dst_ptr_leading_to_static_ptr = adjustedPtr; 138: 498: info->path_dst_ptr_to_static_ptr = path_below; 138: 499: info->number_to_static_ptr = 1; 138: 500: } 20: 501: else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr) -: 502: { -: 503: // We've been here before. Update path to "most public" 2: 504: if (info->path_dst_ptr_to_static_ptr == not_public_path) #####: 505: info->path_dst_ptr_to_static_ptr = path_below; 2: 506: } -: 507: else -: 508: { -: 509: // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr) -: 510: // to a static_type 18: 511: info->number_to_static_ptr += 1; 18: 512: info->path_dst_ptr_to_static_ptr = not_public_path; 18: 513: info->search_done = true; -: 514: } 158: 515:} -: 516: -: 517:void 207: 518:__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, -: 519: void* adjustedPtr, -: 520: int path_below) const -: 521:{ 207: 522: if (is_equal(this, info->static_type, false)) 152: 523: process_found_base_class(info, adjustedPtr, path_below); 207: 524:} -: 525: -: 526:void 82: 527:__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, -: 528: void* adjustedPtr, -: 529: int path_below) const -: 530:{ 82: 531: if (is_equal(this, info->static_type, false)) 2: 532: process_found_base_class(info, adjustedPtr, path_below); -: 533: else 80: 534: __base_type->has_unambiguous_public_base(info, adjustedPtr, path_below); 82: 535:} -: 536: -: 537:void 134: 538:__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, -: 539: void* adjustedPtr, -: 540: int path_below) const -: 541:{ 134: 542: ptrdiff_t offset_to_base = 0; 134: 543: if (adjustedPtr != nullptr) -: 544: { 131: 545: offset_to_base = __offset_flags >> __offset_shift; 131: 546: if (__offset_flags & __virtual_mask) -: 547: { 9: 548: const char* vtable = *static_cast(adjustedPtr); 9: 549: offset_to_base = update_offset_to_base(vtable, offset_to_base); 9: 550: } 131: 551: } 268: 552: __base_type->has_unambiguous_public_base( 134: 553: info, 134: 554: static_cast(adjustedPtr) + offset_to_base, 134: 555: (__offset_flags & __public_mask) ? path_below : not_public_path); 134: 556:} -: 557: -: 558:void 108: 559:__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, -: 560: void* adjustedPtr, -: 561: int path_below) const -: 562:{ 108: 563: if (is_equal(this, info->static_type, false)) 4: 564: process_found_base_class(info, adjustedPtr, path_below); -: 565: else -: 566: { -: 567: typedef const __base_class_type_info* Iter; 104: 568: const Iter e = __base_info + __base_count; 104: 569: Iter p = __base_info; 104: 570: p->has_unambiguous_public_base(info, adjustedPtr, path_below); 104: 571: if (++p < e) -: 572: { 30: 573: do -: 574: { 30: 575: p->has_unambiguous_public_base(info, adjustedPtr, path_below); 30: 576: if (info->search_done) 18: 577: break; 12: 578: } while (++p < e); 30: 579: } -: 580: } 108: 581:} -: 582: -: 583:// Handles bullet 1 for both pointers and member pointers -: 584:bool 20394: 585:__pbase_type_info::can_catch(const __shim_type_info* thrown_type, -: 586: void*&) const -: 587:{ 20394: 588: bool use_strcmp = this->__flags & (__incomplete_class_mask | -: 589: __incomplete_mask); 20394: 590: if (!use_strcmp) { 20383: 591: const __pbase_type_info* thrown_pbase = dynamic_cast( 20383: 592: thrown_type); 20383: 593: if (!thrown_pbase) return false; 20382: 594: use_strcmp = thrown_pbase->__flags & (__incomplete_class_mask | -: 595: __incomplete_mask); 20382: 596: } 20393: 597: return is_equal(this, thrown_type, use_strcmp); 20394: 598:} -: 599: -: 600:#ifdef __clang__ -: 601:#pragma clang diagnostic push -: 602:#pragma clang diagnostic ignored "-Wmissing-field-initializers" -: 603:#endif -: 604: -: 605:// Handles bullets 1, 3 and 4 -: 606:// NOTE: It might not be safe to adjust the pointer if it is not not a pointer -: 607:// type. Only adjust the pointer after we know it is safe to do so. -: 608:bool 20327: 609:__pointer_type_info::can_catch(const __shim_type_info* thrown_type, -: 610: void*& adjustedPtr) const -: 611:{ -: 612: // bullet 4 20327: 613: if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) { 13: 614: adjustedPtr = nullptr; 13: 615: return true; -: 616: } -: 617: -: 618: // bullet 1 20314: 619: if (__pbase_type_info::can_catch(thrown_type, adjustedPtr)) { 322: 620: if (adjustedPtr != NULL) 322: 621: adjustedPtr = *static_cast(adjustedPtr); 322: 622: return true; -: 623: } -: 624: // bullet 3 19992: 625: const __pointer_type_info* thrown_pointer_type = 19992: 626: dynamic_cast(thrown_type); 19992: 627: if (thrown_pointer_type == 0) 22: 628: return false; -: 629: // Do the dereference adjustment 19970: 630: if (adjustedPtr != NULL) 19970: 631: adjustedPtr = *static_cast(adjustedPtr); -: 632: // bullet 3B and 3C 19970: 633: if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask) 8772: 634: return false; 11198: 635: if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask) 1: 636: return false; 11197: 637: if (is_equal(__pointee, thrown_pointer_type->__pointee, false)) 417: 638: return true; -: 639: // bullet 3A 10780: 640: if (is_equal(__pointee, &typeid(void), false)) { -: 641: // pointers to functions cannot be converted to void*. -: 642: // pointers to member functions are not handled here. 10: 643: const __function_type_info* thrown_function = 10: 644: dynamic_cast(thrown_pointer_type->__pointee); 10: 645: return (thrown_function == nullptr); -: 646: } -: 647: // Handle pointer to pointer 10770: 648: const __pointer_type_info* nested_pointer_type = 10770: 649: dynamic_cast(__pointee); 10770: 650: if (nested_pointer_type) { 10193: 651: if (~__flags & __const_mask) return false; 6792: 652: return nested_pointer_type->can_catch_nested(thrown_pointer_type->__pointee); -: 653: } -: 654: -: 655: // Handle pointer to pointer to member 577: 656: const __pointer_to_member_type_info* member_ptr_type = 577: 657: dynamic_cast(__pointee); 577: 658: if (member_ptr_type) { 397: 659: if (~__flags & __const_mask) return false; 264: 660: return member_ptr_type->can_catch_nested(thrown_pointer_type->__pointee); -: 661: } -: 662: -: 663: // Handle pointer to class type 180: 664: const __class_type_info* catch_class_type = 180: 665: dynamic_cast(__pointee); 180: 666: if (catch_class_type == 0) 9: 667: return false; 171: 668: const __class_type_info* thrown_class_type = 171: 669: dynamic_cast(thrown_pointer_type->__pointee); 171: 670: if (thrown_class_type == 0) #####: 671: return false; 171: 672: __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; 171: 673: info.number_of_dst_type = 1; 171: 674: thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path); 171: 675: if (info.path_dst_ptr_to_static_ptr == public_path) -: 676: { 48: 677: if (adjustedPtr != NULL) 46: 678: adjustedPtr = const_cast(info.dst_ptr_leading_to_static_ptr); 48: 679: return true; -: 680: } 123: 681: return false; 20327: 682:} -: 683: 7656: 684:bool __pointer_type_info::can_catch_nested( -: 685: const __shim_type_info* thrown_type) const -: 686:{ 7656: 687: const __pointer_type_info* thrown_pointer_type = 7656: 688: dynamic_cast(thrown_type); 7656: 689: if (thrown_pointer_type == 0) 192: 690: return false; -: 691: // bullet 3B 7464: 692: if (thrown_pointer_type->__flags & ~__flags) 3570: 693: return false; 3894: 694: if (is_equal(__pointee, thrown_pointer_type->__pointee, false)) 870: 695: return true; -: 696: // If the pointed to types differ then the catch type must be const -: 697: // qualified. 3024: 698: if (~__flags & __const_mask) 1008: 699: return false; -: 700: -: 701: // Handle pointer to pointer 2016: 702: const __pointer_type_info* nested_pointer_type = 2016: 703: dynamic_cast(__pointee); 2016: 704: if (nested_pointer_type) { 1728: 705: return nested_pointer_type->can_catch_nested( 864: 706: thrown_pointer_type->__pointee); -: 707: } -: 708: -: 709: // Handle pointer to pointer to member 1152: 710: const __pointer_to_member_type_info* member_ptr_type = 1152: 711: dynamic_cast(__pointee); 1152: 712: if (member_ptr_type) { 864: 713: return member_ptr_type->can_catch_nested(thrown_pointer_type->__pointee); -: 714: } -: 715: 288: 716: return false; 7656: 717:} -: 718: 87: 719:bool __pointer_to_member_type_info::can_catch( -: 720: const __shim_type_info* thrown_type, void*& adjustedPtr) const { -: 721: // bullet 4 87: 722: if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) { -: 723: // We assume that the pointer to member representation is the same for -: 724: // all pointers to data members and for all pointers to member functions. -: 725: struct X {}; 7: 726: if (dynamic_cast(__pointee)) { -: 727: static int (X::*const null_ptr_rep)() = nullptr; #####: 728: adjustedPtr = const_cast(&null_ptr_rep); #####: 729: } else { -: 730: static int X::*const null_ptr_rep = nullptr; 7: 731: adjustedPtr = const_cast(&null_ptr_rep); -: 732: } 7: 733: return true; -: 734: } -: 735: -: 736: // bullet 1 80: 737: if (__pbase_type_info::can_catch(thrown_type, adjustedPtr)) 19: 738: return true; -: 739: 61: 740: const __pointer_to_member_type_info* thrown_pointer_type = 61: 741: dynamic_cast(thrown_type); 61: 742: if (thrown_pointer_type == 0) 22: 743: return false; 39: 744: if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask) 11: 745: return false; 28: 746: if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask) 1: 747: return false; 27: 748: if (!is_equal(__pointee, thrown_pointer_type->__pointee, false)) 6: 749: return false; 21: 750: if (is_equal(__context, thrown_pointer_type->__context, false)) 7: 751: return true; -: 752: -: 753: // [except.handle] does not allow the pointer-to-member conversions mentioned -: 754: // in [mem.conv] to take place. For this reason we don't check Derived->Base -: 755: // for Derived->Base conversions. -: 756: 14: 757: return false; 87: 758:} -: 759: 1128: 760:bool __pointer_to_member_type_info::can_catch_nested( -: 761: const __shim_type_info* thrown_type) const -: 762:{ 1128: 763: const __pointer_to_member_type_info* thrown_member_ptr_type = 1128: 764: dynamic_cast(thrown_type); 1128: 765: if (thrown_member_ptr_type == 0) 192: 766: return false; 936: 767: if (~__flags & thrown_member_ptr_type->__flags) 546: 768: return false; 390: 769: if (!is_equal(__pointee, thrown_member_ptr_type->__pointee, false)) #####: 770: return false; 390: 771: if (!is_equal(__context, thrown_member_ptr_type->__context, false)) #####: 772: return false; 390: 773: return true; 1128: 774:} -: 775: -: 776:#ifdef __clang__ -: 777:#pragma clang diagnostic pop -: 778:#endif -: 779: -: 780:#ifdef __clang__ -: 781:#pragma clang diagnostic push -: 782:#pragma clang diagnostic ignored "-Wmissing-field-initializers" -: 783:#endif -: 784: -: 785:// __dynamic_cast -: 786: -: 787:// static_ptr: pointer to an object of type static_type; nonnull, and since the -: 788:// object is polymorphic, *(void**)static_ptr is a virtual table pointer. -: 789:// static_ptr is &v in the expression dynamic_cast(v). -: 790:// static_type: static type of the object pointed to by static_ptr. -: 791:// dst_type: destination type of the cast (the "T" in "dynamic_cast(v)"). -: 792:// src2dst_offset: a static hint about the location of the -: 793:// source subobject with respect to the complete object; -: 794:// special negative values are: -: 795:// -1: no hint -: 796:// -2: static_type is not a public base of dst_type -: 797:// -3: static_type is a multiple public base type but never a -: 798:// virtual base type -: 799:// otherwise, the static_type type is a unique public nonvirtual -: 800:// base type of dst_type at offset src2dst_offset from the -: 801:// origin of dst_type. -: 802:// -: 803:// (dynamic_ptr, dynamic_type) are the run time type of the complete object -: 804:// referred to by static_ptr and a pointer to it. These can be found from -: 805:// static_ptr for polymorphic types. -: 806:// static_type is guaranteed to be a polymorphic type. -: 807:// -: 808:// (dynamic_ptr, dynamic_type) is the root of a DAG that grows upward. Each -: 809:// node of the tree represents a base class/object of its parent (or parents) below. -: 810:// Each node is uniquely represented by a pointer to the object, and a pointer -: 811:// to a type_info - its type. Different nodes may have the same pointer and -: 812:// different nodes may have the same type. But only one node has a specific -: 813:// (pointer-value, type) pair. In C++ two objects of the same type can not -: 814:// share the same address. -: 815:// -: 816:// There are two flavors of nodes which have the type dst_type: -: 817:// 1. Those that are derived from (below) (static_ptr, static_type). -: 818:// 2. Those that are not derived from (below) (static_ptr, static_type). -: 819:// -: 820:// Invariants of the DAG: -: 821:// -: 822:// There is at least one path from the root (dynamic_ptr, dynamic_type) to -: 823:// the node (static_ptr, static_type). This path may or may not be public. -: 824:// There may be more than one such path (some public some not). Such a path may -: 825:// or may not go through a node having type dst_type. -: 826:// -: 827:// No node of type T appears above a node of the same type. That means that -: 828:// there is only one node with dynamic_type. And if dynamic_type == dst_type, -: 829:// then there is only one dst_type in the DAG. -: 830:// -: 831:// No node of type dst_type appears above a node of type static_type. Such -: 832:// DAG's are possible in C++, but the compiler computes those dynamic_casts at -: 833:// compile time, and only calls __dynamic_cast when dst_type lies below -: 834:// static_type in the DAG. -: 835:// -: 836:// dst_type != static_type: The compiler computes the dynamic_cast in this case too. -: 837:// dynamic_type != static_type: The compiler computes the dynamic_cast in this case too. -: 838:// -: 839:// Returns: -: 840:// -: 841:// If there is exactly one dst_type of flavor 1, and -: 842:// If there is a public path from that dst_type to (static_ptr, static_type), or -: 843:// If there are 0 dst_types of flavor 2, and there is a public path from -: 844:// (dynamic_ptr, dynamic_type) to (static_ptr, static_type) and a public -: 845:// path from (dynamic_ptr, dynamic_type) to the one dst_type, then return -: 846:// a pointer to that dst_type. -: 847:// Else if there are 0 dst_types of flavor 1 and exactly 1 dst_type of flavor 2, and -: 848:// if there is a public path from (dynamic_ptr, dynamic_type) to -: 849:// (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type) -: 850:// to the one dst_type, then return a pointer to that one dst_type. -: 851:// Else return nullptr. -: 852:// -: 853:// If dynamic_type == dst_type, then the above algorithm collapses to the -: 854:// following cheaper algorithm: -: 855:// -: 856:// If there is a public path from (dynamic_ptr, dynamic_type) to -: 857:// (static_ptr, static_type), then return dynamic_ptr. -: 858:// Else return nullptr. -: 859: -: 860:extern "C" _LIBCXXABI_FUNC_VIS void * 66156: 861:__dynamic_cast(const void *static_ptr, const __class_type_info *static_type, -: 862: const __class_type_info *dst_type, -: 863: std::ptrdiff_t src2dst_offset) { -: 864: // Get (dynamic_ptr, dynamic_type) from static_ptr -: 865: derived_object_info derived_info; 66156: 866: dyn_cast_get_derived_info(&derived_info, static_ptr); -: 867: -: 868: // Initialize answer to nullptr. This will be changed from the search -: 869: // results if a non-null answer is found. Regardless, this is what will -: 870: // be returned. 66156: 871: const void* dst_ptr = 0; -: 872: -: 873: // Find out if we can use a giant short cut in the search 66156: 874: if (is_equal(derived_info.dynamic_type, dst_type, false)) -: 875: { 82656: 876: dst_ptr = dyn_cast_to_derived(static_ptr, 41328: 877: derived_info.dynamic_ptr, 41328: 878: static_type, 41328: 879: dst_type, 41328: 880: derived_info.offset_to_derived, 41328: 881: src2dst_offset); 41328: 882: } -: 883: else -: 884: { -: 885: // Optimize toward downcasting: let's first try to do a downcast before -: 886: // falling back to the slow path. 49656: 887: dst_ptr = dyn_cast_try_downcast(static_ptr, 24828: 888: derived_info.dynamic_ptr, 24828: 889: dst_type, 24828: 890: derived_info.dynamic_type, 24828: 891: src2dst_offset); -: 892: 24828: 893: if (!dst_ptr) -: 894: { 8006: 895: dst_ptr = dyn_cast_slow(static_ptr, 4003: 896: derived_info.dynamic_ptr, 4003: 897: static_type, 4003: 898: dst_type, 4003: 899: derived_info.dynamic_type, 4003: 900: src2dst_offset); 4003: 901: } -: 902: } -: 903: 66156: 904: return const_cast(dst_ptr); -: 905:} -: 906: -: 907:#ifdef __clang__ -: 908:#pragma clang diagnostic pop -: 909:#endif -: 910: -: 911:// Call this function when you hit a static_type which is a base (above) a dst_type. -: 912:// Let caller know you hit a static_type. But only start recording details if -: 913:// this is (static_ptr, static_type) -- the node we are casting from. -: 914:// If this is (static_ptr, static_type) -: 915:// Record the path (public or not) from the dst_type to here. There may be -: 916:// multiple paths from the same dst_type to here, record the "most public" one. -: 917:// Record the dst_ptr as pointing to (static_ptr, static_type). -: 918:// If more than one (dst_ptr, dst_type) points to (static_ptr, static_type), -: 919:// then mark this dyanmic_cast as ambiguous and stop the search. -: 920:void 22328: 921:__class_type_info::process_static_type_above_dst(__dynamic_cast_info* info, -: 922: const void* dst_ptr, -: 923: const void* current_ptr, -: 924: int path_below) const -: 925:{ -: 926: // Record that we found a static_type 22328: 927: info->found_any_static_type = true; 22328: 928: if (current_ptr == info->static_ptr) -: 929: { -: 930: // Record that we found (static_ptr, static_type) 21503: 931: info->found_our_static_ptr = true; 21503: 932: if (info->dst_ptr_leading_to_static_ptr == 0) -: 933: { -: 934: // First time here 21466: 935: info->dst_ptr_leading_to_static_ptr = dst_ptr; 21466: 936: info->path_dst_ptr_to_static_ptr = path_below; 21466: 937: info->number_to_static_ptr = 1; -: 938: // If there is only one dst_type in the entire tree and the path from -: 939: // there to here is public then we are done! 21466: 940: if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path) 21027: 941: info->search_done = true; 21466: 942: } 37: 943: else if (info->dst_ptr_leading_to_static_ptr == dst_ptr) -: 944: { -: 945: // We've been here before. Update path to "most public" 34: 946: if (info->path_dst_ptr_to_static_ptr == not_public_path) 34: 947: info->path_dst_ptr_to_static_ptr = path_below; -: 948: // If there is only one dst_type in the entire tree and the path from -: 949: // there to here is public then we are done! 34: 950: if (info->number_of_dst_type == 1 && info->path_dst_ptr_to_static_ptr == public_path) 11: 951: info->search_done = true; 34: 952: } -: 953: else -: 954: { -: 955: // We've detected an ambiguous cast from (static_ptr, static_type) -: 956: // to a dst_type 3: 957: info->number_to_static_ptr += 1; 3: 958: info->search_done = true; -: 959: } 21503: 960: } 22328: 961:} -: 962: -: 963:// Call this function when you hit a static_type which is not a base (above) a dst_type. -: 964:// If this is (static_ptr, static_type) -: 965:// Record the path (public or not) from (dynamic_ptr, dynamic_type) to here. There may be -: 966:// multiple paths from (dynamic_ptr, dynamic_type) to here, record the "most public" one. -: 967:void 4747: 968:__class_type_info::process_static_type_below_dst(__dynamic_cast_info* info, -: 969: const void* current_ptr, -: 970: int path_below) const -: 971:{ 4747: 972: if (current_ptr == info->static_ptr) -: 973: { -: 974: // Record the most public path from (dynamic_ptr, dynamic_type) to -: 975: // (static_ptr, static_type) 4016: 976: if (info->path_dynamic_ptr_to_static_ptr != public_path) 3801: 977: info->path_dynamic_ptr_to_static_ptr = path_below; 4016: 978: } 4747: 979:} -: 980: -: 981:// Call this function when searching below a dst_type node. This function searches -: 982:// for a path to (static_ptr, static_type) and for paths to one or more dst_type nodes. -: 983:// If it finds a static_type node, there is no need to further search base classes -: 984:// above. -: 985:// If it finds a dst_type node it should search base classes using search_above_dst -: 986:// to find out if this dst_type points to (static_ptr, static_type) or not. -: 987:// Either way, the dst_type is recorded as one of two "flavors": one that does -: 988:// or does not point to (static_ptr, static_type). -: 989:// If this is neither a static_type nor a dst_type node, continue searching -: 990:// base classes above. -: 991:// All the hoopla surrounding the search code is doing nothing but looking for -: 992:// excuses to stop the search prematurely (break out of the for-loop). That is, -: 993:// the algorithm below is simply an optimization of this: -: 994:// void -: 995:// __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info, -: 996:// const void* current_ptr, -: 997:// int path_below) const -: 998:// { -: 999:// typedef const __base_class_type_info* Iter; -: 1000:// if (this == info->static_type) -: 1001:// process_static_type_below_dst(info, current_ptr, path_below); -: 1002:// else if (this == info->dst_type) -: 1003:// { -: 1004:// // Record the most public access path that got us here -: 1005:// if (info->path_dynamic_ptr_to_dst_ptr != public_path) -: 1006:// info->path_dynamic_ptr_to_dst_ptr = path_below; -: 1007:// bool does_dst_type_point_to_our_static_type = false; -: 1008:// for (Iter p = __base_info, e= __base_info + __base_count; p < e; ++p) -: 1009:// { -: 1010:// p->search_above_dst(info, current_ptr, current_ptr, public_path); -: 1011:// if (info->found_our_static_ptr) -: 1012:// does_dst_type_point_to_our_static_type = true; -: 1013:// // break out early here if you can detect it doesn't matter if you do -: 1014:// } -: 1015:// if (!does_dst_type_point_to_our_static_type) -: 1016:// { -: 1017:// // We found a dst_type that doesn't point to (static_ptr, static_type) -: 1018:// // So record the address of this dst_ptr and increment the -: 1019:// // count of the number of such dst_types found in the tree. -: 1020:// info->dst_ptr_not_leading_to_static_ptr = current_ptr; -: 1021:// info->number_to_dst_ptr += 1; -: 1022:// } -: 1023:// } -: 1024:// else -: 1025:// { -: 1026:// // This is not a static_type and not a dst_type. -: 1027:// for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p) -: 1028:// { -: 1029:// p->search_below_dst(info, current_ptr, public_path); -: 1030:// // break out early here if you can detect it doesn't matter if you do -: 1031:// } -: 1032:// } -: 1033:// } -: 1034:void 5103: 1035:__vmi_class_type_info::search_below_dst(__dynamic_cast_info* info, -: 1036: const void* current_ptr, -: 1037: int path_below, -: 1038: bool use_strcmp) const -: 1039:{ -: 1040: typedef const __base_class_type_info* Iter; 5103: 1041: if (is_equal(this, info->static_type, use_strcmp)) 314: 1042: process_static_type_below_dst(info, current_ptr, path_below); 4789: 1043: else if (is_equal(this, info->dst_type, use_strcmp)) -: 1044: { -: 1045: // We've been here before if we've recorded current_ptr in one of these -: 1046: // two places: 667: 1047: if (current_ptr == info->dst_ptr_leading_to_static_ptr || 612: 1048: current_ptr == info->dst_ptr_not_leading_to_static_ptr) -: 1049: { -: 1050: // We've seen this node before, and therefore have already searched -: 1051: // its base classes above. -: 1052: // Update path to here that is "most public". 115: 1053: if (path_below == public_path) 115: 1054: info->path_dynamic_ptr_to_dst_ptr = public_path; 115: 1055: } -: 1056: else // We have haven't been here before -: 1057: { -: 1058: // Record the access path that got us here -: 1059: // If there is more than one dst_type this path doesn't matter. 552: 1060: info->path_dynamic_ptr_to_dst_ptr = path_below; 552: 1061: bool does_dst_type_point_to_our_static_type = false; -: 1062: // Only search above here if dst_type derives from static_type, or -: 1063: // if it is unknown if dst_type derives from static_type. 552: 1064: if (info->is_dst_type_derived_from_static_type != no) -: 1065: { -: 1066: // Set up flags to record results from all base classes 552: 1067: bool is_dst_type_derived_from_static_type = false; -: 1068: -: 1069: // We've found a dst_type with a potentially public path to here. -: 1070: // We have to assume the path is public because it may become -: 1071: // public later (if we get back to here with a public path). -: 1072: // We can stop looking above if: -: 1073: // 1. We've found a public path to (static_ptr, static_type). -: 1074: // 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type. -: 1075: // This is detected at the (static_ptr, static_type). -: 1076: // 3. We can prove that there is no public path to (static_ptr, static_type) -: 1077: // above here. 552: 1078: const Iter e = __base_info + __base_count; 864: 1079: for (Iter p = __base_info; p < e; ++p) -: 1080: { -: 1081: // Zero out found flags 762: 1082: info->found_our_static_ptr = false; 762: 1083: info->found_any_static_type = false; 762: 1084: p->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp); 762: 1085: if (info->search_done) 3: 1086: break; 759: 1087: if (info->found_any_static_type) -: 1088: { 585: 1089: is_dst_type_derived_from_static_type = true; 585: 1090: if (info->found_our_static_ptr) -: 1091: { 374: 1092: does_dst_type_point_to_our_static_type = true; -: 1093: // If we found what we're looking for, stop looking above. 374: 1094: if (info->path_dst_ptr_to_static_ptr == public_path) 312: 1095: break; -: 1096: // We found a private path to (static_ptr, static_type) -: 1097: // If there is no diamond then there is only one path -: 1098: // to (static_ptr, static_type) and we just found it. 62: 1099: if (!(__flags & __diamond_shaped_mask)) 39: 1100: break; 23: 1101: } -: 1102: else -: 1103: { -: 1104: // If we found a static_type that isn't the one we're looking -: 1105: // for, and if there are no repeated types above here, -: 1106: // then stop looking. 211: 1107: if (!(__flags & __non_diamond_repeat_mask)) 96: 1108: break; -: 1109: } 138: 1110: } 312: 1111: } -: 1112: // If we found no static_type,s then dst_type doesn't derive -: 1113: // from static_type, else it does. Record this result so that -: 1114: // next time we hit a dst_type we will know not to search above -: 1115: // it if it doesn't derive from static_type. 552: 1116: if (is_dst_type_derived_from_static_type) 499: 1117: info->is_dst_type_derived_from_static_type = yes; -: 1118: else 53: 1119: info->is_dst_type_derived_from_static_type = no; 552: 1120: } 552: 1121: if (!does_dst_type_point_to_our_static_type) -: 1122: { -: 1123: // We found a dst_type that doesn't point to (static_ptr, static_type) -: 1124: // So record the address of this dst_ptr and increment the -: 1125: // count of the number of such dst_types found in the tree. 185: 1126: info->dst_ptr_not_leading_to_static_ptr = current_ptr; 185: 1127: info->number_to_dst_ptr += 1; -: 1128: // If there exists another dst with a private path to -: 1129: // (static_ptr, static_type), then the cast from -: 1130: // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous, -: 1131: // so stop search. 185: 1132: if (info->number_to_static_ptr == 1 && 1: 1133: info->path_dst_ptr_to_static_ptr == not_public_path) 1: 1134: info->search_done = true; 185: 1135: } -: 1136: } 667: 1137: } -: 1138: else -: 1139: { -: 1140: // This is not a static_type and not a dst_type. 4122: 1141: const Iter e = __base_info + __base_count; 4122: 1142: Iter p = __base_info; 4122: 1143: p->search_below_dst(info, current_ptr, path_below, use_strcmp); 4122: 1144: if (++p < e) -: 1145: { 3664: 1146: if ((__flags & __diamond_shaped_mask) || info->number_to_static_ptr == 1) -: 1147: { -: 1148: // If there are multiple paths to a base above from here, or if -: 1149: // a dst_type pointing to (static_ptr, static_type) has been found, -: 1150: // then there is no way to break out of this loop early unless -: 1151: // something below detects the search is done. 2627: 1152: do -: 1153: { 2635: 1154: if (info->search_done) #####: 1155: break; 2635: 1156: p->search_below_dst(info, current_ptr, path_below, use_strcmp); 2635: 1157: } while (++p < e); 2627: 1158: } 1037: 1159: else if (__flags & __non_diamond_repeat_mask) -: 1160: { -: 1161: // There are not multiple paths to any base class from here and a -: 1162: // dst_type pointing to (static_ptr, static_type) has not yet been -: 1163: // found. 24: 1164: do -: 1165: { 28: 1166: if (info->search_done) #####: 1167: break; -: 1168: // If we just found a dst_type with a public path to (static_ptr, static_type), -: 1169: // then the only reason to continue the search is to make sure -: 1170: // no other dst_type points to (static_ptr, static_type). -: 1171: // If !diamond, then we don't need to search here. 28: 1172: if (info->number_to_static_ptr == 1 && #####: 1173: info->path_dst_ptr_to_static_ptr == public_path) #####: 1174: break; 28: 1175: p->search_below_dst(info, current_ptr, path_below, use_strcmp); 28: 1176: } while (++p < e); 24: 1177: } -: 1178: else -: 1179: { -: 1180: // There are no repeated types above this node. -: 1181: // There are no nodes with multiple parents above this node. -: 1182: // no dst_type has been found to (static_ptr, static_type) 1013: 1183: do -: 1184: { 1013: 1185: if (info->search_done) #####: 1186: break; -: 1187: // If we just found a dst_type with a public path to (static_ptr, static_type), -: 1188: // then the only reason to continue the search is to make sure sure -: 1189: // no other dst_type points to (static_ptr, static_type). -: 1190: // If !diamond, then we don't need to search here. -: 1191: // if we just found a dst_type with a private path to (static_ptr, static_type), -: 1192: // then we're only looking for a public path to (static_ptr, static_type) -: 1193: // and to check for other dst_types. -: 1194: // If !diamond & !repeat, then there is not a pointer to (static_ptr, static_type) -: 1195: // and not a dst_type under here. 1013: 1196: if (info->number_to_static_ptr == 1) #####: 1197: break; 1013: 1198: p->search_below_dst(info, current_ptr, path_below, use_strcmp); 1013: 1199: } while (++p < e); -: 1200: } 3664: 1201: } -: 1202: } 5103: 1203:} -: 1204: -: 1205:// This is the same algorithm as __vmi_class_type_info::search_below_dst but -: 1206:// simplified to the case that there is only a single base class. -: 1207:void 9684: 1208:__si_class_type_info::search_below_dst(__dynamic_cast_info* info, -: 1209: const void* current_ptr, -: 1210: int path_below, -: 1211: bool use_strcmp) const -: 1212:{ 9684: 1213: if (is_equal(this, info->static_type, use_strcmp)) 2732: 1214: process_static_type_below_dst(info, current_ptr, path_below); 6952: 1215: else if (is_equal(this, info->dst_type, use_strcmp)) -: 1216: { -: 1217: // We've been here before if we've recorded current_ptr in one of these -: 1218: // two places: 345: 1219: if (current_ptr == info->dst_ptr_leading_to_static_ptr || 321: 1220: current_ptr == info->dst_ptr_not_leading_to_static_ptr) -: 1221: { -: 1222: // We've seen this node before, and therefore have already searched -: 1223: // its base classes above. -: 1224: // Update path to here that is "most public". 72: 1225: if (path_below == public_path) 72: 1226: info->path_dynamic_ptr_to_dst_ptr = public_path; 72: 1227: } -: 1228: else // We have haven't been here before -: 1229: { -: 1230: // Record the access path that got us here -: 1231: // If there is more than one dst_type this path doesn't matter. 273: 1232: info->path_dynamic_ptr_to_dst_ptr = path_below; 273: 1233: bool does_dst_type_point_to_our_static_type = false; -: 1234: // Only search above here if dst_type derives from static_type, or -: 1235: // if it is unknown if dst_type derives from static_type. 273: 1236: if (info->is_dst_type_derived_from_static_type != no) -: 1237: { -: 1238: // Set up flags to record results from all base classes 271: 1239: bool is_dst_type_derived_from_static_type = false; -: 1240: // Zero out found flags 271: 1241: info->found_our_static_ptr = false; 271: 1242: info->found_any_static_type = false; 271: 1243: __base_type->search_above_dst(info, current_ptr, current_ptr, public_path, use_strcmp); 271: 1244: if (info->found_any_static_type) -: 1245: { 132: 1246: is_dst_type_derived_from_static_type = true; 132: 1247: if (info->found_our_static_ptr) 51: 1248: does_dst_type_point_to_our_static_type = true; 132: 1249: } -: 1250: // If we found no static_type,s then dst_type doesn't derive -: 1251: // from static_type, else it does. Record this result so that -: 1252: // next time we hit a dst_type we will know not to search above -: 1253: // it if it doesn't derive from static_type. 271: 1254: if (is_dst_type_derived_from_static_type) 132: 1255: info->is_dst_type_derived_from_static_type = yes; -: 1256: else 139: 1257: info->is_dst_type_derived_from_static_type = no; 271: 1258: } 273: 1259: if (!does_dst_type_point_to_our_static_type) -: 1260: { -: 1261: // We found a dst_type that doesn't point to (static_ptr, static_type) -: 1262: // So record the address of this dst_ptr and increment the -: 1263: // count of the number of such dst_types found in the tree. 222: 1264: info->dst_ptr_not_leading_to_static_ptr = current_ptr; 222: 1265: info->number_to_dst_ptr += 1; -: 1266: // If there exists another dst with a private path to -: 1267: // (static_ptr, static_type), then the cast from -: 1268: // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous. 222: 1269: if (info->number_to_static_ptr == 1 && #####: 1270: info->path_dst_ptr_to_static_ptr == not_public_path) #####: 1271: info->search_done = true; 222: 1272: } -: 1273: } 345: 1274: } -: 1275: else -: 1276: { -: 1277: // This is not a static_type and not a dst_type 6607: 1278: __base_type->search_below_dst(info, current_ptr, path_below, use_strcmp); -: 1279: } 9684: 1280:} -: 1281: -: 1282:// This is the same algorithm as __vmi_class_type_info::search_below_dst but -: 1283:// simplified to the case that there is no base class. -: 1284:void 3621: 1285:__class_type_info::search_below_dst(__dynamic_cast_info* info, -: 1286: const void* current_ptr, -: 1287: int path_below, -: 1288: bool use_strcmp) const -: 1289:{ 3621: 1290: if (is_equal(this, info->static_type, use_strcmp)) 1701: 1291: process_static_type_below_dst(info, current_ptr, path_below); 1920: 1292: else if (is_equal(this, info->dst_type, use_strcmp)) -: 1293: { -: 1294: // We've been here before if we've recorded current_ptr in one of these -: 1295: // two places: 114: 1296: if (current_ptr == info->dst_ptr_leading_to_static_ptr || 114: 1297: current_ptr == info->dst_ptr_not_leading_to_static_ptr) -: 1298: { -: 1299: // We've seen this node before, and therefore have already searched -: 1300: // its base classes above. -: 1301: // Update path to here that is "most public". 16: 1302: if (path_below == public_path) 12: 1303: info->path_dynamic_ptr_to_dst_ptr = public_path; 16: 1304: } -: 1305: else // We have haven't been here before -: 1306: { -: 1307: // Record the access path that got us here -: 1308: // If there is more than one dst_type this path doesn't matter. 98: 1309: info->path_dynamic_ptr_to_dst_ptr = path_below; -: 1310: // We found a dst_type that doesn't point to (static_ptr, static_type) -: 1311: // So record the address of this dst_ptr and increment the -: 1312: // count of the number of such dst_types found in the tree. 98: 1313: info->dst_ptr_not_leading_to_static_ptr = current_ptr; 98: 1314: info->number_to_dst_ptr += 1; -: 1315: // If there exists another dst with a private path to -: 1316: // (static_ptr, static_type), then the cast from -: 1317: // (dynamic_ptr, dynamic_type) to dst_type is now ambiguous. 98: 1318: if (info->number_to_static_ptr == 1 && #####: 1319: info->path_dst_ptr_to_static_ptr == not_public_path) #####: 1320: info->search_done = true; -: 1321: // We found that dst_type does not derive from static_type 98: 1322: info->is_dst_type_derived_from_static_type = no; -: 1323: } 114: 1324: } 3621: 1325:} -: 1326: -: 1327:// Call this function when searching above a dst_type node. This function searches -: 1328:// for a public path to (static_ptr, static_type). -: 1329:// This function is guaranteed not to find a node of type dst_type. -: 1330:// Theoretically this is a very simple function which just stops if it finds a -: 1331:// static_type node: All the hoopla surrounding the search code is doing -: 1332:// nothing but looking for excuses to stop the search prematurely (break out of -: 1333:// the for-loop). That is, the algorithm below is simply an optimization of this: -: 1334:// void -: 1335:// __vmi_class_type_info::search_above_dst(__dynamic_cast_info* info, -: 1336:// const void* dst_ptr, -: 1337:// const void* current_ptr, -: 1338:// int path_below) const -: 1339:// { -: 1340:// if (this == info->static_type) -: 1341:// process_static_type_above_dst(info, dst_ptr, current_ptr, path_below); -: 1342:// else -: 1343:// { -: 1344:// typedef const __base_class_type_info* Iter; -: 1345:// // This is not a static_type and not a dst_type -: 1346:// for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p) -: 1347:// { -: 1348:// p->search_above_dst(info, dst_ptr, current_ptr, public_path); -: 1349:// // break out early here if you can detect it doesn't matter if you do -: 1350:// } -: 1351:// } -: 1352:// } -: 1353:void 3916: 1354:__vmi_class_type_info::search_above_dst(__dynamic_cast_info* info, -: 1355: const void* dst_ptr, -: 1356: const void* current_ptr, -: 1357: int path_below, -: 1358: bool use_strcmp) const -: 1359:{ 3916: 1360: if (is_equal(this, info->static_type, use_strcmp)) 398: 1361: process_static_type_above_dst(info, dst_ptr, current_ptr, path_below); -: 1362: else -: 1363: { -: 1364: typedef const __base_class_type_info* Iter; -: 1365: // This is not a static_type and not a dst_type -: 1366: // Save flags so they can be restored when returning to nodes below. 3518: 1367: bool found_our_static_ptr = info->found_our_static_ptr; 3518: 1368: bool found_any_static_type = info->found_any_static_type; -: 1369: // We've found a dst_type below with a path to here. If the path -: 1370: // to here is not public, there may be another path to here that -: 1371: // is public. So we have to assume that the path to here is public. -: 1372: // We can stop looking above if: -: 1373: // 1. We've found a public path to (static_ptr, static_type). -: 1374: // 2. We've found an ambiguous cast from (static_ptr, static_type) to a dst_type. -: 1375: // This is detected at the (static_ptr, static_type). -: 1376: // 3. We can prove that there is no public path to (static_ptr, static_type) -: 1377: // above here. 3518: 1378: const Iter e = __base_info + __base_count; 3518: 1379: Iter p = __base_info; -: 1380: // Zero out found flags 3518: 1381: info->found_our_static_ptr = false; 3518: 1382: info->found_any_static_type = false; 3518: 1383: p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp); 3518: 1384: found_our_static_ptr |= info->found_our_static_ptr; 3518: 1385: found_any_static_type |= info->found_any_static_type; 3518: 1386: if (++p < e) -: 1387: { 3120: 1388: do -: 1389: { 3120: 1390: if (info->search_done) 494: 1391: break; 2626: 1392: if (info->found_our_static_ptr) -: 1393: { -: 1394: // If we found what we're looking for, stop looking above. 356: 1395: if (info->path_dst_ptr_to_static_ptr == public_path) 254: 1396: break; -: 1397: // We found a private path to (static_ptr, static_type) -: 1398: // If there is no diamond then there is only one path -: 1399: // to (static_ptr, static_type) from here and we just found it. 102: 1400: if (!(__flags & __diamond_shaped_mask)) 29: 1401: break; 73: 1402: } 2270: 1403: else if (info->found_any_static_type) -: 1404: { -: 1405: // If we found a static_type that isn't the one we're looking -: 1406: // for, and if there are no repeated types above here, -: 1407: // then stop looking. 761: 1408: if (!(__flags & __non_diamond_repeat_mask)) 209: 1409: break; 552: 1410: } -: 1411: // Zero out found flags 2134: 1412: info->found_our_static_ptr = false; 2134: 1413: info->found_any_static_type = false; 2134: 1414: p->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp); 2134: 1415: found_our_static_ptr |= info->found_our_static_ptr; 2134: 1416: found_any_static_type |= info->found_any_static_type; 2134: 1417: } while (++p < e); 3120: 1418: } -: 1419: // Restore flags 3518: 1420: info->found_our_static_ptr = found_our_static_ptr; 3518: 1421: info->found_any_static_type = found_any_static_type; -: 1422: } 3916: 1423:} -: 1424: -: 1425:// This is the same algorithm as __vmi_class_type_info::search_above_dst but -: 1426:// simplified to the case that there is only a single base class. -: 1427:void 49827: 1428:__si_class_type_info::search_above_dst(__dynamic_cast_info* info, -: 1429: const void* dst_ptr, -: 1430: const void* current_ptr, -: 1431: int path_below, -: 1432: bool use_strcmp) const -: 1433:{ 49827: 1434: if (is_equal(this, info->static_type, use_strcmp)) 20800: 1435: process_static_type_above_dst(info, dst_ptr, current_ptr, path_below); -: 1436: else 29027: 1437: __base_type->search_above_dst(info, dst_ptr, current_ptr, path_below, use_strcmp); 49827: 1438:} -: 1439: -: 1440:// This is the same algorithm as __vmi_class_type_info::search_above_dst but -: 1441:// simplified to the case that there is no base class. -: 1442:void 5915: 1443:__class_type_info::search_above_dst(__dynamic_cast_info* info, -: 1444: const void* dst_ptr, -: 1445: const void* current_ptr, -: 1446: int path_below, -: 1447: bool use_strcmp) const -: 1448:{ 5915: 1449: if (is_equal(this, info->static_type, use_strcmp)) 1130: 1450: process_static_type_above_dst(info, dst_ptr, current_ptr, path_below); 5915: 1451:} -: 1452: -: 1453:// The search functions for __base_class_type_info are simply convenience -: 1454:// functions for adjusting the current_ptr and path_below as the search is -: 1455:// passed up to the base class node. -: 1456: -: 1457:void 6414: 1458:__base_class_type_info::search_above_dst(__dynamic_cast_info* info, -: 1459: const void* dst_ptr, -: 1460: const void* current_ptr, -: 1461: int path_below, -: 1462: bool use_strcmp) const -: 1463:{ 6414: 1464: ptrdiff_t offset_to_base = __offset_flags >> __offset_shift; 6414: 1465: if (__offset_flags & __virtual_mask) -: 1466: { 1878: 1467: const char* vtable = *static_cast(current_ptr); 1878: 1468: offset_to_base = update_offset_to_base(vtable, offset_to_base); 1878: 1469: } 12828: 1470: __base_type->search_above_dst(info, dst_ptr, 6414: 1471: static_cast(current_ptr) + offset_to_base, 6414: 1472: (__offset_flags & __public_mask) ? 5955: 1473: path_below : -: 1474: not_public_path, 6414: 1475: use_strcmp); 6414: 1476:} -: 1477: -: 1478:void 7798: 1479:__base_class_type_info::search_below_dst(__dynamic_cast_info* info, -: 1480: const void* current_ptr, -: 1481: int path_below, -: 1482: bool use_strcmp) const -: 1483:{ 7798: 1484: ptrdiff_t offset_to_base = __offset_flags >> __offset_shift; 7798: 1485: if (__offset_flags & __virtual_mask) -: 1486: { 2552: 1487: const char* vtable = *static_cast(current_ptr); 2552: 1488: offset_to_base = update_offset_to_base(vtable, offset_to_base); 2552: 1489: } 15596: 1490: __base_type->search_below_dst(info, 7798: 1491: static_cast(current_ptr) + offset_to_base, 7798: 1492: (__offset_flags & __public_mask) ? 7389: 1493: path_below : -: 1494: not_public_path, 7798: 1495: use_strcmp); 7798: 1496:} -: 1497: -: 1498:} // __cxxabiv1