| // RTTI support internals for -*- C++ -*- | |
| // Copyright (C) 1994-2023 Free Software Foundation, Inc. | |
| // This file is part of GCC. | |
| // | |
| // GCC is free software; you can redistribute it and/or modify | |
| // it under the terms of the GNU General Public License as published by | |
| // the Free Software Foundation; either version 3, or (at your option) | |
| // any later version. | |
| // GCC is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // GNU General Public License for more details. | |
| // Under Section 7 of GPL version 3, you are granted additional | |
| // permissions described in the GCC Runtime Library Exception, version | |
| // 3.1, as published by the Free Software Foundation. | |
| // You should have received a copy of the GNU General Public License and | |
| // a copy of the GCC Runtime Library Exception along with this program; | |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| // <http://www.gnu.org/licenses/>. | |
| #include "typeinfo" | |
| #include <cstddef> | |
| // Class declarations shared between the typeinfo implementation files. | |
| #include <cxxabi.h> | |
| namespace __cxxabiv1 { | |
| namespace { | |
| using namespace std; | |
| using namespace abi; | |
| // Initial part of a vtable, this structure is used with offsetof, so we don't | |
| // have to keep alignments consistent manually. | |
| struct vtable_prefix | |
| { | |
| // Offset to most derived object. | |
| ptrdiff_t whole_object; | |
| // Additional padding if necessary. | |
| #ifdef _GLIBCXX_VTABLE_PADDING | |
| ptrdiff_t padding1; | |
| #endif | |
| // Pointer to most derived type_info. | |
| const __class_type_info *whole_type; | |
| // Additional padding if necessary. | |
| #ifdef _GLIBCXX_VTABLE_PADDING | |
| ptrdiff_t padding2; | |
| #endif | |
| // What a class's vptr points to. | |
| const void *origin; | |
| }; | |
| template <typename T> | |
| inline const T * | |
| adjust_pointer (const void *base, ptrdiff_t offset) | |
| { | |
| return reinterpret_cast <const T *> | |
| (reinterpret_cast <const char *> (base) + offset); | |
| } | |
| // ADDR is a pointer to an object. Convert it to a pointer to a base, | |
| // using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base. | |
| inline void const * | |
| convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset) | |
| { | |
| if (is_virtual) | |
| { | |
| const void *vtable = *static_cast <const void *const *> (addr); | |
| offset = *adjust_pointer<ptrdiff_t> (vtable, offset); | |
| } | |
| return adjust_pointer<void> (addr, offset); | |
| } | |
| // some predicate functions for __class_type_info::__sub_kind | |
| inline bool contained_p (__class_type_info::__sub_kind access_path) | |
| { | |
| return access_path >= __class_type_info::__contained_mask; | |
| } | |
| inline bool public_p (__class_type_info::__sub_kind access_path) | |
| { | |
| return access_path & __class_type_info::__contained_public_mask; | |
| } | |
| inline bool virtual_p (__class_type_info::__sub_kind access_path) | |
| { | |
| return (access_path & __class_type_info::__contained_virtual_mask); | |
| } | |
| inline bool contained_public_p (__class_type_info::__sub_kind access_path) | |
| { | |
| return ((access_path & __class_type_info::__contained_public) | |
| == __class_type_info::__contained_public); | |
| } | |
| inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path) | |
| { | |
| return ((access_path & __class_type_info::__contained_public) | |
| == __class_type_info::__contained_mask); | |
| } | |
| inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path) | |
| { | |
| return ((access_path & (__class_type_info::__contained_mask | |
| | __class_type_info::__contained_virtual_mask)) | |
| == __class_type_info::__contained_mask); | |
| } | |
| static const __class_type_info *const nonvirtual_base_type = | |
| static_cast <const __class_type_info *> (0) + 1; | |
| } // namespace | |
| // __upcast_result is used to hold information during traversal of a class | |
| // hierarchy when catch matching. | |
| struct __class_type_info::__upcast_result | |
| { | |
| const void *dst_ptr; // pointer to caught object | |
| __sub_kind part2dst; // path from current base to target | |
| int src_details; // hints about the source type hierarchy | |
| const __class_type_info *base_type; // where we found the target, | |
| // if in vbase the __class_type_info of vbase | |
| // if a non-virtual base then 1 | |
| // else NULL | |
| __upcast_result (int d) | |
| :dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL) | |
| {} | |
| }; | |
| // __dyncast_result is used to hold information during traversal of a class | |
| // hierarchy when dynamic casting. | |
| struct __class_type_info::__dyncast_result | |
| { | |
| const void *dst_ptr; // pointer to target object or NULL | |
| __sub_kind whole2dst; // path from most derived object to target | |
| __sub_kind whole2src; // path from most derived object to sub object | |
| __sub_kind dst2src; // path from target to sub object | |
| int whole_details; // details of the whole class hierarchy | |
| __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask) | |
| :dst_ptr (NULL), whole2dst (__unknown), | |
| whole2src (__unknown), dst2src (__unknown), | |
| whole_details (details_) | |
| {} | |
| protected: | |
| __dyncast_result(const __dyncast_result&); | |
| __dyncast_result& | |
| operator=(const __dyncast_result&); | |
| }; | |
| inline __class_type_info::__sub_kind __class_type_info:: | |
| __find_public_src (ptrdiff_t src2dst, | |
| const void *obj_ptr, | |
| const __class_type_info *src_type, | |
| const void *src_ptr) const | |
| { | |
| if (src2dst >= 0) | |
| return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr | |
| ? __contained_public : __not_contained; | |
| if (src2dst == -2) | |
| return __not_contained; | |
| return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr); | |
| } | |
| } |