OSDN Git Service

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