OSDN Git Service

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