1// Methods for type_info for -*- C++ -*- Run Time Type Identification. 2// Copyright (C) 1994, 96-97, 1998 Free Software Foundation 3 4// This file is part of GNU CC. 5 6// GNU CC 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// GNU CC 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 GNU CC; see the file COPYING. If not, write to 18// the Free Software Foundation, 59 Temple Place - Suite 330, 19// Boston, MA 02111-1307, USA. 20 21// As a special exception, if you link this library with other files, 22// some of which are compiled with GCC, to produce an executable, 23// this library does not by itself cause the resulting executable 24// to be covered by the GNU General Public License. 25// This exception does not however invalidate any other reasons why 26// the executable file might be covered by the GNU General Public License. 27 28#include <stddef.h> 29#include "tinfo.h" 30#include "new" // for placement new 31 32using std::type_info; 33 34bool 35type_info::before (const type_info &arg) const 36{ 37 return strcmp (name (), arg.name ()) < 0; 38} 39 40// type info for pointer type. 41 42struct __pointer_type_info : public type_info { 43 const type_info& type; 44 45 __pointer_type_info (const char *n, const type_info& ti) 46 : type_info (n), type (ti) {} 47}; 48 49// type info for attributes 50 51struct __attr_type_info : public type_info { 52 enum cv { NONE = 0, CONST = 1, VOLATILE = 2, CONSTVOL = 1 | 2 }; 53 54 const type_info& type; 55 cv attr; 56 57 __attr_type_info (const char *n, cv a, const type_info& t) 58 : type_info (n), type (t), attr (a) {} 59}; 60 61// type_info for builtin type 62 63struct __builtin_type_info : public type_info { 64 __builtin_type_info (const char *n): type_info (n) {} 65}; 66 67// type info for function. 68 69struct __func_type_info : public type_info { 70 __func_type_info (const char *n) : type_info (n) {} 71}; 72 73// type info for pointer to member function. 74 75struct __ptmf_type_info : public type_info { 76 __ptmf_type_info (const char *n) : type_info (n) {} 77}; 78 79// type info for pointer to data member. 80 81struct __ptmd_type_info : public type_info { 82 __ptmd_type_info (const char *n): type_info (n) {} 83}; 84 85// type info for array. 86 87struct __array_type_info : public type_info { 88 __array_type_info (const char *n): type_info (n) {} 89}; 90 91// Entry points for the compiler. 92 93/* Low level match routine used by compiler to match types of catch 94 variables and thrown objects. */ 95 96extern "C" void* 97__throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, 98 void *objptr) 99{ 100 const type_info &catch_type = *(const type_info *)catch_type_r; 101 const type_info &throw_type = *(const type_info *)throw_type_r; 102 103 if (catch_type == throw_type) 104 return objptr; 105 106#if 0 107 printf ("We want to match a %s against a %s!\n", 108 throw_type.name (), catch_type.name ()); 109#endif 110 111 void *new_objptr = 0; 112 113 if (const __user_type_info *p 114 = dynamic_cast <const __user_type_info *> (&throw_type)) 115 { 116 /* The 1 skips conversions to private bases. */ 117 new_objptr = p->dcast (catch_type, 1, objptr); 118 } 119 else if (const __pointer_type_info *fr = 120 dynamic_cast <const __pointer_type_info *> (&throw_type)) 121 { 122 const __pointer_type_info *to = 123 dynamic_cast <const __pointer_type_info *> (&catch_type); 124 125 if (! to) 126 goto fail; 127 128 const type_info *subfr = &fr->type, *subto = &to->type; 129 __attr_type_info::cv cvfrom, cvto; 130 131 if (const __attr_type_info *at 132 = dynamic_cast <const __attr_type_info *> (subfr)) 133 { 134 cvfrom = at->attr; 135 subfr = &at->type; 136 } 137 else 138 cvfrom = __attr_type_info::NONE; 139 140 if (const __attr_type_info *at 141 = dynamic_cast <const __attr_type_info *> (subto)) 142 { 143 cvto = at->attr; 144 subto = &at->type; 145 } 146 else 147 cvto = __attr_type_info::NONE; 148 149 if (((cvfrom & __attr_type_info::CONST) 150 > (cvto & __attr_type_info::CONST)) 151 || ((cvfrom & __attr_type_info::VOLATILE) 152 > (cvto & __attr_type_info::VOLATILE))) 153 goto fail; 154 155 if (*subto == *subfr) 156 new_objptr = objptr; 157 else if (*subto == typeid (void) 158 && dynamic_cast <const __func_type_info *> (subfr) == 0) 159 new_objptr = objptr; 160 else if (const __user_type_info *p 161 = dynamic_cast <const __user_type_info *> (subfr)) 162 { 163 /* The 1 skips conversions to private bases. */ 164 new_objptr = p->dcast (*subto, 1, objptr); 165 } 166 else if (const __pointer_type_info *pfr 167 = dynamic_cast <const __pointer_type_info *> (subfr)) 168 { 169 // Multi-level pointer conversion. 170 171 const __pointer_type_info *pto 172 = dynamic_cast <const __pointer_type_info *> (subto); 173 174 if (! pto) 175 goto fail; 176 177 bool constp = (cvto & __attr_type_info::CONST); 178 for (subto = &pto->type, subfr = &pfr->type; ; 179 subto = &pto->type, subfr = &pfr->type) 180 { 181 if (const __attr_type_info *at 182 = dynamic_cast <const __attr_type_info *> (subfr)) 183 { 184 cvfrom = at->attr; 185 subfr = &at->type; 186 } 187 else 188 cvfrom = __attr_type_info::NONE; 189 190 if (const __attr_type_info *at 191 = dynamic_cast <const __attr_type_info *> (subto)) 192 { 193 cvto = at->attr; 194 subto = &at->type; 195 } 196 else 197 cvto = __attr_type_info::NONE; 198 199 if (((cvfrom & __attr_type_info::CONST) 200 > (cvto & __attr_type_info::CONST)) 201 || ((cvfrom & __attr_type_info::VOLATILE) 202 > (cvto & __attr_type_info::VOLATILE))) 203 goto fail; 204 205 if (! constp 206 && (((cvfrom & __attr_type_info::CONST) 207 < (cvto & __attr_type_info::CONST)) 208 || ((cvfrom & __attr_type_info::VOLATILE) 209 < (cvto & __attr_type_info::VOLATILE)))) 210 goto fail; 211 212 if (*subto == *subfr) 213 { 214 new_objptr = objptr; 215 break; 216 } 217 218 pto = dynamic_cast <const __pointer_type_info *> (subto); 219 pfr = dynamic_cast <const __pointer_type_info *> (subfr); 220 if (! pto || ! pfr) 221 goto fail; 222 223 if (! (cvto & __attr_type_info::CONST)) 224 constp = false; 225 } 226 } 227 } 228 fail: 229 230#if 0 231 if (new_objptr) 232 printf ("It converts, delta is %d\n", new_objptr-objptr); 233#endif 234 return new_objptr; 235} 236 237/* Called from __cp_pop_exception. Is P the type_info node for a pointer 238 of some kind? */ 239 240bool 241__is_pointer (void *p) 242{ 243 const type_info *t = reinterpret_cast <const type_info *>(p); 244 const __pointer_type_info *pt = 245 dynamic_cast <const __pointer_type_info *> (t); 246 return pt != 0; 247} 248 249extern "C" void 250__rtti_ptr (void *addr, const char *n, const type_info *ti) 251{ new (addr) __pointer_type_info (n, *ti); } 252 253extern "C" void 254__rtti_attr (void *addr, const char *n, int attrval, const type_info *ti) 255{ 256 new (addr) __attr_type_info 257 (n, static_cast <__attr_type_info::cv> (attrval), *ti); 258} 259 260extern "C" void 261__rtti_func (void *addr, const char *name) 262{ new (addr) __func_type_info (name); } 263 264extern "C" void 265__rtti_ptmf (void *addr, const char *name) 266{ new (addr) __ptmf_type_info (name); } 267 268extern "C" void 269__rtti_ptmd (void *addr, const char *name) 270{ new (addr) __ptmd_type_info (name); } 271 272extern "C" void 273__rtti_array (void *addr, const char *name) 274{ new (addr) __array_type_info (name); } 275 276extern "C" void * 277__dynamic_cast (const type_info& (*from)(void), const type_info& (*to)(void), 278 int require_public, void *address, 279 const type_info & (*sub)(void), void *subptr) 280{ 281 return static_cast <const __user_type_info &> (from ()).dcast 282 (to (), require_public, address, &(sub ()), subptr); 283} 284 285// type_info nodes and functions for the builtin types. The mangling here 286// must match the mangling in gcc/cp/rtti.c. 287 288#define BUILTIN(mangled) \ 289unsigned char __ti##mangled [sizeof (__builtin_type_info)] \ 290 __attribute__ ((aligned (__alignof__ (void *)))); \ 291extern "C" const type_info &__tf##mangled (void) { \ 292 if ((*(void **) __ti##mangled) == 0) \ 293 new (__ti##mangled) __builtin_type_info (#mangled); \ 294 return *(type_info *)__ti##mangled; \ 295} 296 297BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b); 298BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f); 299BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc); 300BUILTIN (Sc); 301