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