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