1// RTTI support internals for -*- C++ -*- 2// Copyright (C) 1994-2015 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 32namespace __cxxabiv1 { 33 34namespace { 35 36using namespace std; 37using namespace abi; 38 39// Initial part of a vtable, this structure is used with offsetof, so we don't 40// have to keep alignments consistent manually. 41struct vtable_prefix 42{ 43 // Offset to most derived object. 44 ptrdiff_t whole_object; 45 46 // Additional padding if necessary. 47#ifdef _GLIBCXX_VTABLE_PADDING 48 ptrdiff_t padding1; 49#endif 50 51 // Pointer to most derived type_info. 52 const __class_type_info *whole_type; 53 54 // Additional padding if necessary. 55#ifdef _GLIBCXX_VTABLE_PADDING 56 ptrdiff_t padding2; 57#endif 58 59 // What a class's vptr points to. 60 const void *origin; 61}; 62 63template <typename T> 64inline const T * 65adjust_pointer (const void *base, ptrdiff_t offset) 66{ 67 return reinterpret_cast <const T *> 68 (reinterpret_cast <const char *> (base) + offset); 69} 70 71// ADDR is a pointer to an object. Convert it to a pointer to a base, 72// using OFFSET. IS_VIRTUAL is true, if we are getting a virtual base. 73inline void const * 74convert_to_base (void const *addr, bool is_virtual, ptrdiff_t offset) 75{ 76 if (is_virtual) 77 { 78 const void *vtable = *static_cast <const void *const *> (addr); 79 80 offset = *adjust_pointer<ptrdiff_t> (vtable, offset); 81 } 82 83 return adjust_pointer<void> (addr, offset); 84} 85 86// some predicate functions for __class_type_info::__sub_kind 87inline bool contained_p (__class_type_info::__sub_kind access_path) 88{ 89 return access_path >= __class_type_info::__contained_mask; 90} 91inline bool public_p (__class_type_info::__sub_kind access_path) 92{ 93 return access_path & __class_type_info::__contained_public_mask; 94} 95inline bool virtual_p (__class_type_info::__sub_kind access_path) 96{ 97 return (access_path & __class_type_info::__contained_virtual_mask); 98} 99inline bool contained_public_p (__class_type_info::__sub_kind access_path) 100{ 101 return ((access_path & __class_type_info::__contained_public) 102 == __class_type_info::__contained_public); 103} 104inline bool contained_nonpublic_p (__class_type_info::__sub_kind access_path) 105{ 106 return ((access_path & __class_type_info::__contained_public) 107 == __class_type_info::__contained_mask); 108} 109inline bool contained_nonvirtual_p (__class_type_info::__sub_kind access_path) 110{ 111 return ((access_path & (__class_type_info::__contained_mask 112 | __class_type_info::__contained_virtual_mask)) 113 == __class_type_info::__contained_mask); 114} 115 116static const __class_type_info *const nonvirtual_base_type = 117 static_cast <const __class_type_info *> (0) + 1; 118 119} // namespace 120 121// __upcast_result is used to hold information during traversal of a class 122// hierarchy when catch matching. 123struct __class_type_info::__upcast_result 124{ 125 const void *dst_ptr; // pointer to caught object 126 __sub_kind part2dst; // path from current base to target 127 int src_details; // hints about the source type hierarchy 128 const __class_type_info *base_type; // where we found the target, 129 // if in vbase the __class_type_info of vbase 130 // if a non-virtual base then 1 131 // else NULL 132 __upcast_result (int d) 133 :dst_ptr (NULL), part2dst (__unknown), src_details (d), base_type (NULL) 134 {} 135}; 136 137// __dyncast_result is used to hold information during traversal of a class 138// hierarchy when dynamic casting. 139struct __class_type_info::__dyncast_result 140{ 141 const void *dst_ptr; // pointer to target object or NULL 142 __sub_kind whole2dst; // path from most derived object to target 143 __sub_kind whole2src; // path from most derived object to sub object 144 __sub_kind dst2src; // path from target to sub object 145 int whole_details; // details of the whole class hierarchy 146 147 __dyncast_result (int details_ = __vmi_class_type_info::__flags_unknown_mask) 148 :dst_ptr (NULL), whole2dst (__unknown), 149 whole2src (__unknown), dst2src (__unknown), 150 whole_details (details_) 151 {} 152 153protected: 154 __dyncast_result(const __dyncast_result&); 155 156 __dyncast_result& 157 operator=(const __dyncast_result&); 158}; 159 160inline __class_type_info::__sub_kind __class_type_info:: 161__find_public_src (ptrdiff_t src2dst, 162 const void *obj_ptr, 163 const __class_type_info *src_type, 164 const void *src_ptr) const 165{ 166 if (src2dst >= 0) 167 return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr 168 ? __contained_public : __not_contained; 169 if (src2dst == -2) 170 return __not_contained; 171 return __do_find_public_src (src2dst, obj_ptr, src_type, src_ptr); 172} 173 174} 175