OSDN Git Service

2004-05-22 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / 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
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   explicit
208   __upcast_result(const __upcast_result& r)
209   : dst_ptr(r.dst_ptr), part2dst(r.part2dst), src_details(r.src_details), 
210     base_type(r.base_type) 
211   { }
212
213   __upcast_result&
214   operator=(const __upcast_result& r)
215   {
216     if (&r != this)
217       {
218         dst_ptr = r.dst_ptr;
219         part2dst = r.part2dst;
220         src_details = r.src_details;
221         base_type = r.base_type;
222       }
223     return *this;
224   }
225 };
226
227 // __dyncast_result is used to hold information during traversal of a class
228 // hierarchy when dynamic casting.
229 struct __class_type_info::__dyncast_result
230 {
231   const void *dst_ptr;        // pointer to target object or NULL
232   __sub_kind whole2dst;       // path from most derived object to target
233   __sub_kind whole2src;       // path from most derived object to sub object
234   __sub_kind dst2src;         // path from target to sub object
235   int whole_details;          // details of the whole class hierarchy
236   
237   __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask)
238     :dst_ptr (NULL), whole2dst (__unknown),
239      whole2src (__unknown), dst2src (__unknown),
240      whole_details (details_)
241     {}
242
243 protected:
244   __dyncast_result(const __dyncast_result&);
245   
246   __dyncast_result&
247   operator=(const __dyncast_result&);
248 };
249
250 bool __class_type_info::
251 __do_catch (const type_info *thr_type,
252             void **thr_obj,
253             unsigned outer) const
254 {
255   if (*this == *thr_type)
256     return true;
257   if (outer >= 4)
258     // Neither `A' nor `A *'.
259     return false;
260   return thr_type->__do_upcast (this, thr_obj);
261 }
262
263 bool __class_type_info::
264 __do_upcast (const __class_type_info *dst_type,
265              void **obj_ptr) const
266 {
267   __upcast_result result (__vmi_class_type_info::__flags_unknown_mask);
268   
269   __do_upcast (dst_type, *obj_ptr, result);
270   if (!contained_public_p (result.part2dst))
271     return false;
272   *obj_ptr = const_cast <void *> (result.dst_ptr);
273   return true;
274 }
275
276 inline __class_type_info::__sub_kind __class_type_info::
277 __find_public_src (ptrdiff_t src2dst,
278                    const void *obj_ptr,
279                    const __class_type_info *src_type,
280                    const void *src_ptr) const
281 {
282   if (src2dst >= 0)
283     return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
284             ? __contained_public : __not_contained;
285   if (src2dst == -2)
286     return __not_contained;
287   return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
288 }
289
290 __class_type_info::__sub_kind __class_type_info::
291 __do_find_public_src (ptrdiff_t,
292                       const void *obj_ptr,
293                       const __class_type_info *,
294                       const void *src_ptr) const
295 {
296   if (src_ptr == obj_ptr)
297     // Must be our type, as the pointers match.
298     return __contained_public;
299   return __not_contained;
300 }
301
302 __class_type_info::__sub_kind __si_class_type_info::
303 __do_find_public_src (ptrdiff_t src2dst,
304                       const void *obj_ptr,
305                       const __class_type_info *src_type,
306                       const void *src_ptr) const
307 {
308   if (src_ptr == obj_ptr && *this == *src_type)
309     return __contained_public;
310   return __base_type->__do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
311 }
312
313 __class_type_info::__sub_kind __vmi_class_type_info::
314 __do_find_public_src (ptrdiff_t src2dst,
315                       const void *obj_ptr,
316                       const __class_type_info *src_type,
317                       const void *src_ptr) const
318 {
319   if (obj_ptr == src_ptr && *this == *src_type)
320     return __contained_public;
321   
322   for (std::size_t i = __base_count; i--;)
323     {
324       if (!__base_info[i].__is_public_p ())
325         continue; // Not public, can't be here.
326       
327       const void *base = obj_ptr;
328       ptrdiff_t offset = __base_info[i].__offset ();
329       bool is_virtual = __base_info[i].__is_virtual_p ();
330       
331       if (is_virtual)
332         {
333           if (src2dst == -3)
334             continue; // Not a virtual base, so can't be here.
335         }
336       base = convert_to_base (base, is_virtual, offset);
337       
338       __sub_kind base_kind = __base_info[i].__base_type->__do_find_public_src
339                               (src2dst, base, src_type, src_ptr);
340       if (contained_p (base_kind))
341         {
342           if (is_virtual)
343             base_kind = __sub_kind (base_kind | __contained_virtual_mask);
344           return base_kind;
345         }
346     }
347   
348   return __not_contained;
349 }
350
351 bool __class_type_info::
352 __do_dyncast (ptrdiff_t,
353               __sub_kind access_path,
354               const __class_type_info *dst_type,
355               const void *obj_ptr,
356               const __class_type_info *src_type,
357               const void *src_ptr,
358               __dyncast_result &__restrict result) const
359 {
360   if (obj_ptr == src_ptr && *this == *src_type)
361     {
362       // The src object we started from. Indicate how we are accessible from
363       // the most derived object.
364       result.whole2src = access_path;
365       return false;
366     }
367   if (*this == *dst_type)
368     {
369       result.dst_ptr = obj_ptr;
370       result.whole2dst = access_path;
371       result.dst2src = __not_contained;
372       return false;
373     }
374   return false;
375 }
376
377 bool __si_class_type_info::
378 __do_dyncast (ptrdiff_t src2dst,
379               __sub_kind access_path,
380               const __class_type_info *dst_type,
381               const void *obj_ptr,
382               const __class_type_info *src_type,
383               const void *src_ptr,
384               __dyncast_result &__restrict result) const
385 {
386   if (*this == *dst_type)
387     {
388       result.dst_ptr = obj_ptr;
389       result.whole2dst = access_path;
390       if (src2dst >= 0)
391         result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
392               ? __contained_public : __not_contained;
393       else if (src2dst == -2)
394         result.dst2src = __not_contained;
395       return false;
396     }
397   if (obj_ptr == src_ptr && *this == *src_type)
398     {
399       // The src object we started from. Indicate how we are accessible from
400       // the most derived object.
401       result.whole2src = access_path;
402       return false;
403     }
404   return __base_type->__do_dyncast (src2dst, access_path, dst_type, obj_ptr,
405                              src_type, src_ptr, result);
406 }
407
408 // This is a big hairy function. Although the run-time behaviour of
409 // dynamic_cast is simple to describe, it gives rise to some non-obvious
410 // behaviour. We also desire to determine as early as possible any definite
411 // answer we can get. Because it is unknown what the run-time ratio of
412 // succeeding to failing dynamic casts is, we do not know in which direction
413 // to bias any optimizations. To that end we make no particular effort towards
414 // early fail answers or early success answers. Instead we try to minimize
415 // work by filling in things lazily (when we know we need the information),
416 // and opportunisticly take early success or failure results.
417 bool __vmi_class_type_info::
418 __do_dyncast (ptrdiff_t src2dst,
419               __sub_kind access_path,
420               const __class_type_info *dst_type,
421               const void *obj_ptr,
422               const __class_type_info *src_type,
423               const void *src_ptr,
424               __dyncast_result &__restrict result) const
425 {
426   if (result.whole_details & __flags_unknown_mask)
427     result.whole_details = __flags;
428   
429   if (obj_ptr == src_ptr && *this == *src_type)
430     {
431       // The src object we started from. Indicate how we are accessible from
432       // the most derived object.
433       result.whole2src = access_path;
434       return false;
435     }
436   if (*this == *dst_type)
437     {
438       result.dst_ptr = obj_ptr;
439       result.whole2dst = access_path;
440       if (src2dst >= 0)
441         result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
442               ? __contained_public : __not_contained;
443       else if (src2dst == -2)
444         result.dst2src = __not_contained;
445       return false;
446     }
447
448   bool result_ambig = false;
449   for (std::size_t i = __base_count; i--;)
450     {
451       __dyncast_result result2 (result.whole_details);
452       void const *base = obj_ptr;
453       __sub_kind base_access = access_path;
454       ptrdiff_t offset = __base_info[i].__offset ();
455       bool is_virtual = __base_info[i].__is_virtual_p ();
456       
457       if (is_virtual)
458         base_access = __sub_kind (base_access | __contained_virtual_mask);
459       base = convert_to_base (base, is_virtual, offset);
460
461       if (!__base_info[i].__is_public_p ())
462         {
463           if (src2dst == -2 &&
464               !(result.whole_details
465                 & (__non_diamond_repeat_mask | __diamond_shaped_mask)))
466             // The hierarchy has no duplicate bases (which might ambiguate
467             // things) and where we started is not a public base of what we
468             // want (so it cannot be a downcast). There is nothing of interest
469             // hiding in a non-public base.
470             continue;
471           base_access = __sub_kind (base_access & ~__contained_public_mask);
472         }
473       
474       bool result2_ambig
475           = __base_info[i].__base_type->__do_dyncast (src2dst, base_access,
476                                              dst_type, base,
477                                              src_type, src_ptr, result2);
478       result.whole2src = __sub_kind (result.whole2src | result2.whole2src);
479       if (result2.dst2src == __contained_public
480           || result2.dst2src == __contained_ambig)
481         {
482           result.dst_ptr = result2.dst_ptr;
483           result.whole2dst = result2.whole2dst;
484           result.dst2src = result2.dst2src;
485           // Found a downcast which can't be bettered or an ambiguous downcast
486           // which can't be disambiguated
487           return result2_ambig;
488         }
489       
490       if (!result_ambig && !result.dst_ptr)
491         {
492           // Not found anything yet.
493           result.dst_ptr = result2.dst_ptr;
494           result.whole2dst = result2.whole2dst;
495           result_ambig = result2_ambig;
496           if (result.dst_ptr && result.whole2src != __unknown
497               && !(__flags & __non_diamond_repeat_mask))
498             // Found dst and src and we don't have repeated bases.
499             return result_ambig;
500         }
501       else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
502         {
503           // Found at same address, must be via virtual.  Pick the most
504           // accessible path.
505           result.whole2dst =
506               __sub_kind (result.whole2dst | result2.whole2dst);
507         }
508       else if ((result.dst_ptr != 0 & result2.dst_ptr != 0)
509                || (result.dst_ptr != 0 & result2_ambig)
510                || (result2.dst_ptr != 0 & result_ambig))
511         {
512           // Found two different DST_TYPE bases, or a valid one and a set of
513           // ambiguous ones, must disambiguate. See whether SRC_PTR is
514           // contained publicly within one of the non-ambiguous choices. If it
515           // is in only one, then that's the choice. If it is in both, then
516           // we're ambiguous and fail. If it is in neither, we're ambiguous,
517           // but don't yet fail as we might later find a third base which does
518           // contain SRC_PTR.
519         
520           __sub_kind new_sub_kind = result2.dst2src;
521           __sub_kind old_sub_kind = result.dst2src;
522           
523           if (contained_p (result.whole2src)
524               && (!virtual_p (result.whole2src)
525                   || !(result.whole_details & __diamond_shaped_mask)))
526             {
527               // We already found SRC_PTR as a base of most derived, and
528               // either it was non-virtual, or the whole hierarchy is
529               // not-diamond shaped. Therefore if it is in either choice, it
530               // can only be in one of them, and we will already know.
531               if (old_sub_kind == __unknown)
532                 old_sub_kind = __not_contained;
533               if (new_sub_kind == __unknown)
534                 new_sub_kind = __not_contained;
535             }
536           else
537             {
538               if (old_sub_kind >= __not_contained)
539                 ;// already calculated
540               else if (contained_p (new_sub_kind)
541                        && (!virtual_p (new_sub_kind)
542                            || !(__flags & __diamond_shaped_mask)))
543                 // Already found inside the other choice, and it was
544                 // non-virtual or we are not diamond shaped.
545                 old_sub_kind = __not_contained;
546               else
547                 old_sub_kind = dst_type->__find_public_src
548                                 (src2dst, result.dst_ptr, src_type, src_ptr);
549           
550               if (new_sub_kind >= __not_contained)
551                 ;// already calculated
552               else if (contained_p (old_sub_kind)
553                        && (!virtual_p (old_sub_kind)
554                            || !(__flags & __diamond_shaped_mask)))
555                 // Already found inside the other choice, and it was
556                 // non-virtual or we are not diamond shaped.
557                 new_sub_kind = __not_contained;
558               else
559                 new_sub_kind = dst_type->__find_public_src
560                                 (src2dst, result2.dst_ptr, src_type, src_ptr);
561             }
562           
563           // Neither sub_kind can be contained_ambig -- we bail out early
564           // when we find those.
565           if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind)))
566             {
567               // Only on one choice, not ambiguous.
568               if (contained_p (new_sub_kind))
569                 {
570                   // Only in new.
571                   result.dst_ptr = result2.dst_ptr;
572                   result.whole2dst = result2.whole2dst;
573                   result_ambig = false;
574                   old_sub_kind = new_sub_kind;
575                 }
576               result.dst2src = old_sub_kind;
577               if (public_p (result.dst2src))
578                 return false; // Can't be an ambiguating downcast for later discovery.
579               if (!virtual_p (result.dst2src))
580                 return false; // Found non-virtually can't be bettered
581             }
582           else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind)))
583             {
584               // In both.
585               result.dst_ptr = NULL;
586               result.dst2src = __contained_ambig;
587               return true;  // Fail.
588             }
589           else
590             {
591               // In neither publicly, ambiguous for the moment, but keep
592               // looking. It is possible that it was private in one or
593               // both and therefore we should fail, but that's just tough.
594               result.dst_ptr = NULL;
595               result.dst2src = __not_contained;
596               result_ambig = true;
597             }
598         }
599       
600       if (result.whole2src == __contained_private)
601         // We found SRC_PTR as a private non-virtual base, therefore all
602         // cross casts will fail. We have already found a down cast, if
603         // there is one.
604         return result_ambig;
605     }
606
607   return result_ambig;
608 }
609
610 bool __class_type_info::
611 __do_upcast (const __class_type_info *dst, const void *obj,
612              __upcast_result &__restrict result) const
613 {
614   if (*this == *dst)
615     {
616       result.dst_ptr = obj;
617       result.base_type = nonvirtual_base_type;
618       result.part2dst = __contained_public;
619       return true;
620     }
621   return false;
622 }
623
624 bool __si_class_type_info::
625 __do_upcast (const __class_type_info *dst, const void *obj_ptr,
626              __upcast_result &__restrict result) const
627 {
628   if (__class_type_info::__do_upcast (dst, obj_ptr, result))
629     return true;
630   
631   return __base_type->__do_upcast (dst, obj_ptr, result);
632 }
633
634 bool __vmi_class_type_info::
635 __do_upcast (const __class_type_info *dst, const void *obj_ptr,
636              __upcast_result &__restrict result) const
637 {
638   if (__class_type_info::__do_upcast (dst, obj_ptr, result))
639     return true;
640   
641   int src_details = result.src_details;
642   if (src_details & __flags_unknown_mask)
643     src_details = __flags;
644   
645   for (std::size_t i = __base_count; i--;)
646     {
647       __upcast_result result2 (src_details);
648       const void *base = obj_ptr;
649       ptrdiff_t offset = __base_info[i].__offset ();
650       bool is_virtual = __base_info[i].__is_virtual_p ();
651       bool is_public = __base_info[i].__is_public_p ();
652       
653       if (!is_public && !(src_details & __non_diamond_repeat_mask))
654         // original cannot have an ambiguous base, so skip private bases
655         continue;
656
657       if (base)
658         base = convert_to_base (base, is_virtual, offset);
659       
660       if (__base_info[i].__base_type->__do_upcast (dst, base, result2))
661         {
662           if (result2.base_type == nonvirtual_base_type && is_virtual)
663             result2.base_type = __base_info[i].__base_type;
664           if (contained_p (result2.part2dst) && !is_public)
665             result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask);
666           
667           if (!result.base_type)
668             {
669               result = result2;
670               if (!contained_p (result.part2dst))
671                 return true; // found ambiguously
672               
673               if (result.part2dst & __contained_public_mask)
674                 {
675                   if (!(__flags & __non_diamond_repeat_mask))
676                     return true;  // cannot have an ambiguous other base
677                 }
678               else
679                 {
680                   if (!virtual_p (result.part2dst))
681                     return true; // cannot have another path
682                   if (!(__flags & __diamond_shaped_mask))
683                     return true; // cannot have a more accessible path
684                 }
685             }
686           else if (result.dst_ptr != result2.dst_ptr)
687             {
688               // Found an ambiguity.
689               result.dst_ptr = NULL;
690               result.part2dst = __contained_ambig;
691               return true;
692             }
693           else if (result.dst_ptr)
694             {
695               // Ok, found real object via a virtual path.
696               result.part2dst
697                   = __sub_kind (result.part2dst | result2.part2dst);
698             }
699           else
700             {
701               // Dealing with a null pointer, need to check vbase
702               // containing each of the two choices.
703               if (result2.base_type == nonvirtual_base_type
704                   || result.base_type == nonvirtual_base_type
705                   || !(*result2.base_type == *result.base_type))
706                 {
707                   // Already ambiguous, not virtual or via different virtuals.
708                   // Cannot match.
709                   result.part2dst = __contained_ambig;
710                   return true;
711                 }
712               result.part2dst
713                   = __sub_kind (result.part2dst | result2.part2dst);
714             }
715         }
716     }
717   return result.part2dst != __unknown;
718 }
719
720 // this is the external interface to the dynamic cast machinery
721 extern "C" void *
722 __dynamic_cast (const void *src_ptr,    // object started from
723                 const __class_type_info *src_type, // type of the starting object
724                 const __class_type_info *dst_type, // desired target type
725                 ptrdiff_t src2dst) // how src and dst are related
726 {
727   const void *vtable = *static_cast <const void *const *> (src_ptr);
728   const vtable_prefix *prefix =
729       adjust_pointer <vtable_prefix> (vtable, 
730                                       -offsetof (vtable_prefix, origin));
731   const void *whole_ptr =
732       adjust_pointer <void> (src_ptr, prefix->whole_object);
733   const __class_type_info *whole_type = prefix->whole_type;
734   __class_type_info::__dyncast_result result;
735   
736   whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
737                             dst_type, whole_ptr, src_type, src_ptr, result);
738   if (!result.dst_ptr)
739     return NULL;
740   if (contained_public_p (result.dst2src))
741     // Src is known to be a public base of dst.
742     return const_cast <void *> (result.dst_ptr);
743   if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst)))
744     // Both src and dst are known to be public bases of whole. Found a valid
745     // cross cast.
746     return const_cast <void *> (result.dst_ptr);
747   if (contained_nonvirtual_p (result.whole2src))
748     // Src is known to be a non-public nonvirtual base of whole, and not a
749     // base of dst. Found an invalid cross cast, which cannot also be a down
750     // cast
751     return NULL;
752   if (result.dst2src == __class_type_info::__unknown)
753     result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
754                                                   src_type, src_ptr);
755   if (contained_public_p (result.dst2src))
756     // Found a valid down cast
757     return const_cast <void *> (result.dst_ptr);
758   // Must be an invalid down cast, or the cross cast wasn't bettered
759   return NULL;
760 }
761
762 } // namespace __cxxabiv1