OSDN Git Service

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