Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

tinfo.cc

Go 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 doxygen1.2.15