]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/libsupc++/tinfo.cc
libsupc++: New directory.
[thirdparty/gcc.git] / libstdc++-v3 / libsupc++ / tinfo.cc
CommitLineData
06bd10fb
BK
1// Methods for type_info for -*- C++ -*- Run Time Type Identification.
2// Copyright (C) 1994, 1996, 1998, 1999, 2000 Free Software Foundation
3
4// This file is part of GNU CC.
5
6// GNU CC is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2, or (at your option)
9// any later version.
10
11// GNU CC is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with GNU CC; see the file COPYING. If not, write to
18// the Free Software Foundation, 59 Temple Place - Suite 330,
19// Boston, MA 02111-1307, USA.
20
21// As a special exception, you may use this file as part of a free software
22// library without restriction. Specifically, if other files instantiate
23// templates or use macros or inline functions from this file, or you compile
24// this file and link it with other files to produce an executable, this
25// file does not by itself cause the resulting executable to be covered by
26// the GNU General Public License. This exception does not however
27// invalidate any other reasons why the executable file might be covered by
28// the GNU General Public License.
29
30#pragma implementation "typeinfo"
31
32#include <stddef.h>
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
40std::type_info::
41~type_info ()
42{ }
43
44#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
45// original (old) abi
46
47namespace
48{
49// ADDR is a pointer to an object. Convert it to a pointer to a base,
50// using OFFSET.
51inline void*
52convert_to_base (void *addr, bool is_virtual, myint32 offset)
53{
54 if (!addr)
55 return NULL;
56
57 if (!is_virtual)
58 return (char *) addr + offset;
59
60 // Under the old ABI, the offset gives us the address of a pointer
61 // to the virtual base.
62 return *((void **) ((char *) addr + offset));
63}
64
65}
66
67// We can't rely on common symbols being shared between shared objects.
68bool std::type_info::
69operator== (const std::type_info& arg) const
70{
71 return (&arg == this) || (__builtin_strcmp (name (), arg.name ()) == 0);
72}
73
74extern "C" void
75__rtti_class (void *addr, const char *name,
76 const __class_type_info::base_info *bl, size_t bn)
77{ new (addr) __class_type_info (name, bl, bn); }
78
79extern "C" void
80__rtti_si (void *addr, const char *n, const std::type_info *ti)
81{
82 new (addr) __si_type_info
83 (n, static_cast <const __user_type_info &> (*ti));
84}
85
86extern "C" void
87__rtti_user (void *addr, const char *name)
88{ new (addr) __user_type_info (name); }
89
90// Upcast for catch checking. OBJPTR points to the thrown object and might be
91// NULL. Return 0 on failure, non-zero on success. Set *ADJPTR to adjusted
92// object pointer.
93int __user_type_info::
94upcast (const type_info &target, void *objptr,
95 void **adjptr) const
96{
97 upcast_result result;
98
99 if (do_upcast (contained_public, target, objptr, result))
100 return 0;
101 *adjptr = result.target_obj;
102 return contained_public_p (result.whole2target);
103}
104
105// Down or cross cast for dynamic_cast. OBJPTR points to the most derrived
106// object, SUBPTR points to the static base object. Both must not be NULL.
107// TARGET specifies the desired target type, SUBTYPE specifies the static
108// type. Both must be defined. Returns adjusted object pointer on success,
109// NULL on failure. [expr.dynamic.cast]/8 says 'unambiguous public base'. This
110// itself is an ambiguous statement. We choose it to mean the base must be
111// separately unambiguous and public, rather than unambiguous considering only
112// public bases.
113void *__user_type_info::
114dyncast (int boff,
115 const type_info &target, void *objptr,
116 const type_info &subtype, void *subptr) const
117{
118 dyncast_result result;
119
120 do_dyncast (boff, contained_public,
121 target, objptr, subtype, subptr, result);
122 if (!result.target_obj)
123 return NULL;
124 if (contained_public_p (result.target2sub))
125 return result.target_obj;
126 if (contained_public_p (sub_kind (result.whole2sub & result.whole2target)))
127 // Found a valid cross cast
128 return result.target_obj;
129 if (contained_nonvirtual_p (result.whole2sub))
130 // Found an invalid cross cast, which cannot also be a down cast
131 return NULL;
132 if (result.target2sub == unknown)
133 result.target2sub = static_cast <const __user_type_info &> (target)
134 .find_public_subobj (boff, subtype,
135 result.target_obj, subptr);
136 if (contained_public_p (result.target2sub))
137 // Found a valid down cast
138 return result.target_obj;
139 // Must be an invalid down cast, or the cross cast wasn't bettered
140 return NULL;
141}
142
143// Catch cast helper. ACCESS_PATH is the access from the complete thrown
144// object to this base. TARGET is the desired type we want to catch. OBJPTR
145// points to this base within the throw object, it might be NULL. Fill in
146// RESULT with what we find. Return true, should we determine catch must fail.
147bool __user_type_info::
148do_upcast (sub_kind access_path,
149 const type_info &target, void *objptr,
150 upcast_result &__restrict result) const
151{
152 if (*this == target)
153 {
154 result.target_obj = objptr;
155 result.base_type = nonvirtual_base_type;
156 result.whole2target = access_path;
157 return contained_nonpublic_p (access_path);
158 }
159 return false;
160}
161
162// dynamic cast helper. ACCESS_PATH gives the access from the most derived
163// object to this base. TARGET indicates the desired type we want. OBJPTR
164// points to this base within the object. SUBTYPE indicates the static type
165// started from and SUBPTR points to that base within the most derived object.
166// Fill in RESULT with what we find. Return true if we have located an
167// ambiguous match.
168bool __user_type_info::
169do_dyncast (int, sub_kind access_path,
170 const type_info &target, void *objptr,
171 const type_info &subtype, void *subptr,
172 dyncast_result &__restrict result) const
173{
174 if (objptr == subptr && *this == subtype)
175 {
176 // The subobject we started from. Indicate how we are accessible from
177 // the most derived object.
178 result.whole2sub = access_path;
179 return false;
180 }
181 if (*this == target)
182 {
183 result.target_obj = objptr;
184 result.whole2target = access_path;
185 result.target2sub = not_contained;
186 return false;
187 }
188 return false;
189}
190
191// find_public_subobj helper. Return contained_public if we are the desired
192// subtype. OBJPTR points to this base type, SUBPTR points to the desired base
193// object.
194__user_type_info::sub_kind __user_type_info::
195do_find_public_subobj (int, const type_info &, void *objptr, void *subptr) const
196{
197 if (subptr == objptr)
198 // Must be our type, as the pointers match.
199 return contained_public;
200 return not_contained;
201}
202
203// catch helper for single public inheritance types. See
204// __user_type_info::do_upcast for semantics.
205bool __si_type_info::
206do_upcast (sub_kind access_path,
207 const type_info &target, void *objptr,
208 upcast_result &__restrict result) const
209{
210 if (*this == target)
211 {
212 result.target_obj = objptr;
213 result.base_type = nonvirtual_base_type;
214 result.whole2target = access_path;
215 return contained_nonpublic_p (access_path);
216 }
217 return base.do_upcast (access_path, target, objptr, result);
218}
219
220// dynamic cast helper for single public inheritance types. See
221// __user_type_info::do_dyncast for semantics. BOFF indicates how SUBTYPE
222// types are inherited by TARGET types.
223bool __si_type_info::
224do_dyncast (int boff, sub_kind access_path,
225 const type_info &target, void *objptr,
226 const type_info &subtype, void *subptr,
227 dyncast_result &__restrict result) const
228{
229 if (objptr == subptr && *this == subtype)
230 {
231 // The subobject we started from. Indicate how we are accessible from
232 // the most derived object.
233 result.whole2sub = access_path;
234 return false;
235 }
236 if (*this == target)
237 {
238 result.target_obj = objptr;
239 result.whole2target = access_path;
240 if (boff >= 0)
241 result.target2sub = ((char *)subptr - (char *)objptr) == boff
242 ? contained_public : not_contained;
243 else if (boff == -2)
244 result.target2sub = not_contained;
245 return false;
246 }
247 return base.do_dyncast (boff, access_path,
248 target, objptr, subtype, subptr, result);
249}
250
251// find_public_subobj helper. See __user_type_info::do_find_public_subobj or
252// semantics. BOFF indicates how SUBTYPE types are inherited by the original
253// target object.
254__user_type_info::sub_kind __si_type_info::
255do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *subptr) const
256{
257 if (subptr == objptr && subtype == *this)
258 return contained_public;
259 return base.do_find_public_subobj (boff, subtype, objptr, subptr);
260}
261
262// catch helper for multiple or non-public inheritance types. See
263// __user_type_info::do_upcast for semantics.
264bool __class_type_info::
265do_upcast (sub_kind access_path,
266 const type_info &target, void *objptr,
267 upcast_result &__restrict result) const
268{
269 if (*this == target)
270 {
271 result.target_obj = objptr;
272 result.base_type = nonvirtual_base_type;
273 result.whole2target = access_path;
274 return contained_nonpublic_p (access_path);
275 }
276
277 for (size_t i = n_bases; i--;)
278 {
279 upcast_result result2;
280 void *p = objptr;
281 sub_kind sub_access = access_path;
282 p = convert_to_base (p,
283 base_list[i].is_virtual,
284 base_list[i].offset);
285 if (base_list[i].is_virtual)
286 sub_access = sub_kind (sub_access | contained_virtual_mask);
287 if (base_list[i].access != PUBLIC)
288 sub_access = sub_kind (sub_access & ~contained_public_mask);
289 if (base_list[i].base->do_upcast (sub_access, target, p, result2)
290 && !contained_virtual_p (result2.whole2target))
291 return true; // must fail
292 if (result2.base_type)
293 {
294 if (result2.base_type == nonvirtual_base_type
295 && base_list[i].is_virtual)
296 result2.base_type = base_list[i].base;
297 if (!result.base_type)
298 result = result2;
299 else if (result.target_obj != result2.target_obj)
300 {
301 // Found an ambiguity.
302 result.target_obj = NULL;
303 result.whole2target = contained_ambig;
304 return true;
305 }
306 else if (result.target_obj)
307 {
308 // Ok, found real object via a virtual path.
309 result.whole2target
310 = sub_kind (result.whole2target | result2.whole2target);
311 }
312 else
313 {
314 // Dealing with a null pointer, need to check vbase
315 // containing each of the two choices.
316 if (result2.base_type == nonvirtual_base_type
317 || result.base_type == nonvirtual_base_type
318 || !(*result2.base_type == *result.base_type))
319 {
320 // Already ambiguous, not virtual or via different virtuals.
321 // Cannot match.
322 result.whole2target = contained_ambig;
323 return true;
324 }
325 result.whole2target
326 = sub_kind (result.whole2target | result2.whole2target);
327 }
328 }
329 }
330 return false;
331}
332
333// dynamic cast helper for non-public or multiple inheritance types. See
334// __user_type_info::do_dyncast for overall semantics.
335// This is a big hairy function. Although the run-time behaviour of
336// dynamic_cast is simple to describe, it gives rise to some non-obvious
337// behaviour. We also desire to determine as early as possible any definite
338// answer we can get. Because it is unknown what the run-time ratio of
339// succeeding to failing dynamic casts is, we do not know in which direction
340// to bias any optimizations. To that end we make no particular effort towards
341// early fail answers or early success answers. Instead we try to minimize
342// work by filling in things lazily (when we know we need the information),
343// and opportunisticly take early success or failure results.
344bool __class_type_info::
345do_dyncast (int boff, sub_kind access_path,
346 const type_info &target, void *objptr,
347 const type_info &subtype, void *subptr,
348 dyncast_result &__restrict result) const
349{
350 if (objptr == subptr && *this == subtype)
351 {
352 // The subobject we started from. Indicate how we are accessible from
353 // the most derived object.
354 result.whole2sub = access_path;
355 return false;
356 }
357 if (*this == target)
358 {
359 result.target_obj = objptr;
360 result.whole2target = access_path;
361 if (boff >= 0)
362 result.target2sub = ((char *)subptr - (char *)objptr) == boff
363 ? contained_public : not_contained;
364 else if (boff == -2)
365 result.target2sub = not_contained;
366 return false;
367 }
368 bool result_ambig = false;
369 for (size_t i = n_bases; i--;)
370 {
371 dyncast_result result2;
372 void *p;
373 sub_kind sub_access = access_path;
374 p = convert_to_base (objptr,
375 base_list[i].is_virtual,
376 base_list[i].offset);
377 if (base_list[i].is_virtual)
378 sub_access = sub_kind (sub_access | contained_virtual_mask);
379 if (base_list[i].access != PUBLIC)
380 sub_access = sub_kind (sub_access & ~contained_public_mask);
381
382 bool result2_ambig
383 = base_list[i].base->do_dyncast (boff, sub_access,
384 target, p, subtype, subptr, result2);
385 result.whole2sub = sub_kind (result.whole2sub | result2.whole2sub);
386 if (result2.target2sub == contained_public
387 || result2.target2sub == contained_ambig)
388 {
389 result.target_obj = result2.target_obj;
390 result.whole2target = result2.whole2target;
391 result.target2sub = result2.target2sub;
392 // Found a downcast which can't be bettered or an ambiguous downcast
393 // which can't be disambiguated
394 return result2_ambig;
395 }
396
397 if (!result_ambig && !result.target_obj)
398 {
399 // Not found anything yet.
400 result.target_obj = result2.target_obj;
401 result.whole2target = result2.whole2target;
402 result_ambig = result2_ambig;
403 }
404 else if (result.target_obj && result.target_obj == result2.target_obj)
405 {
406 // Found at same address, must be via virtual. Pick the most
407 // accessible path.
408 result.whole2target =
409 sub_kind (result.whole2target | result2.whole2target);
410 }
411 else if ((result.target_obj && result2.target_obj)
412 || (result_ambig && result2.target_obj)
413 || (result2_ambig && result.target_obj))
414 {
415 // Found two different TARGET bases, or a valid one and a set of
416 // ambiguous ones, must disambiguate. See whether SUBOBJ is
417 // contained publicly within one of the non-ambiguous choices.
418 // If it is in only one, then that's the choice. If it is in
419 // both, then we're ambiguous and fail. If it is in neither,
420 // we're ambiguous, but don't yet fail as we might later find a
421 // third base which does contain SUBPTR.
422
423 sub_kind new_sub_kind = result2.target2sub;
424 sub_kind old_sub_kind = result.target2sub;
425
426 if (contained_nonvirtual_p (result.whole2sub))
427 {
428 // We already found SUBOBJ as a non-virtual base of most
429 // derived. Therefore if it is in either choice, it can only be
430 // in one of them, and we will already know.
431 if (old_sub_kind == unknown)
432 old_sub_kind = not_contained;
433 if (new_sub_kind == unknown)
434 new_sub_kind = not_contained;
435 }
436 else
437 {
438 const __user_type_info &t =
439 static_cast <const __user_type_info &> (target);
440
441 if (old_sub_kind >= not_contained)
442 ;// already calculated
443 else if (contained_nonvirtual_p (new_sub_kind))
444 // Already found non-virtually inside the other choice,
445 // cannot be in this.
446 old_sub_kind = not_contained;
447 else
448 old_sub_kind = t.find_public_subobj (boff, subtype,
449 result.target_obj, subptr);
450
451 if (new_sub_kind >= not_contained)
452 ;// already calculated
453 else if (contained_nonvirtual_p (old_sub_kind))
454 // Already found non-virtually inside the other choice,
455 // cannot be in this.
456 new_sub_kind = not_contained;
457 else
458 new_sub_kind = t.find_public_subobj (boff, subtype,
459 result2.target_obj, subptr);
460 }
461
462 // Neither sub_kind can be contained_ambig -- we bail out early
463 // when we find those.
464 if (contained_p (sub_kind (new_sub_kind ^ old_sub_kind)))
465 {
466 // Only on one choice, not ambiguous.
467 if (contained_p (new_sub_kind))
468 {
469 // Only in new.
470 result.target_obj = result2.target_obj;
471 result.whole2target = result2.whole2target;
472 result_ambig = false;
473 old_sub_kind = new_sub_kind;
474 }
475 result.target2sub = old_sub_kind;
476 if (result.target2sub == contained_public)
477 return false; // Can't be an ambiguating downcast for later discovery.
478 }
479 else if (contained_p (sub_kind (new_sub_kind & old_sub_kind)))
480 {
481 // In both.
482 result.target_obj = NULL;
483 result.target2sub = contained_ambig;
484 return true; // Fail.
485 }
486 else
487 {
488 // In neither publicly, ambiguous for the moment, but keep
489 // looking. It is possible that it was private in one or
490 // both and therefore we should fail, but that's just tough.
491 result.target_obj = NULL;
492 result.target2sub = not_contained;
493 result_ambig = true;
494 }
495 }
496
497 if (result.whole2sub == contained_private)
498 // We found SUBOBJ as a private non-virtual base, therefore all
499 // cross casts will fail. We have already found a down cast, if
500 // there is one.
501 return result_ambig;
502 }
503
504 return result_ambig;
505}
506
507// find_public_subobj helper for non-public or multiple inheritance types. See
508// __user_type_info::do_find_public_subobj for semantics. We make use of BOFF
509// to prune the base class walk.
510__user_type_info::sub_kind __class_type_info::
511do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *subptr) const
512{
513 if (objptr == subptr && subtype == *this)
514 return contained_public;
515
516 for (size_t i = n_bases; i--;)
517 {
518 if (base_list[i].access != PUBLIC)
519 continue; // Not public, can't be here.
520 void *p;
521
522 if (base_list[i].is_virtual && boff == -3)
523 // Not a virtual base, so can't be here.
524 continue;
525
526 p = convert_to_base (objptr,
527 base_list[i].is_virtual,
528 base_list[i].offset);
529
530 sub_kind base_kind = base_list[i].base->do_find_public_subobj
531 (boff, subtype, p, subptr);
532 if (contained_p (base_kind))
533 {
534 if (base_list[i].is_virtual)
535 base_kind = sub_kind (base_kind | contained_virtual_mask);
536 return base_kind;
537 }
538 }
539
540 return not_contained;
541}
542#else
543// new abi
544
545namespace std {
546
547// return true if this is a type_info for a pointer type
548bool type_info::
549__is_pointer_p () const
550{
551 return false;
552}
553
554// return true if this is a type_info for a function type
555bool type_info::
556__is_function_p () const
557{
558 return false;
559}
560
561// try and catch a thrown object.
562bool type_info::
563__do_catch (const type_info *thr_type, void **, unsigned) const
564{
565 return *this == *thr_type;
566}
567
568// upcast from this type to the target. __class_type_info will override
569bool type_info::
570__do_upcast (const abi::__class_type_info *, void **) const
571{
572 return false;
573}
574
575};
576
577namespace {
578
579using namespace std;
580using namespace abi;
581
582// initial part of a vtable, this structure is used with offsetof, so we don't
583// have to keep alignments consistent manually.
584struct vtable_prefix {
585 ptrdiff_t whole_object; // offset to most derived object
586 const __class_type_info *whole_type; // pointer to most derived type_info
587 const void *origin; // what a class's vptr points to
588};
589
590template <typename T>
591inline const T *
592adjust_pointer (const void *base, ptrdiff_t offset)
593{
594 return reinterpret_cast <const T *>
595 (reinterpret_cast <const char *> (base) + offset);
596}
597
598// ADDR is a pointer to an object. Convert it to a pointer to a base,
599// using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base.
600inline void const *
601convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset)
602{
603 if (is_virtual)
604 {
605 const void *vtable = *static_cast <const void *const *> (addr);
606
607 offset = *adjust_pointer<ptrdiff_t> (vtable, offset);
608 }
609
610 return adjust_pointer<void> (addr, offset);
611}
612
613// some predicate functions for __class_type_info::__sub_kind
614inline bool contained_p (__class_type_info::__sub_kind access_path)
615{
616 return access_path >= __class_type_info::__contained_mask;
617}
618inline bool public_p (__class_type_info::__sub_kind access_path)
619{
620 return access_path & __class_type_info::__contained_public_mask;
621}
622inline bool virtual_p (__class_type_info::__sub_kind access_path)
623{
624 return (access_path & __class_type_info::__contained_virtual_mask);
625}
626inline bool contained_public_p (__class_type_info::__sub_kind access_path)
627{
628 return ((access_path & __class_type_info::__contained_public)
629 == __class_type_info::__contained_public);
630}
631inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path)
632{
633 return ((access_path & __class_type_info::__contained_public)
634 == __class_type_info::__contained_mask);
635}
636inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path)
637{
638 return ((access_path & (__class_type_info::__contained_mask
639 | __class_type_info::__contained_virtual_mask))
640 == __class_type_info::__contained_mask);
641}
642
643static const __class_type_info *const nonvirtual_base_type =
644 static_cast <const __class_type_info *> (0) + 1;
645
646}; // namespace
647
648namespace __cxxabiv1
649{
650
651__class_type_info::
652~__class_type_info ()
653{}
654
655__si_class_type_info::
656~__si_class_type_info ()
657{}
658
659__vmi_class_type_info::
660~__vmi_class_type_info ()
661{}
662
663// __upcast_result is used to hold information during traversal of a class
664// heirarchy when catch matching.
665struct __class_type_info::__upcast_result
666{
667 const void *dst_ptr; // pointer to caught object
668 __sub_kind part2dst; // path from current base to target
669 int src_details; // hints about the source type heirarchy
670 const __class_type_info *base_type; // where we found the target,
671 // if in vbase the __class_type_info of vbase
672 // if a non-virtual base then 1
673 // else NULL
674 public:
675 __upcast_result (int d)
676 :dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL)
677 {}
678};
679
680// __dyncast_result is used to hold information during traversal of a class
681// heirarchy when dynamic casting.
682struct __class_type_info::__dyncast_result
683{
684 const void *dst_ptr; // pointer to target object or NULL
685 __sub_kind whole2dst; // path from most derived object to target
686 __sub_kind whole2src; // path from most derived object to sub object
687 __sub_kind dst2src; // path from target to sub object
688 int whole_details; // details of the whole class heirarchy
689
690 public:
691 __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask)
692 :dst_ptr (NULL), whole2dst (__unknown),
693 whole2src (__unknown), dst2src (__unknown),
694 whole_details (details_)
695 {}
696};
697
698bool __class_type_info::
699__do_catch (const type_info *thr_type,
700 void **thr_obj,
701 unsigned outer) const
702{
703 if (*this == *thr_type)
704 return true;
705 if (outer >= 4)
706 // Neither `A' nor `A *'.
707 return false;
708 return thr_type->__do_upcast (this, thr_obj);
709}
710
711bool __class_type_info::
712__do_upcast (const __class_type_info *dst_type,
713 void **obj_ptr) const
714{
715 __upcast_result result (__vmi_class_type_info::__flags_unknown_mask);
716
717 __do_upcast (dst_type, *obj_ptr, result);
718 if (!contained_public_p (result.part2dst))
719 return false;
720 *obj_ptr = const_cast <void *> (result.dst_ptr);
721 return true;
722}
723
724inline __class_type_info::__sub_kind __class_type_info::
725__find_public_src (ptrdiff_t src2dst,
726 const void *obj_ptr,
727 const __class_type_info *src_type,
728 const void *src_ptr) const
729{
730 if (src2dst >= 0)
731 return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
732 ? __contained_public : __not_contained;
733 if (src2dst == -2)
734 return __not_contained;
735 return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
736}
737
738__class_type_info::__sub_kind __class_type_info::
739__do_find_public_src (ptrdiff_t,
740 const void *obj_ptr,
741 const __class_type_info *,
742 const void *src_ptr) const
743{
744 if (src_ptr == obj_ptr)
745 // Must be our type, as the pointers match.
746 return __contained_public;
747 return __not_contained;
748}
749
750__class_type_info::__sub_kind __si_class_type_info::
751__do_find_public_src (ptrdiff_t src2dst,
752 const void *obj_ptr,
753 const __class_type_info *src_type,
754 const void *src_ptr) const
755{
756 if (src_ptr == obj_ptr && *this == *src_type)
757 return __contained_public;
758 return __base_type->__do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
759}
760
761__class_type_info::__sub_kind __vmi_class_type_info::
762__do_find_public_src (ptrdiff_t src2dst,
763 const void *obj_ptr,
764 const __class_type_info *src_type,
765 const void *src_ptr) const
766{
767 if (obj_ptr == src_ptr && *this == *src_type)
768 return __contained_public;
769
770 for (size_t i = __base_count; i--;)
771 {
772 if (!__base_info[i].__is_public_p ())
773 continue; // Not public, can't be here.
774
775 const void *base = obj_ptr;
776 ptrdiff_t offset = __base_info[i].__offset ();
777 bool is_virtual = __base_info[i].__is_virtual_p ();
778
779 if (is_virtual)
780 {
781 if (src2dst == -3)
782 continue; // Not a virtual base, so can't be here.
783 }
784 base = convert_to_base (base, is_virtual, offset);
785
786 __sub_kind base_kind = __base_info[i].__base->__do_find_public_src
787 (src2dst, base, src_type, src_ptr);
788 if (contained_p (base_kind))
789 {
790 if (is_virtual)
791 base_kind = __sub_kind (base_kind | __contained_virtual_mask);
792 return base_kind;
793 }
794 }
795
796 return __not_contained;
797}
798
799bool __class_type_info::
800__do_dyncast (ptrdiff_t,
801 __sub_kind access_path,
802 const __class_type_info *dst_type,
803 const void *obj_ptr,
804 const __class_type_info *src_type,
805 const void *src_ptr,
806 __dyncast_result &__restrict result) const
807{
808 if (obj_ptr == src_ptr && *this == *src_type)
809 {
810 // The src object we started from. Indicate how we are accessible from
811 // the most derived object.
812 result.whole2src = access_path;
813 return false;
814 }
815 if (*this == *dst_type)
816 {
817 result.dst_ptr = obj_ptr;
818 result.whole2dst = access_path;
819 result.dst2src = __not_contained;
820 return false;
821 }
822 return false;
823}
824
825bool __si_class_type_info::
826__do_dyncast (ptrdiff_t src2dst,
827 __sub_kind access_path,
828 const __class_type_info *dst_type,
829 const void *obj_ptr,
830 const __class_type_info *src_type,
831 const void *src_ptr,
832 __dyncast_result &__restrict result) const
833{
834 if (*this == *dst_type)
835 {
836 result.dst_ptr = obj_ptr;
837 result.whole2dst = access_path;
838 if (src2dst >= 0)
839 result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
840 ? __contained_public : __not_contained;
841 else if (src2dst == -2)
842 result.dst2src = __not_contained;
843 return false;
844 }
845 if (obj_ptr == src_ptr && *this == *src_type)
846 {
847 // The src object we started from. Indicate how we are accessible from
848 // the most derived object.
849 result.whole2src = access_path;
850 return false;
851 }
852 return __base_type->__do_dyncast (src2dst, access_path, dst_type, obj_ptr,
853 src_type, src_ptr, result);
854}
855
856// This is a big hairy function. Although the run-time behaviour of
857// dynamic_cast is simple to describe, it gives rise to some non-obvious
858// behaviour. We also desire to determine as early as possible any definite
859// answer we can get. Because it is unknown what the run-time ratio of
860// succeeding to failing dynamic casts is, we do not know in which direction
861// to bias any optimizations. To that end we make no particular effort towards
862// early fail answers or early success answers. Instead we try to minimize
863// work by filling in things lazily (when we know we need the information),
864// and opportunisticly take early success or failure results.
865bool __vmi_class_type_info::
866__do_dyncast (ptrdiff_t src2dst,
867 __sub_kind access_path,
868 const __class_type_info *dst_type,
869 const void *obj_ptr,
870 const __class_type_info *src_type,
871 const void *src_ptr,
872 __dyncast_result &__restrict result) const
873{
874 if (result.whole_details & __flags_unknown_mask)
875 result.whole_details = __flags;
876
877 if (obj_ptr == src_ptr && *this == *src_type)
878 {
879 // The src object we started from. Indicate how we are accessible from
880 // the most derived object.
881 result.whole2src = access_path;
882 return false;
883 }
884 if (*this == *dst_type)
885 {
886 result.dst_ptr = obj_ptr;
887 result.whole2dst = access_path;
888 if (src2dst >= 0)
889 result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
890 ? __contained_public : __not_contained;
891 else if (src2dst == -2)
892 result.dst2src = __not_contained;
893 return false;
894 }
895
896 bool result_ambig = false;
897 for (size_t i = __base_count; i--;)
898 {
899 __dyncast_result result2 (result.whole_details);
900 void const *base = obj_ptr;
901 __sub_kind base_access = access_path;
902 ptrdiff_t offset = __base_info[i].__offset ();
903 bool is_virtual = __base_info[i].__is_virtual_p ();
904
905 if (is_virtual)
906 base_access = __sub_kind (base_access | __contained_virtual_mask);
907 base = convert_to_base (base, is_virtual, offset);
908
909 if (!__base_info[i].__is_public_p ())
910 {
911 if (src2dst == -2 &&
912 !(result.whole_details
913 & (__non_diamond_repeat_mask | __diamond_shaped_mask)))
914 // The hierarchy has no duplicate bases (which might ambiguate
915 // things) and where we started is not a public base of what we
916 // want (so it cannot be a downcast). There is nothing of interest
917 // hiding in a non-public base.
918 continue;
919 base_access = __sub_kind (base_access & ~__contained_public_mask);
920 }
921
922 bool result2_ambig
923 = __base_info[i].__base->__do_dyncast (src2dst, base_access,
924 dst_type, base,
925 src_type, src_ptr, result2);
926 result.whole2src = __sub_kind (result.whole2src | result2.whole2src);
927 if (result2.dst2src == __contained_public
928 || result2.dst2src == __contained_ambig)
929 {
930 result.dst_ptr = result2.dst_ptr;
931 result.whole2dst = result2.whole2dst;
932 result.dst2src = result2.dst2src;
933 // Found a downcast which can't be bettered or an ambiguous downcast
934 // which can't be disambiguated
935 return result2_ambig;
936 }
937
938 if (!result_ambig && !result.dst_ptr)
939 {
940 // Not found anything yet.
941 result.dst_ptr = result2.dst_ptr;
942 result.whole2dst = result2.whole2dst;
943 result_ambig = result2_ambig;
944 if (result.dst_ptr && result.whole2src != __unknown
945 && !(__flags & __non_diamond_repeat_mask))
946 // Found dst and src and we don't have repeated bases.
947 return result_ambig;
948 }
949 else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
950 {
951 // Found at same address, must be via virtual. Pick the most
952 // accessible path.
953 result.whole2dst =
954 __sub_kind (result.whole2dst | result2.whole2dst);
955 }
956 else if ((result.dst_ptr != 0 | result_ambig)
957 && (result2.dst_ptr != 0 | result2_ambig))
958 {
959 // Found two different DST_TYPE bases, or a valid one and a set of
960 // ambiguous ones, must disambiguate. See whether SRC_PTR is
961 // contained publicly within one of the non-ambiguous choices. If it
962 // is in only one, then that's the choice. If it is in both, then
963 // we're ambiguous and fail. If it is in neither, we're ambiguous,
964 // but don't yet fail as we might later find a third base which does
965 // contain SRC_PTR.
966
967 __sub_kind new_sub_kind = result2.dst2src;
968 __sub_kind old_sub_kind = result.dst2src;
969
970 if (contained_p (result.whole2src)
971 && (!virtual_p (result.whole2src)
972 || !(result.whole_details & __diamond_shaped_mask)))
973 {
974 // We already found SRC_PTR as a base of most derived, and
975 // either it was non-virtual, or the whole heirarchy is
976 // not-diamond shaped. Therefore if it is in either choice, it
977 // can only be in one of them, and we will already know.
978 if (old_sub_kind == __unknown)
979 old_sub_kind = __not_contained;
980 if (new_sub_kind == __unknown)
981 new_sub_kind = __not_contained;
982 }
983 else
984 {
985 if (old_sub_kind >= __not_contained)
986 ;// already calculated
987 else if (contained_p (new_sub_kind)
988 && (!virtual_p (new_sub_kind)
989 || !(__flags & __diamond_shaped_mask)))
990 // Already found inside the other choice, and it was
991 // non-virtual or we are not diamond shaped.
992 old_sub_kind = __not_contained;
993 else
994 old_sub_kind = dst_type->__find_public_src
995 (src2dst, result.dst_ptr, src_type, src_ptr);
996
997 if (new_sub_kind >= __not_contained)
998 ;// already calculated
999 else if (contained_p (old_sub_kind)
1000 && (!virtual_p (old_sub_kind)
1001 || !(__flags & __diamond_shaped_mask)))
1002 // Already found inside the other choice, and it was
1003 // non-virtual or we are not diamond shaped.
1004 new_sub_kind = __not_contained;
1005 else
1006 new_sub_kind = dst_type->__find_public_src
1007 (src2dst, result2.dst_ptr, src_type, src_ptr);
1008 }
1009
1010 // Neither sub_kind can be contained_ambig -- we bail out early
1011 // when we find those.
1012 if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind)))
1013 {
1014 // Only on one choice, not ambiguous.
1015 if (contained_p (new_sub_kind))
1016 {
1017 // Only in new.
1018 result.dst_ptr = result2.dst_ptr;
1019 result.whole2dst = result2.whole2dst;
1020 result_ambig = false;
1021 old_sub_kind = new_sub_kind;
1022 }
1023 result.dst2src = old_sub_kind;
1024 if (public_p (result.dst2src))
1025 return false; // Can't be an ambiguating downcast for later discovery.
1026 if (!virtual_p (result.dst2src))
1027 return false; // Found non-virtually can't be bettered
1028 }
1029 else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind)))
1030 {
1031 // In both.
1032 result.dst_ptr = NULL;
1033 result.dst2src = __contained_ambig;
1034 return true; // Fail.
1035 }
1036 else
1037 {
1038 // In neither publicly, ambiguous for the moment, but keep
1039 // looking. It is possible that it was private in one or
1040 // both and therefore we should fail, but that's just tough.
1041 result.dst_ptr = NULL;
1042 result.dst2src = __not_contained;
1043 result_ambig = true;
1044 }
1045 }
1046
1047 if (result.whole2src == __contained_private)
1048 // We found SRC_PTR as a private non-virtual base, therefore all
1049 // cross casts will fail. We have already found a down cast, if
1050 // there is one.
1051 return result_ambig;
1052 }
1053
1054 return result_ambig;
1055}
1056
1057bool __class_type_info::
1058__do_upcast (const __class_type_info *dst, const void *obj,
1059 __upcast_result &__restrict result) const
1060{
1061 if (*this == *dst)
1062 {
1063 result.dst_ptr = obj;
1064 result.base_type = nonvirtual_base_type;
1065 result.part2dst = __contained_public;
1066 return true;
1067 }
1068 return false;
1069}
1070
1071bool __si_class_type_info::
1072__do_upcast (const __class_type_info *dst, const void *obj_ptr,
1073 __upcast_result &__restrict result) const
1074{
1075 if (__class_type_info::__do_upcast (dst, obj_ptr, result))
1076 return true;
1077
1078 return __base_type->__do_upcast (dst, obj_ptr, result);
1079}
1080
1081bool __vmi_class_type_info::
1082__do_upcast (const __class_type_info *dst, const void *obj_ptr,
1083 __upcast_result &__restrict result) const
1084{
1085 if (__class_type_info::__do_upcast (dst, obj_ptr, result))
1086 return true;
1087
1088 int src_details = result.src_details;
1089 if (src_details & __flags_unknown_mask)
1090 src_details = __flags;
1091
1092 for (size_t i = __base_count; i--;)
1093 {
1094 __upcast_result result2 (src_details);
1095 const void *base = obj_ptr;
1096 ptrdiff_t offset = __base_info[i].__offset ();
1097 bool is_virtual = __base_info[i].__is_virtual_p ();
1098 bool is_public = __base_info[i].__is_public_p ();
1099
1100 if (!is_public && !(src_details & __non_diamond_repeat_mask))
1101 // original cannot have an ambiguous base, so skip private bases
1102 continue;
1103
1104 if (base)
1105 base = convert_to_base (base, is_virtual, offset);
1106
1107 if (__base_info[i].__base->__do_upcast (dst, base, result2))
1108 {
1109 if (result2.base_type == nonvirtual_base_type && is_virtual)
1110 result2.base_type = __base_info[i].__base;
1111 if (contained_p (result2.part2dst) && !is_public)
1112 result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask);
1113
1114 if (!result.base_type)
1115 {
1116 result = result2;
1117 if (!contained_p (result.part2dst))
1118 return true; // found ambiguously
1119
1120 if (result.part2dst & __contained_public_mask)
1121 {
1122 if (!(__flags & __non_diamond_repeat_mask))
1123 return true; // cannot have an ambiguous other base
1124 }
1125 else
1126 {
1127 if (!virtual_p (result.part2dst))
1128 return true; // cannot have another path
1129 if (!(__flags & __diamond_shaped_mask))
1130 return true; // cannot have a more accessible path
1131 }
1132 }
1133 else if (result.dst_ptr != result2.dst_ptr)
1134 {
1135 // Found an ambiguity.
1136 result.dst_ptr = NULL;
1137 result.part2dst = __contained_ambig;
1138 return true;
1139 }
1140 else if (result.dst_ptr)
1141 {
1142 // Ok, found real object via a virtual path.
1143 result.part2dst
1144 = __sub_kind (result.part2dst | result2.part2dst);
1145 }
1146 else
1147 {
1148 // Dealing with a null pointer, need to check vbase
1149 // containing each of the two choices.
1150 if (result2.base_type == nonvirtual_base_type
1151 || result.base_type == nonvirtual_base_type
1152 || !(*result2.base_type == *result.base_type))
1153 {
1154 // Already ambiguous, not virtual or via different virtuals.
1155 // Cannot match.
1156 result.part2dst = __contained_ambig;
1157 return true;
1158 }
1159 result.part2dst
1160 = __sub_kind (result.part2dst | result2.part2dst);
1161 }
1162 }
1163 }
1164 return result.part2dst != __unknown;
1165}
1166
1167// this is the external interface to the dynamic cast machinery
1168extern "C" void *
1169__dynamic_cast (const void *src_ptr, // object started from
1170 const __class_type_info *src_type, // type of the starting object
1171 const __class_type_info *dst_type, // desired target type
1172 ptrdiff_t src2dst) // how src and dst are related
1173{
1174 const void *vtable = *static_cast <const void *const *> (src_ptr);
1175 const vtable_prefix *prefix =
1176 adjust_pointer <vtable_prefix> (vtable,
1177 -offsetof (vtable_prefix, origin));
1178 const void *whole_ptr =
1179 adjust_pointer <void> (src_ptr, prefix->whole_object);
1180 const __class_type_info *whole_type = prefix->whole_type;
1181 __class_type_info::__dyncast_result result;
1182
1183 whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
1184 dst_type, whole_ptr, src_type, src_ptr, result);
1185 if (!result.dst_ptr)
1186 return NULL;
1187 if (contained_public_p (result.dst2src))
1188 // Src is known to be a public base of dst.
1189 return const_cast <void *> (result.dst_ptr);
1190 if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst)))
1191 // Both src and dst are known to be public bases of whole. Found a valid
1192 // cross cast.
1193 return const_cast <void *> (result.dst_ptr);
1194 if (contained_nonvirtual_p (result.whole2src))
1195 // Src is known to be a non-public nonvirtual base of whole, and not a
1196 // base of dst. Found an invalid cross cast, which cannot also be a down
1197 // cast
1198 return NULL;
1199 if (result.dst2src == __class_type_info::__unknown)
1200 result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
1201 src_type, src_ptr);
1202 if (contained_public_p (result.dst2src))
1203 // Found a valid down cast
1204 return const_cast <void *> (result.dst_ptr);
1205 // Must be an invalid down cast, or the cross cast wasn't bettered
1206 return NULL;
1207}
1208
1209}; // namespace __cxxabiv1
1210#endif