]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libstdc++-v3/contrib/libstdc++-v3-4.3.3/libsupc++/vmi_class_type_info.cc
Inital import
[l4.git] / l4 / pkg / libstdc++-v3 / contrib / libstdc++-v3-4.3.3 / libsupc++ / vmi_class_type_info.cc
1 // Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007
2 // Free Software Foundation
3 //
4 // This file is part of GCC.
5 //
6 // GCC 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 // GCC 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 GCC; see the file COPYING.  If not, write to
18 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 // Boston, MA 02110-1301, 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 enums 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 #include "tinfo.h"
31
32 namespace __cxxabiv1 {
33
34 __vmi_class_type_info::
35 ~__vmi_class_type_info ()
36 {}
37
38 __class_type_info::__sub_kind __vmi_class_type_info::
39 __do_find_public_src (ptrdiff_t src2dst,
40                       const void *obj_ptr,
41                       const __class_type_info *src_type,
42                       const void *src_ptr) const
43 {
44   if (obj_ptr == src_ptr && *this == *src_type)
45     return __contained_public;
46   
47   for (std::size_t i = __base_count; i--;)
48     {
49       if (!__base_info[i].__is_public_p ())
50         continue; // Not public, can't be here.
51       
52       const void *base = obj_ptr;
53       ptrdiff_t offset = __base_info[i].__offset ();
54       bool is_virtual = __base_info[i].__is_virtual_p ();
55       
56       if (is_virtual)
57         {
58           if (src2dst == -3)
59             continue; // Not a virtual base, so can't be here.
60         }
61       base = convert_to_base (base, is_virtual, offset);
62       
63       __sub_kind base_kind = __base_info[i].__base_type->__do_find_public_src
64                               (src2dst, base, src_type, src_ptr);
65       if (contained_p (base_kind))
66         {
67           if (is_virtual)
68             base_kind = __sub_kind (base_kind | __contained_virtual_mask);
69           return base_kind;
70         }
71     }
72   
73   return __not_contained;
74 }
75
76 // This is a big hairy function. Although the run-time behaviour of
77 // dynamic_cast is simple to describe, it gives rise to some non-obvious
78 // behaviour. We also desire to determine as early as possible any definite
79 // answer we can get. Because it is unknown what the run-time ratio of
80 // succeeding to failing dynamic casts is, we do not know in which direction
81 // to bias any optimizations. To that end we make no particular effort towards
82 // early fail answers or early success answers. Instead we try to minimize
83 // work by filling in things lazily (when we know we need the information),
84 // and opportunisticly take early success or failure results.
85 bool __vmi_class_type_info::
86 __do_dyncast (ptrdiff_t src2dst,
87               __sub_kind access_path,
88               const __class_type_info *dst_type,
89               const void *obj_ptr,
90               const __class_type_info *src_type,
91               const void *src_ptr,
92               __dyncast_result &__restrict result) const
93 {
94   if (result.whole_details & __flags_unknown_mask)
95     result.whole_details = __flags;
96   
97   if (obj_ptr == src_ptr && *this == *src_type)
98     {
99       // The src object we started from. Indicate how we are accessible from
100       // the most derived object.
101       result.whole2src = access_path;
102       return false;
103     }
104   if (*this == *dst_type)
105     {
106       result.dst_ptr = obj_ptr;
107       result.whole2dst = access_path;
108       if (src2dst >= 0)
109         result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
110               ? __contained_public : __not_contained;
111       else if (src2dst == -2)
112         result.dst2src = __not_contained;
113       return false;
114     }
115
116   bool result_ambig = false;
117   for (std::size_t i = __base_count; i--;)
118     {
119       __dyncast_result result2 (result.whole_details);
120       void const *base = obj_ptr;
121       __sub_kind base_access = access_path;
122       ptrdiff_t offset = __base_info[i].__offset ();
123       bool is_virtual = __base_info[i].__is_virtual_p ();
124       
125       if (is_virtual)
126         base_access = __sub_kind (base_access | __contained_virtual_mask);
127       base = convert_to_base (base, is_virtual, offset);
128
129       if (!__base_info[i].__is_public_p ())
130         {
131           if (src2dst == -2 &&
132               !(result.whole_details
133                 & (__non_diamond_repeat_mask | __diamond_shaped_mask)))
134             // The hierarchy has no duplicate bases (which might ambiguate
135             // things) and where we started is not a public base of what we
136             // want (so it cannot be a downcast). There is nothing of interest
137             // hiding in a non-public base.
138             continue;
139           base_access = __sub_kind (base_access & ~__contained_public_mask);
140         }
141       
142       bool result2_ambig
143           = __base_info[i].__base_type->__do_dyncast (src2dst, base_access,
144                                              dst_type, base,
145                                              src_type, src_ptr, result2);
146       result.whole2src = __sub_kind (result.whole2src | result2.whole2src);
147       if (result2.dst2src == __contained_public
148           || result2.dst2src == __contained_ambig)
149         {
150           result.dst_ptr = result2.dst_ptr;
151           result.whole2dst = result2.whole2dst;
152           result.dst2src = result2.dst2src;
153           // Found a downcast which can't be bettered or an ambiguous downcast
154           // which can't be disambiguated
155           return result2_ambig;
156         }
157       
158       if (!result_ambig && !result.dst_ptr)
159         {
160           // Not found anything yet.
161           result.dst_ptr = result2.dst_ptr;
162           result.whole2dst = result2.whole2dst;
163           result_ambig = result2_ambig;
164           if (result.dst_ptr && result.whole2src != __unknown
165               && !(__flags & __non_diamond_repeat_mask))
166             // Found dst and src and we don't have repeated bases.
167             return result_ambig;
168         }
169       else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
170         {
171           // Found at same address, must be via virtual.  Pick the most
172           // accessible path.
173           result.whole2dst =
174               __sub_kind (result.whole2dst | result2.whole2dst);
175         }
176       else if ((result.dst_ptr != 0 && result2.dst_ptr != 0)
177                || (result.dst_ptr != 0 && result2_ambig)
178                || (result2.dst_ptr != 0 && result_ambig))
179         {
180           // Found two different DST_TYPE bases, or a valid one and a set of
181           // ambiguous ones, must disambiguate. See whether SRC_PTR is
182           // contained publicly within one of the non-ambiguous choices. If it
183           // is in only one, then that's the choice. If it is in both, then
184           // we're ambiguous and fail. If it is in neither, we're ambiguous,
185           // but don't yet fail as we might later find a third base which does
186           // contain SRC_PTR.
187         
188           __sub_kind new_sub_kind = result2.dst2src;
189           __sub_kind old_sub_kind = result.dst2src;
190           
191           if (contained_p (result.whole2src)
192               && (!virtual_p (result.whole2src)
193                   || !(result.whole_details & __diamond_shaped_mask)))
194             {
195               // We already found SRC_PTR as a base of most derived, and
196               // either it was non-virtual, or the whole hierarchy is
197               // not-diamond shaped. Therefore if it is in either choice, it
198               // can only be in one of them, and we will already know.
199               if (old_sub_kind == __unknown)
200                 old_sub_kind = __not_contained;
201               if (new_sub_kind == __unknown)
202                 new_sub_kind = __not_contained;
203             }
204           else
205             {
206               if (old_sub_kind >= __not_contained)
207                 ;// already calculated
208               else if (contained_p (new_sub_kind)
209                        && (!virtual_p (new_sub_kind)
210                            || !(__flags & __diamond_shaped_mask)))
211                 // Already found inside the other choice, and it was
212                 // non-virtual or we are not diamond shaped.
213                 old_sub_kind = __not_contained;
214               else
215                 old_sub_kind = dst_type->__find_public_src
216                                 (src2dst, result.dst_ptr, src_type, src_ptr);
217           
218               if (new_sub_kind >= __not_contained)
219                 ;// already calculated
220               else if (contained_p (old_sub_kind)
221                        && (!virtual_p (old_sub_kind)
222                            || !(__flags & __diamond_shaped_mask)))
223                 // Already found inside the other choice, and it was
224                 // non-virtual or we are not diamond shaped.
225                 new_sub_kind = __not_contained;
226               else
227                 new_sub_kind = dst_type->__find_public_src
228                                 (src2dst, result2.dst_ptr, src_type, src_ptr);
229             }
230           
231           // Neither sub_kind can be contained_ambig -- we bail out early
232           // when we find those.
233           if (contained_p (__sub_kind (new_sub_kind ^ old_sub_kind)))
234             {
235               // Only on one choice, not ambiguous.
236               if (contained_p (new_sub_kind))
237                 {
238                   // Only in new.
239                   result.dst_ptr = result2.dst_ptr;
240                   result.whole2dst = result2.whole2dst;
241                   result_ambig = false;
242                   old_sub_kind = new_sub_kind;
243                 }
244               result.dst2src = old_sub_kind;
245               if (public_p (result.dst2src))
246                 return false; // Can't be an ambiguating downcast for later discovery.
247               if (!virtual_p (result.dst2src))
248                 return false; // Found non-virtually can't be bettered
249             }
250           else if (contained_p (__sub_kind (new_sub_kind & old_sub_kind)))
251             {
252               // In both.
253               result.dst_ptr = NULL;
254               result.dst2src = __contained_ambig;
255               return true;  // Fail.
256             }
257           else
258             {
259               // In neither publicly, ambiguous for the moment, but keep
260               // looking. It is possible that it was private in one or
261               // both and therefore we should fail, but that's just tough.
262               result.dst_ptr = NULL;
263               result.dst2src = __not_contained;
264               result_ambig = true;
265             }
266         }
267       
268       if (result.whole2src == __contained_private)
269         // We found SRC_PTR as a private non-virtual base, therefore all
270         // cross casts will fail. We have already found a down cast, if
271         // there is one.
272         return result_ambig;
273     }
274
275   return result_ambig;
276 }
277
278 bool __vmi_class_type_info::
279 __do_upcast (const __class_type_info *dst, const void *obj_ptr,
280              __upcast_result &__restrict result) const
281 {
282   if (__class_type_info::__do_upcast (dst, obj_ptr, result))
283     return true;
284   
285   int src_details = result.src_details;
286   if (src_details & __flags_unknown_mask)
287     src_details = __flags;
288   
289   for (std::size_t i = __base_count; i--;)
290     {
291       __upcast_result result2 (src_details);
292       const void *base = obj_ptr;
293       ptrdiff_t offset = __base_info[i].__offset ();
294       bool is_virtual = __base_info[i].__is_virtual_p ();
295       bool is_public = __base_info[i].__is_public_p ();
296       
297       if (!is_public && !(src_details & __non_diamond_repeat_mask))
298         // original cannot have an ambiguous base, so skip private bases
299         continue;
300
301       if (base)
302         base = convert_to_base (base, is_virtual, offset);
303       
304       if (__base_info[i].__base_type->__do_upcast (dst, base, result2))
305         {
306           if (result2.base_type == nonvirtual_base_type && is_virtual)
307             result2.base_type = __base_info[i].__base_type;
308           if (contained_p (result2.part2dst) && !is_public)
309             result2.part2dst = __sub_kind (result2.part2dst & ~__contained_public_mask);
310           
311           if (!result.base_type)
312             {
313               result = result2;
314               if (!contained_p (result.part2dst))
315                 return true; // found ambiguously
316               
317               if (result.part2dst & __contained_public_mask)
318                 {
319                   if (!(__flags & __non_diamond_repeat_mask))
320                     return true;  // cannot have an ambiguous other base
321                 }
322               else
323                 {
324                   if (!virtual_p (result.part2dst))
325                     return true; // cannot have another path
326                   if (!(__flags & __diamond_shaped_mask))
327                     return true; // cannot have a more accessible path
328                 }
329             }
330           else if (result.dst_ptr != result2.dst_ptr)
331             {
332               // Found an ambiguity.
333               result.dst_ptr = NULL;
334               result.part2dst = __contained_ambig;
335               return true;
336             }
337           else if (result.dst_ptr)
338             {
339               // Ok, found real object via a virtual path.
340               result.part2dst
341                   = __sub_kind (result.part2dst | result2.part2dst);
342             }
343           else
344             {
345               // Dealing with a null pointer, need to check vbase
346               // containing each of the two choices.
347               if (result2.base_type == nonvirtual_base_type
348                   || result.base_type == nonvirtual_base_type
349                   || !(*result2.base_type == *result.base_type))
350                 {
351                   // Already ambiguous, not virtual or via different virtuals.
352                   // Cannot match.
353                   result.part2dst = __contained_ambig;
354                   return true;
355                 }
356               result.part2dst
357                   = __sub_kind (result.part2dst | result2.part2dst);
358             }
359         }
360     }
361   return result.part2dst != __unknown;
362 }
363
364 }