]>
Commit | Line | Data |
---|---|---|
9ab916b8 RH |
1 | // Methods for type_info for -*- C++ -*- Run Time Type Identification. |
2 | // Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000 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, you may use this file as part of a free software | |
22 | // library without restriction. Specifically, if other files instantiate | |
23 | // templates or use macros or inline functions from this file, or you compile | |
24 | // this file and link it with other files to produce an executable, this | |
25 | // file does not by itself cause the resulting executable to be covered by | |
26 | // the GNU General Public License. This exception does not however | |
27 | // invalidate any other reasons why the executable file might be covered by | |
28 | // the GNU General Public License. | |
29 | ||
30 | #include <stddef.h> | |
31 | #include "tinfo.hP" | |
32 | #include "new" // for placement new | |
33 | ||
34 | // We can't rely on having stdlib.h if we're freestanding. | |
35 | extern "C" void abort (); | |
36 | ||
37 | using std::type_info; | |
38 | ||
39 | #if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 | |
40 | bool | |
41 | type_info::before (const type_info &arg) const | |
42 | { | |
43 | return __builtin_strcmp (name (), arg.name ()) < 0; | |
44 | } | |
45 | ||
46 | // type info for pointer type. | |
47 | ||
48 | struct __pointer_type_info : public type_info { | |
49 | const type_info& type; | |
50 | ||
51 | __pointer_type_info (const char *n, const type_info& ti) | |
52 | : type_info (n), type (ti) {} | |
53 | }; | |
54 | ||
55 | // type info for attributes | |
56 | ||
57 | struct __attr_type_info : public type_info { | |
58 | enum cv { NONE = 0, CONST = 1, VOLATILE = 2, CONSTVOL = 1 | 2 }; | |
59 | ||
60 | const type_info& type; | |
61 | cv attr; | |
62 | ||
63 | __attr_type_info (const char *n, cv a, const type_info& t) | |
64 | : type_info (n), type (t), attr (a) {} | |
65 | }; | |
66 | ||
67 | // type_info for builtin type | |
68 | ||
69 | struct __builtin_type_info : public type_info { | |
70 | __builtin_type_info (const char *n): type_info (n) {} | |
71 | }; | |
72 | ||
73 | // type info for function. | |
74 | ||
75 | struct __func_type_info : public type_info { | |
76 | __func_type_info (const char *n) : type_info (n) {} | |
77 | }; | |
78 | ||
79 | // type info for pointer to member function. | |
80 | ||
81 | struct __ptmf_type_info : public type_info { | |
82 | __ptmf_type_info (const char *n) : type_info (n) {} | |
83 | }; | |
84 | ||
85 | // type info for pointer to data member. | |
86 | ||
87 | struct __ptmd_type_info : public type_info { | |
88 | __ptmd_type_info (const char *n): type_info (n) {} | |
89 | }; | |
90 | ||
91 | // type info for array. | |
92 | ||
93 | struct __array_type_info : public type_info { | |
94 | __array_type_info (const char *n): type_info (n) {} | |
95 | }; | |
96 | ||
97 | #else | |
98 | ||
99 | #include <cxxabi.h> | |
100 | #endif | |
101 | ||
102 | #if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 | |
103 | namespace __cxxabiv1 { | |
104 | ||
105 | using namespace std; | |
106 | ||
107 | // This has special meaning to the compiler, and will cause it | |
108 | // to emit the type_info structures for the fundamental types which are | |
109 | // mandated to exist in the runtime. | |
110 | __fundamental_type_info:: | |
111 | ~__fundamental_type_info () | |
112 | {} | |
113 | ||
114 | __array_type_info:: | |
115 | ~__array_type_info () | |
116 | {} | |
117 | ||
118 | __function_type_info:: | |
119 | ~__function_type_info () | |
120 | {} | |
121 | ||
122 | __enum_type_info:: | |
123 | ~__enum_type_info () | |
124 | {} | |
125 | ||
126 | __pbase_type_info:: | |
127 | ~__pbase_type_info () | |
128 | {} | |
129 | ||
130 | __pointer_type_info:: | |
131 | ~__pointer_type_info () | |
132 | {} | |
133 | ||
134 | __pointer_to_member_type_info:: | |
135 | ~__pointer_to_member_type_info () | |
136 | {} | |
137 | ||
138 | bool __pointer_type_info:: | |
139 | __is_pointer_p () const | |
140 | { | |
141 | return true; | |
142 | } | |
143 | ||
144 | bool __function_type_info:: | |
145 | __is_function_p () const | |
146 | { | |
147 | return true; | |
148 | } | |
149 | ||
150 | bool __pbase_type_info:: | |
151 | __do_catch (const type_info *thr_type, | |
152 | void **thr_obj, | |
153 | unsigned outer) const | |
154 | { | |
155 | if (*this == *thr_type) | |
156 | return true; // same type | |
157 | if (typeid (*this) != typeid (*thr_type)) | |
158 | return false; // not both same kind of pointers | |
159 | ||
160 | if (!(outer & 1)) | |
161 | // We're not the same and our outer pointers are not all const qualified | |
162 | // Therefore there must at least be a qualification conversion involved | |
163 | // But for that to be valid, our outer pointers must be const qualified. | |
164 | return false; | |
165 | ||
166 | const __pbase_type_info *thrown_type = | |
167 | static_cast <const __pbase_type_info *> (thr_type); | |
168 | ||
169 | if (thrown_type->__qualifier_flags & ~__qualifier_flags) | |
170 | // We're less qualified. | |
171 | return false; | |
172 | ||
173 | if (!(__qualifier_flags & __const_mask)) | |
174 | outer &= ~1; | |
175 | ||
176 | return __pointer_catch (thrown_type, thr_obj, outer); | |
177 | } | |
178 | ||
179 | inline bool __pbase_type_info:: | |
180 | __pointer_catch (const __pbase_type_info *thrown_type, | |
181 | void **thr_obj, | |
182 | unsigned outer) const | |
183 | { | |
184 | return __pointee->__do_catch (thrown_type->__pointee, thr_obj, outer + 2); | |
185 | } | |
186 | ||
187 | bool __pointer_type_info:: | |
188 | __pointer_catch (const __pbase_type_info *thrown_type, | |
189 | void **thr_obj, | |
190 | unsigned outer) const | |
191 | { | |
192 | if (outer < 2 && *__pointee == typeid (void)) | |
193 | { | |
194 | // conversion to void | |
195 | return !thrown_type->__pointee->__is_function_p (); | |
196 | } | |
197 | ||
198 | return __pbase_type_info::__pointer_catch (thrown_type, thr_obj, outer); | |
199 | } | |
200 | ||
201 | bool __pointer_to_member_type_info:: | |
202 | __pointer_catch (const __pbase_type_info *thr_type, | |
203 | void **thr_obj, | |
204 | unsigned outer) const | |
205 | { | |
206 | // This static cast is always valid, as our caller will have determined that | |
207 | // thr_type is really a __pointer_to_member_type_info. | |
208 | const __pointer_to_member_type_info *thrown_type = | |
209 | static_cast <const __pointer_to_member_type_info *> (thr_type); | |
210 | ||
211 | if (*__context_class != *thrown_type->__context_class) | |
212 | return false; // not pointers to member of same class | |
213 | ||
214 | return __pbase_type_info::__pointer_catch (thrown_type, thr_obj, outer); | |
215 | } | |
216 | ||
217 | } // namespace std | |
218 | #endif | |
219 | ||
220 | // Entry points for the compiler. | |
221 | ||
222 | /* Low level match routine used by compiler to match types of catch | |
223 | variables and thrown objects. */ | |
224 | ||
225 | extern "C" int | |
226 | __throw_type_match_rtti_2 (const void *catch_type_r, const void *throw_type_r, | |
227 | void *objptr, void **valp) | |
228 | { | |
229 | const type_info &catch_type = *(const type_info *)catch_type_r; | |
230 | const type_info &throw_type = *(const type_info *)throw_type_r; | |
231 | ||
232 | *valp = objptr; | |
233 | ||
234 | #if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 | |
235 | // old abi | |
236 | if (catch_type == throw_type) | |
237 | return 1; | |
238 | ||
239 | if (const __user_type_info *p | |
240 | = dynamic_cast <const __user_type_info *> (&throw_type)) | |
241 | { | |
242 | return p->upcast (catch_type, objptr, valp); | |
243 | } | |
244 | else if (const __pointer_type_info *fr = | |
245 | dynamic_cast <const __pointer_type_info *> (&throw_type)) | |
246 | { | |
247 | const __pointer_type_info *to = | |
248 | dynamic_cast <const __pointer_type_info *> (&catch_type); | |
249 | ||
250 | if (! to) | |
251 | return 0; | |
252 | ||
253 | const type_info *subfr = &fr->type, *subto = &to->type; | |
254 | __attr_type_info::cv cvfrom, cvto; | |
255 | ||
256 | if (const __attr_type_info *at | |
257 | = dynamic_cast <const __attr_type_info *> (subfr)) | |
258 | { | |
259 | cvfrom = at->attr; | |
260 | subfr = &at->type; | |
261 | } | |
262 | else | |
263 | cvfrom = __attr_type_info::NONE; | |
264 | ||
265 | if (const __attr_type_info *at | |
266 | = dynamic_cast <const __attr_type_info *> (subto)) | |
267 | { | |
268 | cvto = at->attr; | |
269 | subto = &at->type; | |
270 | } | |
271 | else | |
272 | cvto = __attr_type_info::NONE; | |
273 | ||
274 | if (((cvfrom & __attr_type_info::CONST) | |
275 | > (cvto & __attr_type_info::CONST)) | |
276 | || ((cvfrom & __attr_type_info::VOLATILE) | |
277 | > (cvto & __attr_type_info::VOLATILE))) | |
278 | return 0; | |
279 | ||
280 | if (*subto == *subfr) | |
281 | return 1; | |
282 | else if (*subto == typeid (void) | |
283 | && dynamic_cast <const __func_type_info *> (subfr) == 0) | |
284 | return 1; | |
285 | else if (const __user_type_info *p | |
286 | = dynamic_cast <const __user_type_info *> (subfr)) | |
287 | return p->upcast (*subto, objptr, valp); | |
288 | else if (const __pointer_type_info *pfr | |
289 | = dynamic_cast <const __pointer_type_info *> (subfr)) | |
290 | { | |
291 | // Multi-level pointer conversion. | |
292 | ||
293 | const __pointer_type_info *pto | |
294 | = dynamic_cast <const __pointer_type_info *> (subto); | |
295 | ||
296 | if (! pto) | |
297 | return 0; | |
298 | ||
299 | bool constp = (cvto & __attr_type_info::CONST); | |
300 | for (subto = &pto->type, subfr = &pfr->type; ; | |
301 | subto = &pto->type, subfr = &pfr->type) | |
302 | { | |
303 | if (const __attr_type_info *at | |
304 | = dynamic_cast <const __attr_type_info *> (subfr)) | |
305 | { | |
306 | cvfrom = at->attr; | |
307 | subfr = &at->type; | |
308 | } | |
309 | else | |
310 | cvfrom = __attr_type_info::NONE; | |
311 | ||
312 | if (const __attr_type_info *at | |
313 | = dynamic_cast <const __attr_type_info *> (subto)) | |
314 | { | |
315 | cvto = at->attr; | |
316 | subto = &at->type; | |
317 | } | |
318 | else | |
319 | cvto = __attr_type_info::NONE; | |
320 | ||
321 | if (((cvfrom & __attr_type_info::CONST) | |
322 | > (cvto & __attr_type_info::CONST)) | |
323 | || ((cvfrom & __attr_type_info::VOLATILE) | |
324 | > (cvto & __attr_type_info::VOLATILE))) | |
325 | return 0; | |
326 | ||
327 | if (! constp | |
328 | && (((cvfrom & __attr_type_info::CONST) | |
329 | < (cvto & __attr_type_info::CONST)) | |
330 | || ((cvfrom & __attr_type_info::VOLATILE) | |
331 | < (cvto & __attr_type_info::VOLATILE)))) | |
332 | return 0; | |
333 | ||
334 | if (*subto == *subfr) | |
335 | return 1; | |
336 | ||
337 | pto = dynamic_cast <const __pointer_type_info *> (subto); | |
338 | pfr = dynamic_cast <const __pointer_type_info *> (subfr); | |
339 | if (! pto || ! pfr) | |
340 | return 0; | |
341 | ||
342 | if (! (cvto & __attr_type_info::CONST)) | |
343 | constp = false; | |
344 | } | |
345 | } | |
346 | } | |
347 | #else | |
348 | // new abi | |
349 | ||
350 | return catch_type.__do_catch (&throw_type, valp, 1); | |
351 | #endif | |
352 | return 0; | |
353 | } | |
354 | ||
355 | #if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 | |
356 | /* Backward compatibility wrapper. */ | |
357 | ||
358 | extern "C" void* | |
359 | __throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r, | |
360 | void *objptr) | |
361 | { | |
362 | void *ret; | |
363 | if (__throw_type_match_rtti_2 (catch_type_r, throw_type_r, objptr, &ret)) | |
364 | return ret; | |
365 | return NULL; | |
366 | } | |
367 | #endif | |
368 | ||
369 | /* Called from __cp_pop_exception. Is P the type_info node for a pointer | |
370 | of some kind? */ | |
371 | ||
372 | bool | |
373 | __is_pointer (void *p) | |
374 | { | |
375 | const type_info *t = reinterpret_cast <const type_info *>(p); | |
376 | #if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 | |
377 | // old abi | |
378 | const __pointer_type_info *pt = | |
379 | dynamic_cast <const __pointer_type_info *> (t); | |
380 | return pt != 0; | |
381 | #else | |
382 | // new abi | |
383 | return t->__is_pointer_p (); | |
384 | #endif | |
385 | } | |
386 | ||
387 | #if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 | |
388 | // old abi | |
389 | ||
390 | extern "C" void | |
391 | __rtti_ptr (void *addr, const char *n, const type_info *ti) | |
392 | { new (addr) __pointer_type_info (n, *ti); } | |
393 | ||
394 | extern "C" void | |
395 | __rtti_attr (void *addr, const char *n, int attrval, const type_info *ti) | |
396 | { | |
397 | new (addr) __attr_type_info | |
398 | (n, static_cast <__attr_type_info::cv> (attrval), *ti); | |
399 | } | |
400 | ||
401 | extern "C" void | |
402 | __rtti_func (void *addr, const char *name) | |
403 | { new (addr) __func_type_info (name); } | |
404 | ||
405 | extern "C" void | |
406 | __rtti_ptmf (void *addr, const char *name) | |
407 | { new (addr) __ptmf_type_info (name); } | |
408 | ||
409 | extern "C" void | |
410 | __rtti_ptmd (void *addr, const char *name) | |
411 | { new (addr) __ptmd_type_info (name); } | |
412 | ||
413 | extern "C" void | |
414 | __rtti_array (void *addr, const char *name) | |
415 | { new (addr) __array_type_info (name); } | |
416 | ||
417 | extern "C" void * | |
418 | __dynamic_cast (const type_info& (*from)(void), const type_info& (*to)(void), | |
419 | int require_public, void *address, const type_info & (*sub)(void), void *subptr) | |
420 | { | |
421 | if (!require_public) abort(); | |
422 | return static_cast <__user_type_info const &> (from ()).dyncast | |
423 | (/*boff=*/-1, to (), address, sub (), subptr); | |
424 | } | |
425 | ||
426 | extern "C" void * | |
427 | __dynamic_cast_2 (const type_info& (*from)(void), const type_info& (*to)(void), | |
428 | int boff, | |
429 | void *address, const type_info & (*sub)(void), void *subptr) | |
430 | { | |
431 | return static_cast <__user_type_info const &> (from ()).dyncast | |
432 | (boff, to (), address, sub (), subptr); | |
433 | } | |
434 | ||
435 | // type_info nodes and functions for the builtin types. The mangling here | |
436 | // must match the mangling in gcc/cp/rtti.c. | |
437 | ||
438 | #define BUILTIN(mangled) \ | |
439 | unsigned char __ti##mangled [sizeof (__builtin_type_info)] \ | |
440 | __attribute__ ((aligned (__alignof__ (void *)))); \ | |
441 | extern "C" const type_info &__tf##mangled (void) { \ | |
442 | if ((*(void **) __ti##mangled) == 0) \ | |
443 | new (__ti##mangled) __builtin_type_info (#mangled); \ | |
444 | return *(type_info *)__ti##mangled; \ | |
445 | } | |
446 | ||
447 | BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b); | |
448 | BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f); | |
449 | BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc); | |
450 | BUILTIN (Sc); | |
451 | ||
452 | #endif |