OSDN Git Service

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