1*ec02198aSmrg // Copyright (C) 1994-2020 Free Software Foundation, Inc.
210d565efSmrg //
310d565efSmrg // This file is part of GCC.
410d565efSmrg //
510d565efSmrg // GCC is free software; you can redistribute it and/or modify
610d565efSmrg // it under the terms of the GNU General Public License as published by
710d565efSmrg // the Free Software Foundation; either version 3, or (at your option)
810d565efSmrg // any later version.
910d565efSmrg 
1010d565efSmrg // GCC is distributed in the hope that it will be useful,
1110d565efSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
1210d565efSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1310d565efSmrg // GNU General Public License for more details.
1410d565efSmrg 
1510d565efSmrg // Under Section 7 of GPL version 3, you are granted additional
1610d565efSmrg // permissions described in the GCC Runtime Library Exception, version
1710d565efSmrg // 3.1, as published by the Free Software Foundation.
1810d565efSmrg 
1910d565efSmrg // You should have received a copy of the GNU General Public License and
2010d565efSmrg // a copy of the GCC Runtime Library Exception along with this program;
2110d565efSmrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2210d565efSmrg // <http://www.gnu.org/licenses/>.
2310d565efSmrg 
2410d565efSmrg #include "tinfo.h"
2510d565efSmrg 
2610d565efSmrg namespace __cxxabiv1 {
2710d565efSmrg 
2810d565efSmrg __vmi_class_type_info::
~__vmi_class_type_info()2910d565efSmrg ~__vmi_class_type_info ()
3010d565efSmrg {}
3110d565efSmrg 
3210d565efSmrg __class_type_info::__sub_kind __vmi_class_type_info::
__do_find_public_src(ptrdiff_t src2dst,const void * obj_ptr,const __class_type_info * src_type,const void * src_ptr) const3310d565efSmrg __do_find_public_src (ptrdiff_t src2dst,
3410d565efSmrg                       const void *obj_ptr,
3510d565efSmrg                       const __class_type_info *src_type,
3610d565efSmrg                       const void *src_ptr) const
3710d565efSmrg {
3810d565efSmrg   if (obj_ptr == src_ptr && *this == *src_type)
3910d565efSmrg     return __contained_public;
4010d565efSmrg 
4110d565efSmrg   for (std::size_t i = __base_count; i--;)
4210d565efSmrg     {
4310d565efSmrg       if (!__base_info[i].__is_public_p ())
4410d565efSmrg         continue; // Not public, can't be here.
4510d565efSmrg 
4610d565efSmrg       const void *base = obj_ptr;
4710d565efSmrg       ptrdiff_t offset = __base_info[i].__offset ();
4810d565efSmrg       bool is_virtual = __base_info[i].__is_virtual_p ();
4910d565efSmrg 
5010d565efSmrg       if (is_virtual)
5110d565efSmrg         {
5210d565efSmrg           if (src2dst == -3)
5310d565efSmrg             continue; // Not a virtual base, so can't be here.
5410d565efSmrg         }
5510d565efSmrg       base = convert_to_base (base, is_virtual, offset);
5610d565efSmrg 
5710d565efSmrg       __sub_kind base_kind = __base_info[i].__base_type->__do_find_public_src
5810d565efSmrg                               (src2dst, base, src_type, src_ptr);
5910d565efSmrg       if (contained_p (base_kind))
6010d565efSmrg         {
6110d565efSmrg           if (is_virtual)
6210d565efSmrg             base_kind = __sub_kind (base_kind | __contained_virtual_mask);
6310d565efSmrg           return base_kind;
6410d565efSmrg         }
6510d565efSmrg     }
6610d565efSmrg 
6710d565efSmrg   return __not_contained;
6810d565efSmrg }
6910d565efSmrg 
7010d565efSmrg // This is a big hairy function. Although the run-time behaviour of
7110d565efSmrg // dynamic_cast is simple to describe, it gives rise to some non-obvious
7210d565efSmrg // behaviour. We also desire to determine as early as possible any definite
7310d565efSmrg // answer we can get. Because it is unknown what the run-time ratio of
7410d565efSmrg // succeeding to failing dynamic casts is, we do not know in which direction
7510d565efSmrg // to bias any optimizations. To that end we make no particular effort towards
7610d565efSmrg // early fail answers or early success answers. Instead we try to minimize
7710d565efSmrg // work by filling in things lazily (when we know we need the information),
7810d565efSmrg // and opportunisticly take early success or failure results.
7910d565efSmrg bool __vmi_class_type_info::
__do_dyncast(ptrdiff_t src2dst,__sub_kind access_path,const __class_type_info * dst_type,const void * obj_ptr,const __class_type_info * src_type,const void * src_ptr,__dyncast_result & __restrict result) const8010d565efSmrg __do_dyncast (ptrdiff_t src2dst,
8110d565efSmrg               __sub_kind access_path,
8210d565efSmrg               const __class_type_info *dst_type,
8310d565efSmrg               const void *obj_ptr,
8410d565efSmrg               const __class_type_info *src_type,
8510d565efSmrg               const void *src_ptr,
8610d565efSmrg               __dyncast_result &__restrict result) const
8710d565efSmrg {
8810d565efSmrg   if (result.whole_details & __flags_unknown_mask)
8910d565efSmrg     result.whole_details = __flags;
9010d565efSmrg 
9110d565efSmrg   if (obj_ptr == src_ptr && *this == *src_type)
9210d565efSmrg     {
9310d565efSmrg       // The src object we started from. Indicate how we are accessible from
9410d565efSmrg       // the most derived object.
9510d565efSmrg       result.whole2src = access_path;
9610d565efSmrg       return false;
9710d565efSmrg     }
9810d565efSmrg   if (*this == *dst_type)
9910d565efSmrg     {
10010d565efSmrg       result.dst_ptr = obj_ptr;
10110d565efSmrg       result.whole2dst = access_path;
10210d565efSmrg       if (src2dst >= 0)
10310d565efSmrg         result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
10410d565efSmrg               ? __contained_public : __not_contained;
10510d565efSmrg       else if (src2dst == -2)
10610d565efSmrg         result.dst2src = __not_contained;
10710d565efSmrg       return false;
10810d565efSmrg     }
10910d565efSmrg 
11010d565efSmrg   // If src_type is a unique non-virtual base of dst_type, we have a good
11110d565efSmrg   // guess at the address we want, so in the first pass try skipping any
11210d565efSmrg   // bases which don't contain that address.
11310d565efSmrg   const void *dst_cand = NULL;
11410d565efSmrg   if (src2dst >= 0)
11510d565efSmrg     dst_cand = adjust_pointer<void>(src_ptr, -src2dst);
11610d565efSmrg   bool first_pass = true;
11710d565efSmrg   bool skipped = false;
11810d565efSmrg 
11910d565efSmrg   bool result_ambig = false;
12010d565efSmrg  again:
12110d565efSmrg   for (std::size_t i = __base_count; i--;)
12210d565efSmrg     {
12310d565efSmrg       __dyncast_result result2 (result.whole_details);
12410d565efSmrg       void const *base = obj_ptr;
12510d565efSmrg       __sub_kind base_access = access_path;
12610d565efSmrg       ptrdiff_t offset = __base_info[i].__offset ();
12710d565efSmrg       bool is_virtual = __base_info[i].__is_virtual_p ();
12810d565efSmrg 
12910d565efSmrg       if (is_virtual)
13010d565efSmrg         base_access = __sub_kind (base_access | __contained_virtual_mask);
13110d565efSmrg       base = convert_to_base (base, is_virtual, offset);
13210d565efSmrg 
13310d565efSmrg       if (dst_cand)
13410d565efSmrg 	{
13510d565efSmrg 	  bool skip_on_first_pass = base > dst_cand;
13610d565efSmrg 	  if (skip_on_first_pass == first_pass)
13710d565efSmrg 	    {
13810d565efSmrg 	      // We aren't interested in this base on this pass: either
13910d565efSmrg 	      // we're on the first pass and this base doesn't contain the
14010d565efSmrg 	      // likely address, or we're on the second pass and we checked
14110d565efSmrg 	      // this base on the first pass.
14210d565efSmrg 	      skipped = true;
14310d565efSmrg 	      continue;
14410d565efSmrg 	    }
14510d565efSmrg 	}
14610d565efSmrg 
14710d565efSmrg       if (!__base_info[i].__is_public_p ())
14810d565efSmrg         {
14910d565efSmrg           if (src2dst == -2 &&
15010d565efSmrg               !(result.whole_details
15110d565efSmrg                 & (__non_diamond_repeat_mask | __diamond_shaped_mask)))
15210d565efSmrg             // The hierarchy has no duplicate bases (which might ambiguate
15310d565efSmrg             // things) and where we started is not a public base of what we
15410d565efSmrg             // want (so it cannot be a downcast). There is nothing of interest
15510d565efSmrg             // hiding in a non-public base.
15610d565efSmrg             continue;
15710d565efSmrg           base_access = __sub_kind (base_access & ~__contained_public_mask);
15810d565efSmrg         }
15910d565efSmrg 
16010d565efSmrg       bool result2_ambig
16110d565efSmrg           = __base_info[i].__base_type->__do_dyncast (src2dst, base_access,
16210d565efSmrg                                              dst_type, base,
16310d565efSmrg                                              src_type, src_ptr, result2);
16410d565efSmrg       result.whole2src = __sub_kind (result.whole2src | result2.whole2src);
16510d565efSmrg       if (result2.dst2src == __contained_public
16610d565efSmrg           || result2.dst2src == __contained_ambig)
16710d565efSmrg         {
16810d565efSmrg           result.dst_ptr = result2.dst_ptr;
16910d565efSmrg           result.whole2dst = result2.whole2dst;
17010d565efSmrg           result.dst2src = result2.dst2src;
17110d565efSmrg           // Found a downcast which can't be bettered or an ambiguous downcast
17210d565efSmrg           // which can't be disambiguated
17310d565efSmrg           return result2_ambig;
17410d565efSmrg         }
17510d565efSmrg 
17610d565efSmrg       if (!result_ambig && !result.dst_ptr)
17710d565efSmrg         {
17810d565efSmrg           // Not found anything yet.
17910d565efSmrg           result.dst_ptr = result2.dst_ptr;
18010d565efSmrg           result.whole2dst = result2.whole2dst;
18110d565efSmrg           result_ambig = result2_ambig;
18210d565efSmrg           if (result.dst_ptr && result.whole2src != __unknown
18310d565efSmrg               && !(__flags & __non_diamond_repeat_mask))
18410d565efSmrg             // Found dst and src and we don't have repeated bases.
18510d565efSmrg             return result_ambig;
18610d565efSmrg         }
18710d565efSmrg       else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
18810d565efSmrg         {
18910d565efSmrg           // Found at same address, must be via virtual.  Pick the most
19010d565efSmrg           // accessible path.
19110d565efSmrg           result.whole2dst =
19210d565efSmrg               __sub_kind (result.whole2dst | result2.whole2dst);
19310d565efSmrg         }
19410d565efSmrg       else if ((result.dst_ptr != 0 && result2.dst_ptr != 0)
19510d565efSmrg 	       || (result.dst_ptr != 0 && result2_ambig)
19610d565efSmrg 	       || (result2.dst_ptr != 0 && result_ambig))
19710d565efSmrg         {
19810d565efSmrg           // Found two different DST_TYPE bases, or a valid one and a set of
19910d565efSmrg           // ambiguous ones, must disambiguate. See whether SRC_PTR is
20010d565efSmrg           // contained publicly within one of the non-ambiguous choices. If it
20110d565efSmrg           // is in only one, then that's the choice. If it is in both, then
20210d565efSmrg           // we're ambiguous and fail. If it is in neither, we're ambiguous,
20310d565efSmrg           // but don't yet fail as we might later find a third base which does
20410d565efSmrg           // contain SRC_PTR.
20510d565efSmrg 
20610d565efSmrg           __sub_kind new_sub_kind = result2.dst2src;
20710d565efSmrg           __sub_kind old_sub_kind = result.dst2src;
20810d565efSmrg 
20910d565efSmrg           if (contained_p (result.whole2src)
21010d565efSmrg               && (!virtual_p (result.whole2src)
21110d565efSmrg                   || !(result.whole_details & __diamond_shaped_mask)))
21210d565efSmrg             {
21310d565efSmrg               // We already found SRC_PTR as a base of most derived, and
21410d565efSmrg               // either it was non-virtual, or the whole hierarchy is
21510d565efSmrg               // not-diamond shaped. Therefore if it is in either choice, it
21610d565efSmrg               // can only be in one of them, and we will already know.
21710d565efSmrg               if (old_sub_kind == __unknown)
21810d565efSmrg                 old_sub_kind = __not_contained;
21910d565efSmrg               if (new_sub_kind == __unknown)
22010d565efSmrg                 new_sub_kind = __not_contained;
22110d565efSmrg             }
22210d565efSmrg           else
22310d565efSmrg             {
22410d565efSmrg               if (old_sub_kind >= __not_contained)
22510d565efSmrg                 ;// already calculated
22610d565efSmrg               else if (contained_p (new_sub_kind)
22710d565efSmrg                        && (!virtual_p (new_sub_kind)
22810d565efSmrg                            || !(__flags & __diamond_shaped_mask)))
22910d565efSmrg                 // Already found inside the other choice, and it was
23010d565efSmrg                 // non-virtual or we are not diamond shaped.
23110d565efSmrg                 old_sub_kind = __not_contained;
23210d565efSmrg               else
23310d565efSmrg                 old_sub_kind = dst_type->__find_public_src
23410d565efSmrg                                 (src2dst, result.dst_ptr, src_type, src_ptr);
23510d565efSmrg 
23610d565efSmrg               if (new_sub_kind >= __not_contained)
23710d565efSmrg                 ;// already calculated
23810d565efSmrg               else if (contained_p (old_sub_kind)
23910d565efSmrg                        && (!virtual_p (old_sub_kind)
24010d565efSmrg                            || !(__flags & __diamond_shaped_mask)))
24110d565efSmrg                 // Already found inside the other choice, and it was
24210d565efSmrg                 // non-virtual or we are not diamond shaped.
24310d565efSmrg                 new_sub_kind = __not_contained;
24410d565efSmrg               else
24510d565efSmrg                 new_sub_kind = dst_type->__find_public_src
24610d565efSmrg                                 (src2dst, result2.dst_ptr, src_type, src_ptr);
24710d565efSmrg             }
24810d565efSmrg 
24910d565efSmrg           // Neither sub_kind can be contained_ambig -- we bail out early
25010d565efSmrg           // when we find those.
25110d565efSmrg           if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind)))
25210d565efSmrg             {
25310d565efSmrg               // Only on one choice, not ambiguous.
25410d565efSmrg               if (contained_p (new_sub_kind))
25510d565efSmrg                 {
25610d565efSmrg                   // Only in new.
25710d565efSmrg                   result.dst_ptr = result2.dst_ptr;
25810d565efSmrg                   result.whole2dst = result2.whole2dst;
25910d565efSmrg                   result_ambig = false;
26010d565efSmrg                   old_sub_kind = new_sub_kind;
26110d565efSmrg                 }
26210d565efSmrg               result.dst2src = old_sub_kind;
26310d565efSmrg               if (public_p (result.dst2src))
26410d565efSmrg                 return false; // Can't be an ambiguating downcast for later discovery.
26510d565efSmrg               if (!virtual_p (result.dst2src))
26610d565efSmrg                 return false; // Found non-virtually can't be bettered
26710d565efSmrg             }
26810d565efSmrg           else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind)))
26910d565efSmrg             {
27010d565efSmrg               // In both.
27110d565efSmrg               result.dst_ptr = NULL;
27210d565efSmrg               result.dst2src = __contained_ambig;
27310d565efSmrg               return true;  // Fail.
27410d565efSmrg             }
27510d565efSmrg           else
27610d565efSmrg             {
27710d565efSmrg               // In neither publicly, ambiguous for the moment, but keep
27810d565efSmrg               // looking. It is possible that it was private in one or
27910d565efSmrg               // both and therefore we should fail, but that's just tough.
28010d565efSmrg               result.dst_ptr = NULL;
28110d565efSmrg               result.dst2src = __not_contained;
28210d565efSmrg               result_ambig = true;
28310d565efSmrg             }
28410d565efSmrg         }
28510d565efSmrg 
28610d565efSmrg       if (result.whole2src == __contained_private)
28710d565efSmrg         // We found SRC_PTR as a private non-virtual base, therefore all
28810d565efSmrg         // cross casts will fail. We have already found a down cast, if
28910d565efSmrg         // there is one.
29010d565efSmrg         return result_ambig;
29110d565efSmrg     }
29210d565efSmrg 
29310d565efSmrg   if (skipped && first_pass)
29410d565efSmrg     {
29510d565efSmrg       // We didn't find dst where we expected it, so let's go back and try
29610d565efSmrg       // the bases we skipped (if any).
29710d565efSmrg       first_pass = false;
29810d565efSmrg       goto again;
29910d565efSmrg     }
30010d565efSmrg 
30110d565efSmrg   return result_ambig;
30210d565efSmrg }
30310d565efSmrg 
30410d565efSmrg bool __vmi_class_type_info::
__do_upcast(const __class_type_info * dst,const void * obj_ptr,__upcast_result & __restrict result) const30510d565efSmrg __do_upcast (const __class_type_info *dst, const void *obj_ptr,
30610d565efSmrg              __upcast_result &__restrict result) const
30710d565efSmrg {
30810d565efSmrg   if (__class_type_info::__do_upcast (dst, obj_ptr, result))
30910d565efSmrg     return true;
31010d565efSmrg 
31110d565efSmrg   int src_details = result.src_details;
31210d565efSmrg   if (src_details & __flags_unknown_mask)
31310d565efSmrg     src_details = __flags;
31410d565efSmrg 
31510d565efSmrg   for (std::size_t i = __base_count; i--;)
31610d565efSmrg     {
31710d565efSmrg       __upcast_result result2 (src_details);
31810d565efSmrg       const void *base = obj_ptr;
31910d565efSmrg       ptrdiff_t offset = __base_info[i].__offset ();
32010d565efSmrg       bool is_virtual = __base_info[i].__is_virtual_p ();
32110d565efSmrg       bool is_public = __base_info[i].__is_public_p ();
32210d565efSmrg 
32310d565efSmrg       if (!is_public && !(src_details & __non_diamond_repeat_mask))
32410d565efSmrg         // original cannot have an ambiguous base, so skip private bases
32510d565efSmrg         continue;
32610d565efSmrg 
32710d565efSmrg       if (base)
32810d565efSmrg         base = convert_to_base (base, is_virtual, offset);
32910d565efSmrg 
33010d565efSmrg       if (__base_info[i].__base_type->__do_upcast (dst, base, result2))
33110d565efSmrg         {
33210d565efSmrg           if (result2.base_type == nonvirtual_base_type && is_virtual)
33310d565efSmrg             result2.base_type = __base_info[i].__base_type;
33410d565efSmrg           if (contained_p (result2.part2dst) && !is_public)
33510d565efSmrg             result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask);
33610d565efSmrg 
33710d565efSmrg           if (!result.base_type)
33810d565efSmrg             {
33910d565efSmrg               result = result2;
34010d565efSmrg               if (!contained_p (result.part2dst))
34110d565efSmrg                 return true; // found ambiguously
34210d565efSmrg 
34310d565efSmrg               if (result.part2dst & __contained_public_mask)
34410d565efSmrg                 {
34510d565efSmrg                   if (!(__flags & __non_diamond_repeat_mask))
34610d565efSmrg                     return true;  // cannot have an ambiguous other base
34710d565efSmrg                 }
34810d565efSmrg               else
34910d565efSmrg                 {
35010d565efSmrg                   if (!virtual_p (result.part2dst))
35110d565efSmrg                     return true; // cannot have another path
35210d565efSmrg                   if (!(__flags & __diamond_shaped_mask))
35310d565efSmrg                     return true; // cannot have a more accessible path
35410d565efSmrg                 }
35510d565efSmrg             }
35610d565efSmrg           else if (result.dst_ptr != result2.dst_ptr)
35710d565efSmrg             {
35810d565efSmrg               // Found an ambiguity.
35910d565efSmrg 	      result.dst_ptr = NULL;
36010d565efSmrg 	      result.part2dst = __contained_ambig;
36110d565efSmrg 	      return true;
36210d565efSmrg             }
36310d565efSmrg           else if (result.dst_ptr)
36410d565efSmrg             {
36510d565efSmrg               // Ok, found real object via a virtual path.
36610d565efSmrg               result.part2dst
36710d565efSmrg                   = __sub_kind (result.part2dst | result2.part2dst);
36810d565efSmrg             }
36910d565efSmrg           else
37010d565efSmrg             {
37110d565efSmrg               // Dealing with a null pointer, need to check vbase
37210d565efSmrg               // containing each of the two choices.
37310d565efSmrg               if (result2.base_type == nonvirtual_base_type
37410d565efSmrg                   || result.base_type == nonvirtual_base_type
37510d565efSmrg                   || !(*result2.base_type == *result.base_type))
37610d565efSmrg                 {
37710d565efSmrg                   // Already ambiguous, not virtual or via different virtuals.
37810d565efSmrg                   // Cannot match.
37910d565efSmrg                   result.part2dst = __contained_ambig;
38010d565efSmrg                   return true;
38110d565efSmrg                 }
38210d565efSmrg               result.part2dst
38310d565efSmrg                   = __sub_kind (result.part2dst | result2.part2dst);
38410d565efSmrg             }
38510d565efSmrg         }
38610d565efSmrg     }
38710d565efSmrg   return result.part2dst != __unknown;
38810d565efSmrg }
38910d565efSmrg 
39010d565efSmrg }
391