Whole document tree
    

Whole document tree

tinfo.cc Source File
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