197403Sobrien// Methods for type_info for -*- C++ -*- Run Time Type Identification.
2169691Skan// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3169691Skan// 2003, 2004, 2005, 2006, 2007
497403Sobrien// Free Software Foundation
597403Sobrien//
6132720Skan// This file is part of GCC.
797403Sobrien//
8132720Skan// GCC is free software; you can redistribute it and/or modify
997403Sobrien// it under the terms of the GNU General Public License as published by
1097403Sobrien// the Free Software Foundation; either version 2, or (at your option)
1197403Sobrien// any later version.
1297403Sobrien
13132720Skan// GCC is distributed in the hope that it will be useful,
1497403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1597403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1697403Sobrien// GNU General Public License for more details.
1797403Sobrien
1897403Sobrien// You should have received a copy of the GNU General Public License
19132720Skan// along with GCC; see the file COPYING.  If not, write to
20169691Skan// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21169691Skan// Boston, MA 02110-1301, USA.
2297403Sobrien
2397403Sobrien// As a special exception, you may use this file as part of a free software
2497403Sobrien// library without restriction.  Specifically, if other files instantiate
2597403Sobrien// templates or use macros or inline functions from this file, or you compile
2697403Sobrien// this file and link it with other files to produce an executable, this
2797403Sobrien// file does not by itself cause the resulting executable to be covered by
2897403Sobrien// the GNU General Public License.  This exception does not however
2997403Sobrien// invalidate any other reasons why the executable file might be covered by
3097403Sobrien// the GNU General Public License.
3197403Sobrien
32117397Skan#include <bits/c++config.h>
3397403Sobrien#include <cstddef>
3497403Sobrien#include "tinfo.h"
3597403Sobrien#include "new"			// for placement new
3697403Sobrien
3797403Sobrien// This file contains the minimal working set necessary to link with code
3897403Sobrien// that uses virtual functions and -frtti but does not actually use RTTI
3997403Sobrien// functionality.
4097403Sobrien
4197403Sobrienstd::type_info::
4297403Sobrien~type_info ()
4397403Sobrien{ }
4497403Sobrien
4597403Sobrienstd::bad_cast::~bad_cast() throw() { }
4697403Sobrienstd::bad_typeid::~bad_typeid() throw() { }
4797403Sobrien
48169691Skanconst char*
49169691Skanstd::bad_cast::what() const throw()
50169691Skan{
51169691Skan  return "std::bad_cast";
52169691Skan}
53169691Skan
54169691Skanconst char*
55169691Skanstd::bad_typeid::what() const throw()
56169691Skan{
57169691Skan  return "std::bad_typeid";
58169691Skan}
59169691Skan
6097403Sobrien#if !__GXX_MERGED_TYPEINFO_NAMES
6197403Sobrien
6297403Sobrien// We can't rely on common symbols being shared between shared objects.
6397403Sobrienbool std::type_info::
6497403Sobrienoperator== (const std::type_info& arg) const
6597403Sobrien{
6697403Sobrien  return (&arg == this) || (__builtin_strcmp (name (), arg.name ()) == 0);
6797403Sobrien}
6897403Sobrien
6997403Sobrien#endif
7097403Sobrien
7197403Sobriennamespace std {
7297403Sobrien
7397403Sobrien// return true if this is a type_info for a pointer type
7497403Sobrienbool type_info::
7597403Sobrien__is_pointer_p () const
7697403Sobrien{
7797403Sobrien  return false;
7897403Sobrien}
7997403Sobrien
8097403Sobrien// return true if this is a type_info for a function type
8197403Sobrienbool type_info::
8297403Sobrien__is_function_p () const
8397403Sobrien{
8497403Sobrien  return false;
8597403Sobrien}
8697403Sobrien
8797403Sobrien// try and catch a thrown object.
8897403Sobrienbool type_info::
8997403Sobrien__do_catch (const type_info *thr_type, void **, unsigned) const
9097403Sobrien{
9197403Sobrien  return *this == *thr_type;
9297403Sobrien}
9397403Sobrien
9497403Sobrien// upcast from this type to the target. __class_type_info will override
9597403Sobrienbool type_info::
9697403Sobrien__do_upcast (const abi::__class_type_info *, void **) const
9797403Sobrien{
9897403Sobrien  return false;
9997403Sobrien}
10097403Sobrien
101132720Skan}
10297403Sobrien
10397403Sobriennamespace {
10497403Sobrien
10597403Sobrienusing namespace std;
10697403Sobrienusing namespace abi;
10797403Sobrien
108117397Skan// Initial part of a vtable, this structure is used with offsetof, so we don't
10997403Sobrien// have to keep alignments consistent manually.
110117397Skanstruct vtable_prefix
111117397Skan{
112117397Skan  // Offset to most derived object.
113117397Skan  ptrdiff_t whole_object;
114117397Skan
115117397Skan  // Additional padding if necessary.
116132720Skan#ifdef _GLIBCXX_VTABLE_PADDING
117117397Skan  ptrdiff_t padding1;
118117397Skan#endif
119117397Skan
120117397Skan  // Pointer to most derived type_info.
121117397Skan  const __class_type_info *whole_type;
122117397Skan
123117397Skan  // Additional padding if necessary.
124132720Skan#ifdef _GLIBCXX_VTABLE_PADDING
125117397Skan  ptrdiff_t padding2;
126117397Skan#endif
127117397Skan
128117397Skan  // What a class's vptr points to.
129117397Skan  const void *origin;
13097403Sobrien};
13197403Sobrien
13297403Sobrientemplate <typename T>
13397403Sobrieninline const T *
13497403Sobrienadjust_pointer (const void *base, ptrdiff_t offset)
13597403Sobrien{
13697403Sobrien  return reinterpret_cast <const T *>
13797403Sobrien    (reinterpret_cast <const char *> (base) + offset);
13897403Sobrien}
13997403Sobrien
14097403Sobrien// ADDR is a pointer to an object.  Convert it to a pointer to a base,
14197403Sobrien// using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base.
14297403Sobrieninline void const *
14397403Sobrienconvert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset)
14497403Sobrien{
14597403Sobrien  if (is_virtual)
14697403Sobrien    {
14797403Sobrien      const void *vtable = *static_cast <const void *const *> (addr);
14897403Sobrien
14997403Sobrien      offset = *adjust_pointer<ptrdiff_t> (vtable, offset);
15097403Sobrien    }
15197403Sobrien
15297403Sobrien  return adjust_pointer<void> (addr, offset);
15397403Sobrien}
15497403Sobrien
15597403Sobrien// some predicate functions for __class_type_info::__sub_kind
15697403Sobrieninline bool contained_p (__class_type_info::__sub_kind access_path)
15797403Sobrien{
15897403Sobrien  return access_path >= __class_type_info::__contained_mask;
15997403Sobrien}
16097403Sobrieninline bool public_p (__class_type_info::__sub_kind access_path)
16197403Sobrien{
16297403Sobrien  return access_path & __class_type_info::__contained_public_mask;
16397403Sobrien}
16497403Sobrieninline bool virtual_p (__class_type_info::__sub_kind access_path)
16597403Sobrien{
16697403Sobrien  return (access_path & __class_type_info::__contained_virtual_mask);
16797403Sobrien}
16897403Sobrieninline bool contained_public_p (__class_type_info::__sub_kind access_path)
16997403Sobrien{
17097403Sobrien  return ((access_path & __class_type_info::__contained_public)
17197403Sobrien          == __class_type_info::__contained_public);
17297403Sobrien}
17397403Sobrieninline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path)
17497403Sobrien{
17597403Sobrien  return ((access_path & __class_type_info::__contained_public)
17697403Sobrien          == __class_type_info::__contained_mask);
17797403Sobrien}
17897403Sobrieninline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path)
17997403Sobrien{
18097403Sobrien  return ((access_path & (__class_type_info::__contained_mask
18197403Sobrien                          | __class_type_info::__contained_virtual_mask))
18297403Sobrien          == __class_type_info::__contained_mask);
18397403Sobrien}
18497403Sobrien
18597403Sobrienstatic const __class_type_info *const nonvirtual_base_type =
18697403Sobrien    static_cast <const __class_type_info *> (0) + 1;
18797403Sobrien
188132720Skan} // namespace
18997403Sobrien
19097403Sobriennamespace __cxxabiv1
19197403Sobrien{
19297403Sobrien
19397403Sobrien__class_type_info::
19497403Sobrien~__class_type_info ()
19597403Sobrien{}
19697403Sobrien
19797403Sobrien__si_class_type_info::
19897403Sobrien~__si_class_type_info ()
19997403Sobrien{}
20097403Sobrien
20197403Sobrien__vmi_class_type_info::
20297403Sobrien~__vmi_class_type_info ()
20397403Sobrien{}
20497403Sobrien
20597403Sobrien// __upcast_result is used to hold information during traversal of a class
20697403Sobrien// hierarchy when catch matching.
20797403Sobrienstruct __class_type_info::__upcast_result
20897403Sobrien{
20997403Sobrien  const void *dst_ptr;        // pointer to caught object
21097403Sobrien  __sub_kind part2dst;        // path from current base to target
21197403Sobrien  int src_details;            // hints about the source type hierarchy
21297403Sobrien  const __class_type_info *base_type; // where we found the target,
21397403Sobrien                              // if in vbase the __class_type_info of vbase
21497403Sobrien                              // if a non-virtual base then 1
21597403Sobrien                              // else NULL
21697403Sobrien  __upcast_result (int d)
21797403Sobrien    :dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL)
21897403Sobrien    {}
21997403Sobrien};
22097403Sobrien
22197403Sobrien// __dyncast_result is used to hold information during traversal of a class
22297403Sobrien// hierarchy when dynamic casting.
22397403Sobrienstruct __class_type_info::__dyncast_result
22497403Sobrien{
22597403Sobrien  const void *dst_ptr;        // pointer to target object or NULL
22697403Sobrien  __sub_kind whole2dst;       // path from most derived object to target
22797403Sobrien  __sub_kind whole2src;       // path from most derived object to sub object
22897403Sobrien  __sub_kind dst2src;         // path from target to sub object
22997403Sobrien  int whole_details;          // details of the whole class hierarchy
23097403Sobrien
23197403Sobrien  __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask)
23297403Sobrien    :dst_ptr (NULL), whole2dst (__unknown),
23397403Sobrien     whole2src (__unknown), dst2src (__unknown),
23497403Sobrien     whole_details (details_)
23597403Sobrien    {}
236132720Skan
237132720Skanprotected:
238132720Skan  __dyncast_result(const __dyncast_result&);
239132720Skan
240132720Skan  __dyncast_result&
241132720Skan  operator=(const __dyncast_result&);
24297403Sobrien};
24397403Sobrien
24497403Sobrienbool __class_type_info::
24597403Sobrien__do_catch (const type_info *thr_type,
24697403Sobrien            void **thr_obj,
24797403Sobrien            unsigned outer) const
24897403Sobrien{
24997403Sobrien  if (*this == *thr_type)
25097403Sobrien    return true;
25197403Sobrien  if (outer >= 4)
25297403Sobrien    // Neither `A' nor `A *'.
25397403Sobrien    return false;
25497403Sobrien  return thr_type->__do_upcast (this, thr_obj);
25597403Sobrien}
25697403Sobrien
25797403Sobrienbool __class_type_info::
25897403Sobrien__do_upcast (const __class_type_info *dst_type,
25997403Sobrien             void **obj_ptr) const
26097403Sobrien{
26197403Sobrien  __upcast_result result (__vmi_class_type_info::__flags_unknown_mask);
26297403Sobrien
26397403Sobrien  __do_upcast (dst_type, *obj_ptr, result);
26497403Sobrien  if (!contained_public_p (result.part2dst))
26597403Sobrien    return false;
26697403Sobrien  *obj_ptr = const_cast <void *> (result.dst_ptr);
26797403Sobrien  return true;
26897403Sobrien}
26997403Sobrien
27097403Sobrieninline __class_type_info::__sub_kind __class_type_info::
27197403Sobrien__find_public_src (ptrdiff_t src2dst,
27297403Sobrien                   const void *obj_ptr,
27397403Sobrien                   const __class_type_info *src_type,
27497403Sobrien                   const void *src_ptr) const
27597403Sobrien{
27697403Sobrien  if (src2dst >= 0)
27797403Sobrien    return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
27897403Sobrien            ? __contained_public : __not_contained;
27997403Sobrien  if (src2dst == -2)
28097403Sobrien    return __not_contained;
28197403Sobrien  return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
28297403Sobrien}
28397403Sobrien
28497403Sobrien__class_type_info::__sub_kind __class_type_info::
28597403Sobrien__do_find_public_src (ptrdiff_t,
28697403Sobrien                      const void *obj_ptr,
28797403Sobrien                      const __class_type_info *,
28897403Sobrien                      const void *src_ptr) const
28997403Sobrien{
29097403Sobrien  if (src_ptr == obj_ptr)
29197403Sobrien    // Must be our type, as the pointers match.
29297403Sobrien    return __contained_public;
29397403Sobrien  return __not_contained;
29497403Sobrien}
29597403Sobrien
29697403Sobrien__class_type_info::__sub_kind __si_class_type_info::
29797403Sobrien__do_find_public_src (ptrdiff_t src2dst,
29897403Sobrien                      const void *obj_ptr,
29997403Sobrien                      const __class_type_info *src_type,
30097403Sobrien                      const void *src_ptr) const
30197403Sobrien{
30297403Sobrien  if (src_ptr == obj_ptr && *this == *src_type)
30397403Sobrien    return __contained_public;
30497403Sobrien  return __base_type->__do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
30597403Sobrien}
30697403Sobrien
30797403Sobrien__class_type_info::__sub_kind __vmi_class_type_info::
30897403Sobrien__do_find_public_src (ptrdiff_t src2dst,
30997403Sobrien                      const void *obj_ptr,
31097403Sobrien                      const __class_type_info *src_type,
31197403Sobrien                      const void *src_ptr) const
31297403Sobrien{
31397403Sobrien  if (obj_ptr == src_ptr && *this == *src_type)
31497403Sobrien    return __contained_public;
31597403Sobrien
31697403Sobrien  for (std::size_t i = __base_count; i--;)
31797403Sobrien    {
31897403Sobrien      if (!__base_info[i].__is_public_p ())
31997403Sobrien        continue; // Not public, can't be here.
32097403Sobrien
32197403Sobrien      const void *base = obj_ptr;
32297403Sobrien      ptrdiff_t offset = __base_info[i].__offset ();
32397403Sobrien      bool is_virtual = __base_info[i].__is_virtual_p ();
32497403Sobrien
32597403Sobrien      if (is_virtual)
32697403Sobrien        {
32797403Sobrien          if (src2dst == -3)
32897403Sobrien            continue; // Not a virtual base, so can't be here.
32997403Sobrien        }
33097403Sobrien      base = convert_to_base (base, is_virtual, offset);
33197403Sobrien
332102782Skan      __sub_kind base_kind = __base_info[i].__base_type->__do_find_public_src
33397403Sobrien                              (src2dst, base, src_type, src_ptr);
33497403Sobrien      if (contained_p (base_kind))
33597403Sobrien        {
33697403Sobrien          if (is_virtual)
33797403Sobrien            base_kind = __sub_kind (base_kind | __contained_virtual_mask);
33897403Sobrien          return base_kind;
33997403Sobrien        }
34097403Sobrien    }
34197403Sobrien
34297403Sobrien  return __not_contained;
34397403Sobrien}
34497403Sobrien
34597403Sobrienbool __class_type_info::
34697403Sobrien__do_dyncast (ptrdiff_t,
34797403Sobrien              __sub_kind access_path,
34897403Sobrien              const __class_type_info *dst_type,
34997403Sobrien              const void *obj_ptr,
35097403Sobrien              const __class_type_info *src_type,
35197403Sobrien              const void *src_ptr,
35297403Sobrien              __dyncast_result &__restrict result) const
35397403Sobrien{
35497403Sobrien  if (obj_ptr == src_ptr && *this == *src_type)
35597403Sobrien    {
35697403Sobrien      // The src object we started from. Indicate how we are accessible from
35797403Sobrien      // the most derived object.
35897403Sobrien      result.whole2src = access_path;
35997403Sobrien      return false;
36097403Sobrien    }
36197403Sobrien  if (*this == *dst_type)
36297403Sobrien    {
36397403Sobrien      result.dst_ptr = obj_ptr;
36497403Sobrien      result.whole2dst = access_path;
36597403Sobrien      result.dst2src = __not_contained;
36697403Sobrien      return false;
36797403Sobrien    }
36897403Sobrien  return false;
36997403Sobrien}
37097403Sobrien
37197403Sobrienbool __si_class_type_info::
37297403Sobrien__do_dyncast (ptrdiff_t src2dst,
37397403Sobrien              __sub_kind access_path,
37497403Sobrien              const __class_type_info *dst_type,
37597403Sobrien              const void *obj_ptr,
37697403Sobrien              const __class_type_info *src_type,
37797403Sobrien              const void *src_ptr,
37897403Sobrien              __dyncast_result &__restrict result) const
37997403Sobrien{
38097403Sobrien  if (*this == *dst_type)
38197403Sobrien    {
38297403Sobrien      result.dst_ptr = obj_ptr;
38397403Sobrien      result.whole2dst = access_path;
38497403Sobrien      if (src2dst >= 0)
38597403Sobrien        result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
38697403Sobrien              ? __contained_public : __not_contained;
38797403Sobrien      else if (src2dst == -2)
38897403Sobrien        result.dst2src = __not_contained;
38997403Sobrien      return false;
39097403Sobrien    }
39197403Sobrien  if (obj_ptr == src_ptr && *this == *src_type)
39297403Sobrien    {
39397403Sobrien      // The src object we started from. Indicate how we are accessible from
39497403Sobrien      // the most derived object.
39597403Sobrien      result.whole2src = access_path;
39697403Sobrien      return false;
39797403Sobrien    }
39897403Sobrien  return __base_type->__do_dyncast (src2dst, access_path, dst_type, obj_ptr,
39997403Sobrien                             src_type, src_ptr, result);
40097403Sobrien}
40197403Sobrien
40297403Sobrien// This is a big hairy function. Although the run-time behaviour of
40397403Sobrien// dynamic_cast is simple to describe, it gives rise to some non-obvious
40497403Sobrien// behaviour. We also desire to determine as early as possible any definite
40597403Sobrien// answer we can get. Because it is unknown what the run-time ratio of
40697403Sobrien// succeeding to failing dynamic casts is, we do not know in which direction
40797403Sobrien// to bias any optimizations. To that end we make no particular effort towards
40897403Sobrien// early fail answers or early success answers. Instead we try to minimize
40997403Sobrien// work by filling in things lazily (when we know we need the information),
41097403Sobrien// and opportunisticly take early success or failure results.
41197403Sobrienbool __vmi_class_type_info::
41297403Sobrien__do_dyncast (ptrdiff_t src2dst,
41397403Sobrien              __sub_kind access_path,
41497403Sobrien              const __class_type_info *dst_type,
41597403Sobrien              const void *obj_ptr,
41697403Sobrien              const __class_type_info *src_type,
41797403Sobrien              const void *src_ptr,
41897403Sobrien              __dyncast_result &__restrict result) const
41997403Sobrien{
42097403Sobrien  if (result.whole_details & __flags_unknown_mask)
42197403Sobrien    result.whole_details = __flags;
42297403Sobrien
42397403Sobrien  if (obj_ptr == src_ptr && *this == *src_type)
42497403Sobrien    {
42597403Sobrien      // The src object we started from. Indicate how we are accessible from
42697403Sobrien      // the most derived object.
42797403Sobrien      result.whole2src = access_path;
42897403Sobrien      return false;
42997403Sobrien    }
43097403Sobrien  if (*this == *dst_type)
43197403Sobrien    {
43297403Sobrien      result.dst_ptr = obj_ptr;
43397403Sobrien      result.whole2dst = access_path;
43497403Sobrien      if (src2dst >= 0)
43597403Sobrien        result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
43697403Sobrien              ? __contained_public : __not_contained;
43797403Sobrien      else if (src2dst == -2)
43897403Sobrien        result.dst2src = __not_contained;
43997403Sobrien      return false;
44097403Sobrien    }
44197403Sobrien
44297403Sobrien  bool result_ambig = false;
44397403Sobrien  for (std::size_t i = __base_count; i--;)
44497403Sobrien    {
44597403Sobrien      __dyncast_result result2 (result.whole_details);
44697403Sobrien      void const *base = obj_ptr;
44797403Sobrien      __sub_kind base_access = access_path;
44897403Sobrien      ptrdiff_t offset = __base_info[i].__offset ();
44997403Sobrien      bool is_virtual = __base_info[i].__is_virtual_p ();
45097403Sobrien
45197403Sobrien      if (is_virtual)
45297403Sobrien        base_access = __sub_kind (base_access | __contained_virtual_mask);
45397403Sobrien      base = convert_to_base (base, is_virtual, offset);
45497403Sobrien
45597403Sobrien      if (!__base_info[i].__is_public_p ())
45697403Sobrien        {
45797403Sobrien          if (src2dst == -2 &&
45897403Sobrien              !(result.whole_details
45997403Sobrien                & (__non_diamond_repeat_mask | __diamond_shaped_mask)))
46097403Sobrien            // The hierarchy has no duplicate bases (which might ambiguate
46197403Sobrien            // things) and where we started is not a public base of what we
46297403Sobrien            // want (so it cannot be a downcast). There is nothing of interest
46397403Sobrien            // hiding in a non-public base.
46497403Sobrien            continue;
46597403Sobrien          base_access = __sub_kind (base_access & ~__contained_public_mask);
46697403Sobrien        }
46797403Sobrien
46897403Sobrien      bool result2_ambig
469102782Skan          = __base_info[i].__base_type->__do_dyncast (src2dst, base_access,
47097403Sobrien                                             dst_type, base,
47197403Sobrien                                             src_type, src_ptr, result2);
47297403Sobrien      result.whole2src = __sub_kind (result.whole2src | result2.whole2src);
47397403Sobrien      if (result2.dst2src == __contained_public
47497403Sobrien          || result2.dst2src == __contained_ambig)
47597403Sobrien        {
47697403Sobrien          result.dst_ptr = result2.dst_ptr;
47797403Sobrien          result.whole2dst = result2.whole2dst;
47897403Sobrien          result.dst2src = result2.dst2src;
47997403Sobrien          // Found a downcast which can't be bettered or an ambiguous downcast
48097403Sobrien          // which can't be disambiguated
48197403Sobrien          return result2_ambig;
48297403Sobrien        }
48397403Sobrien
48497403Sobrien      if (!result_ambig && !result.dst_ptr)
48597403Sobrien        {
48697403Sobrien          // Not found anything yet.
48797403Sobrien          result.dst_ptr = result2.dst_ptr;
48897403Sobrien          result.whole2dst = result2.whole2dst;
48997403Sobrien          result_ambig = result2_ambig;
49097403Sobrien          if (result.dst_ptr && result.whole2src != __unknown
49197403Sobrien              && !(__flags & __non_diamond_repeat_mask))
49297403Sobrien            // Found dst and src and we don't have repeated bases.
49397403Sobrien            return result_ambig;
49497403Sobrien        }
49597403Sobrien      else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
49697403Sobrien        {
49797403Sobrien          // Found at same address, must be via virtual.  Pick the most
49897403Sobrien          // accessible path.
49997403Sobrien          result.whole2dst =
50097403Sobrien              __sub_kind (result.whole2dst | result2.whole2dst);
50197403Sobrien        }
502241959Sdim      else if ((result.dst_ptr != 0 && result2.dst_ptr != 0)
503241959Sdim	       || (result.dst_ptr != 0 && result2_ambig)
504241959Sdim	       || (result2.dst_ptr != 0 && result_ambig))
50597403Sobrien        {
50697403Sobrien          // Found two different DST_TYPE bases, or a valid one and a set of
50797403Sobrien          // ambiguous ones, must disambiguate. See whether SRC_PTR is
50897403Sobrien          // contained publicly within one of the non-ambiguous choices. If it
50997403Sobrien          // is in only one, then that's the choice. If it is in both, then
51097403Sobrien          // we're ambiguous and fail. If it is in neither, we're ambiguous,
51197403Sobrien          // but don't yet fail as we might later find a third base which does
51297403Sobrien          // contain SRC_PTR.
51397403Sobrien
51497403Sobrien          __sub_kind new_sub_kind = result2.dst2src;
51597403Sobrien          __sub_kind old_sub_kind = result.dst2src;
51697403Sobrien
51797403Sobrien          if (contained_p (result.whole2src)
51897403Sobrien              && (!virtual_p (result.whole2src)
51997403Sobrien                  || !(result.whole_details & __diamond_shaped_mask)))
52097403Sobrien            {
52197403Sobrien              // We already found SRC_PTR as a base of most derived, and
52297403Sobrien              // either it was non-virtual, or the whole hierarchy is
52397403Sobrien              // not-diamond shaped. Therefore if it is in either choice, it
52497403Sobrien              // can only be in one of them, and we will already know.
52597403Sobrien              if (old_sub_kind == __unknown)
52697403Sobrien                old_sub_kind = __not_contained;
52797403Sobrien              if (new_sub_kind == __unknown)
52897403Sobrien                new_sub_kind = __not_contained;
52997403Sobrien            }
53097403Sobrien          else
53197403Sobrien            {
53297403Sobrien              if (old_sub_kind >= __not_contained)
53397403Sobrien                ;// already calculated
53497403Sobrien              else if (contained_p (new_sub_kind)
53597403Sobrien                       && (!virtual_p (new_sub_kind)
53697403Sobrien                           || !(__flags & __diamond_shaped_mask)))
53797403Sobrien                // Already found inside the other choice, and it was
53897403Sobrien                // non-virtual or we are not diamond shaped.
53997403Sobrien                old_sub_kind = __not_contained;
54097403Sobrien              else
54197403Sobrien                old_sub_kind = dst_type->__find_public_src
54297403Sobrien                                (src2dst, result.dst_ptr, src_type, src_ptr);
54397403Sobrien
54497403Sobrien              if (new_sub_kind >= __not_contained)
54597403Sobrien                ;// already calculated
54697403Sobrien              else if (contained_p (old_sub_kind)
54797403Sobrien                       && (!virtual_p (old_sub_kind)
54897403Sobrien                           || !(__flags & __diamond_shaped_mask)))
54997403Sobrien                // Already found inside the other choice, and it was
55097403Sobrien                // non-virtual or we are not diamond shaped.
55197403Sobrien                new_sub_kind = __not_contained;
55297403Sobrien              else
55397403Sobrien                new_sub_kind = dst_type->__find_public_src
55497403Sobrien                                (src2dst, result2.dst_ptr, src_type, src_ptr);
55597403Sobrien            }
55697403Sobrien
55797403Sobrien          // Neither sub_kind can be contained_ambig -- we bail out early
55897403Sobrien          // when we find those.
55997403Sobrien          if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind)))
56097403Sobrien            {
56197403Sobrien              // Only on one choice, not ambiguous.
56297403Sobrien              if (contained_p (new_sub_kind))
56397403Sobrien                {
56497403Sobrien                  // Only in new.
56597403Sobrien                  result.dst_ptr = result2.dst_ptr;
56697403Sobrien                  result.whole2dst = result2.whole2dst;
56797403Sobrien                  result_ambig = false;
56897403Sobrien                  old_sub_kind = new_sub_kind;
56997403Sobrien                }
57097403Sobrien              result.dst2src = old_sub_kind;
57197403Sobrien              if (public_p (result.dst2src))
57297403Sobrien                return false; // Can't be an ambiguating downcast for later discovery.
57397403Sobrien              if (!virtual_p (result.dst2src))
57497403Sobrien                return false; // Found non-virtually can't be bettered
57597403Sobrien            }
57697403Sobrien          else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind)))
57797403Sobrien            {
57897403Sobrien              // In both.
57997403Sobrien              result.dst_ptr = NULL;
58097403Sobrien              result.dst2src = __contained_ambig;
58197403Sobrien              return true;  // Fail.
58297403Sobrien            }
58397403Sobrien          else
58497403Sobrien            {
58597403Sobrien              // In neither publicly, ambiguous for the moment, but keep
58697403Sobrien              // looking. It is possible that it was private in one or
58797403Sobrien              // both and therefore we should fail, but that's just tough.
58897403Sobrien              result.dst_ptr = NULL;
58997403Sobrien              result.dst2src = __not_contained;
59097403Sobrien              result_ambig = true;
59197403Sobrien            }
59297403Sobrien        }
59397403Sobrien
59497403Sobrien      if (result.whole2src == __contained_private)
59597403Sobrien        // We found SRC_PTR as a private non-virtual base, therefore all
59697403Sobrien        // cross casts will fail. We have already found a down cast, if
59797403Sobrien        // there is one.
59897403Sobrien        return result_ambig;
59997403Sobrien    }
60097403Sobrien
60197403Sobrien  return result_ambig;
60297403Sobrien}
60397403Sobrien
60497403Sobrienbool __class_type_info::
60597403Sobrien__do_upcast (const __class_type_info *dst, const void *obj,
60697403Sobrien             __upcast_result &__restrict result) const
60797403Sobrien{
60897403Sobrien  if (*this == *dst)
60997403Sobrien    {
61097403Sobrien      result.dst_ptr = obj;
61197403Sobrien      result.base_type = nonvirtual_base_type;
61297403Sobrien      result.part2dst = __contained_public;
61397403Sobrien      return true;
61497403Sobrien    }
61597403Sobrien  return false;
61697403Sobrien}
61797403Sobrien
61897403Sobrienbool __si_class_type_info::
61997403Sobrien__do_upcast (const __class_type_info *dst, const void *obj_ptr,
62097403Sobrien             __upcast_result &__restrict result) const
62197403Sobrien{
62297403Sobrien  if (__class_type_info::__do_upcast (dst, obj_ptr, result))
62397403Sobrien    return true;
62497403Sobrien
62597403Sobrien  return __base_type->__do_upcast (dst, obj_ptr, result);
62697403Sobrien}
62797403Sobrien
62897403Sobrienbool __vmi_class_type_info::
62997403Sobrien__do_upcast (const __class_type_info *dst, const void *obj_ptr,
63097403Sobrien             __upcast_result &__restrict result) const
63197403Sobrien{
63297403Sobrien  if (__class_type_info::__do_upcast (dst, obj_ptr, result))
63397403Sobrien    return true;
63497403Sobrien
63597403Sobrien  int src_details = result.src_details;
63697403Sobrien  if (src_details & __flags_unknown_mask)
63797403Sobrien    src_details = __flags;
63897403Sobrien
63997403Sobrien  for (std::size_t i = __base_count; i--;)
64097403Sobrien    {
64197403Sobrien      __upcast_result result2 (src_details);
64297403Sobrien      const void *base = obj_ptr;
64397403Sobrien      ptrdiff_t offset = __base_info[i].__offset ();
64497403Sobrien      bool is_virtual = __base_info[i].__is_virtual_p ();
64597403Sobrien      bool is_public = __base_info[i].__is_public_p ();
64697403Sobrien
64797403Sobrien      if (!is_public && !(src_details & __non_diamond_repeat_mask))
64897403Sobrien        // original cannot have an ambiguous base, so skip private bases
64997403Sobrien        continue;
65097403Sobrien
65197403Sobrien      if (base)
65297403Sobrien        base = convert_to_base (base, is_virtual, offset);
65397403Sobrien
654102782Skan      if (__base_info[i].__base_type->__do_upcast (dst, base, result2))
65597403Sobrien        {
65697403Sobrien          if (result2.base_type == nonvirtual_base_type && is_virtual)
657102782Skan            result2.base_type = __base_info[i].__base_type;
65897403Sobrien          if (contained_p (result2.part2dst) && !is_public)
65997403Sobrien            result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask);
66097403Sobrien
66197403Sobrien          if (!result.base_type)
66297403Sobrien            {
66397403Sobrien              result = result2;
66497403Sobrien              if (!contained_p (result.part2dst))
66597403Sobrien                return true; // found ambiguously
66697403Sobrien
66797403Sobrien              if (result.part2dst & __contained_public_mask)
66897403Sobrien                {
66997403Sobrien                  if (!(__flags & __non_diamond_repeat_mask))
67097403Sobrien                    return true;  // cannot have an ambiguous other base
67197403Sobrien                }
67297403Sobrien              else
67397403Sobrien                {
67497403Sobrien                  if (!virtual_p (result.part2dst))
67597403Sobrien                    return true; // cannot have another path
67697403Sobrien                  if (!(__flags & __diamond_shaped_mask))
67797403Sobrien                    return true; // cannot have a more accessible path
67897403Sobrien                }
67997403Sobrien            }
68097403Sobrien          else if (result.dst_ptr != result2.dst_ptr)
68197403Sobrien            {
68297403Sobrien              // Found an ambiguity.
68397403Sobrien	      result.dst_ptr = NULL;
68497403Sobrien	      result.part2dst = __contained_ambig;
68597403Sobrien	      return true;
68697403Sobrien            }
68797403Sobrien          else if (result.dst_ptr)
68897403Sobrien            {
68997403Sobrien              // Ok, found real object via a virtual path.
69097403Sobrien              result.part2dst
69197403Sobrien                  = __sub_kind (result.part2dst | result2.part2dst);
69297403Sobrien            }
69397403Sobrien          else
69497403Sobrien            {
69597403Sobrien              // Dealing with a null pointer, need to check vbase
69697403Sobrien              // containing each of the two choices.
69797403Sobrien              if (result2.base_type == nonvirtual_base_type
69897403Sobrien                  || result.base_type == nonvirtual_base_type
69997403Sobrien                  || !(*result2.base_type == *result.base_type))
70097403Sobrien                {
70197403Sobrien                  // Already ambiguous, not virtual or via different virtuals.
70297403Sobrien                  // Cannot match.
70397403Sobrien                  result.part2dst = __contained_ambig;
70497403Sobrien                  return true;
70597403Sobrien                }
70697403Sobrien              result.part2dst
70797403Sobrien                  = __sub_kind (result.part2dst | result2.part2dst);
70897403Sobrien            }
70997403Sobrien        }
71097403Sobrien    }
71197403Sobrien  return result.part2dst != __unknown;
71297403Sobrien}
71397403Sobrien
71497403Sobrien// this is the external interface to the dynamic cast machinery
71597403Sobrienextern "C" void *
71697403Sobrien__dynamic_cast (const void *src_ptr,    // object started from
71797403Sobrien                const __class_type_info *src_type, // type of the starting object
71897403Sobrien                const __class_type_info *dst_type, // desired target type
71997403Sobrien                ptrdiff_t src2dst) // how src and dst are related
72097403Sobrien{
72197403Sobrien  const void *vtable = *static_cast <const void *const *> (src_ptr);
72297403Sobrien  const vtable_prefix *prefix =
72397403Sobrien      adjust_pointer <vtable_prefix> (vtable,
72497403Sobrien				      -offsetof (vtable_prefix, origin));
72597403Sobrien  const void *whole_ptr =
72697403Sobrien      adjust_pointer <void> (src_ptr, prefix->whole_object);
72797403Sobrien  const __class_type_info *whole_type = prefix->whole_type;
72897403Sobrien  __class_type_info::__dyncast_result result;
72997403Sobrien
73097403Sobrien  whole_type->__do_dyncast (src2dst, __class_type_info::__contained_public,
73197403Sobrien                            dst_type, whole_ptr, src_type, src_ptr, result);
73297403Sobrien  if (!result.dst_ptr)
73397403Sobrien    return NULL;
73497403Sobrien  if (contained_public_p (result.dst2src))
73597403Sobrien    // Src is known to be a public base of dst.
73697403Sobrien    return const_cast <void *> (result.dst_ptr);
73797403Sobrien  if (contained_public_p (__class_type_info::__sub_kind (result.whole2src & result.whole2dst)))
73897403Sobrien    // Both src and dst are known to be public bases of whole. Found a valid
73997403Sobrien    // cross cast.
74097403Sobrien    return const_cast <void *> (result.dst_ptr);
74197403Sobrien  if (contained_nonvirtual_p (result.whole2src))
74297403Sobrien    // Src is known to be a non-public nonvirtual base of whole, and not a
74397403Sobrien    // base of dst. Found an invalid cross cast, which cannot also be a down
74497403Sobrien    // cast
74597403Sobrien    return NULL;
74697403Sobrien  if (result.dst2src == __class_type_info::__unknown)
74797403Sobrien    result.dst2src = dst_type->__find_public_src (src2dst, result.dst_ptr,
74897403Sobrien                                                  src_type, src_ptr);
74997403Sobrien  if (contained_public_p (result.dst2src))
75097403Sobrien    // Found a valid down cast
75197403Sobrien    return const_cast <void *> (result.dst_ptr);
75297403Sobrien  // Must be an invalid down cast, or the cross cast wasn't bettered
75397403Sobrien  return NULL;
75497403Sobrien}
75597403Sobrien
756132720Skan} // namespace __cxxabiv1
757