00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <cstddef>
00031 #include "tinfo.h"
00032 #include "new"
00033
00034
00035
00036
00037
00038 std::type_info::
00039 ~type_info ()
00040 { }
00041
00042 std::bad_cast::~bad_cast() throw() { }
00043 std::bad_typeid::~bad_typeid() throw() { }
00044
00045 #if !__GXX_MERGED_TYPEINFO_NAMES
00046
00047
00048 bool
00049 std::type_info::operator== (const std::type_info& arg) const
00050 {
00051 return (&arg == this) || (__builtin_strcmp (name (), arg.name ()) == 0);
00052 }
00053
00054 #endif
00055
00056 namespace std {
00057
00058
00059 bool type_info::
00060 __is_pointer_p () const
00061 {
00062 return false;
00063 }
00064
00065
00066 bool type_info::
00067 __is_function_p () const
00068 {
00069 return false;
00070 }
00071
00072
00073 bool type_info::
00074 __do_catch (const type_info *thr_type, void **, unsigned) const
00075 {
00076 return *this == *thr_type;
00077 }
00078
00079
00080 bool type_info::
00081 __do_upcast (const abi::__class_type_info *, void **) const
00082 {
00083 return false;
00084 }
00085
00086 };
00087
00088 namespace {
00089
00090 using namespace std;
00091 using namespace abi;
00092
00093
00094
00095 struct vtable_prefix {
00096 ptrdiff_t whole_object;
00097 const __class_type_info *whole_type;
00098 const void *origin;
00099 };
00100
00101 template <typename T>
00102 inline const T *
00103 adjust_pointer (const void *base, ptrdiff_t offset)
00104 {
00105 return reinterpret_cast <const T *>
00106 (reinterpret_cast <const char *> (base) + offset);
00107 }
00108
00109
00110
00111 inline void const *
00112 convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset)
00113 {
00114 if (is_virtual)
00115 {
00116 const void *vtable = *static_cast <const void *const *> (addr);
00117
00118 offset = *adjust_pointer<ptrdiff_t> (vtable, offset);
00119 }
00120
00121 return adjust_pointer<void> (addr, offset);
00122 }
00123
00124
00125 inline bool contained_p (__class_type_info::__sub_kind access_path)
00126 {
00127 return access_path >= __class_type_info::__contained_mask;
00128 }
00129 inline bool public_p (__class_type_info::__sub_kind access_path)
00130 {
00131 return access_path & __class_type_info::__contained_public_mask;
00132 }
00133 inline bool virtual_p (__class_type_info::__sub_kind access_path)
00134 {
00135 return (access_path & __class_type_info::__contained_virtual_mask);
00136 }
00137 inline bool contained_public_p (__class_type_info::__sub_kind access_path)
00138 {
00139 return ((access_path & __class_type_info::__contained_public)
00140 == __class_type_info::__contained_public);
00141 }
00142 inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path)
00143 {
00144 return ((access_path & __class_type_info::__contained_public)
00145 == __class_type_info::__contained_mask);
00146 }
00147 inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path)
00148 {
00149 return ((access_path & (__class_type_info::__contained_mask
00150 | __class_type_info::__contained_virtual_mask))
00151 == __class_type_info::__contained_mask);
00152 }
00153
00154 static const __class_type_info *const nonvirtual_base_type =
00155 static_cast <const __class_type_info *> (0) + 1;
00156
00157 };
00158
00159 namespace __cxxabiv1
00160 {
00161
00162 __class_type_info::
00163 ~__class_type_info ()
00164 {}
00165
00166 __si_class_type_info::
00167 ~__si_class_type_info ()
00168 {}
00169
00170 __vmi_class_type_info::
00171 ~__vmi_class_type_info ()
00172 {}
00173
00174
00175
00176 struct __class_type_info::__upcast_result
00177 {
00178 const void *dst_ptr;
00179 __sub_kind part2dst;
00180 int src_details;
00181 const __class_type_info *base_type;
00182
00183
00184
00185 public:
00186 __upcast_result (int d)
00187 :dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL)
00188 {}
00189 };
00190
00191
00192
00193 struct __class_type_info::__dyncast_result
00194 {
00195 const void *dst_ptr;
00196 __sub_kind whole2dst;
00197 __sub_kind whole2src;
00198 __sub_kind dst2src;
00199 int whole_details;
00200
00201 public:
00202 __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask)
00203 :dst_ptr (NULL), whole2dst (__unknown),
00204 whole2src (__unknown), dst2src (__unknown),
00205 whole_details (details_)
00206 {}
00207 };
00208
00209 bool __class_type_info::
00210 __do_catch (const type_info *thr_type,
00211 void **thr_obj,
00212 unsigned outer) const
00213 {
00214 if (*this == *thr_type)
00215 return true;
00216 if (outer >= 4)
00217
00218 return false;
00219 return thr_type->__do_upcast (this, thr_obj);
00220 }
00221
00222 bool __class_type_info::
00223 __do_upcast (const __class_type_info *dst_type,
00224 void **obj_ptr) const
00225 {
00226 __upcast_result result (__vmi_class_type_info::__flags_unknown_mask);
00227
00228 __do_upcast (dst_type, *obj_ptr, result);
00229 if (!contained_public_p (result.part2dst))
00230 return false;
00231 *obj_ptr = const_cast <void *> (result.dst_ptr);
00232 return true;
00233 }
00234
00235 inline __class_type_info::__sub_kind __class_type_info::
00236 __find_public_src (ptrdiff_t src2dst,
00237 const void *obj_ptr,
00238 const __class_type_info *src_type,
00239 const void *src_ptr) const
00240 {
00241 if (src2dst >= 0)
00242 return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
00243 ? __contained_public : __not_contained;
00244 if (src2dst == -2)
00245 return __not_contained;
00246 return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
00247 }
00248
00249 __class_type_info::__sub_kind __class_type_info::
00250 __do_find_public_src (ptrdiff_t,
00251 const void *obj_ptr,
00252 const __class_type_info *,
00253 const void *src_ptr) const
00254 {
00255 if (src_ptr == obj_ptr)
00256
00257 return __contained_public;
00258 return __not_contained;
00259 }
00260
00261 __class_type_info::__sub_kind __si_class_type_info::
00262 __do_find_public_src (ptrdiff_t src2dst,
00263 const void *obj_ptr,
00264 const __class_type_info *src_type,
00265 const void *src_ptr) const
00266 {
00267 if (src_ptr == obj_ptr && *this == *src_type)
00268 return __contained_public;
00269 return __base_type->__do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
00270 }
00271
00272 __class_type_info::__sub_kind __vmi_class_type_info::
00273 __do_find_public_src (ptrdiff_t src2dst,
00274 const void *obj_ptr,
00275 const __class_type_info *src_type,
00276 const void *src_ptr) const
00277 {
00278 if (obj_ptr == src_ptr && *this == *src_type)
00279 return __contained_public;
00280
00281 for (std::size_t i = __base_count; i--;)
00282 {
00283 if (!__base_info[i].__is_public_p ())
00284 continue;
00285
00286 const void *base = obj_ptr;
00287 ptrdiff_t offset = __base_info[i].__offset ();
00288 bool is_virtual = __base_info[i].__is_virtual_p ();
00289
00290 if (is_virtual)
00291 {
00292 if (src2dst == -3)
00293 continue;
00294 }
00295 base = convert_to_base (base, is_virtual, offset);
00296
00297 __sub_kind base_kind = __base_info[i].__base->__do_find_public_src
00298 (src2dst, base, src_type, src_ptr);
00299 if (contained_p (base_kind))
00300 {
00301 if (is_virtual)
00302 base_kind = __sub_kind (base_kind | __contained_virtual_mask);
00303 return base_kind;
00304 }
00305 }
00306
00307 return __not_contained;
00308 }
00309
00310 bool __class_type_info::
00311 __do_dyncast (ptrdiff_t,
00312 __sub_kind access_path,
00313 const __class_type_info *dst_type,
00314 const void *obj_ptr,
00315 const __class_type_info *src_type,
00316 const void *src_ptr,
00317 __dyncast_result &__restrict result) const
00318 {
00319 if (obj_ptr == src_ptr && *this == *src_type)
00320 {
00321
00322
00323 result.whole2src = access_path;
00324 return false;
00325 }
00326 if (*this == *dst_type)
00327 {
00328 result.dst_ptr = obj_ptr;
00329 result.whole2dst = access_path;
00330 result.dst2src = __not_contained;
00331 return false;
00332 }
00333 return false;
00334 }
00335
00336 bool __si_class_type_info::
00337 __do_dyncast (ptrdiff_t src2dst,
00338 __sub_kind access_path,
00339 const __class_type_info *dst_type,
00340 const void *obj_ptr,
00341 const __class_type_info *src_type,
00342 const void *src_ptr,
00343 __dyncast_result &__restrict result) const
00344 {
00345 if (*this == *dst_type)
00346 {
00347 result.dst_ptr = obj_ptr;
00348 result.whole2dst = access_path;
00349 if (src2dst >= 0)
00350 result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
00351 ? __contained_public : __not_contained;
00352 else if (src2dst == -2)
00353 result.dst2src = __not_contained;
00354 return false;
00355 }
00356 if (obj_ptr == src_ptr && *this == *src_type)
00357 {
00358
00359
00360 result.whole2src = access_path;
00361 return false;
00362 }
00363 return __base_type->__do_dyncast (src2dst, access_path, dst_type, obj_ptr,
00364 src_type, src_ptr, result);
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 bool __vmi_class_type_info::
00377 __do_dyncast (ptrdiff_t src2dst,
00378 __sub_kind access_path,
00379 const __class_type_info *dst_type,
00380 const void *obj_ptr,
00381 const __class_type_info *src_type,
00382 const void *src_ptr,
00383 __dyncast_result &__restrict result) const
00384 {
00385 if (result.whole_details & __flags_unknown_mask)
00386 result.whole_details = __flags;
00387
00388 if (obj_ptr == src_ptr && *this == *src_type)
00389 {
00390
00391
00392 result.whole2src = access_path;
00393 return false;
00394 }
00395 if (*this == *dst_type)
00396 {
00397 result.dst_ptr = obj_ptr;
00398 result.whole2dst = access_path;
00399 if (src2dst >= 0)
00400 result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
00401 ? __contained_public : __not_contained;
00402 else if (src2dst == -2)
00403 result.dst2src = __not_contained;
00404 return false;
00405 }
00406
00407 bool result_ambig = false;
00408 for (std::size_t i = __base_count; i--;)
00409 {
00410 __dyncast_result result2 (result.whole_details);
00411 void const *base = obj_ptr;
00412 __sub_kind base_access = access_path;
00413 ptrdiff_t offset = __base_info[i].__offset ();
00414 bool is_virtual = __base_info[i].__is_virtual_p ();
00415
00416 if (is_virtual)
00417 base_access = __sub_kind (base_access | __contained_virtual_mask);
00418 base = convert_to_base (base, is_virtual, offset);
00419
00420 if (!__base_info[i].__is_public_p ())
00421 {
00422 if (src2dst == -2 &&
00423 !(result.whole_details
00424 & (__non_diamond_repeat_mask | __diamond_shaped_mask)))
00425
00426
00427
00428
00429 continue;
00430 base_access = __sub_kind (base_access & ~__contained_public_mask);
00431 }
00432
00433 bool result2_ambig
00434 = __base_info[i].__base->__do_dyncast (src2dst, base_access,
00435 dst_type, base,
00436 src_type, src_ptr, result2);
00437 result.whole2src = __sub_kind (result.whole2src | result2.whole2src);
00438 if (result2.dst2src == __contained_public
00439 || result2.dst2src == __contained_ambig)
00440 {
00441 result.dst_ptr = result2.dst_ptr;
00442 result.whole2dst = result2.whole2dst;
00443 result.dst2src = result2.dst2src;
00444
00445
00446 return result2_ambig;
00447 }
00448
00449 if (!result_ambig && !result.dst_ptr)
00450 {
00451
00452 result.dst_ptr = result2.dst_ptr;
00453 result.whole2dst = result2.whole2dst;
00454 result_ambig = result2_ambig;
00455 if (result.dst_ptr && result.whole2src != __unknown
00456 && !(__flags & __non_diamond_repeat_mask))
00457
00458 return result_ambig;
00459 }
00460 else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
00461 {
00462
00463
00464 result.whole2dst =
00465 __sub_kind (result.whole2dst | result2.whole2dst);
00466 }
00467 else if ((result.dst_ptr != 0 | result_ambig)
00468 && (result2.dst_ptr != 0 | result2_ambig))
00469 {
00470
00471
00472
00473
00474
00475
00476
00477
00478 __sub_kind new_sub_kind = result2.dst2src;
00479 __sub_kind old_sub_kind = result.dst2src;
00480
00481 if (contained_p (result.whole2src)
00482 && (!virtual_p (result.whole2src)
00483 || !(result.whole_details & __diamond_shaped_mask)))
00484 {
00485
00486
00487
00488
00489 if (old_sub_kind == __unknown)
00490 old_sub_kind = __not_contained;
00491 if (new_sub_kind == __unknown)
00492 new_sub_kind = __not_contained;
00493 }
00494 else
00495 {
00496 if (old_sub_kind >= __not_contained)
00497 ;
00498 else if (contained_p (new_sub_kind)
00499 && (!virtual_p (new_sub_kind)
00500 || !(__flags & __diamond_shaped_mask)))
00501
00502
00503 old_sub_kind = __not_contained;
00504 else
00505 old_sub_kind = dst_type->__find_public_src
00506 (src2dst, result.dst_ptr, src_type, src_ptr);
00507
00508 if (new_sub_kind >= __not_contained)
00509 ;
00510 else if (contained_p (old_sub_kind)
00511 && (!virtual_p (old_sub_kind)
00512 || !(__flags & __diamond_shaped_mask)))
00513
00514
00515 new_sub_kind = __not_contained;
00516 else
00517 new_sub_kind = dst_type->__find_public_src
00518 (src2dst, result2.dst_ptr, src_type, src_ptr);
00519 }
00520
00521
00522
00523 if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind)))
00524 {
00525
00526 if (contained_p (new_sub_kind))
00527 {
00528
00529 result.dst_ptr = result2.dst_ptr;
00530 result.whole2dst = result2.whole2dst;
00531 result_ambig = false;
00532 old_sub_kind = new_sub_kind;
00533 }
00534 result.dst2src = old_sub_kind;
00535 if (public_p (result.dst2src))
00536 return false;
00537 if (!virtual_p (result.dst2src))
00538 return false;
00539 }
00540 else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind)))
00541 {
00542
00543 result.dst_ptr = NULL;
00544 result.dst2src = __contained_ambig;
00545 return true;
00546 }
00547 else
00548 {
00549
00550
00551
00552 result.dst_ptr = NULL;
00553 result.dst2src = __not_contained;
00554 result_ambig = true;
00555 }
00556 }
00557
00558 if (result.whole2src == __contained_private)
00559
00560
00561
00562 return result_ambig;
00563 }
00564
00565 return result_ambig;
00566 }
00567
00568 bool __class_type_info::
00569 __do_upcast (const __class_type_info *dst, const void *obj,
00570 __upcast_result &__restrict result) const
00571 {
00572 if (*this == *dst)
00573 {
00574 result.dst_ptr = obj;
00575 result.base_type = nonvirtual_base_type;
00576 result.part2dst = __contained_public;
00577 return true;
00578 }
00579 return false;
00580 }
00581
00582 bool __si_class_type_info::
00583 __do_upcast (const __class_type_info *dst, const void *obj_ptr,
00584 __upcast_result &__restrict result) const
00585 {
00586 if (__class_type_info::__do_upcast (dst, obj_ptr, result))
00587 return true;
00588
00589 return __base_type->__do_upcast (dst, obj_ptr, result);
00590 }
00591
00592 bool __vmi_class_type_info::
00593 __do_upcast (const __class_type_info *dst, const void *obj_ptr,
00594 __upcast_result &__restrict result) const
00595 {
00596 if (__class_type_info::__do_upcast (dst, obj_ptr, result))
00597 return true;
00598
00599 int src_details = result.src_details;
00600 if (src_details & __flags_unknown_mask)
00601 src_details = __flags;
00602
00603 for (std::size_t i = __base_count; i--;)
00604 {
00605 __upcast_result result2 (src_details);
00606 const void *base = obj_ptr;
00607 ptrdiff_t offset = __base_info[i].__offset ();
00608 bool is_virtual = __base_info[i].__is_virtual_p ();
00609 bool is_public = __base_info[i].__is_public_p ();
00610
00611 if (!is_public && !(src_details & __non_diamond_repeat_mask))
00612
00613 continue;
00614
00615 if (base)
00616 base = convert_to_base (base, is_virtual, offset);
00617
00618 if (__base_info[i].__base->__do_upcast (dst, base, result2))
00619 {
00620 if (result2.base_type == nonvirtual_base_type && is_virtual)
00621 result2.base_type = __base_info[i].__base;
00622 if (contained_p (result2.part2dst) && !is_public)
00623 result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask);
00624
00625 if (!result.base_type)
00626 {
00627 result = result2;
00628 if (!contained_p (result.part2dst))
00629 return true;
00630
00631 if (result.part2dst & __contained_public_mask)
00632 {
00633 if (!(__flags & __non_diamond_repeat_mask))
00634 return true;
00635 }
00636 else
00637 {
00638 if (!virtual_p (result.part2dst))
00639 return true;
00640 if (!(__flags & __diamond_shaped_mask))
00641 return true;
00642 }
00643 }
00644 else if (result.dst_ptr != result2.dst_ptr)
00645 {
00646
00647 result.dst_ptr = NULL;
00648 result.part2dst = __contained_ambig;
00649 return true;
00650 }
00651 else if (result.dst_ptr)
00652 {
00653
00654 result.part2dst
00655 = __sub_kind (result.part2dst | result2.part2dst);
00656 }
00657 else
00658 {
00659
00660
00661 if (result2.base_type == nonvirtual_base_type
00662 || result.base_type == nonvirtual_base_type
00663 || !(*result2.base_type == *result.base_type))
00664 {
00665
00666
00667 result.part2dst = __contained_ambig;
00668 return true;
00669 }
00670 result.part2dst
00671 = __sub_kind (result.part2dst | result2.part2dst);
00672 }
00673 }
00674 }
00675 return result.part2dst != __unknown;
00676 }
00677
00678
00679 extern "C" void *
00680 __dynamic_cast (const void *src_ptr,
00681 const __class_type_info *src_type,
00682 const __class_type_info *dst_type,
00683 ptrdiff_t src2dst)
00684 {
00685 const void *vtable = *static_cast <const void *const *> (src_ptr);
00686 const vtable_prefix *prefix =
00687 adjust_pointer <vtable_prefix> (vtable,
00688 -offsetof (vtable_prefix, origin));
00689 const void *whole_ptr =
00690 adjust_pointer <void> (src_ptr, prefix->whole_object);
00691 const __class_type_info *whole_type = prefix->whole_type;
00692 __class_type_info::__dyncast_result result;
00693
00694 whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
00695 dst_type, whole_ptr, src_type, src_ptr, result);
00696 if (!result.dst_ptr)
00697 return NULL;
00698 if (contained_public_p (result.dst2src))
00699
00700 return const_cast <void *> (result.dst_ptr);
00701 if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst)))
00702
00703
00704 return const_cast <void *> (result.dst_ptr);
00705 if (contained_nonvirtual_p (result.whole2src))
00706
00707
00708
00709 return NULL;
00710 if (result.dst2src == __class_type_info::__unknown)
00711 result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
00712 src_type, src_ptr);
00713 if (contained_public_p (result.dst2src))
00714
00715 return const_cast <void *> (result.dst_ptr);
00716
00717 return NULL;
00718 }
00719
00720 };