1 // Methods for type_info for -*- C++ -*- Run Time Type Identification. 2 // Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 3 // 2003, 2004, 2005, 2006, 2007 4 // Free Software Foundation 5 // 6 // This file is part of GCC. 7 // 8 // GCC is free software; you can redistribute it and/or modify 9 // it under the terms of the GNU General Public License as published by 10 // the Free Software Foundation; either version 2, or (at your option) 11 // any later version. 12 13 // GCC is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 18 // You should have received a copy of the GNU General Public License 19 // along with GCC; see the file COPYING. If not, write to 20 // the Free Software Foundation, 51 Franklin Street, Fifth Floor, 21 // Boston, MA 02110-1301, USA. 22 23 // As a special exception, you may use this file as part of a free software 24 // library without restriction. Specifically, if other files instantiate 25 // templates or use macros or inline functions from this file, or you compile 26 // this file and link it with other files to produce an executable, this 27 // file does not by itself cause the resulting executable to be covered by 28 // the GNU General Public License. This exception does not however 29 // invalidate any other reasons why the executable file might be covered by 30 // the GNU General Public License. 31 32 #include <bits/c++config.h> 33 #include <cstddef> 34 #include "tinfo.h" 35 #include "new" // for placement new 36 37 // This file contains the minimal working set necessary to link with code 38 // that uses virtual functions and -frtti but does not actually use RTTI 39 // functionality. 40 41 std::type_info:: 42 ~type_info () 43 { } 44 45 std::bad_cast::~bad_cast() throw() { } 46 std::bad_typeid::~bad_typeid() throw() { } 47 48 const char* 49 std::bad_cast::what() const throw() 50 { 51 return "std::bad_cast"; 52 } 53 54 const char* 55 std::bad_typeid::what() const throw() 56 { 57 return "std::bad_typeid"; 58 } 59 60 #if !__GXX_MERGED_TYPEINFO_NAMES 61 62 // We can't rely on common symbols being shared between shared objects. 63 bool std::type_info:: 64 operator== (const std::type_info& arg) const 65 { 66 return (&arg == this) || (__builtin_strcmp (name (), arg.name ()) == 0); 67 } 68 69 #endif 70 71 namespace std { 72 73 // return true if this is a type_info for a pointer type 74 bool type_info:: 75 __is_pointer_p () const 76 { 77 return false; 78 } 79 80 // return true if this is a type_info for a function type 81 bool type_info:: 82 __is_function_p () const 83 { 84 return false; 85 } 86 87 // try and catch a thrown object. 88 bool type_info:: 89 __do_catch (const type_info *thr_type, void **, unsigned) const 90 { 91 return *this == *thr_type; 92 } 93 94 // upcast from this type to the target. __class_type_info will override 95 bool type_info:: 96 __do_upcast (const abi::__class_type_info *, void **) const 97 { 98 return false; 99 } 100 101 } 102 103 namespace { 104 105 using namespace std; 106 using namespace abi; 107 108 // Initial part of a vtable, this structure is used with offsetof, so we don't 109 // have to keep alignments consistent manually. 110 struct vtable_prefix 111 { 112 // Offset to most derived object. 113 ptrdiff_t whole_object; 114 115 // Additional padding if necessary. 116 #ifdef _GLIBCXX_VTABLE_PADDING 117 ptrdiff_t padding1; 118 #endif 119 120 // Pointer to most derived type_info. 121 const __class_type_info *whole_type; 122 123 // Additional padding if necessary. 124 #ifdef _GLIBCXX_VTABLE_PADDING 125 ptrdiff_t padding2; 126 #endif 127 128 // What a class's vptr points to. 129 const void *origin; 130 }; 131 132 template <typename T> 133 inline const T * 134 adjust_pointer (const void *base, ptrdiff_t offset) 135 { 136 return reinterpret_cast <const T *> 137 (reinterpret_cast <const char *> (base) + offset); 138 } 139 140 // ADDR is a pointer to an object. Convert it to a pointer to a base, 141 // using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base. 142 inline void const * 143 convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset) 144 { 145 if (is_virtual) 146 { 147 const void *vtable = *static_cast <const void *const *> (addr); 148 149 offset = *adjust_pointer<ptrdiff_t> (vtable, offset); 150 } 151 152 return adjust_pointer<void> (addr, offset); 153 } 154 155 // some predicate functions for __class_type_info::__sub_kind 156 inline bool contained_p (__class_type_info::__sub_kind access_path) 157 { 158 return access_path >= __class_type_info::__contained_mask; 159 } 160 inline bool public_p (__class_type_info::__sub_kind access_path) 161 { 162 return access_path & __class_type_info::__contained_public_mask; 163 } 164 inline bool virtual_p (__class_type_info::__sub_kind access_path) 165 { 166 return (access_path & __class_type_info::__contained_virtual_mask); 167 } 168 inline bool contained_public_p (__class_type_info::__sub_kind access_path) 169 { 170 return ((access_path & __class_type_info::__contained_public) 171 == __class_type_info::__contained_public); 172 } 173 inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path) 174 { 175 return ((access_path & __class_type_info::__contained_public) 176 == __class_type_info::__contained_mask); 177 } 178 inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path) 179 { 180 return ((access_path & (__class_type_info::__contained_mask 181 | __class_type_info::__contained_virtual_mask)) 182 == __class_type_info::__contained_mask); 183 } 184 185 static const __class_type_info *const nonvirtual_base_type = 186 static_cast <const __class_type_info *> (0) + 1; 187 188 } // namespace 189 190 namespace __cxxabiv1 191 { 192 193 __class_type_info:: 194 ~__class_type_info () 195 {} 196 197 __si_class_type_info:: 198 ~__si_class_type_info () 199 {} 200 201 __vmi_class_type_info:: 202 ~__vmi_class_type_info () 203 {} 204 205 // __upcast_result is used to hold information during traversal of a class 206 // hierarchy when catch matching. 207 struct __class_type_info::__upcast_result 208 { 209 const void *dst_ptr; // pointer to caught object 210 __sub_kind part2dst; // path from current base to target 211 int src_details; // hints about the source type hierarchy 212 const __class_type_info *base_type; // where we found the target, 213 // if in vbase the __class_type_info of vbase 214 // if a non-virtual base then 1 215 // else NULL 216 __upcast_result (int d) 217 :dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL) 218 {} 219 }; 220 221 // __dyncast_result is used to hold information during traversal of a class 222 // hierarchy when dynamic casting. 223 struct __class_type_info::__dyncast_result 224 { 225 const void *dst_ptr; // pointer to target object or NULL 226 __sub_kind whole2dst; // path from most derived object to target 227 __sub_kind whole2src; // path from most derived object to sub object 228 __sub_kind dst2src; // path from target to sub object 229 int whole_details; // details of the whole class hierarchy 230 231 __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask) 232 :dst_ptr (NULL), whole2dst (__unknown), 233 whole2src (__unknown), dst2src (__unknown), 234 whole_details (details_) 235 {} 236 237 protected: 238 __dyncast_result(const __dyncast_result&); 239 240 __dyncast_result& 241 operator=(const __dyncast_result&); 242 }; 243 244 bool __class_type_info:: 245 __do_catch (const type_info *thr_type, 246 void **thr_obj, 247 unsigned outer) const 248 { 249 if (*this == *thr_type) 250 return true; 251 if (outer >= 4) 252 // Neither `A' nor `A *'. 253 return false; 254 return thr_type->__do_upcast (this, thr_obj); 255 } 256 257 bool __class_type_info:: 258 __do_upcast (const __class_type_info *dst_type, 259 void **obj_ptr) const 260 { 261 __upcast_result result (__vmi_class_type_info::__flags_unknown_mask); 262 263 __do_upcast (dst_type, *obj_ptr, result); 264 if (!contained_public_p (result.part2dst)) 265 return false; 266 *obj_ptr = const_cast <void *> (result.dst_ptr); 267 return true; 268 } 269 270 inline __class_type_info::__sub_kind __class_type_info:: 271 __find_public_src (ptrdiff_t src2dst, 272 const void *obj_ptr, 273 const __class_type_info *src_type, 274 const void *src_ptr) const 275 { 276 if (src2dst >= 0) 277 return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr 278 ? __contained_public : __not_contained; 279 if (src2dst == -2) 280 return __not_contained; 281 return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr); 282 } 283 284 __class_type_info::__sub_kind __class_type_info:: 285 __do_find_public_src (ptrdiff_t, 286 const void *obj_ptr, 287 const __class_type_info *, 288 const void *src_ptr) const 289 { 290 if (src_ptr == obj_ptr) 291 // Must be our type, as the pointers match. 292 return __contained_public; 293 return __not_contained; 294 } 295 296 __class_type_info::__sub_kind __si_class_type_info:: 297 __do_find_public_src (ptrdiff_t src2dst, 298 const void *obj_ptr, 299 const __class_type_info *src_type, 300 const void *src_ptr) const 301 { 302 if (src_ptr == obj_ptr && *this == *src_type) 303 return __contained_public; 304 return __base_type->__do_find_public_src (src2dst, obj_ptr, src_type, src_ptr); 305 } 306 307 __class_type_info::__sub_kind __vmi_class_type_info:: 308 __do_find_public_src (ptrdiff_t src2dst, 309 const void *obj_ptr, 310 const __class_type_info *src_type, 311 const void *src_ptr) const 312 { 313 if (obj_ptr == src_ptr && *this == *src_type) 314 return __contained_public; 315 316 for (std::size_t i = __base_count; i--;) 317 { 318 if (!__base_info[i].__is_public_p ()) 319 continue; // Not public, can't be here. 320 321 const void *base = obj_ptr; 322 ptrdiff_t offset = __base_info[i].__offset (); 323 bool is_virtual = __base_info[i].__is_virtual_p (); 324 325 if (is_virtual) 326 { 327 if (src2dst == -3) 328 continue; // Not a virtual base, so can't be here. 329 } 330 base = convert_to_base (base, is_virtual, offset); 331 332 __sub_kind base_kind = __base_info[i].__base_type->__do_find_public_src 333 (src2dst, base, src_type, src_ptr); 334 if (contained_p (base_kind)) 335 { 336 if (is_virtual) 337 base_kind = __sub_kind (base_kind | __contained_virtual_mask); 338 return base_kind; 339 } 340 } 341 342 return __not_contained; 343 } 344 345 bool __class_type_info:: 346 __do_dyncast (ptrdiff_t, 347 __sub_kind access_path, 348 const __class_type_info *dst_type, 349 const void *obj_ptr, 350 const __class_type_info *src_type, 351 const void *src_ptr, 352 __dyncast_result &__restrict result) const 353 { 354 if (obj_ptr == src_ptr && *this == *src_type) 355 { 356 // The src object we started from. Indicate how we are accessible from 357 // the most derived object. 358 result.whole2src = access_path; 359 return false; 360 } 361 if (*this == *dst_type) 362 { 363 result.dst_ptr = obj_ptr; 364 result.whole2dst = access_path; 365 result.dst2src = __not_contained; 366 return false; 367 } 368 return false; 369 } 370 371 bool __si_class_type_info:: 372 __do_dyncast (ptrdiff_t src2dst, 373 __sub_kind access_path, 374 const __class_type_info *dst_type, 375 const void *obj_ptr, 376 const __class_type_info *src_type, 377 const void *src_ptr, 378 __dyncast_result &__restrict result) const 379 { 380 if (*this == *dst_type) 381 { 382 result.dst_ptr = obj_ptr; 383 result.whole2dst = access_path; 384 if (src2dst >= 0) 385 result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr 386 ? __contained_public : __not_contained; 387 else if (src2dst == -2) 388 result.dst2src = __not_contained; 389 return false; 390 } 391 if (obj_ptr == src_ptr && *this == *src_type) 392 { 393 // The src object we started from. Indicate how we are accessible from 394 // the most derived object. 395 result.whole2src = access_path; 396 return false; 397 } 398 return __base_type->__do_dyncast (src2dst, access_path, dst_type, obj_ptr, 399 src_type, src_ptr, result); 400 } 401 402 // This is a big hairy function. Although the run-time behaviour of 403 // dynamic_cast is simple to describe, it gives rise to some non-obvious 404 // behaviour. We also desire to determine as early as possible any definite 405 // answer we can get. Because it is unknown what the run-time ratio of 406 // succeeding to failing dynamic casts is, we do not know in which direction 407 // to bias any optimizations. To that end we make no particular effort towards 408 // early fail answers or early success answers. Instead we try to minimize 409 // work by filling in things lazily (when we know we need the information), 410 // and opportunisticly take early success or failure results. 411 bool __vmi_class_type_info:: 412 __do_dyncast (ptrdiff_t src2dst, 413 __sub_kind access_path, 414 const __class_type_info *dst_type, 415 const void *obj_ptr, 416 const __class_type_info *src_type, 417 const void *src_ptr, 418 __dyncast_result &__restrict result) const 419 { 420 if (result.whole_details & __flags_unknown_mask) 421 result.whole_details = __flags; 422 423 if (obj_ptr == src_ptr && *this == *src_type) 424 { 425 // The src object we started from. Indicate how we are accessible from 426 // the most derived object. 427 result.whole2src = access_path; 428 return false; 429 } 430 if (*this == *dst_type) 431 { 432 result.dst_ptr = obj_ptr; 433 result.whole2dst = access_path; 434 if (src2dst >= 0) 435 result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr 436 ? __contained_public : __not_contained; 437 else if (src2dst == -2) 438 result.dst2src = __not_contained; 439 return false; 440 } 441 442 bool result_ambig = false; 443 for (std::size_t i = __base_count; i--;) 444 { 445 __dyncast_result result2 (result.whole_details); 446 void const *base = obj_ptr; 447 __sub_kind base_access = access_path; 448 ptrdiff_t offset = __base_info[i].__offset (); 449 bool is_virtual = __base_info[i].__is_virtual_p (); 450 451 if (is_virtual) 452 base_access = __sub_kind (base_access | __contained_virtual_mask); 453 base = convert_to_base (base, is_virtual, offset); 454 455 if (!__base_info[i].__is_public_p ()) 456 { 457 if (src2dst == -2 && 458 !(result.whole_details 459 & (__non_diamond_repeat_mask | __diamond_shaped_mask))) 460 // The hierarchy has no duplicate bases (which might ambiguate 461 // things) and where we started is not a public base of what we 462 // want (so it cannot be a downcast). There is nothing of interest 463 // hiding in a non-public base. 464 continue; 465 base_access = __sub_kind (base_access & ~__contained_public_mask); 466 } 467 468 bool result2_ambig 469 = __base_info[i].__base_type->__do_dyncast (src2dst, base_access, 470 dst_type, base, 471 src_type, src_ptr, result2); 472 result.whole2src = __sub_kind (result.whole2src | result2.whole2src); 473 if (result2.dst2src == __contained_public 474 || result2.dst2src == __contained_ambig) 475 { 476 result.dst_ptr = result2.dst_ptr; 477 result.whole2dst = result2.whole2dst; 478 result.dst2src = result2.dst2src; 479 // Found a downcast which can't be bettered or an ambiguous downcast 480 // which can't be disambiguated 481 return result2_ambig; 482 } 483 484 if (!result_ambig && !result.dst_ptr) 485 { 486 // Not found anything yet. 487 result.dst_ptr = result2.dst_ptr; 488 result.whole2dst = result2.whole2dst; 489 result_ambig = result2_ambig; 490 if (result.dst_ptr && result.whole2src != __unknown 491 && !(__flags & __non_diamond_repeat_mask)) 492 // Found dst and src and we don't have repeated bases. 493 return result_ambig; 494 } 495 else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr) 496 { 497 // Found at same address, must be via virtual. Pick the most 498 // accessible path. 499 result.whole2dst = 500 __sub_kind (result.whole2dst | result2.whole2dst); 501 } 502 else if ((result.dst_ptr != 0 & result2.dst_ptr != 0) 503 || (result.dst_ptr != 0 & result2_ambig) 504 || (result2.dst_ptr != 0 & result_ambig)) 505 { 506 // Found two different DST_TYPE bases, or a valid one and a set of 507 // ambiguous ones, must disambiguate. See whether SRC_PTR is 508 // contained publicly within one of the non-ambiguous choices. If it 509 // is in only one, then that's the choice. If it is in both, then 510 // we're ambiguous and fail. If it is in neither, we're ambiguous, 511 // but don't yet fail as we might later find a third base which does 512 // contain SRC_PTR. 513 514 __sub_kind new_sub_kind = result2.dst2src; 515 __sub_kind old_sub_kind = result.dst2src; 516 517 if (contained_p (result.whole2src) 518 && (!virtual_p (result.whole2src) 519 || !(result.whole_details & __diamond_shaped_mask))) 520 { 521 // We already found SRC_PTR as a base of most derived, and 522 // either it was non-virtual, or the whole hierarchy is 523 // not-diamond shaped. Therefore if it is in either choice, it 524 // can only be in one of them, and we will already know. 525 if (old_sub_kind == __unknown) 526 old_sub_kind = __not_contained; 527 if (new_sub_kind == __unknown) 528 new_sub_kind = __not_contained; 529 } 530 else 531 { 532 if (old_sub_kind >= __not_contained) 533 ;// already calculated 534 else if (contained_p (new_sub_kind) 535 && (!virtual_p (new_sub_kind) 536 || !(__flags & __diamond_shaped_mask))) 537 // Already found inside the other choice, and it was 538 // non-virtual or we are not diamond shaped. 539 old_sub_kind = __not_contained; 540 else 541 old_sub_kind = dst_type->__find_public_src 542 (src2dst, result.dst_ptr, src_type, src_ptr); 543 544 if (new_sub_kind >= __not_contained) 545 ;// already calculated 546 else if (contained_p (old_sub_kind) 547 && (!virtual_p (old_sub_kind) 548 || !(__flags & __diamond_shaped_mask))) 549 // Already found inside the other choice, and it was 550 // non-virtual or we are not diamond shaped. 551 new_sub_kind = __not_contained; 552 else 553 new_sub_kind = dst_type->__find_public_src 554 (src2dst, result2.dst_ptr, src_type, src_ptr); 555 } 556 557 // Neither sub_kind can be contained_ambig -- we bail out early 558 // when we find those. 559 if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind))) 560 { 561 // Only on one choice, not ambiguous. 562 if (contained_p (new_sub_kind)) 563 { 564 // Only in new. 565 result.dst_ptr = result2.dst_ptr; 566 result.whole2dst = result2.whole2dst; 567 result_ambig = false; 568 old_sub_kind = new_sub_kind; 569 } 570 result.dst2src = old_sub_kind; 571 if (public_p (result.dst2src)) 572 return false; // Can't be an ambiguating downcast for later discovery. 573 if (!virtual_p (result.dst2src)) 574 return false; // Found non-virtually can't be bettered 575 } 576 else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind))) 577 { 578 // In both. 579 result.dst_ptr = NULL; 580 result.dst2src = __contained_ambig; 581 return true; // Fail. 582 } 583 else 584 { 585 // In neither publicly, ambiguous for the moment, but keep 586 // looking. It is possible that it was private in one or 587 // both and therefore we should fail, but that's just tough. 588 result.dst_ptr = NULL; 589 result.dst2src = __not_contained; 590 result_ambig = true; 591 } 592 } 593 594 if (result.whole2src == __contained_private) 595 // We found SRC_PTR as a private non-virtual base, therefore all 596 // cross casts will fail. We have already found a down cast, if 597 // there is one. 598 return result_ambig; 599 } 600 601 return result_ambig; 602 } 603 604 bool __class_type_info:: 605 __do_upcast (const __class_type_info *dst, const void *obj, 606 __upcast_result &__restrict result) const 607 { 608 if (*this == *dst) 609 { 610 result.dst_ptr = obj; 611 result.base_type = nonvirtual_base_type; 612 result.part2dst = __contained_public; 613 return true; 614 } 615 return false; 616 } 617 618 bool __si_class_type_info:: 619 __do_upcast (const __class_type_info *dst, const void *obj_ptr, 620 __upcast_result &__restrict result) const 621 { 622 if (__class_type_info::__do_upcast (dst, obj_ptr, result)) 623 return true; 624 625 return __base_type->__do_upcast (dst, obj_ptr, result); 626 } 627 628 bool __vmi_class_type_info:: 629 __do_upcast (const __class_type_info *dst, const void *obj_ptr, 630 __upcast_result &__restrict result) const 631 { 632 if (__class_type_info::__do_upcast (dst, obj_ptr, result)) 633 return true; 634 635 int src_details = result.src_details; 636 if (src_details & __flags_unknown_mask) 637 src_details = __flags; 638 639 for (std::size_t i = __base_count; i--;) 640 { 641 __upcast_result result2 (src_details); 642 const void *base = obj_ptr; 643 ptrdiff_t offset = __base_info[i].__offset (); 644 bool is_virtual = __base_info[i].__is_virtual_p (); 645 bool is_public = __base_info[i].__is_public_p (); 646 647 if (!is_public && !(src_details & __non_diamond_repeat_mask)) 648 // original cannot have an ambiguous base, so skip private bases 649 continue; 650 651 if (base) 652 base = convert_to_base (base, is_virtual, offset); 653 654 if (__base_info[i].__base_type->__do_upcast (dst, base, result2)) 655 { 656 if (result2.base_type == nonvirtual_base_type && is_virtual) 657 result2.base_type = __base_info[i].__base_type; 658 if (contained_p (result2.part2dst) && !is_public) 659 result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask); 660 661 if (!result.base_type) 662 { 663 result = result2; 664 if (!contained_p (result.part2dst)) 665 return true; // found ambiguously 666 667 if (result.part2dst & __contained_public_mask) 668 { 669 if (!(__flags & __non_diamond_repeat_mask)) 670 return true; // cannot have an ambiguous other base 671 } 672 else 673 { 674 if (!virtual_p (result.part2dst)) 675 return true; // cannot have another path 676 if (!(__flags & __diamond_shaped_mask)) 677 return true; // cannot have a more accessible path 678 } 679 } 680 else if (result.dst_ptr != result2.dst_ptr) 681 { 682 // Found an ambiguity. 683 result.dst_ptr = NULL; 684 result.part2dst = __contained_ambig; 685 return true; 686 } 687 else if (result.dst_ptr) 688 { 689 // Ok, found real object via a virtual path. 690 result.part2dst 691 = __sub_kind (result.part2dst | result2.part2dst); 692 } 693 else 694 { 695 // Dealing with a null pointer, need to check vbase 696 // containing each of the two choices. 697 if (result2.base_type == nonvirtual_base_type 698 || result.base_type == nonvirtual_base_type 699 || !(*result2.base_type == *result.base_type)) 700 { 701 // Already ambiguous, not virtual or via different virtuals. 702 // Cannot match. 703 result.part2dst = __contained_ambig; 704 return true; 705 } 706 result.part2dst 707 = __sub_kind (result.part2dst | result2.part2dst); 708 } 709 } 710 } 711 return result.part2dst != __unknown; 712 } 713 714 // this is the external interface to the dynamic cast machinery 715 extern "C" void * 716 __dynamic_cast (const void *src_ptr, // object started from 717 const __class_type_info *src_type, // type of the starting object 718 const __class_type_info *dst_type, // desired target type 719 ptrdiff_t src2dst) // how src and dst are related 720 { 721 const void *vtable = *static_cast <const void *const *> (src_ptr); 722 const vtable_prefix *prefix = 723 adjust_pointer <vtable_prefix> (vtable, 724 -offsetof (vtable_prefix, origin)); 725 const void *whole_ptr = 726 adjust_pointer <void> (src_ptr, prefix->whole_object); 727 const __class_type_info *whole_type = prefix->whole_type; 728 __class_type_info::__dyncast_result result; 729 730 whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public, 731 dst_type, whole_ptr, src_type, src_ptr, result); 732 if (!result.dst_ptr) 733 return NULL; 734 if (contained_public_p (result.dst2src)) 735 // Src is known to be a public base of dst. 736 return const_cast <void *> (result.dst_ptr); 737 if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst))) 738 // Both src and dst are known to be public bases of whole. Found a valid 739 // cross cast. 740 return const_cast <void *> (result.dst_ptr); 741 if (contained_nonvirtual_p (result.whole2src)) 742 // Src is known to be a non-public nonvirtual base of whole, and not a 743 // base of dst. Found an invalid cross cast, which cannot also be a down 744 // cast 745 return NULL; 746 if (result.dst2src == __class_type_info::__unknown) 747 result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr, 748 src_type, src_ptr); 749 if (contained_public_p (result.dst2src)) 750 // Found a valid down cast 751 return const_cast <void *> (result.dst_ptr); 752 // Must be an invalid down cast, or the cross cast wasn't bettered 753 return NULL; 754 } 755 756 } // namespace __cxxabiv1 757