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