OSDN Git Service

2000-11-07 Eric Christopher <echristo@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++ / tinfo2.cc
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