OSDN Git Service

* cp-tree.h (make_temp_vec): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / cp / rtti.c
1 /* RunTime Type Identification
2    Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
3    Mostly written by Jason Merrill (jason@cygnus.com).
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22
23 #include "config.h"
24 #include "system.h"
25 #include "tree.h"
26 #include "cp-tree.h"
27 #include "flags.h"
28 #include "output.h"
29 #include "assert.h"
30 #include "toplev.h"
31
32 #ifndef INT_TYPE_SIZE
33 #define INT_TYPE_SIZE BITS_PER_WORD
34 #endif
35
36 extern struct obstack permanent_obstack;
37
38 static tree call_void_fn PROTO((const char *));
39 static tree build_headof_sub PROTO((tree));
40 static tree build_headof PROTO((tree));
41 static tree get_tinfo_var PROTO((tree));
42 static tree ifnonnull PROTO((tree, tree));
43 static tree build_dynamic_cast_1 PROTO((tree, tree));
44 static void expand_si_desc PROTO((tree, tree));
45 static void expand_class_desc PROTO((tree, tree));
46 static void expand_attr_desc PROTO((tree, tree));
47 static void expand_ptr_desc PROTO((tree, tree));
48 static void expand_generic_desc PROTO((tree, tree, const char *));
49 static tree throw_bad_cast PROTO((void));
50 static tree throw_bad_typeid PROTO((void));
51 \f
52 void
53 init_rtti_processing ()
54 {
55   if (flag_honor_std)
56     push_namespace (get_identifier ("std"));
57   type_info_type_node = xref_tag
58     (class_type_node, get_identifier ("type_info"), 1);
59   if (flag_honor_std)
60     pop_namespace ();
61   tinfo_fn_id = get_identifier ("__tf");
62   tinfo_fn_type = build_function_type
63     (build_reference_type (build_qualified_type (type_info_type_node, 
64                                                  TYPE_QUAL_CONST)),
65      void_list_node);
66 }
67
68 /* Given a pointer to an object with at least one virtual table
69    pointer somewhere, return a pointer to a possible sub-object that
70    has a virtual table pointer in it that is the vtable parent for
71    that sub-object.  */
72
73 static tree
74 build_headof_sub (exp)
75      tree exp;
76 {
77   tree type = TREE_TYPE (TREE_TYPE (exp));
78   tree basetype = CLASSTYPE_RTTI (type);
79   tree binfo = get_binfo (basetype, type, 0);
80
81   exp = convert_pointer_to_real (binfo, exp);
82   return exp;
83 }
84
85 /* Given the expression EXP of type `class *', return the head of the
86    object pointed to by EXP with type cv void*, if the class has any
87    virtual functions (TYPE_VIRTUAL_P), else just return the
88    expression.  */
89
90 static tree
91 build_headof (exp)
92      tree exp;
93 {
94   tree type = TREE_TYPE (exp);
95   tree aref;
96   tree offset;
97
98   if (TREE_CODE (type) != POINTER_TYPE)
99     {
100       error ("`headof' applied to non-pointer type");
101       return error_mark_node;
102     }
103   type = TREE_TYPE (type);
104
105   if (!TYPE_VIRTUAL_P (type))
106     return exp;
107   if (CLASSTYPE_COM_INTERFACE (type))
108     {
109       cp_error ("RTTI not supported for COM interface type `%T'", type);
110       return error_mark_node;
111     }
112
113   /* If we don't have rtti stuff, get to a sub-object that does.  */
114   if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
115     exp = build_headof_sub (exp);
116
117   /* We use this a couple of times below, protect it.  */
118   exp = save_expr (exp);
119
120   aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
121
122   if (flag_vtable_thunks)
123     offset = aref;
124   else
125     offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
126
127   type = build_qualified_type (ptr_type_node, 
128                                CP_TYPE_QUALS (TREE_TYPE (exp)));
129   return build (PLUS_EXPR, type, exp,
130                 cp_convert (ptrdiff_type_node, offset));
131 }
132
133 /* Build a call to a generic entry point taking and returning void.  */
134
135 static tree
136 call_void_fn (name)
137      const char *name;
138 {
139   tree d = get_identifier (name);
140   tree type;
141   
142   if (IDENTIFIER_GLOBAL_VALUE (d))
143     d = IDENTIFIER_GLOBAL_VALUE (d);
144   else
145     {
146       push_obstacks (&permanent_obstack, &permanent_obstack);
147
148       type = build_function_type (void_type_node, void_list_node);
149       d = build_lang_decl (FUNCTION_DECL, d, type);
150       DECL_EXTERNAL (d) = 1;
151       TREE_PUBLIC (d) = 1;
152       DECL_ARTIFICIAL (d) = 1;
153       pushdecl_top_level (d);
154       make_function_rtl (d);
155       pop_obstacks ();
156     }
157
158   mark_used (d);
159   return build_call (d, void_type_node, NULL_TREE);
160 }
161
162 /* Get a bad_cast node for the program to throw...
163
164    See libstdc++/exception.cc for __throw_bad_cast */
165
166 static tree
167 throw_bad_cast ()
168 {
169   return call_void_fn ("__throw_bad_cast");
170 }
171
172 static tree
173 throw_bad_typeid ()
174 {
175   return call_void_fn ("__throw_bad_typeid");
176 }
177 \f
178 /* Return the type_info function associated with the expression EXP.  If
179    EXP is a reference to a polymorphic class, return the dynamic type;
180    otherwise return the static type of the expression.  */
181
182 tree
183 get_tinfo_fn_dynamic (exp)
184      tree exp;
185 {
186   tree type;
187
188   if (exp == error_mark_node)
189     return error_mark_node;
190
191   if (type_unknown_p (exp))
192     {
193       error ("typeid of overloaded function");
194       return error_mark_node;
195     }
196
197   type = TREE_TYPE (exp);
198
199   /* peel back references, so they match.  */
200   if (TREE_CODE (type) == REFERENCE_TYPE)
201     type = TREE_TYPE (type);
202
203   /* Peel off cv qualifiers.  */
204   type = TYPE_MAIN_VARIANT (type);
205
206   if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
207     {
208       cp_error ("taking typeid of incomplete type `%T'", type);
209       return error_mark_node;
210     }
211
212   /* If exp is a reference to polymorphic type, get the real type_info.  */
213   if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
214     {
215       /* build reference to type_info from vtable.  */
216       tree t;
217
218       if (! flag_rtti)
219         error ("taking dynamic typeid of object with -fno-rtti");
220       if (CLASSTYPE_COM_INTERFACE (type))
221         {
222           cp_error ("RTTI not supported for COM interface type `%T'", type);
223           return error_mark_node;
224         }
225
226       /* If we don't have rtti stuff, get to a sub-object that does.  */
227       if (! CLASSTYPE_VFIELDS (type))
228         {
229           exp = build_unary_op (ADDR_EXPR, exp, 0);
230           exp = build_headof_sub (exp);
231           exp = build_indirect_ref (exp, NULL_PTR);
232         }
233
234       if (flag_vtable_thunks)
235         t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
236       else
237         t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
238       TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
239       return t;
240     }
241
242   /* otherwise return the type_info for the static type of the expr.  */
243   return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
244 }
245
246 tree
247 build_typeid (exp)
248      tree exp;
249 {
250   exp = get_tinfo_fn_dynamic (exp);
251   exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
252   return convert_from_reference (exp);
253 }  
254
255 tree
256 build_x_typeid (exp)
257      tree exp;
258 {
259   tree cond = NULL_TREE;
260   tree type;
261   int nonnull;
262
263   if (! flag_rtti)
264     {
265       error ("cannot use typeid with -fno-rtti");
266       return error_mark_node;
267     }
268   
269   if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
270     {
271       error ("must #include <typeinfo> before using typeid");
272       return error_mark_node;
273     }
274   
275   if (processing_template_decl)
276     return build_min_nt (TYPEID_EXPR, exp);
277
278   if (TREE_CODE (exp) == INDIRECT_REF
279       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
280       && TYPE_VIRTUAL_P (TREE_TYPE (exp))
281       && ! resolves_to_fixed_type_p (exp, &nonnull)
282       && ! nonnull)
283     {
284       exp = stabilize_reference (exp);
285       cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
286     }
287
288   exp = get_tinfo_fn_dynamic (exp);
289
290   if (exp == error_mark_node)
291     return error_mark_node;
292
293   type = TREE_TYPE (tinfo_fn_type);
294   exp = build_call (exp, type, NULL_TREE);
295
296   if (cond)
297     {
298       tree bad = throw_bad_typeid ();
299
300       bad = build_compound_expr
301         (tree_cons (NULL_TREE, bad, build_expr_list
302                     (NULL_TREE, cp_convert (type, integer_zero_node))));
303       exp = build (COND_EXPR, type, cond, exp, bad);
304     }
305
306   return convert_from_reference (exp);
307 }
308
309 static tree
310 get_tinfo_var (type)
311      tree type;
312 {
313   tree tname = build_overload_with_type (get_identifier ("__ti"), type);
314   tree tdecl, arrtype;
315   int size;
316
317   if (IDENTIFIER_GLOBAL_VALUE (tname))
318     return IDENTIFIER_GLOBAL_VALUE (tname);
319     
320   /* Figure out how much space we need to allocate for the type_info object.
321      If our struct layout or the type_info classes are changed, this will
322      need to be modified.  */
323   if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
324     size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
325   else if (TREE_CODE (type) == POINTER_TYPE
326            && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
327                  || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
328     size = 3 * POINTER_SIZE;
329   else if (IS_AGGR_TYPE (type))
330     {
331       if (CLASSTYPE_N_BASECLASSES (type) == 0)
332         size = 2 * POINTER_SIZE;
333       else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
334                && (TREE_VIA_PUBLIC
335                    (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
336         size = 3 * POINTER_SIZE;
337       else
338         size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);
339     }
340   else
341     size = 2 * POINTER_SIZE;
342
343   push_obstacks (&permanent_obstack, &permanent_obstack);
344
345   /* The type for a character array of the appropriate size.  */
346   arrtype = build_cplus_array_type
347     (unsigned_char_type_node,
348      build_index_type (size_int (size / BITS_PER_UNIT - 1)));
349
350   tdecl = build_decl (VAR_DECL, tname, arrtype);
351   TREE_PUBLIC (tdecl) = 1;
352   DECL_EXTERNAL (tdecl) = 1;
353   DECL_ARTIFICIAL (tdecl) = 1;
354   push_to_top_level ();
355   pushdecl (tdecl);
356   cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
357   pop_from_top_level ();
358
359   pop_obstacks ();
360
361   return tdecl;
362 }
363
364 tree
365 get_tinfo_fn (type)
366      tree type;
367 {
368   tree name;
369   tree d;
370
371   if (TREE_CODE (type) == OFFSET_TYPE)
372     type = TREE_TYPE (type);
373   if (TREE_CODE (type) == METHOD_TYPE)
374     type = build_function_type (TREE_TYPE (type),
375                                 TREE_CHAIN (TYPE_ARG_TYPES (type)));
376
377   name = build_overload_with_type (tinfo_fn_id, type);
378
379   if (IDENTIFIER_GLOBAL_VALUE (name))
380     return IDENTIFIER_GLOBAL_VALUE (name);
381
382   push_obstacks (&permanent_obstack, &permanent_obstack);
383
384   d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
385   DECL_EXTERNAL (d) = 1;
386   TREE_PUBLIC (d) = 1;
387   DECL_ARTIFICIAL (d) = 1;
388   DECL_NOT_REALLY_EXTERN (d) = 1;
389   SET_DECL_TINFO_FN_P (d);
390   TREE_TYPE (name) = type;
391
392   pushdecl_top_level (d);
393   make_function_rtl (d);
394   mark_used (d);
395   mark_inline_for_output (d);
396   pop_obstacks ();
397
398   return d;
399 }
400
401 tree
402 get_typeid_1 (type)
403      tree type;
404 {
405   tree t;
406
407   t = build_call
408     (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
409   return convert_from_reference (t);
410 }
411   
412 /* Return the type_info object for TYPE, creating it if necessary.  */
413
414 tree
415 get_typeid (type)
416      tree type;
417 {
418   if (type == error_mark_node)
419     return error_mark_node;
420
421   if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
422     {
423       error ("must #include <typeinfo> before using typeid");
424       return error_mark_node;
425     }
426   
427   if (processing_template_decl)
428     return build_min_nt (TYPEID_EXPR, type);
429
430   /* If the type of the type-id is a reference type, the result of the
431      typeid expression refers to a type_info object representing the
432      referenced type.  */
433   if (TREE_CODE (type) == REFERENCE_TYPE)
434     type = TREE_TYPE (type);
435
436   /* The top-level cv-qualifiers of the lvalue expression or the type-id
437      that is the operand of typeid are always ignored.  */
438   type = TYPE_MAIN_VARIANT (type);
439
440   if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
441     {
442       cp_error ("taking typeid of incomplete type `%T'", type);
443       return error_mark_node;
444     }
445
446   return get_typeid_1 (type);
447 }
448
449 /* Check whether TEST is null before returning RESULT.  If TEST is used in
450    RESULT, it must have previously had a save_expr applied to it.  */
451
452 static tree
453 ifnonnull (test, result)
454      tree test, result;
455 {
456   return build (COND_EXPR, TREE_TYPE (result),
457                 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
458                 cp_convert (TREE_TYPE (result), integer_zero_node),
459                 result);
460 }
461
462 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
463    paper.  */
464
465 static tree
466 build_dynamic_cast_1 (type, expr)
467      tree type, expr;
468 {
469   enum tree_code tc = TREE_CODE (type);
470   tree exprtype;
471   enum tree_code ec;
472   tree dcast_fn;
473   tree old_expr = expr;
474
475   if (TREE_CODE (expr) == OFFSET_REF)
476     expr = resolve_offset_ref (expr);
477   
478   exprtype = TREE_TYPE (expr);
479   assert (exprtype != NULL_TREE);
480   ec = TREE_CODE (exprtype);
481
482   switch (tc)
483     {
484     case POINTER_TYPE:
485       if (ec == REFERENCE_TYPE)
486         {
487           expr = convert_from_reference (expr);
488           exprtype = TREE_TYPE (expr);
489           ec = TREE_CODE (exprtype);
490         }
491       if (ec != POINTER_TYPE)
492         goto fail;
493       if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
494         goto fail;
495       if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
496         goto fail;
497       if (!at_least_as_qualified_p (TREE_TYPE (type),
498                                     TREE_TYPE (exprtype)))
499         goto fail;
500       if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
501         break;
502       /* else fall through */
503     case REFERENCE_TYPE:
504       if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
505         goto fail;
506       if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
507         goto fail;
508       break;
509       /* else fall through */
510     default:
511       goto fail;
512     }
513
514   /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
515   if (ec == RECORD_TYPE)
516     {
517       exprtype = build_reference_type (exprtype);
518       expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
519                                    LOOKUP_NORMAL, NULL_TREE);
520       ec = REFERENCE_TYPE;
521     }
522
523   if (tc == REFERENCE_TYPE)
524     {
525       if (ec != REFERENCE_TYPE)
526         goto fail;
527       if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
528         goto fail;
529       if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
530         goto fail;
531       if (!at_least_as_qualified_p (TREE_TYPE (type),
532                                     TREE_TYPE (exprtype)))
533         goto fail;
534     }
535
536   /* If *type is an unambiguous accessible base class of *exprtype,
537      convert statically.  */
538   {
539     int distance;
540     tree path;
541
542     distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
543                                   &path);
544
545     if (distance == -2)
546       {
547         cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
548                   TREE_TYPE (exprtype), TREE_TYPE (type));
549         return error_mark_node;
550       }
551     if (distance == -3)
552       {
553         cp_error ("dynamic_cast from `%T' to private base class `%T'",
554                   TREE_TYPE (exprtype), TREE_TYPE (type));
555         return error_mark_node;
556       }
557
558     if (distance >= 0)
559       return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
560   }
561
562   /* Otherwise *exprtype must be a polymorphic class (have a vtbl).  */
563   if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
564     {
565       tree expr1;
566       /* if TYPE is `void *', return pointer to complete object.  */
567       if (tc == POINTER_TYPE
568           && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
569         {
570           /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b.  */
571           if (TREE_CODE (expr) == ADDR_EXPR
572               && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
573               && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
574             return build1 (NOP_EXPR, type, expr);
575
576           /* Since expr is used twice below, save it.  */
577           expr = save_expr (expr);
578
579           expr1 = build_headof (expr);
580           if (TREE_TYPE (expr1) != type)
581             expr1 = build1 (NOP_EXPR, type, expr1);
582           return ifnonnull (expr, expr1);
583         }
584       else
585         {
586           tree retval;
587           tree result, td1, td2, td3, elems, expr2;
588           tree static_type, target_type, boff;
589
590           /* If we got here, we can't convert statically.  Therefore,
591              dynamic_cast<D&>(b) (b an object) cannot succeed.  */
592           if (ec == REFERENCE_TYPE)
593             {
594               if (TREE_CODE (old_expr) == VAR_DECL
595                   && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
596                 {
597                   cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
598                               old_expr, type);
599                   return throw_bad_cast ();
600                 }
601             }
602           /* Ditto for dynamic_cast<D*>(&b).  */
603           else if (TREE_CODE (expr) == ADDR_EXPR)
604             {
605               tree op = TREE_OPERAND (expr, 0);
606               if (TREE_CODE (op) == VAR_DECL
607                   && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
608                 {
609                   cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
610                               op, type);
611                   retval = build_int_2 (0, 0); 
612                   TREE_TYPE (retval) = type; 
613                   return retval;
614                 }
615             }
616
617           /* Since expr is used twice below, save it.  */
618           expr = save_expr (expr);
619
620           expr1 = expr;
621           if (tc == REFERENCE_TYPE)
622             expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
623
624           /* Build run-time conversion.  */
625           expr2 = build_headof (expr1);
626
627           if (ec == POINTER_TYPE)
628             td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
629           else
630             td1 = get_tinfo_fn_dynamic (expr);
631           td1 = decay_conversion (td1);
632           
633           target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
634           static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype));
635           td2 = decay_conversion (get_tinfo_fn (target_type));
636           td3 = decay_conversion (get_tinfo_fn (static_type));
637
638           /* Determine how T and V are related.  */
639           boff = get_dynamic_cast_base_type (static_type, target_type);
640
641           elems = tree_cons
642             (NULL_TREE, td1, tree_cons
643              (NULL_TREE, td2, tree_cons
644               (NULL_TREE, boff, tree_cons
645                (NULL_TREE, expr2, tree_cons
646                 (NULL_TREE, td3, tree_cons
647                  (NULL_TREE, expr1, NULL_TREE))))));
648
649           dcast_fn = get_identifier ("__dynamic_cast_2");
650           if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
651             dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
652           else
653             {
654               tree tmp;
655
656               push_obstacks (&permanent_obstack, &permanent_obstack);
657               tmp = tree_cons
658                 (NULL_TREE, TREE_TYPE (td1), tree_cons
659                  (NULL_TREE, TREE_TYPE (td1), tree_cons
660                   (NULL_TREE, integer_type_node, tree_cons
661                    (NULL_TREE, ptr_type_node, tree_cons
662                     (NULL_TREE, TREE_TYPE (td1), tree_cons
663                      (NULL_TREE, ptr_type_node, void_list_node))))));
664               tmp = build_function_type (ptr_type_node, tmp);
665               dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
666               DECL_EXTERNAL (dcast_fn) = 1;
667               TREE_PUBLIC (dcast_fn) = 1;
668               DECL_ARTIFICIAL (dcast_fn) = 1;
669               pushdecl_top_level (dcast_fn);
670               make_function_rtl (dcast_fn);
671               pop_obstacks ();
672             }
673           
674           mark_used (dcast_fn);
675           result = build_call
676             (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
677
678           if (tc == REFERENCE_TYPE)
679             {
680               expr1 = throw_bad_cast ();
681               expr1 = build_compound_expr
682                 (tree_cons (NULL_TREE, expr1,
683                             build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
684               TREE_TYPE (expr1) = type;
685               result = save_expr (result);
686               return build (COND_EXPR, type, result, result, expr1);
687             }
688
689           /* Now back to the type we want from a void*.  */
690           result = cp_convert (type, result);
691           return ifnonnull (expr, result);
692         }
693     }
694
695  fail:
696   cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
697             expr, exprtype, type);
698   return error_mark_node;
699 }
700
701 tree
702 build_dynamic_cast (type, expr)
703      tree type, expr;
704 {
705   if (type == error_mark_node || expr == error_mark_node)
706     return error_mark_node;
707   
708   if (processing_template_decl)
709     return build_min (DYNAMIC_CAST_EXPR, type, expr);
710
711   return convert_from_reference (build_dynamic_cast_1 (type, expr));
712 }
713 \f
714 /* Build and initialize various sorts of descriptors.  Every descriptor
715    node has a name associated with it (the name created by mangling).
716    For this reason, we use the identifier as our access to the __*_desc
717    nodes, instead of sticking them directly in the types.  Otherwise we
718    would burden all built-in types (and pointer types) with slots that
719    we don't necessarily want to use.
720
721    For each descriptor we build, we build a variable that contains
722    the descriptor's information.  When we need this info at runtime,
723    all we need is access to these variables.
724
725    Note: these constructors always return the address of the descriptor
726    info, since that is simplest for their mutual interaction.  */
727
728 /* Build an initializer for a __si_type_info node.  */
729
730 static void
731 expand_si_desc (tdecl, type)
732      tree tdecl;
733      tree type;
734 {
735   tree t, elems, fn;
736   const char *name = build_overload_name (type, 1, 1);
737   tree name_string = combine_strings (build_string (strlen (name)+1, name));
738
739   type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
740   finish_expr_stmt (get_typeid_1 (type));
741   t = decay_conversion (get_tinfo_var (type));
742   elems = tree_cons
743     (NULL_TREE, decay_conversion (tdecl), tree_cons
744      (NULL_TREE, decay_conversion (name_string), tree_cons
745       (NULL_TREE, t, NULL_TREE)));
746
747   fn = get_identifier ("__rtti_si");
748   if (IDENTIFIER_GLOBAL_VALUE (fn))
749     fn = IDENTIFIER_GLOBAL_VALUE (fn);
750   else
751     {
752       tree tmp;
753       push_obstacks (&permanent_obstack, &permanent_obstack);
754       tmp = tree_cons
755         (NULL_TREE, ptr_type_node, tree_cons
756          (NULL_TREE, const_string_type_node, tree_cons
757           (NULL_TREE, build_pointer_type (type_info_type_node),
758            void_list_node)));
759       tmp = build_function_type (void_type_node, tmp);
760   
761       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
762       DECL_EXTERNAL (fn) = 1;
763       TREE_PUBLIC (fn) = 1;
764       DECL_ARTIFICIAL (fn) = 1;
765       pushdecl_top_level (fn);
766       make_function_rtl (fn);
767       pop_obstacks ();
768     }
769
770   mark_used (fn);
771   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
772   finish_expr_stmt (fn);
773 }
774
775 /* Build an initializer for a __class_type_info node.  */
776
777 static void
778 expand_class_desc (tdecl, type)
779      tree tdecl;
780      tree type;
781 {
782   tree name_string;
783   tree fn, tmp;
784   const char *name;
785
786   int i = CLASSTYPE_N_BASECLASSES (type);
787   int base_cnt = 0;
788   tree binfos = TYPE_BINFO_BASETYPES (type);
789 #if 0
790   /* See code below that used these.  */
791   tree vb = CLASSTYPE_VBASECLASSES (type);
792   int n_base = i;
793 #endif
794   tree base, elems, access, offset, isvir;
795   tree elt, elts = NULL_TREE;
796   static tree base_info_type_node;
797
798   if (base_info_type_node == NULL_TREE)
799     {
800       tree fields [4];
801
802       /* A reasonably close approximation of __class_type_info::base_info */
803
804       push_obstacks (&permanent_obstack, &permanent_obstack);
805       base_info_type_node = make_lang_type (RECORD_TYPE);
806
807       /* Actually const __user_type_info * */
808       fields [0] = build_lang_decl
809         (FIELD_DECL, NULL_TREE,
810          build_pointer_type (build_qualified_type
811                              (type_info_type_node,
812                               TYPE_QUAL_CONST)));
813       fields [1] = build_lang_decl
814         (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
815       DECL_BIT_FIELD (fields[1]) = 1;
816       DECL_FIELD_SIZE (fields[1]) = 29;
817
818       fields [2] = build_lang_decl
819         (FIELD_DECL, NULL_TREE, boolean_type_node);
820       DECL_BIT_FIELD (fields[2]) = 1;
821       DECL_FIELD_SIZE (fields[2]) = 1;
822
823       /* Actually enum access */
824       fields [3] = build_lang_decl
825         (FIELD_DECL, NULL_TREE, integer_type_node);
826       DECL_BIT_FIELD (fields[3]) = 1;
827       DECL_FIELD_SIZE (fields[3]) = 2;
828
829       finish_builtin_type (base_info_type_node, "__base_info", fields,
830                            3, ptr_type_node);
831       pop_obstacks ();
832     }
833
834   while (--i >= 0)
835     {
836       tree binfo = TREE_VEC_ELT (binfos, i);
837
838       finish_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
839       base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
840
841       if (TREE_VIA_VIRTUAL (binfo))
842         {
843           tree t = BINFO_TYPE (binfo);
844           const char *name;
845           tree field;
846
847           FORMAT_VBASE_NAME (name, t);
848           field = lookup_field (type, get_identifier (name), 0, 0);
849           offset = size_binop (FLOOR_DIV_EXPR, 
850                 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
851           offset = convert (sizetype, offset);
852         }
853       else
854         offset = BINFO_OFFSET (binfo);
855
856       if (TREE_VIA_PUBLIC (binfo))
857         access = access_public_node;
858       else if (TREE_VIA_PROTECTED (binfo))
859         access = access_protected_node;
860       else
861         access = access_private_node;
862       if (TREE_VIA_VIRTUAL (binfo))
863         isvir = boolean_true_node;
864       else
865         isvir = boolean_false_node;
866
867       elt = build
868         (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
869          (NULL_TREE, base, tree_cons
870           (NULL_TREE, offset, tree_cons
871            (NULL_TREE, isvir, tree_cons
872             (NULL_TREE, access, NULL_TREE)))));
873       TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
874       elts = tree_cons (NULL_TREE, elt, elts);
875       base_cnt++;
876     }
877 #if 0
878   i = n_base;
879   while (vb)
880     {
881       tree b;
882       access = access_public_node;
883       while (--i >= 0)
884         {
885           b = TREE_VEC_ELT (binfos, i);
886           if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
887             {
888               if (TREE_VIA_PUBLIC (b))
889                 access = access_public_node;
890               else if (TREE_VIA_PROTECTED (b))
891                 access = access_protected_node;
892               else
893                 access = access_private_node;
894               break;
895             }
896         }
897       base = build_t_desc (BINFO_TYPE (vb), 1);
898       offset = BINFO_OFFSET (vb);
899       isvir = build_int_2 (1, 0);
900
901       base_list = tree_cons (NULL_TREE, base, base_list);
902       isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
903       acc_list = tree_cons (NULL_TREE, access, acc_list);
904       off_list = tree_cons (NULL_TREE, offset, off_list);
905
906       base_cnt++;
907       vb = TREE_CHAIN (vb);
908     }
909 #endif
910
911   name = build_overload_name (type, 1, 1);
912   name_string = combine_strings (build_string (strlen (name)+1, name));
913
914   {
915     tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
916     elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
917     TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
918       = TREE_STATIC (elts) = 1;
919     complete_array_type (arrtype, elts, 1);
920   }
921
922   elems = tree_cons
923     (NULL_TREE, decay_conversion (tdecl), tree_cons
924      (NULL_TREE, decay_conversion (name_string), tree_cons
925       (NULL_TREE, decay_conversion (elts), tree_cons
926        (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
927         NULL_TREE))));
928
929   fn = get_identifier ("__rtti_class");
930   if (IDENTIFIER_GLOBAL_VALUE (fn))
931     fn = IDENTIFIER_GLOBAL_VALUE (fn);
932   else
933     {
934       push_obstacks (&permanent_obstack, &permanent_obstack);
935       tmp = tree_cons
936         (NULL_TREE, ptr_type_node, tree_cons
937          (NULL_TREE, const_string_type_node, tree_cons
938           (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
939            (NULL_TREE, sizetype, void_list_node))));
940       tmp = build_function_type (void_type_node, tmp);
941   
942       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
943       DECL_EXTERNAL (fn) = 1;
944       TREE_PUBLIC (fn) = 1;
945       DECL_ARTIFICIAL (fn) = 1;
946       pushdecl_top_level (fn);
947       make_function_rtl (fn);
948       pop_obstacks ();
949     }
950
951   mark_used (fn);
952   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
953   finish_expr_stmt (fn);
954 }
955
956 /* Build an initializer for a __pointer_type_info node.  */
957
958 static void
959 expand_ptr_desc (tdecl, type)
960      tree tdecl;
961      tree type;
962 {
963   tree t, elems, fn;
964   const char *name = build_overload_name (type, 1, 1);
965   tree name_string = combine_strings (build_string (strlen (name)+1, name));
966
967   type = TREE_TYPE (type);
968   finish_expr_stmt (get_typeid_1 (type));
969   t = decay_conversion (get_tinfo_var (type));
970   elems = tree_cons
971     (NULL_TREE, decay_conversion (tdecl), tree_cons
972      (NULL_TREE, decay_conversion (name_string), tree_cons
973       (NULL_TREE, t, NULL_TREE)));
974
975   fn = get_identifier ("__rtti_ptr");
976   if (IDENTIFIER_GLOBAL_VALUE (fn))
977     fn = IDENTIFIER_GLOBAL_VALUE (fn);
978   else
979     {
980       tree tmp;
981       push_obstacks (&permanent_obstack, &permanent_obstack);
982       tmp = tree_cons
983         (NULL_TREE, ptr_type_node, tree_cons
984          (NULL_TREE, const_string_type_node, tree_cons
985           (NULL_TREE, build_pointer_type (type_info_type_node),
986            void_list_node)));
987       tmp = build_function_type (void_type_node, tmp);
988   
989       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
990       DECL_EXTERNAL (fn) = 1;
991       TREE_PUBLIC (fn) = 1;
992       DECL_ARTIFICIAL (fn) = 1;
993       pushdecl_top_level (fn);
994       make_function_rtl (fn);
995       pop_obstacks ();
996     }
997
998   mark_used (fn);
999   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1000   finish_expr_stmt (fn);
1001 }
1002
1003 /* Build an initializer for a __attr_type_info node.  */
1004
1005 static void
1006 expand_attr_desc (tdecl, type)
1007      tree tdecl;
1008      tree type;
1009 {
1010   tree elems, t, fn;
1011   const char *name = build_overload_name (type, 1, 1);
1012   tree name_string = combine_strings (build_string (strlen (name)+1, name));
1013   tree attrval = build_int_2 (TYPE_QUALS (type), 0);
1014
1015   finish_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
1016   t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
1017   elems = tree_cons
1018     (NULL_TREE, decay_conversion (tdecl), tree_cons
1019      (NULL_TREE, decay_conversion (name_string), tree_cons
1020       (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE))));
1021
1022   fn = get_identifier ("__rtti_attr");
1023   if (IDENTIFIER_GLOBAL_VALUE (fn))
1024     fn = IDENTIFIER_GLOBAL_VALUE (fn);
1025   else
1026     {
1027       tree tmp;
1028       push_obstacks (&permanent_obstack, &permanent_obstack);
1029       tmp = tree_cons
1030         (NULL_TREE, ptr_type_node, tree_cons
1031          (NULL_TREE, const_string_type_node, tree_cons
1032           (NULL_TREE, integer_type_node, tree_cons
1033            (NULL_TREE, build_pointer_type (type_info_type_node),
1034             void_list_node))));
1035       tmp = build_function_type (void_type_node, tmp);
1036   
1037       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1038       DECL_EXTERNAL (fn) = 1;
1039       TREE_PUBLIC (fn) = 1;
1040       DECL_ARTIFICIAL (fn) = 1;
1041       pushdecl_top_level (fn);
1042       make_function_rtl (fn);
1043       pop_obstacks ();
1044     }
1045
1046   mark_used (fn);
1047   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1048   finish_expr_stmt (fn);
1049 }
1050
1051 /* Build an initializer for a type_info node that just has a name.  */
1052
1053 static void
1054 expand_generic_desc (tdecl, type, fnname)
1055      tree tdecl;
1056      tree type;
1057      const char *fnname;
1058 {
1059   const char *name = build_overload_name (type, 1, 1);
1060   tree name_string = combine_strings (build_string (strlen (name)+1, name));
1061   tree elems = tree_cons
1062     (NULL_TREE, decay_conversion (tdecl), tree_cons
1063      (NULL_TREE, decay_conversion (name_string), NULL_TREE));
1064
1065   tree fn = get_identifier (fnname);
1066   if (IDENTIFIER_GLOBAL_VALUE (fn))
1067     fn = IDENTIFIER_GLOBAL_VALUE (fn);
1068   else
1069     {
1070       tree tmp;
1071       push_obstacks (&permanent_obstack, &permanent_obstack);
1072       tmp = tree_cons
1073         (NULL_TREE, ptr_type_node, tree_cons
1074          (NULL_TREE, const_string_type_node, void_list_node));
1075       tmp = build_function_type (void_type_node, tmp);
1076   
1077       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1078       DECL_EXTERNAL (fn) = 1;
1079       TREE_PUBLIC (fn) = 1;
1080       DECL_ARTIFICIAL (fn) = 1;
1081       pushdecl_top_level (fn);
1082       make_function_rtl (fn);
1083       pop_obstacks ();
1084     }
1085
1086   mark_used (fn);
1087   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1088   finish_expr_stmt (fn);
1089 }
1090
1091 /* Generate the code for a type_info initialization function.
1092    Note that we take advantage of the passage
1093
1094    5.2.7  Type identification                               [expr.typeid]
1095    
1096    Whether or not the destructor is called for the type_info object at the
1097    end of the program is unspecified.
1098
1099    and don't bother to arrange for these objects to be destroyed.  It
1100    doesn't matter, anyway, since the destructors don't do anything.
1101        
1102    This must only be called from toplevel (i.e. from finish_file)!  */
1103
1104 void
1105 synthesize_tinfo_fn (fndecl)
1106      tree fndecl;
1107 {
1108   tree type = TREE_TYPE (DECL_NAME (fndecl));
1109   tree tmp, addr, tdecl;
1110   tree compound_stmt;
1111   tree if_stmt;
1112   tree then_clause;
1113
1114   if (at_eof)
1115     {
1116       import_export_decl (fndecl);
1117       if (DECL_REALLY_EXTERN (fndecl))
1118         return;
1119     }
1120
1121   /* Declare the static typeinfo variable.  */
1122   tdecl = get_tinfo_var (type);
1123   DECL_EXTERNAL (tdecl) = 0;
1124   TREE_STATIC (tdecl) = 1;
1125   DECL_COMMON (tdecl) = 1;
1126   TREE_USED (tdecl) = 1;
1127   DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1128   cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1129
1130   /* Begin processing the function.  */
1131   start_function (NULL_TREE, fndecl, NULL_TREE, 
1132                   SF_DEFAULT | SF_PRE_PARSED);
1133   store_parm_decls ();
1134   clear_last_expr ();
1135
1136   /* Begin the body of the function.  */
1137   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
1138
1139   /* For convenience, we save away the address of the static
1140      variable.  */
1141   addr = decay_conversion (tdecl);
1142
1143   /* If the first word of the array (the vtable) is non-zero, we've already
1144      initialized the object, so don't do it again.  */
1145   if_stmt = begin_if_stmt ();
1146   tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
1147   tmp = build_indirect_ref (tmp, 0);
1148   tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node);
1149   finish_if_stmt_cond (tmp, if_stmt);
1150   then_clause = begin_compound_stmt (/*has_no_scope=*/0);
1151
1152   if (TREE_CODE (type) == FUNCTION_TYPE)
1153     expand_generic_desc (tdecl, type, "__rtti_func");
1154   else if (TREE_CODE (type) == ARRAY_TYPE)
1155     expand_generic_desc (tdecl, type, "__rtti_array");
1156   else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
1157     expand_attr_desc (tdecl, type);
1158   else if (TREE_CODE (type) == POINTER_TYPE)
1159     {
1160       if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1161         expand_generic_desc (tdecl, type, "__rtti_ptmd");
1162       else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1163         expand_generic_desc (tdecl, type, "__rtti_ptmf");
1164       else
1165         expand_ptr_desc (tdecl, type);
1166     }
1167   else if (TYPE_PTRMEMFUNC_P (type))
1168     expand_generic_desc (tdecl, type, "__rtti_ptmf");
1169   else if (IS_AGGR_TYPE (type))
1170     {
1171       if (CLASSTYPE_N_BASECLASSES (type) == 0)
1172         expand_generic_desc (tdecl, type, "__rtti_user");
1173       else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1174                && (TREE_VIA_PUBLIC
1175                    (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1176         expand_si_desc (tdecl, type);
1177       else
1178         expand_class_desc (tdecl, type);
1179     }
1180   else if (TREE_CODE (type) == ENUMERAL_TYPE)
1181     expand_generic_desc (tdecl, type, "__rtti_user");
1182   else
1183     my_friendly_abort (252);
1184
1185   finish_compound_stmt (/*has_no_scope=*/0, then_clause);
1186   finish_then_clause (if_stmt);
1187   finish_if_stmt ();
1188
1189   /* OK, now return the type_info object.  */
1190   tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
1191   tmp = build_indirect_ref (tmp, 0);
1192   finish_return_stmt (tmp);
1193   /* Finish the function body.  */
1194   finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
1195   expand_body (finish_function (lineno, 0));
1196 }