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