Whole document tree tinfo.ccGo to the documentation of this file.00001 // Methods for type_info for -*- C++ -*- Run Time Type Identification. 00002 // Copyright (C) 1994, 1996, 1998, 1999, 2000, 2001 Free Software Foundation 00003 // 00004 // This file is part of GNU CC. 00005 // 00006 // GNU CC is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation; either version 2, or (at your option) 00009 // any later version. 00010 00011 // GNU CC is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // You should have received a copy of the GNU General Public License 00017 // along with GNU CC; see the file COPYING. If not, write to 00018 // the Free Software Foundation, 59 Temple Place - Suite 330, 00019 // Boston, MA 02111-1307, USA. 00020 00021 // As a special exception, you may use this file as part of a free software 00022 // library without restriction. Specifically, if other files instantiate 00023 // templates or use macros or inline functions from this file, or you compile 00024 // this file and link it with other files to produce an executable, this 00025 // file does not by itself cause the resulting executable to be covered by 00026 // the GNU General Public License. This exception does not however 00027 // invalidate any other reasons why the executable file might be covered by 00028 // the GNU General Public License. 00029 00030 #include <cstddef> 00031 #include "tinfo.h" 00032 #include "new" // for placement new 00033 00034 // This file contains the minimal working set necessary to link with code 00035 // that uses virtual functions and -frtti but does not actually use RTTI 00036 // functionality. 00037 00038 00039 std::type_info::~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 // We can't rely on common symbols being shared between shared objects. 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 // return true if this is a type_info for a pointer type 00059 bool type_info:: 00060 __is_pointer_p () const 00061 { 00062 return false; 00063 } 00064 00065 // return true if this is a type_info for a function type 00066 bool type_info:: 00067 __is_function_p () const 00068 { 00069 return false; 00070 } 00071 00072 // try and catch a thrown object. 00073 bool type_info:: 00074 __do_catch (const type_info *thr_type, void **, unsigned) const 00075 { 00076 return *this == *thr_type; 00077 } 00078 00079 // upcast from this type to the target. __class_type_info will override 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 // initial part of a vtable, this structure is used with offsetof, so we don't 00094 // have to keep alignments consistent manually. 00095 struct vtable_prefix { 00096 ptrdiff_t whole_object; // offset to most derived object 00097 const __class_type_info *whole_type; // pointer to most derived type_info 00098 const void *origin; // what a class's vptr points to 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 // ADDR is a pointer to an object. Convert it to a pointer to a base, 00110 // using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base. 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 // some predicate functions for __class_type_info::__sub_kind 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 }; // namespace 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 // __upcast_result is used to hold information during traversal of a class 00175 // heirarchy when catch matching. 00176 struct __class_type_info::__upcast_result 00177 { 00178 const void *dst_ptr; // pointer to caught object 00179 __sub_kind part2dst; // path from current base to target 00180 int src_details; // hints about the source type heirarchy 00181 const __class_type_info *base_type; // where we found the target, 00182 // if in vbase the __class_type_info of vbase 00183 // if a non-virtual base then 1 00184 // else NULL 00185 public: 00186 __upcast_result (int d) 00187 :dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL) 00188 {} 00189 }; 00190 00191 // __dyncast_result is used to hold information during traversal of a class 00192 // heirarchy when dynamic casting. 00193 struct __class_type_info::__dyncast_result 00194 { 00195 const void *dst_ptr; // pointer to target object or NULL 00196 __sub_kind whole2dst; // path from most derived object to target 00197 __sub_kind whole2src; // path from most derived object to sub object 00198 __sub_kind dst2src; // path from target to sub object 00199 int whole_details; // details of the whole class heirarchy 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 // Neither `A' nor `A *'. 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 // Must be our type, as the pointers match. 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; // Not public, can't be here. 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; // Not a virtual base, so can't be here. 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 // The src object we started from. Indicate how we are accessible from 00322 // the most derived object. 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 // The src object we started from. Indicate how we are accessible from 00359 // the most derived object. 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 // This is a big hairy function. Although the run-time behaviour of 00368 // dynamic_cast is simple to describe, it gives rise to some non-obvious 00369 // behaviour. We also desire to determine as early as possible any definite 00370 // answer we can get. Because it is unknown what the run-time ratio of 00371 // succeeding to failing dynamic casts is, we do not know in which direction 00372 // to bias any optimizations. To that end we make no particular effort towards 00373 // early fail answers or early success answers. Instead we try to minimize 00374 // work by filling in things lazily (when we know we need the information), 00375 // and opportunisticly take early success or failure results. 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 // The src object we started from. Indicate how we are accessible from 00391 // the most derived object. 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 // The hierarchy has no duplicate bases (which might ambiguate 00426 // things) and where we started is not a public base of what we 00427 // want (so it cannot be a downcast). There is nothing of interest 00428 // hiding in a non-public base. 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 // Found a downcast which can't be bettered or an ambiguous downcast 00445 // which can't be disambiguated 00446 return result2_ambig; 00447 } 00448 00449 if (!result_ambig && !result.dst_ptr) 00450 { 00451 // Not found anything yet. 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 // Found dst and src and we don't have repeated bases. 00458 return result_ambig; 00459 } 00460 else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr) 00461 { 00462 // Found at same address, must be via virtual. Pick the most 00463 // accessible path. 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 // Found two different DST_TYPE bases, or a valid one and a set of 00471 // ambiguous ones, must disambiguate. See whether SRC_PTR is 00472 // contained publicly within one of the non-ambiguous choices. If it 00473 // is in only one, then that's the choice. If it is in both, then 00474 // we're ambiguous and fail. If it is in neither, we're ambiguous, 00475 // but don't yet fail as we might later find a third base which does 00476 // contain SRC_PTR. 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 // We already found SRC_PTR as a base of most derived, and 00486 // either it was non-virtual, or the whole heirarchy is 00487 // not-diamond shaped. Therefore if it is in either choice, it 00488 // can only be in one of them, and we will already know. 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 ;// already calculated 00498 else if (contained_p (new_sub_kind) 00499 && (!virtual_p (new_sub_kind) 00500 || !(__flags & __diamond_shaped_mask))) 00501 // Already found inside the other choice, and it was 00502 // non-virtual or we are not diamond shaped. 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 ;// already calculated 00510 else if (contained_p (old_sub_kind) 00511 && (!virtual_p (old_sub_kind) 00512 || !(__flags & __diamond_shaped_mask))) 00513 // Already found inside the other choice, and it was 00514 // non-virtual or we are not diamond shaped. 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 // Neither sub_kind can be contained_ambig -- we bail out early 00522 // when we find those. 00523 if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind))) 00524 { 00525 // Only on one choice, not ambiguous. 00526 if (contained_p (new_sub_kind)) 00527 { 00528 // Only in new. 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; // Can't be an ambiguating downcast for later discovery. 00537 if (!virtual_p (result.dst2src)) 00538 return false; // Found non-virtually can't be bettered 00539 } 00540 else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind))) 00541 { 00542 // In both. 00543 result.dst_ptr = NULL; 00544 result.dst2src = __contained_ambig; 00545 return true; // Fail. 00546 } 00547 else 00548 { 00549 // In neither publicly, ambiguous for the moment, but keep 00550 // looking. It is possible that it was private in one or 00551 // both and therefore we should fail, but that's just tough. 00552 result.dst_ptr = NULL; 00553 result.dst2src = __not_contained; 00554 result_ambig = true; 00555 } 00556 } 00557 00558 if (result.whole2src == __contained_private) 00559 // We found SRC_PTR as a private non-virtual base, therefore all 00560 // cross casts will fail. We have already found a down cast, if 00561 // there is one. 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 // original cannot have an ambiguous base, so skip private bases 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; // found ambiguously 00630 00631 if (result.part2dst & __contained_public_mask) 00632 { 00633 if (!(__flags & __non_diamond_repeat_mask)) 00634 return true; // cannot have an ambiguous other base 00635 } 00636 else 00637 { 00638 if (!virtual_p (result.part2dst)) 00639 return true; // cannot have another path 00640 if (!(__flags & __diamond_shaped_mask)) 00641 return true; // cannot have a more accessible path 00642 } 00643 } 00644 else if (result.dst_ptr != result2.dst_ptr) 00645 { 00646 // Found an ambiguity. 00647 result.dst_ptr = NULL; 00648 result.part2dst = __contained_ambig; 00649 return true; 00650 } 00651 else if (result.dst_ptr) 00652 { 00653 // Ok, found real object via a virtual path. 00654 result.part2dst 00655 = __sub_kind (result.part2dst | result2.part2dst); 00656 } 00657 else 00658 { 00659 // Dealing with a null pointer, need to check vbase 00660 // containing each of the two choices. 00661 if (result2.base_type == nonvirtual_base_type 00662 || result.base_type == nonvirtual_base_type 00663 || !(*result2.base_type == *result.base_type)) 00664 { 00665 // Already ambiguous, not virtual or via different virtuals. 00666 // Cannot match. 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 // this is the external interface to the dynamic cast machinery 00679 extern "C" void * 00680 __dynamic_cast (const void *src_ptr, // object started from 00681 const __class_type_info *src_type, // type of the starting object 00682 const __class_type_info *dst_type, // desired target type 00683 ptrdiff_t src2dst) // how src and dst are related 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 // Src is known to be a public base of dst. 00700 return const_cast <void *> (result.dst_ptr); 00701 if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst))) 00702 // Both src and dst are known to be public bases of whole. Found a valid 00703 // cross cast. 00704 return const_cast <void *> (result.dst_ptr); 00705 if (contained_nonvirtual_p (result.whole2src)) 00706 // Src is known to be a non-public nonvirtual base of whole, and not a 00707 // base of dst. Found an invalid cross cast, which cannot also be a down 00708 // cast 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 // Found a valid down cast 00715 return const_cast <void *> (result.dst_ptr); 00716 // Must be an invalid down cast, or the cross cast wasn't bettered 00717 return NULL; 00718 } 00719 00720 }; // namespace __cxxabiv1 Generated on Mon Apr 8 03:11:46 2002 for libstdc++-v3 Source by ![]() |