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