1 // RTTI support internals for -*- C++ -*- 2 // Copyright (C) 1994-2013 Free Software Foundation, Inc. 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 #include "typeinfo" 26 #include <cstddef> 27 28 // Class declarations shared between the typeinfo implementation files. 29 30 #include <cxxabi.h> 31 32 namespace __cxxabiv1 { 33 34 inline bool __pbase_type_info:: 35 __pointer_catch (const __pbase_type_info *thrown_type, 36 void **thr_obj, 37 unsigned outer) const 38 { 39 return __pointee->__do_catch (thrown_type->__pointee, thr_obj, outer + 2); 40 } 41 42 namespace { 43 44 using namespace std; 45 using namespace abi; 46 47 // Initial part of a vtable, this structure is used with offsetof, so we don't 48 // have to keep alignments consistent manually. 49 struct vtable_prefix 50 { 51 // Offset to most derived object. 52 ptrdiff_t whole_object; 53 54 // Additional padding if necessary. 55 #ifdef _GLIBCXX_VTABLE_PADDING 56 ptrdiff_t padding1; 57 #endif 58 59 // Pointer to most derived type_info. 60 const __class_type_info *whole_type; 61 62 // Additional padding if necessary. 63 #ifdef _GLIBCXX_VTABLE_PADDING 64 ptrdiff_t padding2; 65 #endif 66 67 // What a class's vptr points to. 68 const void *origin; 69 }; 70 71 template <typename T> 72 inline const T * 73 adjust_pointer (const void *base, ptrdiff_t offset) 74 { 75 return reinterpret_cast <const T *> 76 (reinterpret_cast <const char *> (base) + offset); 77 } 78 79 // ADDR is a pointer to an object. Convert it to a pointer to a base, 80 // using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base. 81 inline void const * 82 convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset) 83 { 84 if (is_virtual) 85 { 86 const void *vtable = *static_cast <const void *const *> (addr); 87 88 offset = *adjust_pointer<ptrdiff_t> (vtable, offset); 89 } 90 91 return adjust_pointer<void> (addr, offset); 92 } 93 94 // some predicate functions for __class_type_info::__sub_kind 95 inline bool contained_p (__class_type_info::__sub_kind access_path) 96 { 97 return access_path >= __class_type_info::__contained_mask; 98 } 99 inline bool public_p (__class_type_info::__sub_kind access_path) 100 { 101 return access_path & __class_type_info::__contained_public_mask; 102 } 103 inline bool virtual_p (__class_type_info::__sub_kind access_path) 104 { 105 return (access_path & __class_type_info::__contained_virtual_mask); 106 } 107 inline bool contained_public_p (__class_type_info::__sub_kind access_path) 108 { 109 return ((access_path & __class_type_info::__contained_public) 110 == __class_type_info::__contained_public); 111 } 112 inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path) 113 { 114 return ((access_path & __class_type_info::__contained_public) 115 == __class_type_info::__contained_mask); 116 } 117 inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path) 118 { 119 return ((access_path & (__class_type_info::__contained_mask 120 | __class_type_info::__contained_virtual_mask)) 121 == __class_type_info::__contained_mask); 122 } 123 124 static const __class_type_info *const nonvirtual_base_type = 125 static_cast <const __class_type_info *> (0) + 1; 126 127 } // namespace 128 129 // __upcast_result is used to hold information during traversal of a class 130 // hierarchy when catch matching. 131 struct __class_type_info::__upcast_result 132 { 133 const void *dst_ptr; // pointer to caught object 134 __sub_kind part2dst; // path from current base to target 135 int src_details; // hints about the source type hierarchy 136 const __class_type_info *base_type; // where we found the target, 137 // if in vbase the __class_type_info of vbase 138 // if a non-virtual base then 1 139 // else NULL 140 __upcast_result (int d) 141 :dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL) 142 {} 143 }; 144 145 // __dyncast_result is used to hold information during traversal of a class 146 // hierarchy when dynamic casting. 147 struct __class_type_info::__dyncast_result 148 { 149 const void *dst_ptr; // pointer to target object or NULL 150 __sub_kind whole2dst; // path from most derived object to target 151 __sub_kind whole2src; // path from most derived object to sub object 152 __sub_kind dst2src; // path from target to sub object 153 int whole_details; // details of the whole class hierarchy 154 155 __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask) 156 :dst_ptr (NULL), whole2dst (__unknown), 157 whole2src (__unknown), dst2src (__unknown), 158 whole_details (details_) 159 {} 160 161 protected: 162 __dyncast_result(const __dyncast_result&); 163 164 __dyncast_result& 165 operator=(const __dyncast_result&); 166 }; 167 168 inline __class_type_info::__sub_kind __class_type_info:: 169 __find_public_src (ptrdiff_t src2dst, 170 const void *obj_ptr, 171 const __class_type_info *src_type, 172 const void *src_ptr) const 173 { 174 if (src2dst >= 0) 175 return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr 176 ? __contained_public : __not_contained; 177 if (src2dst == -2) 178 return __not_contained; 179 return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr); 180 } 181 182 } 183