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